tunacode-cli 0.0.32__tar.gz → 0.0.34__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.

Files changed (195) hide show
  1. {tunacode_cli-0.0.32/src/tunacode_cli.egg-info → tunacode_cli-0.0.34}/PKG-INFO +20 -1
  2. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/README.md +19 -0
  3. tunacode_cli-0.0.34/TUNACODE.md +27 -0
  4. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/pyproject.toml +1 -1
  5. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/cli/commands.py +42 -8
  6. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/cli/repl.py +7 -3
  7. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/configuration/defaults.py +1 -1
  8. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/constants.py +1 -1
  9. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/agents/main.py +35 -2
  10. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/setup/config_setup.py +15 -9
  11. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/utils/user_configuration.py +20 -3
  12. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34/src/tunacode_cli.egg-info}/PKG-INFO +20 -1
  13. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode_cli.egg-info/SOURCES.txt +12 -2
  14. tunacode_cli-0.0.34/src/tunacode_cli.egg-info/top_level.txt +1 -0
  15. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/agent/test_agent_creation.py +32 -26
  16. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/agent/test_process_request.py +5 -5
  17. tunacode_cli-0.0.34/tests/characterization/commands/__init__.py +1 -0
  18. tunacode_cli-0.0.34/tests/characterization/commands/test_init_command.py +252 -0
  19. tunacode_cli-0.0.34/tests/characterization/context/__init__.py +1 -0
  20. tunacode_cli-0.0.34/tests/characterization/context/test_context_acceptance.py +94 -0
  21. tunacode_cli-0.0.34/tests/characterization/context/test_context_integration.py +106 -0
  22. tunacode_cli-0.0.34/tests/characterization/context/test_context_loading.py +143 -0
  23. tunacode_cli-0.0.34/tests/characterization/context/test_tunacode_logging.py +80 -0
  24. tunacode_cli-0.0.34/tests/test_characterization_grep_performance.py +287 -0
  25. tunacode_cli-0.0.34/tests/test_characterization_iteration_limits.py +145 -0
  26. tunacode_cli-0.0.34/tests/test_characterization_tool_ui_behavior.py +464 -0
  27. tunacode_cli-0.0.34/tests/test_config_directory_creation.py +105 -0
  28. tunacode_cli-0.0.34/tests/test_tool_handler_ui_messages.py +105 -0
  29. tunacode_cli-0.0.32/TUNACODE.md +0 -0
  30. tunacode_cli-0.0.32/src/api/auth.py +0 -13
  31. tunacode_cli-0.0.32/src/api/users.py +0 -8
  32. tunacode_cli-0.0.32/src/tunacode_cli.egg-info/top_level.txt +0 -3
  33. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/CLAUDE.md +0 -0
  34. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/LICENSE +0 -0
  35. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/MANIFEST.in +0 -0
  36. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/setup.cfg +0 -0
  37. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/setup.py +0 -0
  38. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/__init__.py +0 -0
  39. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/cli/__init__.py +0 -0
  40. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/cli/main.py +0 -0
  41. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/cli/textual_app.py +0 -0
  42. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/cli/textual_bridge.py +0 -0
  43. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/configuration/__init__.py +0 -0
  44. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/configuration/models.py +0 -0
  45. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/configuration/settings.py +0 -0
  46. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/context.py +0 -0
  47. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/__init__.py +0 -0
  48. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/agents/__init__.py +0 -0
  49. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/background/__init__.py +0 -0
  50. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/background/manager.py +0 -0
  51. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/code_index.py +0 -0
  52. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/llm/__init__.py +0 -0
  53. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/setup/__init__.py +0 -0
  54. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/setup/agent_setup.py +0 -0
  55. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/setup/base.py +0 -0
  56. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/setup/coordinator.py +0 -0
  57. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/setup/environment_setup.py +0 -0
  58. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/setup/git_safety_setup.py +0 -0
  59. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/state.py +0 -0
  60. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/core/tool_handler.py +0 -0
  61. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/exceptions.py +0 -0
  62. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/prompts/system.md +0 -0
  63. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/py.typed +0 -0
  64. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/services/__init__.py +0 -0
  65. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/services/mcp.py +0 -0
  66. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/setup.py +0 -0
  67. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/tools/__init__.py +0 -0
  68. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/tools/base.py +0 -0
  69. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/tools/bash.py +0 -0
  70. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/tools/glob.py +0 -0
  71. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/tools/grep.py +0 -0
  72. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/tools/list_dir.py +0 -0
  73. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/tools/read_file.py +0 -0
  74. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/tools/read_file_async_poc.py +0 -0
  75. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/tools/run_command.py +0 -0
  76. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/tools/update_file.py +0 -0
  77. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/tools/write_file.py +0 -0
  78. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/types.py +0 -0
  79. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/ui/__init__.py +0 -0
  80. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/ui/completers.py +0 -0
  81. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/ui/console.py +0 -0
  82. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/ui/constants.py +0 -0
  83. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/ui/decorators.py +0 -0
  84. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/ui/input.py +0 -0
  85. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/ui/keybindings.py +0 -0
  86. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/ui/lexers.py +0 -0
  87. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/ui/output.py +0 -0
  88. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/ui/panels.py +0 -0
  89. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/ui/prompt_manager.py +0 -0
  90. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/ui/tool_ui.py +0 -0
  91. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/ui/validators.py +0 -0
  92. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/utils/__init__.py +0 -0
  93. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/utils/bm25.py +0 -0
  94. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/utils/diff_utils.py +0 -0
  95. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/utils/file_utils.py +0 -0
  96. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/utils/import_cache.py +0 -0
  97. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/utils/ripgrep.py +0 -0
  98. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/utils/system.py +0 -0
  99. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/utils/text_utils.py +0 -0
  100. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode/utils/token_counter.py +0 -0
  101. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode_cli.egg-info/dependency_links.txt +0 -0
  102. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode_cli.egg-info/entry_points.txt +0 -0
  103. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/src/tunacode_cli.egg-info/requires.txt +0 -0
  104. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/agent/__init__.py +0 -0
  105. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/agent/conftest.py +0 -0
  106. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/agent/test_json_tool_parsing.py +0 -0
  107. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/agent/test_process_node.py +0 -0
  108. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/agent/test_tool_message_patching.py +0 -0
  109. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/background/test_background_edge_cases.py +0 -0
  110. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/background/test_cleanup.py +0 -0
  111. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/background/test_task_cancellation.py +0 -0
  112. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/background/test_task_creation.py +0 -0
  113. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/background/test_task_execution.py +0 -0
  114. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/code_index/test_cache_management.py +0 -0
  115. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/code_index/test_file_scanning.py +0 -0
  116. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/code_index/test_index_building.py +0 -0
  117. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/code_index/test_search_operations.py +0 -0
  118. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/code_index/test_symbol_extraction.py +0 -0
  119. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/conftest.py +0 -0
  120. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/repl/test_command_parsing.py +0 -0
  121. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/repl/test_input_handling.py +0 -0
  122. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/repl/test_keyboard_interrupts.py +0 -0
  123. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/repl/test_multiline_input.py +0 -0
  124. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/repl/test_repl_initialization.py +0 -0
  125. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/repl/test_session_flow.py +0 -0
  126. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/services/test_error_recovery.py +0 -0
  127. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/services/test_llm_routing.py +0 -0
  128. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/services/test_mcp_integration.py +0 -0
  129. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/services/test_service_lifecycle.py +0 -0
  130. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/state/test_agent_tracking.py +0 -0
  131. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/state/test_message_history.py +0 -0
  132. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/state/test_permissions.py +0 -0
  133. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/state/test_session_management.py +0 -0
  134. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/state/test_state_initialization.py +0 -0
  135. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/state/test_user_config.py +0 -0
  136. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/test_characterization_commands.py +0 -0
  137. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/ui/test_async_ui.py +0 -0
  138. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/ui/test_console_output.py +0 -0
  139. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/ui/test_diff_display.py +0 -0
  140. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/ui/test_prompt_rendering.py +0 -0
  141. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/ui/test_tool_confirmations.py +0 -0
  142. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/utils/test_file_operations.py +0 -0
  143. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/utils/test_git_commands.py +0 -0
  144. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/utils/test_token_counting.py +0 -0
  145. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/characterization/utils/test_utils_edge_cases.py +0 -0
  146. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/conftest.py +0 -0
  147. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/crud/test_core_file_operations.py +0 -0
  148. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/fixtures/__init__.py +0 -0
  149. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/fixtures/file_operations.py +0 -0
  150. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/integration/test_error_recovery_flow.py +0 -0
  151. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/integration/test_full_session_flow.py +0 -0
  152. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/integration/test_mcp_tool_flow.py +0 -0
  153. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/integration/test_multi_tool_operations.py +0 -0
  154. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/integration/test_performance_scenarios.py +0 -0
  155. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_actual_parallelism.py +0 -0
  156. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_agent_initialization.py +0 -0
  157. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_background_manager.py +0 -0
  158. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_characterization_agent_main.py +0 -0
  159. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_characterization_bash.py +0 -0
  160. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_characterization_commands_system.py +0 -0
  161. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_characterization_glob.py +0 -0
  162. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_characterization_grep.py +0 -0
  163. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_characterization_list_dir.py +0 -0
  164. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_characterization_read_file.py +0 -0
  165. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_characterization_repl_utils.py +0 -0
  166. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_characterization_run_command.py +0 -0
  167. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_characterization_setup_system.py +0 -0
  168. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_characterization_update_file.py +0 -0
  169. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_characterization_utilities.py +0 -0
  170. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_characterization_write_file.py +0 -0
  171. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_cli_command_flow.py +0 -0
  172. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_cli_file_operations_integration.py +0 -0
  173. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_config_setup_async.py +0 -0
  174. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_enhanced_visual_feedback.py +0 -0
  175. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_fallback_responses.py +0 -0
  176. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_fast_glob_search.py +0 -0
  177. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_file_operations_edge_cases.py +0 -0
  178. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_file_operations_stress.py +0 -0
  179. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_file_reference_context_tracking.py +0 -0
  180. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_file_reference_expansion.py +0 -0
  181. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_grep_fast_glob.py +0 -0
  182. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_grep_legacy_compat.py +0 -0
  183. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_grep_timeout.py +0 -0
  184. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_json_tool_parsing.py +0 -0
  185. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_list_dir.py +0 -0
  186. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_parallel_execution_demo.py +0 -0
  187. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_parallel_execution_freeze_fix.py +0 -0
  188. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_parallel_execution_integration.py +0 -0
  189. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_parallel_read_only_tools.py +0 -0
  190. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_parallel_tool_execution.py +0 -0
  191. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_read_only_confirmation.py +0 -0
  192. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_tool_categorization.py +0 -0
  193. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_tool_combinations.py +0 -0
  194. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/tests/test_update_command.py +0 -0
  195. {tunacode_cli-0.0.32 → tunacode_cli-0.0.34}/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.32
3
+ Version: 0.0.34
4
4
  Summary: Your agentic CLI developer.
5
5
  Author-email: larock22 <noreply@github.com>
6
6
  License-Expression: MIT
@@ -40,6 +40,7 @@ Dynamic: license-file
40
40
  <div align="center">
41
41
 
42
42
  [![PyPI version](https://badge.fury.io/py/tunacode-cli.svg)](https://badge.fury.io/py/tunacode-cli)
43
+ [![Downloads](https://pepy.tech/badge/tunacode-cli)](https://pepy.tech/project/tunacode-cli)
43
44
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
44
45
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
45
46
 
@@ -78,6 +79,17 @@ tunacode --model "openrouter:openai/gpt-4o" --key "sk-or-your-openrouter-key"
78
79
 
79
80
  Your config is saved to `~/.config/tunacode.json` (edit directly with `nvim ~/.config/tunacode.json`)
80
81
 
82
+ ### Recommended Models
83
+
84
+ Based on extensive testing, these models provide the best performance:
85
+ - `google/gemini-2.5-pro` - Excellent for complex reasoning
86
+ - `openai/gpt-4.1` - Strong general-purpose model
87
+ - `deepseek/deepseek-r1-0528` - Great for code generation
88
+ - `openai/gpt-4.1-mini` - Fast and cost-effective
89
+ - `anthropic/claude-4-sonnet-20250522` - Superior context handling
90
+
91
+ *Note: Formal evaluations coming soon. Any model can work, but these have shown the best results in practice.*
92
+
81
93
  ## Start Coding
82
94
 
83
95
  ```bash
@@ -105,6 +117,13 @@ TunaCode leverages parallel execution for read-only operations, achieving **3x f
105
117
 
106
118
  Multiple file reads, directory listings, and searches execute concurrently using async I/O, making code exploration significantly faster.
107
119
 
120
+ ## Features in Development
121
+
122
+ - **Streaming UI**: Currently working on implementing streaming responses for better user experience
123
+ - **Bug Fixes**: Actively addressing issues - please report any bugs you encounter!
124
+
125
+ *Note: While the tool is fully functional, we're focusing on stability and core features before optimizing for speed.*
126
+
108
127
  ## Safety First
109
128
 
110
129
  ⚠️ **Important**: TunaCode can modify your codebase. Always:
@@ -3,6 +3,7 @@
3
3
  <div align="center">
4
4
 
5
5
  [![PyPI version](https://badge.fury.io/py/tunacode-cli.svg)](https://badge.fury.io/py/tunacode-cli)
6
+ [![Downloads](https://pepy.tech/badge/tunacode-cli)](https://pepy.tech/project/tunacode-cli)
6
7
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
7
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
9
 
@@ -41,6 +42,17 @@ tunacode --model "openrouter:openai/gpt-4o" --key "sk-or-your-openrouter-key"
41
42
 
42
43
  Your config is saved to `~/.config/tunacode.json` (edit directly with `nvim ~/.config/tunacode.json`)
43
44
 
45
+ ### Recommended Models
46
+
47
+ Based on extensive testing, these models provide the best performance:
48
+ - `google/gemini-2.5-pro` - Excellent for complex reasoning
49
+ - `openai/gpt-4.1` - Strong general-purpose model
50
+ - `deepseek/deepseek-r1-0528` - Great for code generation
51
+ - `openai/gpt-4.1-mini` - Fast and cost-effective
52
+ - `anthropic/claude-4-sonnet-20250522` - Superior context handling
53
+
54
+ *Note: Formal evaluations coming soon. Any model can work, but these have shown the best results in practice.*
55
+
44
56
  ## Start Coding
45
57
 
46
58
  ```bash
@@ -68,6 +80,13 @@ TunaCode leverages parallel execution for read-only operations, achieving **3x f
68
80
 
69
81
  Multiple file reads, directory listings, and searches execute concurrently using async I/O, making code exploration significantly faster.
70
82
 
83
+ ## Features in Development
84
+
85
+ - **Streaming UI**: Currently working on implementing streaming responses for better user experience
86
+ - **Bug Fixes**: Actively addressing issues - please report any bugs you encounter!
87
+
88
+ *Note: While the tool is fully functional, we're focusing on stability and core features before optimizing for speed.*
89
+
71
90
  ## Safety First
72
91
 
73
92
  ⚠️ **Important**: TunaCode can modify your codebase. Always:
@@ -0,0 +1,27 @@
1
+ # TUNACODE.md
2
+
3
+ ## Build Commands
4
+ - Run all tests: `make test`
5
+ - Run single test: `pytest tests/test_file.py::test_name`
6
+ - Run quick tests: `pytest -m "not slow"`
7
+ - Lint code: `make lint`
8
+ - Build package: `make build`
9
+ - Clean artifacts: `make clean`
10
+
11
+ ## Code Style
12
+ - Use type hints for all function signatures
13
+ - Prefer guard clauses over nested conditionals
14
+ - Keep functions focused and under 50 lines
15
+ - Use descriptive variable names
16
+ - Follow PEP 8 conventions
17
+ - Maximum line length: 120 characters
18
+ - Use black for formatting
19
+ - Use isort for imports
20
+ - Use snake_case for variables and functions
21
+ - Use PascalCase for classes
22
+ - Prefer explicit error handling, avoid bare excepts
23
+
24
+ ## Architecture Notes
25
+ - Agent creation loads this file and appends to system prompt
26
+ - Context is loaded synchronously to avoid event loop issues
27
+ - TUNACODE.md is walked up directory tree (closest first)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tunacode-cli"
7
- version = "0.0.32"
7
+ version = "0.0.34"
8
8
  description = "Your agentic CLI developer."
9
9
  keywords = ["cli", "agent", "development", "automation"]
10
10
  readme = "README.md"
@@ -6,7 +6,7 @@ from enum import Enum
6
6
  from typing import Any, Dict, List, Optional, Type
7
7
 
8
8
  from .. import utils
9
- from ..exceptions import ValidationError
9
+ from ..exceptions import ConfigurationError, ValidationError
10
10
  from ..types import CommandArgs, CommandContext, CommandResult, ProcessRequestCallback
11
11
  from ..ui import console as ui
12
12
 
@@ -184,8 +184,8 @@ class IterationsCommand(SimpleCommand):
184
184
  if args:
185
185
  try:
186
186
  new_limit = int(args[0])
187
- if new_limit < 1 or new_limit > 50:
188
- await ui.error("Iterations must be between 1 and 50")
187
+ if new_limit < 1 or new_limit > 100:
188
+ await ui.error("Iterations must be between 1 and 100")
189
189
  return
190
190
 
191
191
  # Update the user config
@@ -198,9 +198,9 @@ class IterationsCommand(SimpleCommand):
198
198
  except ValueError:
199
199
  await ui.error("Please provide a valid number")
200
200
  else:
201
- current = state.user_config.get("settings", {}).get("max_iterations", 15)
201
+ current = state.user_config.get("settings", {}).get("max_iterations", 40)
202
202
  await ui.info(f"Current maximum iterations: {current}")
203
- await ui.muted("Usage: /iterations <number> (1-50)")
203
+ await ui.muted("Usage: /iterations <number> (1-100)")
204
204
 
205
205
 
206
206
  class ClearCommand(SimpleCommand):
@@ -628,9 +628,13 @@ class ModelCommand(SimpleCommand):
628
628
 
629
629
  # Check if setting as default
630
630
  if len(args) > 1 and args[1] == "default":
631
- utils.user_configuration.set_default_model(model_name, context.state_manager)
632
- await ui.muted("Updating default model")
633
- return "restart"
631
+ try:
632
+ utils.user_configuration.set_default_model(model_name, context.state_manager)
633
+ await ui.muted("Updating default model")
634
+ return "restart"
635
+ except ConfigurationError as e:
636
+ await ui.error(str(e))
637
+ return None
634
638
 
635
639
  # Show success message with the new model
636
640
  await ui.success(f"Switched to model: {model_name}")
@@ -669,6 +673,35 @@ class CommandFactory:
669
673
  setattr(self.dependencies, key, value)
670
674
 
671
675
 
676
+ class InitCommand(SimpleCommand):
677
+ """Creates or updates TUNACODE.md with project-specific context."""
678
+
679
+ spec = CommandSpec(
680
+ name="/init",
681
+ aliases=[],
682
+ description="Analyze codebase and create/update TUNACODE.md file",
683
+ category=CommandCategory.DEVELOPMENT,
684
+ )
685
+
686
+ async def execute(self, args, context: CommandContext) -> CommandResult:
687
+ """Execute the init command."""
688
+ # Minimal implementation to make test pass
689
+ prompt = """Please analyze this codebase and create a TUNACODE.md file containing:
690
+ 1. Build/lint/test commands - especially for running a single test
691
+ 2. Code style guidelines including imports, formatting, types, naming conventions, error handling, etc.
692
+
693
+ The file you create will be given to agentic coding agents (such as yourself) that operate in this repository.
694
+ Make it about 20 lines long.
695
+ If there's already a TUNACODE.md, improve it.
696
+ If there are Cursor rules (in .cursor/rules/ or .cursorrules) or Copilot rules (in .github/copilot-instructions.md),
697
+ make sure to include them."""
698
+
699
+ # Call the agent to analyze and create/update the file
700
+ await context.process_request(prompt, context.state_manager)
701
+
702
+ return None
703
+
704
+
672
705
  class CommandRegistry:
673
706
  """Registry for managing commands with auto-discovery and categories."""
674
707
 
@@ -726,6 +759,7 @@ class CommandRegistry:
726
759
  BranchCommand,
727
760
  CompactCommand,
728
761
  ModelCommand,
762
+ InitCommand,
729
763
  ]
730
764
 
731
765
  # Register all discovered commands
@@ -88,12 +88,16 @@ async def _tool_confirm(tool_call, node, state_manager: StateManager):
88
88
 
89
89
  async def _tool_handler(part, node, state_manager: StateManager):
90
90
  """Handle tool execution with separated business logic and UI."""
91
- await ui.info(f"Tool({part.tool_name})")
91
+ # Create tool handler with state first to check if confirmation is needed
92
+ tool_handler = ToolHandler(state_manager)
93
+
94
+ # Only show tool info for tools that require confirmation
95
+ if tool_handler.should_confirm(part.tool_name):
96
+ await ui.info(f"Tool({part.tool_name})")
97
+
92
98
  state_manager.session.spinner.stop()
93
99
 
94
100
  try:
95
- # Create tool handler with state
96
- tool_handler = ToolHandler(state_manager)
97
101
  args = _parse_args(part.args)
98
102
 
99
103
  # Use a synchronous function in run_in_terminal to avoid async deadlocks
@@ -18,7 +18,7 @@ DEFAULT_USER_CONFIG: UserConfig = {
18
18
  },
19
19
  "settings": {
20
20
  "max_retries": 10,
21
- "max_iterations": 20,
21
+ "max_iterations": 40,
22
22
  "tool_ignore": [TOOL_READ_FILE],
23
23
  "guide_file": GUIDE_FILE_NAME,
24
24
  "fallback_response": True,
@@ -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.32"
10
+ APP_VERSION = "0.0.34"
11
11
 
12
12
  # File patterns
13
13
  GUIDE_FILE_PATTERN = "{name}.md"
@@ -345,6 +345,11 @@ async def _process_node(
345
345
  # Check if ALL tools in this node are read-only
346
346
  all_read_only = all(part.tool_name in READ_ONLY_TOOLS for part in tool_parts)
347
347
 
348
+ # TODO: Currently only batches if ALL tools are read-only. Should be updated to use
349
+ # batch_read_only_tools() function to group consecutive read-only tools and execute
350
+ # them in parallel even when mixed with write/execute tools. For example:
351
+ # [read, read, write, read] should execute as: [read||read], [write], [read]
352
+ # instead of all sequential. The batch_read_only_tools() function exists but is unused.
348
353
  if all_read_only and len(tool_parts) > 1 and buffering_callback:
349
354
  # Execute read-only tools in parallel!
350
355
  import time
@@ -452,6 +457,26 @@ def get_or_create_agent(model: ModelName, state_manager: StateManager) -> Pydant
452
457
  # Use a default system prompt if neither file exists
453
458
  system_prompt = "You are a helpful AI assistant for software development tasks."
454
459
 
460
+ # Load TUNACODE.md context
461
+ # Use sync version of get_code_style to avoid nested event loop issues
462
+ try:
463
+ from pathlib import Path as PathlibPath
464
+
465
+ tunacode_path = PathlibPath.cwd() / "TUNACODE.md"
466
+ if tunacode_path.exists():
467
+ tunacode_content = tunacode_path.read_text(encoding="utf-8")
468
+ if tunacode_content.strip():
469
+ # Log that we found TUNACODE.md
470
+ print("📄 TUNACODE.md located: Loading context...")
471
+
472
+ system_prompt += "\n\n# Project Context from TUNACODE.md\n" + tunacode_content
473
+ else:
474
+ # Log that TUNACODE.md was not found
475
+ print("📄 TUNACODE.md not found: Using default context")
476
+ except Exception:
477
+ # Ignore errors loading TUNACODE.md
478
+ pass
479
+
455
480
  state_manager.session.agents[model] = Agent(
456
481
  model=model,
457
482
  system_prompt=system_prompt,
@@ -651,8 +676,8 @@ async def process_request(
651
676
  ) -> AgentRun:
652
677
  agent = get_or_create_agent(model, state_manager)
653
678
  mh = state_manager.session.messages.copy()
654
- # Get max iterations from config (default: 20)
655
- max_iterations = state_manager.session.user_config.get("settings", {}).get("max_iterations", 20)
679
+ # Get max iterations from config (default: 40)
680
+ max_iterations = state_manager.session.user_config.get("settings", {}).get("max_iterations", 40)
656
681
  fallback_enabled = state_manager.session.user_config.get("settings", {}).get(
657
682
  "fallback_response", True
658
683
  )
@@ -665,6 +690,14 @@ async def process_request(
665
690
  # Create a request-level buffer for batching read-only tools across nodes
666
691
  tool_buffer = ToolBuffer()
667
692
 
693
+ # Show TUNACODE.md preview if it was loaded and thoughts are enabled
694
+ if state_manager.session.show_thoughts and hasattr(state_manager, "tunacode_preview"):
695
+ from tunacode.ui import console as ui
696
+
697
+ await ui.muted(state_manager.tunacode_preview)
698
+ # Clear the preview after displaying it once
699
+ delattr(state_manager, "tunacode_preview")
700
+
668
701
  # Show what we're sending to the API when thoughts are enabled
669
702
  if state_manager.session.show_thoughts:
670
703
  from tunacode.ui import console as ui
@@ -82,9 +82,13 @@ class ConfigSetup(BaseSetup):
82
82
  ):
83
83
  self.state_manager.session.user_config = {}
84
84
  self.state_manager.session.user_config = DEFAULT_USER_CONFIG.copy()
85
- user_configuration.save_config(
86
- self.state_manager
87
- ) # Save the default config initially
85
+ try:
86
+ user_configuration.save_config(
87
+ self.state_manager
88
+ ) # Save the default config initially
89
+ except ConfigurationError as e:
90
+ await ui.error(str(e))
91
+ raise
88
92
  await self._onboarding()
89
93
  else:
90
94
  # No config found - show CLI usage instead of onboarding
@@ -172,11 +176,12 @@ class ConfigSetup(BaseSetup):
172
176
  # Compare configs to see if anything changed
173
177
  current_config = json.dumps(self.state_manager.session.user_config, sort_keys=True)
174
178
  if initial_config != current_config:
175
- if user_configuration.save_config(self.state_manager):
179
+ try:
180
+ user_configuration.save_config(self.state_manager)
176
181
  message = f"Config saved to: [bold]{self.config_file}[/bold]"
177
182
  await ui.panel("Finished", message, top=0, border_style=UI_COLORS["success"])
178
- else:
179
- await ui.error("Failed to save configuration.")
183
+ except ConfigurationError as e:
184
+ await ui.error(str(e))
180
185
  else:
181
186
  await ui.panel(
182
187
  "Setup canceled",
@@ -320,8 +325,9 @@ class ConfigSetup(BaseSetup):
320
325
  ]
321
326
 
322
327
  # Save the configuration
323
- if user_configuration.save_config(self.state_manager):
328
+ try:
329
+ user_configuration.save_config(self.state_manager)
324
330
  await ui.warning("Model set without validation - verify the model name is correct")
325
331
  await ui.success(f"Configuration saved to: {self.config_file}")
326
- else:
327
- await ui.error("Failed to save configuration.")
332
+ except ConfigurationError as e:
333
+ await ui.error(str(e))
@@ -58,11 +58,23 @@ def save_config(state_manager: "StateManager") -> bool:
58
58
  """Save user config to file"""
59
59
  app_settings = ApplicationSettings()
60
60
  try:
61
+ # Ensure config directory exists
62
+ app_settings.paths.config_dir.mkdir(mode=0o700, parents=True, exist_ok=True)
63
+
64
+ # Write config file
61
65
  with open(app_settings.paths.config_file, "w") as f:
62
66
  json.dump(state_manager.session.user_config, f, indent=4)
63
67
  return True
64
- except Exception:
65
- return False
68
+ except PermissionError as e:
69
+ raise ConfigurationError(
70
+ f"Permission denied writing to {app_settings.paths.config_file}: {e}"
71
+ )
72
+ except OSError as e:
73
+ raise ConfigurationError(
74
+ f"Failed to save configuration to {app_settings.paths.config_file}: {e}"
75
+ )
76
+ except Exception as e:
77
+ raise ConfigurationError(f"Unexpected error saving configuration: {e}")
66
78
 
67
79
 
68
80
  def get_mcp_servers(state_manager: "StateManager") -> MCPServers:
@@ -73,4 +85,9 @@ def get_mcp_servers(state_manager: "StateManager") -> MCPServers:
73
85
  def set_default_model(model_name: ModelName, state_manager: "StateManager") -> bool:
74
86
  """Set the default model in the user config and save"""
75
87
  state_manager.session.user_config["default_model"] = model_name
76
- return save_config(state_manager)
88
+ try:
89
+ save_config(state_manager)
90
+ return True
91
+ except ConfigurationError:
92
+ # Re-raise ConfigurationError to be handled by caller
93
+ raise
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tunacode-cli
3
- Version: 0.0.32
3
+ Version: 0.0.34
4
4
  Summary: Your agentic CLI developer.
5
5
  Author-email: larock22 <noreply@github.com>
6
6
  License-Expression: MIT
@@ -40,6 +40,7 @@ Dynamic: license-file
40
40
  <div align="center">
41
41
 
42
42
  [![PyPI version](https://badge.fury.io/py/tunacode-cli.svg)](https://badge.fury.io/py/tunacode-cli)
43
+ [![Downloads](https://pepy.tech/badge/tunacode-cli)](https://pepy.tech/project/tunacode-cli)
43
44
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
44
45
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
45
46
 
@@ -78,6 +79,17 @@ tunacode --model "openrouter:openai/gpt-4o" --key "sk-or-your-openrouter-key"
78
79
 
79
80
  Your config is saved to `~/.config/tunacode.json` (edit directly with `nvim ~/.config/tunacode.json`)
80
81
 
82
+ ### Recommended Models
83
+
84
+ Based on extensive testing, these models provide the best performance:
85
+ - `google/gemini-2.5-pro` - Excellent for complex reasoning
86
+ - `openai/gpt-4.1` - Strong general-purpose model
87
+ - `deepseek/deepseek-r1-0528` - Great for code generation
88
+ - `openai/gpt-4.1-mini` - Fast and cost-effective
89
+ - `anthropic/claude-4-sonnet-20250522` - Superior context handling
90
+
91
+ *Note: Formal evaluations coming soon. Any model can work, but these have shown the best results in practice.*
92
+
81
93
  ## Start Coding
82
94
 
83
95
  ```bash
@@ -105,6 +117,13 @@ TunaCode leverages parallel execution for read-only operations, achieving **3x f
105
117
 
106
118
  Multiple file reads, directory listings, and searches execute concurrently using async I/O, making code exploration significantly faster.
107
119
 
120
+ ## Features in Development
121
+
122
+ - **Streaming UI**: Currently working on implementing streaming responses for better user experience
123
+ - **Bug Fixes**: Actively addressing issues - please report any bugs you encounter!
124
+
125
+ *Note: While the tool is fully functional, we're focusing on stability and core features before optimizing for speed.*
126
+
108
127
  ## Safety First
109
128
 
110
129
  ⚠️ **Important**: TunaCode can modify your codebase. Always:
@@ -5,8 +5,6 @@ README.md
5
5
  TUNACODE.md
6
6
  pyproject.toml
7
7
  setup.py
8
- src/api/auth.py
9
- src/api/users.py
10
8
  src/tunacode/__init__.py
11
9
  src/tunacode/constants.py
12
10
  src/tunacode/context.py
@@ -92,16 +90,20 @@ tests/test_characterization_bash.py
92
90
  tests/test_characterization_commands_system.py
93
91
  tests/test_characterization_glob.py
94
92
  tests/test_characterization_grep.py
93
+ tests/test_characterization_grep_performance.py
94
+ tests/test_characterization_iteration_limits.py
95
95
  tests/test_characterization_list_dir.py
96
96
  tests/test_characterization_read_file.py
97
97
  tests/test_characterization_repl_utils.py
98
98
  tests/test_characterization_run_command.py
99
99
  tests/test_characterization_setup_system.py
100
+ tests/test_characterization_tool_ui_behavior.py
100
101
  tests/test_characterization_update_file.py
101
102
  tests/test_characterization_utilities.py
102
103
  tests/test_characterization_write_file.py
103
104
  tests/test_cli_command_flow.py
104
105
  tests/test_cli_file_operations_integration.py
106
+ tests/test_config_directory_creation.py
105
107
  tests/test_config_setup_async.py
106
108
  tests/test_enhanced_visual_feedback.py
107
109
  tests/test_fallback_responses.py
@@ -123,6 +125,7 @@ tests/test_parallel_tool_execution.py
123
125
  tests/test_read_only_confirmation.py
124
126
  tests/test_tool_categorization.py
125
127
  tests/test_tool_combinations.py
128
+ tests/test_tool_handler_ui_messages.py
126
129
  tests/test_update_command.py
127
130
  tests/test_visual_parallel_feedback.py
128
131
  tests/characterization/conftest.py
@@ -144,6 +147,13 @@ tests/characterization/code_index/test_file_scanning.py
144
147
  tests/characterization/code_index/test_index_building.py
145
148
  tests/characterization/code_index/test_search_operations.py
146
149
  tests/characterization/code_index/test_symbol_extraction.py
150
+ tests/characterization/commands/__init__.py
151
+ tests/characterization/commands/test_init_command.py
152
+ tests/characterization/context/__init__.py
153
+ tests/characterization/context/test_context_acceptance.py
154
+ tests/characterization/context/test_context_integration.py
155
+ tests/characterization/context/test_context_loading.py
156
+ tests/characterization/context/test_tunacode_logging.py
147
157
  tests/characterization/repl/test_command_parsing.py
148
158
  tests/characterization/repl/test_input_handling.py
149
159
  tests/characterization/repl/test_keyboard_interrupts.py
@@ -38,20 +38,22 @@ class TestAgentCreation:
38
38
  with patch('tunacode.core.agents.main.get_agent_tool', return_value=(mock_agent_class, mock_tool_class)):
39
39
  with patch('builtins.open', mock_open(read_data=system_prompt)):
40
40
  with patch('tunacode.core.agents.main.get_mcp_servers', return_value=[]):
41
- # Act
42
- result = get_or_create_agent(model, self.state_manager)
43
-
44
- # Assert - Golden master
45
- assert model in self.state_manager.session.agents
46
- assert self.state_manager.session.agents[model] == mock_agent_class.return_value
47
-
48
- # Verify agent was created with correct parameters
49
- mock_agent_class.assert_called_once()
50
- call_kwargs = mock_agent_class.call_args.kwargs
51
- assert call_kwargs['model'] == model
52
- assert call_kwargs['system_prompt'] == system_prompt
53
- assert len(call_kwargs['tools']) == 8 # All 8 tools registered
54
- assert call_kwargs['mcp_servers'] == []
41
+ # Mock TUNACODE.md not existing to get predictable system prompt
42
+ with patch('pathlib.Path.exists', return_value=False):
43
+ # Act
44
+ result = get_or_create_agent(model, self.state_manager)
45
+
46
+ # Assert - Golden master
47
+ assert model in self.state_manager.session.agents
48
+ assert self.state_manager.session.agents[model] == mock_agent_class.return_value
49
+
50
+ # Verify agent was created with correct parameters
51
+ mock_agent_class.assert_called_once()
52
+ call_kwargs = mock_agent_class.call_args.kwargs
53
+ assert call_kwargs['model'] == model
54
+ assert call_kwargs['system_prompt'] == system_prompt
55
+ assert len(call_kwargs['tools']) == 8 # All 8 tools registered
56
+ assert call_kwargs['mcp_servers'] == []
55
57
 
56
58
  def test_get_or_create_agent_cached(self):
57
59
  """Capture behavior when agent already exists."""
@@ -83,12 +85,14 @@ class TestAgentCreation:
83
85
  with patch('tunacode.core.agents.main.get_agent_tool', return_value=(mock_agent_class, mock_tool_class)):
84
86
  with patch('builtins.open', side_effect=mock_open_side_effect):
85
87
  with patch('tunacode.core.agents.main.get_mcp_servers', return_value=[]):
86
- # Act
87
- result = get_or_create_agent(model, self.state_manager)
88
-
89
- # Assert - Golden master
90
- call_kwargs = mock_agent_class.call_args.kwargs
91
- assert call_kwargs['system_prompt'] == fallback_prompt
88
+ # Mock TUNACODE.md not existing
89
+ with patch('pathlib.Path.exists', return_value=False):
90
+ # Act
91
+ result = get_or_create_agent(model, self.state_manager)
92
+
93
+ # Assert - Golden master
94
+ call_kwargs = mock_agent_class.call_args.kwargs
95
+ assert call_kwargs['system_prompt'] == fallback_prompt
92
96
 
93
97
  def test_get_or_create_agent_default_prompt(self):
94
98
  """Capture behavior when neither prompt file exists."""
@@ -100,12 +104,14 @@ class TestAgentCreation:
100
104
  with patch('tunacode.core.agents.main.get_agent_tool', return_value=(mock_agent_class, mock_tool_class)):
101
105
  with patch('builtins.open', side_effect=FileNotFoundError):
102
106
  with patch('tunacode.core.agents.main.get_mcp_servers', return_value=[]):
103
- # Act
104
- result = get_or_create_agent(model, self.state_manager)
105
-
106
- # Assert - Golden master
107
- call_kwargs = mock_agent_class.call_args.kwargs
108
- assert call_kwargs['system_prompt'] == "You are a helpful AI assistant for software development tasks."
107
+ # Mock TUNACODE.md not existing
108
+ with patch('pathlib.Path.exists', return_value=False):
109
+ # Act
110
+ result = get_or_create_agent(model, self.state_manager)
111
+
112
+ # Assert - Golden master
113
+ call_kwargs = mock_agent_class.call_args.kwargs
114
+ assert call_kwargs['system_prompt'] == "You are a helpful AI assistant for software development tasks."
109
115
 
110
116
  def test_get_or_create_agent_tools_registered(self):
111
117
  """Capture behavior of tool registration with max_retries."""
@@ -37,7 +37,7 @@ class TestProcessRequest:
37
37
  self.state_manager.session.user_config = {
38
38
  "settings": {
39
39
  "max_retries": 3,
40
- "max_iterations": 20,
40
+ "max_iterations": 40,
41
41
  "fallback_response": True,
42
42
  "fallback_verbosity": "normal"
43
43
  }
@@ -250,11 +250,11 @@ class TestProcessRequest:
250
250
  await process_request("openai:gpt-4", message, self.state_manager, AsyncMock())
251
251
 
252
252
  # Assert - Golden master
253
- calls = [call[0][0] for call in mock_muted.call_args_list]
253
+ calls = [str(call[0][0]) if call[0] else "" for call in mock_muted.call_args_list]
254
254
 
255
- # Should show iteration progress
256
- assert any("ITERATION: 1/20" in call for call in calls)
257
- assert any("ITERATION: 2/20" in call for call in calls)
255
+ # Should show iteration progress (default is now 40)
256
+ assert any("ITERATION: 1/40" in call for call in calls)
257
+ assert any("ITERATION: 2/40" in call for call in calls)
258
258
 
259
259
  # Should show tool summary
260
260
  assert any("TOOLS USED: read_file: 2, bash: 1" in call for call in calls)
@@ -0,0 +1 @@
1
+ """Characterization tests for individual commands."""