tunacode-cli 0.0.55__py3-none-any.whl → 0.0.78.6__py3-none-any.whl

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 (114) hide show
  1. tunacode/cli/commands/__init__.py +2 -2
  2. tunacode/cli/commands/implementations/__init__.py +2 -3
  3. tunacode/cli/commands/implementations/command_reload.py +48 -0
  4. tunacode/cli/commands/implementations/debug.py +2 -2
  5. tunacode/cli/commands/implementations/development.py +10 -8
  6. tunacode/cli/commands/implementations/model.py +357 -29
  7. tunacode/cli/commands/implementations/quickstart.py +43 -0
  8. tunacode/cli/commands/implementations/system.py +96 -3
  9. tunacode/cli/commands/implementations/template.py +0 -2
  10. tunacode/cli/commands/registry.py +139 -5
  11. tunacode/cli/commands/slash/__init__.py +32 -0
  12. tunacode/cli/commands/slash/command.py +157 -0
  13. tunacode/cli/commands/slash/loader.py +135 -0
  14. tunacode/cli/commands/slash/processor.py +294 -0
  15. tunacode/cli/commands/slash/types.py +93 -0
  16. tunacode/cli/commands/slash/validator.py +400 -0
  17. tunacode/cli/main.py +23 -2
  18. tunacode/cli/repl.py +217 -190
  19. tunacode/cli/repl_components/command_parser.py +38 -4
  20. tunacode/cli/repl_components/error_recovery.py +85 -4
  21. tunacode/cli/repl_components/output_display.py +12 -1
  22. tunacode/cli/repl_components/tool_executor.py +1 -1
  23. tunacode/configuration/defaults.py +12 -3
  24. tunacode/configuration/key_descriptions.py +284 -0
  25. tunacode/configuration/settings.py +0 -1
  26. tunacode/constants.py +12 -40
  27. tunacode/core/agents/__init__.py +43 -2
  28. tunacode/core/agents/agent_components/__init__.py +7 -0
  29. tunacode/core/agents/agent_components/agent_config.py +249 -55
  30. tunacode/core/agents/agent_components/agent_helpers.py +43 -13
  31. tunacode/core/agents/agent_components/node_processor.py +179 -139
  32. tunacode/core/agents/agent_components/response_state.py +123 -6
  33. tunacode/core/agents/agent_components/state_transition.py +116 -0
  34. tunacode/core/agents/agent_components/streaming.py +296 -0
  35. tunacode/core/agents/agent_components/task_completion.py +19 -6
  36. tunacode/core/agents/agent_components/tool_buffer.py +21 -1
  37. tunacode/core/agents/agent_components/tool_executor.py +10 -0
  38. tunacode/core/agents/main.py +522 -370
  39. tunacode/core/agents/main_legact.py +538 -0
  40. tunacode/core/agents/prompts.py +66 -0
  41. tunacode/core/agents/utils.py +29 -121
  42. tunacode/core/code_index.py +83 -29
  43. tunacode/core/setup/__init__.py +0 -2
  44. tunacode/core/setup/config_setup.py +110 -20
  45. tunacode/core/setup/config_wizard.py +230 -0
  46. tunacode/core/setup/coordinator.py +14 -5
  47. tunacode/core/state.py +16 -20
  48. tunacode/core/token_usage/usage_tracker.py +5 -3
  49. tunacode/core/tool_authorization.py +352 -0
  50. tunacode/core/tool_handler.py +67 -40
  51. tunacode/exceptions.py +119 -5
  52. tunacode/prompts/system.xml +751 -0
  53. tunacode/services/mcp.py +125 -7
  54. tunacode/setup.py +5 -25
  55. tunacode/tools/base.py +163 -0
  56. tunacode/tools/bash.py +110 -1
  57. tunacode/tools/glob.py +332 -34
  58. tunacode/tools/grep.py +179 -82
  59. tunacode/tools/grep_components/result_formatter.py +98 -4
  60. tunacode/tools/list_dir.py +132 -2
  61. tunacode/tools/prompts/bash_prompt.xml +72 -0
  62. tunacode/tools/prompts/glob_prompt.xml +45 -0
  63. tunacode/tools/prompts/grep_prompt.xml +98 -0
  64. tunacode/tools/prompts/list_dir_prompt.xml +31 -0
  65. tunacode/tools/prompts/react_prompt.xml +23 -0
  66. tunacode/tools/prompts/read_file_prompt.xml +54 -0
  67. tunacode/tools/prompts/run_command_prompt.xml +64 -0
  68. tunacode/tools/prompts/update_file_prompt.xml +53 -0
  69. tunacode/tools/prompts/write_file_prompt.xml +37 -0
  70. tunacode/tools/react.py +153 -0
  71. tunacode/tools/read_file.py +91 -0
  72. tunacode/tools/run_command.py +114 -0
  73. tunacode/tools/schema_assembler.py +167 -0
  74. tunacode/tools/update_file.py +94 -0
  75. tunacode/tools/write_file.py +86 -0
  76. tunacode/tools/xml_helper.py +83 -0
  77. tunacode/tutorial/__init__.py +9 -0
  78. tunacode/tutorial/content.py +98 -0
  79. tunacode/tutorial/manager.py +182 -0
  80. tunacode/tutorial/steps.py +124 -0
  81. tunacode/types.py +20 -27
  82. tunacode/ui/completers.py +434 -50
  83. tunacode/ui/config_dashboard.py +585 -0
  84. tunacode/ui/console.py +63 -11
  85. tunacode/ui/input.py +20 -3
  86. tunacode/ui/keybindings.py +7 -4
  87. tunacode/ui/model_selector.py +395 -0
  88. tunacode/ui/output.py +40 -19
  89. tunacode/ui/panels.py +212 -43
  90. tunacode/ui/path_heuristics.py +91 -0
  91. tunacode/ui/prompt_manager.py +5 -1
  92. tunacode/ui/tool_ui.py +33 -10
  93. tunacode/utils/api_key_validation.py +93 -0
  94. tunacode/utils/config_comparator.py +340 -0
  95. tunacode/utils/json_utils.py +206 -0
  96. tunacode/utils/message_utils.py +14 -4
  97. tunacode/utils/models_registry.py +593 -0
  98. tunacode/utils/ripgrep.py +332 -9
  99. tunacode/utils/text_utils.py +18 -1
  100. tunacode/utils/user_configuration.py +45 -0
  101. tunacode_cli-0.0.78.6.dist-info/METADATA +260 -0
  102. tunacode_cli-0.0.78.6.dist-info/RECORD +158 -0
  103. {tunacode_cli-0.0.55.dist-info → tunacode_cli-0.0.78.6.dist-info}/WHEEL +1 -2
  104. tunacode/cli/commands/implementations/todo.py +0 -217
  105. tunacode/context.py +0 -71
  106. tunacode/core/setup/git_safety_setup.py +0 -182
  107. tunacode/prompts/system.md +0 -731
  108. tunacode/tools/read_file_async_poc.py +0 -196
  109. tunacode/tools/todo.py +0 -349
  110. tunacode_cli-0.0.55.dist-info/METADATA +0 -322
  111. tunacode_cli-0.0.55.dist-info/RECORD +0 -126
  112. tunacode_cli-0.0.55.dist-info/top_level.txt +0 -1
  113. {tunacode_cli-0.0.55.dist-info → tunacode_cli-0.0.78.6.dist-info}/entry_points.txt +0 -0
  114. {tunacode_cli-0.0.55.dist-info → tunacode_cli-0.0.78.6.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,158 @@
1
+ tunacode/__init__.py,sha256=yUul8igNYMfUrHnYfioIGAqvrH8b5BKiO_pt1wVnmd0,119
2
+ tunacode/constants.py,sha256=r08u5GRo9jK_ySVI4g_itxnvNs09kRVrrnazwavAVes,5151
3
+ tunacode/exceptions.py,sha256=m80njR-LqBXhFAEOPqCE7N2QPU4Fkjlf_f6CWKO0_Is,8479
4
+ tunacode/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ tunacode/setup.py,sha256=m8-198OY5Yp9NSR3OzS_rWeFQPD83ex2UCazDarjA04,1341
6
+ tunacode/types.py,sha256=XllBT4miOtpz4maY5Q6qWoWJLhZB4ksVuMEWDtPlGps,8366
7
+ tunacode/cli/__init__.py,sha256=zgs0UbAck8hfvhYsWhWOfBe5oK09ug2De1r4RuQZREA,55
8
+ tunacode/cli/main.py,sha256=cRqSto2PNYipgGxOX5Q4zabsYR0YCwbaVmGjAx0FuTA,3699
9
+ tunacode/cli/repl.py,sha256=L4dtH7j9io9SKzD7S8heFC41bgTSA5NKR2iaVQLA8U4,17315
10
+ tunacode/cli/commands/__init__.py,sha256=XmDNszfG0AnLK46P6OHP8LR6khKNYahXfqgmkSJt6wc,1758
11
+ tunacode/cli/commands/base.py,sha256=Ge_lNQA-GDfcb1Ap1oznCH3UrifBiHH3bA9DNL-tCDw,2519
12
+ tunacode/cli/commands/registry.py,sha256=WMmZCK5rMDrtW9cjKbK51GDquvE-dfO_m36XzFVdwcA,14906
13
+ tunacode/cli/commands/template_shortcut.py,sha256=ApYTPkDVBRaLxa7rWaPrsGcJdkR7eg09k18KyTjYg_E,3447
14
+ tunacode/cli/commands/implementations/__init__.py,sha256=QLOS4S2mXxRH65bIXcX3r4IMek_aVaRNJMK1wW0oN2I,1019
15
+ tunacode/cli/commands/implementations/command_reload.py,sha256=GyjeKvJbgE4VYkaasGajspdk9wffumZMNLzfCUeNazM,1555
16
+ tunacode/cli/commands/implementations/conversation.py,sha256=ZijCNaRi1p5v1Q-IaVHtU2_BripSW3JCVKTtqFkOUjg,4676
17
+ tunacode/cli/commands/implementations/debug.py,sha256=w2fUgqFB4ipBCmNotbvaOOVW4OiCwJM6MXNWlyKyoqs,6754
18
+ tunacode/cli/commands/implementations/development.py,sha256=arMtmRX8Nw7irbeV7xCbkma5iEOp5r9sS7OQ26KItYk,2839
19
+ tunacode/cli/commands/implementations/model.py,sha256=dFRmMlcN78TdGMFX-B2OPyoWqOVQL72XC8ayPyUQmpA,16166
20
+ tunacode/cli/commands/implementations/quickstart.py,sha256=53H7ubYMGMgmCeYCs6o_F91Q4pd3Ky008lCU4GPuRP8,1363
21
+ tunacode/cli/commands/implementations/system.py,sha256=EV3-_bvygRWdVRAIUqm5pGKIZ8uKWE2DcHWrKX9-I0w,12023
22
+ tunacode/cli/commands/implementations/template.py,sha256=Akm4kz0sQCx3n0KWQmACQrVyvTLhavC9I2Eg9SRjNu8,5394
23
+ tunacode/cli/commands/slash/__init__.py,sha256=O5EiITHZJgzIciKA_nylj5PyOZNvXE9jPmOHioDk3cU,824
24
+ tunacode/cli/commands/slash/command.py,sha256=ewtyLJNAW0cJLwpSiycyVH0LpqsR3xVqCBhSym7d_7w,6329
25
+ tunacode/cli/commands/slash/loader.py,sha256=i37m_reKbcezK405-J-OmnpyBzV_QXoZB3Oa_bPw8kY,5632
26
+ tunacode/cli/commands/slash/processor.py,sha256=JQ_sE9Vu7LAdSnUmMz-hBPfD8E60aIHPNeaFMn7PQjM,11751
27
+ tunacode/cli/commands/slash/types.py,sha256=v52tDX7T5I3nEETakloXLQzJqWXSyxcM1K5FbFNdtzw,2375
28
+ tunacode/cli/commands/slash/validator.py,sha256=UKPE4dijq6VbhcyKcAnuij7Gw1IkvHUijheeiWWEer0,13985
29
+ tunacode/cli/repl_components/__init__.py,sha256=5ZjPJ3yUvZ5x6Vg9EYJ03-tdxfEEdmfradCmwSlVY3E,334
30
+ tunacode/cli/repl_components/command_parser.py,sha256=iRSs4K6aKjKstNNNCYQoGWd3hN1FHDrQrOa7uB9z0Z4,2376
31
+ tunacode/cli/repl_components/error_recovery.py,sha256=1Zm9W_AE9WKfv8n5LnTA_myAu9qotRPEVt72_hnaSq4,6222
32
+ tunacode/cli/repl_components/output_display.py,sha256=7a5CIUjm99RUyK7jj1taEySI1lKlcQxa3T3DzKUa4Go,1107
33
+ tunacode/cli/repl_components/tool_executor.py,sha256=dbvrJFfL1i2kf2XpPXhvCgbTKVSyCAA110brA2ze5B4,3142
34
+ tunacode/configuration/__init__.py,sha256=MbVXy8bGu0yKehzgdgZ_mfWlYGvIdb1dY2Ly75nfuPE,17
35
+ tunacode/configuration/defaults.py,sha256=eFUDD73tTWa3HM320BEn0VWM-XuDKW7d6m32qTK2eRI,1313
36
+ tunacode/configuration/key_descriptions.py,sha256=tvFhdA98RgRoE-Xsb5gfuzB3HSl_GY568Q5vg0C8s2A,11249
37
+ tunacode/configuration/models.py,sha256=buH8ZquvcYI3OQBDIZeJ08cu00rSCeNABtUwl3VQS0E,4103
38
+ tunacode/configuration/settings.py,sha256=zLeTmntMY94M87aD9xPNhS4yc8yApdPWltw6u4slP2Q,1020
39
+ tunacode/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
+ tunacode/core/code_index.py,sha256=2qxEn2eTIegV4F_gLeZO5lAOv8mkf4Y_t21whZ9F2Fk,17370
41
+ tunacode/core/state.py,sha256=esGjB3zCfdwqcZzurH7oxAC5Klkd0gskkAgY3fviCDU,6367
42
+ tunacode/core/tool_authorization.py,sha256=VBPNCWxoxlq_dEuo8EfkQoSwCJqCdn0vOIu9spB82v4,11655
43
+ tunacode/core/tool_handler.py,sha256=PzLg3VYtIGj9dnyJ4kCfCwyncmuxzsMgPwQqn2jmzqI,4444
44
+ tunacode/core/agents/__init__.py,sha256=HmrifkzSUykt4hcL-SeZUgEshYVSZBxLDUSgaS81-A8,1107
45
+ tunacode/core/agents/main.py,sha256=H3PHfQCvDYazlu-hqzlmeEUE-uImjSf1aqYcBmb0vQo,23314
46
+ tunacode/core/agents/main_legact.py,sha256=5p5k7Em1_dH5ZoytWEhPHYKx3Nhb71KoE_TN-mwOfOE,20856
47
+ tunacode/core/agents/prompts.py,sha256=Eps3qQm8zdgPnyYOvRYwINMGVa71ttuqGlgtH17-3ag,2357
48
+ tunacode/core/agents/utils.py,sha256=jqR7xIeeqj45SbFjUcIBi1-f10Af8iKwM2Abezvb0II,10607
49
+ tunacode/core/agents/agent_components/__init__.py,sha256=65V5ijSKen0F0zLvUO3AkZJmCrocSW3lEbqNPrHqxoc,1706
50
+ tunacode/core/agents/agent_components/agent_config.py,sha256=9mjZlRVUTSJh7Y2fbBmyLrojBHfSGpqwQ4ES5-C6ozc,11872
51
+ tunacode/core/agents/agent_components/agent_helpers.py,sha256=pfoP_pX4N1g950UDcLkZS-FSq5at3IvNDZhJStt7IWk,9157
52
+ tunacode/core/agents/agent_components/json_tool_parser.py,sha256=HuyNT0rs-ppx_gLAI2e0XMVGbR_F0WXZfP3sx38VoMg,3447
53
+ tunacode/core/agents/agent_components/message_handler.py,sha256=KJGOtb9VhumgZpxxwO45HrKLhU9_MwuoWRsSQwJviNU,3704
54
+ tunacode/core/agents/agent_components/node_processor.py,sha256=2DqM__dU2bNlcrCS7ptD05a3xI7mR4GURCj5DzofuiY,21533
55
+ tunacode/core/agents/agent_components/response_state.py,sha256=XHaJrkn4kWecVM008kWf_nEAkoR2UPYfqaH-azdzhj8,5061
56
+ tunacode/core/agents/agent_components/result_wrapper.py,sha256=9CFK0wpsfZx2WT4PBHfkSv22GxL1gAQuUYVMlmYtCJU,1761
57
+ tunacode/core/agents/agent_components/state_transition.py,sha256=uyvLJriexosBDQIrxbVDLR_luvXAMG6tnDsX10mbZcI,4077
58
+ tunacode/core/agents/agent_components/streaming.py,sha256=hVtxxZTkJZPSqlQxi5twRoWz0FXRApQ8pG83zRNSHSU,15207
59
+ tunacode/core/agents/agent_components/task_completion.py,sha256=iLzwspVDtkXTJNQFk8YNSbb6wzMWEelmSMwSnzLIzbk,1193
60
+ tunacode/core/agents/agent_components/tool_buffer.py,sha256=h9PeP9glW_rlGKElH-JD_CPUVhS3tS4AUwZSn4oINzg,1520
61
+ tunacode/core/agents/agent_components/tool_executor.py,sha256=MMGjRmjBnuyYnKh64fMTAQJujIEgDizQFMUdNSbP0Cc,2401
62
+ tunacode/core/agents/agent_components/truncation_checker.py,sha256=XbJ3wwtdC4NhgIMIvFR0z_cfNnYMkiYAZo9zGDBPU8Y,2685
63
+ tunacode/core/background/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
+ tunacode/core/background/manager.py,sha256=AxNcuuE7T2pqeI2lLIGJgaS_jEw60YzBfZY9EOY54fc,1160
65
+ tunacode/core/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
+ tunacode/core/logging/__init__.py,sha256=vykmcZPOo_FhIPJvPuH0gbUqprpGp9Sbrj13X0iOil4,709
67
+ tunacode/core/logging/config.py,sha256=bhJ6KYrEliKC5BehXKXZHHPBJUBX0g5O3uxbr8qUKQ0,2515
68
+ tunacode/core/logging/formatters.py,sha256=uWx-M0jSvsAVo5JVdCK1VIVawXNONjJ2CvMwPuuUTg8,1236
69
+ tunacode/core/logging/handlers.py,sha256=lkLczpcI6kSammSdjrCccosGMrRdcAA_3UmuTOiPnxg,3788
70
+ tunacode/core/logging/logger.py,sha256=9RjRuX0GoUojRJ8WnJGQPFdXiluiJMCoFmvc8xEioB8,142
71
+ tunacode/core/setup/__init__.py,sha256=edzZ5tdWPdokPaOuFgYGEUGY_Fcn6bcWSiDOhGGZTBc,372
72
+ tunacode/core/setup/agent_setup.py,sha256=tpOIW85C6o1m8pwAZQBIMKxKIyBUOpHHn4JJmDBFH3Q,1403
73
+ tunacode/core/setup/base.py,sha256=FMjBQQS_q3KOxHqfg7NJGmKq-1nxC40htiPZprzTu7I,970
74
+ tunacode/core/setup/config_setup.py,sha256=lzVsnXZ6jnrD1tasjd4BDPFrSrFNcreZXEf3Twp_re0,19192
75
+ tunacode/core/setup/config_wizard.py,sha256=0QnJk6UzdXhfNWlu_YgndLP5oMyxJEt-zzGdQaRFjnU,9376
76
+ tunacode/core/setup/coordinator.py,sha256=_tGi5QuV00IJ4QK8mYfpaHZn0esB6CWCuiTE55zhSuw,2407
77
+ tunacode/core/setup/environment_setup.py,sha256=n3IrObKEynHZSwtUJ1FddMg2C4sHz7ca42awemImV8s,2225
78
+ tunacode/core/setup/template_setup.py,sha256=0lDGhNVCvGN7ykqHnl3pj4CONH3I2PvMzkmIZibfSoc,2640
79
+ tunacode/core/token_usage/api_response_parser.py,sha256=plLltHg4zGVzxjv3MFj45bbd-NOJeT_v3P0Ki4zlvn4,1831
80
+ tunacode/core/token_usage/cost_calculator.py,sha256=RjO-O0JENBuGOrWP7QgBZlZxeXC-PAIr8tj_9p_BxOU,2058
81
+ tunacode/core/token_usage/usage_tracker.py,sha256=lF-ehx-UQnorS4T1Xxa06GGRRjpaEnfmZl5LukGW9LY,6068
82
+ tunacode/prompts/system.xml,sha256=CdUctusc2qBoTYF3zWAzXv9djrqAZcj68-eyT3FF714,25122
83
+ tunacode/services/__init__.py,sha256=w_E8QK6RnvKSvU866eDe8BCRV26rAm4d3R-Yg06OWCU,19
84
+ tunacode/services/mcp.py,sha256=AXDbEEDiVA6VhcGUmSm4uo7cBk-2qBHp-j6r57Cjt3k,7573
85
+ tunacode/templates/__init__.py,sha256=ssEOPrPjyCywtKI-QFcoqcWhMjlfI5TbI8Ip0_wyqGM,241
86
+ tunacode/templates/loader.py,sha256=6_Dk4jX47_GKUAWxlHG2Mzkl9lkXFUOiAdlcJqb6rBA,6765
87
+ tunacode/tools/__init__.py,sha256=ECBuUWWF1JjHW42CCceaPKgVTQyuljbz3RlhuA2fe2s,314
88
+ tunacode/tools/base.py,sha256=PqXBYbXncGoUDWrLPwMxLJiM0CLFqGmieIMBnoi3TL8,12767
89
+ tunacode/tools/bash.py,sha256=3fQgeJSm0bCwNbr3DoGYGiDbagGMl0GtzABeoUWLUrU,13160
90
+ tunacode/tools/glob.py,sha256=OEs-DZmXGn1ak-hcMBLJC3vMo2hwU2O-C5eauRdm1dY,22998
91
+ tunacode/tools/grep.py,sha256=cI73BKgW-StCVsGyjWowgPrCEHqptOvH3MA82ZHwxK8,21597
92
+ tunacode/tools/list_dir.py,sha256=aJ2FdAUU-HxOmAwBk188KYIYB94thESIrSBflzoUlYs,12402
93
+ tunacode/tools/react.py,sha256=qEXhtxFM3skoz__L9R0Rabt1bmKdNkRyFMyAgNB_TFo,5602
94
+ tunacode/tools/read_file.py,sha256=Xy8vkckjq8kBNNYJMpMhq0pabVi4Kp8b57C3C3picI4,6729
95
+ tunacode/tools/run_command.py,sha256=C267wJG6uw2goSTzLhCPTeDphoI0wXTC9zX043iagks,8846
96
+ tunacode/tools/schema_assembler.py,sha256=sUePWvprfTHz9hau1q7hmWd12ew3rHdbASAGkpjBhuM,5507
97
+ tunacode/tools/update_file.py,sha256=0KTbEe1awS53CZPh1G3F3-TWuemWWBuDVQhcRYwXKOg,7619
98
+ tunacode/tools/write_file.py,sha256=WHEXdUKqUHZZ8Jh1muyupJgjud-x6h99x7qAMaloLao,6021
99
+ tunacode/tools/xml_helper.py,sha256=iDEUeLDNWwdGFyb8T9Vqfo_V7oX7oXm4l3IFPTdJtCM,2996
100
+ tunacode/tools/grep_components/__init__.py,sha256=qy3kwzxOiE6ydlRzpCC39TaIp5BJc5X_bRfXukiu4eM,266
101
+ tunacode/tools/grep_components/file_filter.py,sha256=-XYlmVLOipjuAGdLhHDApLMKZJ1qtlzRUXvOvHc7VYU,3152
102
+ tunacode/tools/grep_components/pattern_matcher.py,sha256=ZvEUqBZ6UWf9wZzb1DIRGSTFQuJCBV0GJG3DVG4r4Ss,5177
103
+ tunacode/tools/grep_components/result_formatter.py,sha256=S2TKdkJ81akFWyhwico0xR4jSx4yubfqchErEW-mEDQ,5223
104
+ tunacode/tools/grep_components/search_result.py,sha256=xzb_htSANuPIPVWViPAqIMsCCWVA8loxWdaZOA8RqMs,869
105
+ tunacode/tools/prompts/bash_prompt.xml,sha256=TzbZDFPhpRdYit0w3AVX66uCtJGDQhrdCEqY_FbHSC8,4051
106
+ tunacode/tools/prompts/glob_prompt.xml,sha256=G_ZTrHrhgzL3IvO9GIZPMBT6uEKy6AUU_xYTl7ZVPsU,1940
107
+ tunacode/tools/prompts/grep_prompt.xml,sha256=yxZcebUH_TtmllepXUdPnifr1TFlG0jsk3o1wOjl3mM,4944
108
+ tunacode/tools/prompts/list_dir_prompt.xml,sha256=oijSGEMOVh7FglSFQUawQMmmutfC_msZYBJt_KC6mjs,1401
109
+ tunacode/tools/prompts/react_prompt.xml,sha256=etF23T96I5XFs8MczeScjF7NH6jeEHaPOOmwGBwnnv0,829
110
+ tunacode/tools/prompts/read_file_prompt.xml,sha256=K_5FxytYACoj45oAvAnzrrOgU5CJMs421jdzuckUZaE,3123
111
+ tunacode/tools/prompts/run_command_prompt.xml,sha256=JVz0CXdXrI6nthI9QaWN-b1OTTlbIy-TQ7_3MwBs7hI,2332
112
+ tunacode/tools/prompts/update_file_prompt.xml,sha256=TmIc8K6myqgT_eauYMZmHPfhj-y1S3Gcp680e40pfyA,2831
113
+ tunacode/tools/prompts/write_file_prompt.xml,sha256=n7Q2evuCT0NLEDcoiiBkFcjBeQayF66TF5u-bYplk7U,1610
114
+ tunacode/tutorial/__init__.py,sha256=JyTt2S2cy8u1PnoChBmcOPk1Ru7ElhierltCLqZ-2BY,163
115
+ tunacode/tutorial/content.py,sha256=qaQewFwXtKKEmzLH-4oMECGAa4Z4nd1qh2HfRWLpwyk,3278
116
+ tunacode/tutorial/manager.py,sha256=ZgkzSC6ZtYSDq5Ce_TfYk9O9cvgFSL-pXrLZb7_HStM,6309
117
+ tunacode/tutorial/steps.py,sha256=l2bbRVJuYlC186A-U1TIoMPBtLl4j053h4Wlzo1VO8c,4393
118
+ tunacode/ui/__init__.py,sha256=aRNE2pS50nFAX6y--rSGMNYwhz905g14gRd6g4BolYU,13
119
+ tunacode/ui/completers.py,sha256=QAXnJeq5-p5BFkohCJ-VEe30U7ugetUXo7ZNO7kGMYM,19554
120
+ tunacode/ui/config_dashboard.py,sha256=iwY-52zTeC2EOVn7Cg6LKa2Soxcy9VAGZW-91qOGElI,22213
121
+ tunacode/ui/console.py,sha256=H9BoQpmo-rFpGFcfXW41XAFxbNZn4N7dmcg_PTPvORk,3801
122
+ tunacode/ui/constants.py,sha256=A76B_KpM8jCuBYRg4cPmhi8_j6LLyWttO7_jjv47r3w,421
123
+ tunacode/ui/decorators.py,sha256=jJDNztO8MyX_IG1nqXAL8-sQUFjaAzBnc5BsM3ioX24,1955
124
+ tunacode/ui/input.py,sha256=Mg-w2FvZqf4aw0bS840KfxDq9NY1fMMrzOSlDqo0pD8,3430
125
+ tunacode/ui/keybindings.py,sha256=BGEP3-Gv4p_PbDmCJYy5eJsWhnGbDJpaK-o6xuXJ_Hw,1692
126
+ tunacode/ui/lexers.py,sha256=tmg4ic1enyTRLzanN5QPP7D_0n12YjX_8ZhsffzhXA4,1340
127
+ tunacode/ui/logging_compat.py,sha256=5v6lcjVaG1CxdY1Zm9FAGr9H7Sy-tP6ihGfhP-5YvAY,1406
128
+ tunacode/ui/model_selector.py,sha256=PZH7P6C3sJMU8TAne-VAOCcdUSnwmBChUQ_gqaDiqHc,13449
129
+ tunacode/ui/output.py,sha256=oMozluhzospH8zGSj6Vu2egzWSCJgYSa-T1P7wS8iGM,6381
130
+ tunacode/ui/panels.py,sha256=EeXFMbITcuY44L_1rBpFyKc4tcfhILon10hB4g2BggM,18396
131
+ tunacode/ui/path_heuristics.py,sha256=YfAP7AteI5FCUH2jZX9erSLADfDuH4OCny96OWb0M-Q,2185
132
+ tunacode/ui/prompt_manager.py,sha256=YRtSKPe7uVaJOizNEoTghB82a01K9dnhN-PKka8ZbFU,4767
133
+ tunacode/ui/tool_descriptions.py,sha256=vk61JPIXy7gHNfJ--77maXgK6WwNwxqY47QYsw_a2uw,4126
134
+ tunacode/ui/tool_ui.py,sha256=tB1w01ffPVtWJn1veutcUrOZE6yb7t7kMqzxVNPfZZs,8132
135
+ tunacode/ui/utils.py,sha256=yvoCTz8AOdRfV0XIqUX3sgg88g_wntV9yhnQP6WzAVs,114
136
+ tunacode/ui/validators.py,sha256=MMIMT1I2v0l2jIy-gxX_4GSApvUTi8XWIOACr_dmoBA,758
137
+ tunacode/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
138
+ tunacode/utils/api_key_validation.py,sha256=djfayP2g01d7YDVQXZUdW5ZhFtWAWw5oPhHCo_p74t0,2677
139
+ tunacode/utils/bm25.py,sha256=fd59YQXovC8rXwZrdoqIAfFrLn_WCVjzCh0pkU22APE,1966
140
+ tunacode/utils/config_comparator.py,sha256=iMShhYCKlo0dXycbfpRu5rj3ckT460FoDvkbr5_-yTY,12879
141
+ tunacode/utils/diff_utils.py,sha256=V9QqQ0q4MfabVTnWptF3IXDp3estnfOKcJtDe_Sj14I,2372
142
+ tunacode/utils/file_utils.py,sha256=84g-MQRzmBI2aG_CuXsDl2OhvvWoSL7YdL5Kz_UKSwk,979
143
+ tunacode/utils/import_cache.py,sha256=q_xjJbtju05YbFopLDSkIo1hOtCx3DOTl3GQE5FFDgs,295
144
+ tunacode/utils/json_utils.py,sha256=cMVctSwwV9Z1c-rZdj6UuOlZwsUPSTF5oUruP6uPix0,6470
145
+ tunacode/utils/message_utils.py,sha256=V4MrZZPmwO22_MVGupMqtE5ltQEBwaSIqGD5LEb_bLw,1050
146
+ tunacode/utils/models_registry.py,sha256=Tn2ByGFV1yJsWumFYy6JuT0eVpuPeZ1Zxj6JYsRRy1g,21277
147
+ tunacode/utils/retry.py,sha256=AHdUzY6m-mwlT4OPXdtWWMAafL_NeS7JAMORGyM8c5k,4931
148
+ tunacode/utils/ripgrep.py,sha256=VdGWYPQ1zCwUidw2QicuVmG5OiAgqI93jAsjS3y3ksE,11001
149
+ tunacode/utils/security.py,sha256=i3eGKg4o-qY2S_ObTlEaHO93q14iBfiPXR5O7srHn58,6579
150
+ tunacode/utils/system.py,sha256=J8KqJ4ZqQrNSnM5rrJxPeMk9z2xQQp6dWtI1SKBY1-0,11121
151
+ tunacode/utils/text_utils.py,sha256=KBI_xARsttD03rnCipNHG2RsC-0HV_TPbraT36M9tEI,8218
152
+ tunacode/utils/token_counter.py,sha256=dmFuqVz4ywGFdLfAi5Mg9bAGf8v87Ek-mHU-R3fsYjI,2711
153
+ tunacode/utils/user_configuration.py,sha256=OA-L0BgWNbf9sWpc8lyivgLscwJdpdI8TAYbe0wRs1s,4836
154
+ tunacode_cli-0.0.78.6.dist-info/METADATA,sha256=UcS7USp5Eibu_5fxYd0n6feaOsXqV5kz3VgT3dbNRdc,9004
155
+ tunacode_cli-0.0.78.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
156
+ tunacode_cli-0.0.78.6.dist-info/entry_points.txt,sha256=hbkytikj4dGu6rizPuAd_DGUPBGF191RTnhr9wdhORY,51
157
+ tunacode_cli-0.0.78.6.dist-info/licenses/LICENSE,sha256=Btzdu2kIoMbdSp6OyCLupB1aRgpTCJ_szMimgEnpkkE,1056
158
+ tunacode_cli-0.0.78.6.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
@@ -1,217 +0,0 @@
1
- """Todo command implementation."""
2
-
3
- from datetime import datetime
4
-
5
- from rich.box import ROUNDED
6
- from rich.table import Table
7
-
8
- from tunacode.types import CommandArgs, CommandContext, CommandResult, TodoItem
9
- from tunacode.ui import console as ui
10
-
11
- from ..base import CommandCategory, CommandSpec, SimpleCommand
12
-
13
-
14
- class TodoCommand(SimpleCommand):
15
- """Manage todo items."""
16
-
17
- spec = CommandSpec(
18
- name="todo",
19
- aliases=["/todo", "todos"],
20
- description="Manage todo items.",
21
- category=CommandCategory.DEVELOPMENT,
22
- )
23
-
24
- async def execute(self, args: CommandArgs, context: CommandContext) -> CommandResult:
25
- if not args:
26
- await self.list_todos(context)
27
- return
28
-
29
- subcommand = args[0].lower()
30
- subcommand_args = args[1:]
31
-
32
- if subcommand == "list":
33
- await self.list_todos(context)
34
- elif subcommand == "add":
35
- await self.add_todo(subcommand_args, context)
36
- elif subcommand == "done":
37
- await self.mark_done(subcommand_args, context)
38
- elif subcommand == "update":
39
- await self.update_todo(subcommand_args, context)
40
- elif subcommand == "priority":
41
- await self.set_priority(subcommand_args, context)
42
- elif subcommand == "remove":
43
- await self.remove_todo(subcommand_args, context)
44
- elif subcommand == "clear":
45
- await self.clear_todos(context)
46
- else:
47
- await ui.error(
48
- "Invalid todo subcommand. Available subcommands: list, add, done, update, priority, remove, clear"
49
- )
50
-
51
- async def list_todos(self, context: CommandContext) -> None:
52
- """Display the todo list with Rich formatting."""
53
- todos = context.state_manager.session.todos
54
- if not todos:
55
- await ui.info("No todos found.")
56
- return
57
-
58
- # Create Rich table
59
- table = Table(show_header=True, box=ROUNDED, padding=(0, 1))
60
- table.add_column("ID", style="bold cyan", width=4, justify="center")
61
- table.add_column("Status", width=12, justify="center")
62
- table.add_column("Task", style="white", min_width=20)
63
- table.add_column("Priority", width=10, justify="center")
64
- table.add_column("Created", style="dim", width=12)
65
-
66
- # Sort todos by status and priority
67
- pending = [t for t in todos if t.status == "pending"]
68
- in_progress = [t for t in todos if t.status == "in_progress"]
69
- completed = [t for t in todos if t.status == "completed"]
70
-
71
- # Sort each group by priority (high->medium->low)
72
- priority_order = {"high": 0, "medium": 1, "low": 2}
73
-
74
- for group in [in_progress, pending, completed]:
75
- group.sort(key=lambda x: priority_order.get(x.priority, 3))
76
-
77
- # Add rows to table
78
- for todo in in_progress + pending + completed:
79
- # Status with emoji
80
- if todo.status == "pending":
81
- status_display = "○ pending"
82
- elif todo.status == "in_progress":
83
- status_display = "○ in progress"
84
- else:
85
- status_display = "✓ completed"
86
-
87
- # Priority with color coding
88
- if todo.priority == "high":
89
- priority_display = "[red] high[/red]"
90
- elif todo.priority == "medium":
91
- priority_display = "[yellow] medium[/yellow]"
92
- else:
93
- priority_display = "[green] low[/green]"
94
-
95
- # Format created date
96
- created_display = todo.created_at.strftime("%m/%d %H:%M")
97
-
98
- table.add_row(todo.id, status_display, todo.content, priority_display, created_display)
99
-
100
- await ui.print(table)
101
-
102
- async def add_todo(self, args: CommandArgs, context: CommandContext) -> None:
103
- """Add a new todo and show updated list."""
104
- if not args:
105
- await ui.error("Please provide a task to add.")
106
- return
107
-
108
- content = " ".join(args)
109
- new_id = f"{int(datetime.now().timestamp() * 1000000)}"
110
- new_todo = TodoItem(
111
- id=new_id,
112
- content=content,
113
- status="pending",
114
- priority="medium",
115
- created_at=datetime.now(),
116
- )
117
- context.state_manager.add_todo(new_todo)
118
-
119
- await ui.success(f"Todo created: {content}")
120
- await self.list_todos(context)
121
-
122
- async def mark_done(self, args: CommandArgs, context: CommandContext) -> None:
123
- """Mark a todo as done and show updated list."""
124
- if not args:
125
- await ui.error("Please provide a todo ID to mark as done.")
126
- return
127
-
128
- todo_id = args[0]
129
- # Find the todo to get its content for feedback
130
- todo_content = None
131
- for todo in context.state_manager.session.todos:
132
- if todo.id == todo_id:
133
- todo_content = todo.content
134
- break
135
-
136
- if not todo_content:
137
- await ui.error(f"Todo with id {todo_id} not found.")
138
- return
139
-
140
- context.state_manager.update_todo(todo_id, "completed")
141
- await ui.success(f"Marked todo {todo_id} as done: {todo_content}")
142
- await self.list_todos(context)
143
-
144
- async def update_todo(self, args: CommandArgs, context: CommandContext) -> None:
145
- """Update a todo status and show updated list."""
146
- if len(args) < 2:
147
- await ui.error("Please provide a todo ID and a new status.")
148
- return
149
-
150
- todo_id = args[0]
151
- new_status = args[1].lower()
152
- if new_status not in ["pending", "in_progress", "completed"]:
153
- await ui.error("Invalid status. Must be one of: pending, in_progress, completed")
154
- return
155
-
156
- for todo in context.state_manager.session.todos:
157
- if todo.id == todo_id:
158
- todo.status = new_status
159
- await ui.success(f"Updated todo {todo_id} to status {new_status}: {todo.content}")
160
- await self.list_todos(context)
161
- return
162
-
163
- await ui.error(f"Todo with id {todo_id} not found.")
164
-
165
- async def set_priority(self, args: CommandArgs, context: CommandContext) -> None:
166
- """Set todo priority and show updated list."""
167
- if len(args) < 2:
168
- await ui.error("Please provide a todo ID and a new priority.")
169
- return
170
-
171
- todo_id = args[0]
172
- new_priority = args[1].lower()
173
- if new_priority not in ["high", "medium", "low"]:
174
- await ui.error("Invalid priority. Must be one of: high, medium, low")
175
- return
176
-
177
- for todo in context.state_manager.session.todos:
178
- if todo.id == todo_id:
179
- todo.priority = new_priority
180
- await ui.success(f"Set todo {todo_id} to priority {new_priority}: {todo.content}")
181
- await self.list_todos(context)
182
- return
183
-
184
- await ui.error(f"Todo with id {todo_id} not found.")
185
-
186
- async def remove_todo(self, args: CommandArgs, context: CommandContext) -> None:
187
- """Remove a todo and show updated list."""
188
- if not args:
189
- await ui.error("Please provide a todo ID to remove.")
190
- return
191
-
192
- todo_id = args[0]
193
- # Find the todo to get its content for feedback
194
- todo_content = None
195
- for todo in context.state_manager.session.todos:
196
- if todo.id == todo_id:
197
- todo_content = todo.content
198
- break
199
-
200
- if not todo_content:
201
- await ui.error(f"Todo with id {todo_id} not found.")
202
- return
203
-
204
- context.state_manager.remove_todo(todo_id)
205
- await ui.success(f"Removed todo {todo_id}: {todo_content}")
206
- await self.list_todos(context)
207
-
208
- async def clear_todos(self, context: CommandContext) -> None:
209
- """Clear all todos and show confirmation."""
210
- todo_count = len(context.state_manager.session.todos)
211
- if todo_count == 0:
212
- await ui.info("No todos to clear.")
213
- return
214
-
215
- context.state_manager.clear_todos()
216
- await ui.success(f"Cleared all {todo_count} todos.")
217
- await self.list_todos(context)
tunacode/context.py DELETED
@@ -1,71 +0,0 @@
1
- import logging
2
- import subprocess
3
- from pathlib import Path
4
- from typing import Dict, List
5
-
6
- from tunacode.utils.ripgrep import ripgrep
7
- from tunacode.utils.system import list_cwd
8
-
9
- logger = logging.getLogger(__name__)
10
-
11
-
12
- async def get_git_status() -> Dict[str, object]:
13
- """Return git branch and dirty state information."""
14
- try:
15
- result = subprocess.run(
16
- ["git", "status", "--porcelain", "--branch"],
17
- capture_output=True,
18
- text=True,
19
- check=True,
20
- timeout=5,
21
- )
22
- lines = result.stdout.splitlines()
23
- branch_line = lines[0][2:] if lines else ""
24
- branch = branch_line.split("...")[0]
25
- ahead = behind = 0
26
- if "[" in branch_line and "]" in branch_line:
27
- bracket = branch_line.split("[", 1)[1].split("]", 1)[0]
28
- for part in bracket.split(","):
29
- if "ahead" in part:
30
- ahead = int(part.split("ahead")[1].strip().strip(" ]"))
31
- if "behind" in part:
32
- behind = int(part.split("behind")[1].strip().strip(" ]"))
33
- dirty = any(line for line in lines[1:])
34
- return {"branch": branch, "ahead": ahead, "behind": behind, "dirty": dirty}
35
- except Exception as e:
36
- logger.warning(f"Failed to get git status: {e}")
37
- return {}
38
-
39
-
40
- async def get_directory_structure(max_depth: int = 3) -> str:
41
- """Return a simple directory tree string."""
42
- files = list_cwd(max_depth=max_depth)
43
- lines: List[str] = []
44
- for path in files:
45
- depth = path.count("/")
46
- indent = " " * depth
47
- name = path.split("/")[-1]
48
- lines.append(f"{indent}{name}")
49
- return "\n".join(lines)
50
-
51
-
52
- async def get_code_style() -> str:
53
- """Concatenate contents of all TUNACODE.md files up the directory tree."""
54
- parts: List[str] = []
55
- current = Path.cwd()
56
- while True:
57
- file = current / "TUNACODE.md"
58
- if file.exists():
59
- try:
60
- parts.append(file.read_text(encoding="utf-8"))
61
- except Exception as e:
62
- logger.debug(f"Failed to read TUNACODE.md at {file}: {e}")
63
- if current == current.parent:
64
- break
65
- current = current.parent
66
- return "\n".join(parts)
67
-
68
-
69
- async def get_claude_files() -> List[str]:
70
- """Return a list of additional TUNACODE.md files in the repo."""
71
- return ripgrep("TUNACODE.md", ".")
@@ -1,182 +0,0 @@
1
- """Git safety setup to create a working branch for TunaCode."""
2
-
3
- import subprocess
4
- from pathlib import Path
5
-
6
- from tunacode.core.setup.base import BaseSetup
7
- from tunacode.core.state import StateManager
8
- from tunacode.ui import console as ui
9
- from tunacode.ui.input import input as prompt_input
10
- from tunacode.ui.panels import panel
11
-
12
-
13
- async def yes_no_prompt(question: str, default: bool = True) -> bool:
14
- """Simple yes/no prompt."""
15
- default_text = "[Y/n]" if default else "[y/N]"
16
- response = await prompt_input(session_key="yes_no", pretext=f"{question} {default_text}: ")
17
-
18
- if not response.strip():
19
- return default
20
-
21
- return response.lower().strip() in ["y", "yes"]
22
-
23
-
24
- class GitSafetySetup(BaseSetup):
25
- """Setup step to create a safe working branch for TunaCode."""
26
-
27
- def __init__(self, state_manager: StateManager):
28
- super().__init__(state_manager)
29
-
30
- @property
31
- def name(self) -> str:
32
- """Return the name of this setup step."""
33
- return "Git Safety"
34
-
35
- async def should_run(self, _force: bool = False) -> bool:
36
- """Check if we should run git safety setup."""
37
- # Always run unless user has explicitly disabled it
38
- return not self.state_manager.session.user_config.get("skip_git_safety", False)
39
-
40
- async def execute(self, _force: bool = False) -> None:
41
- """Create a safety branch for TunaCode operations."""
42
- try:
43
- # Check if git is installed
44
- result = subprocess.run(
45
- ["git", "--version"], capture_output=True, text=True, check=False
46
- )
47
-
48
- if result.returncode != 0:
49
- await panel(
50
- " Git Not Found",
51
- "Git is not installed or not in PATH. TunaCode will modify files directly.\n"
52
- "It's strongly recommended to install Git for safety.",
53
- border_style="yellow",
54
- )
55
- return
56
-
57
- # Check if we're in a git repository
58
- result = subprocess.run(
59
- ["git", "rev-parse", "--git-dir"],
60
- capture_output=True,
61
- text=True,
62
- check=False,
63
- cwd=Path.cwd(),
64
- )
65
-
66
- if result.returncode != 0:
67
- await panel(
68
- " Not a Git Repository",
69
- "This directory is not a Git repository. TunaCode will modify files directly.\n"
70
- "Consider initializing a Git repository for safety: git init",
71
- border_style="yellow",
72
- )
73
- return
74
-
75
- # Get current branch name
76
- result = subprocess.run(
77
- ["git", "branch", "--show-current"], capture_output=True, text=True, check=True
78
- )
79
- current_branch = result.stdout.strip()
80
-
81
- if not current_branch:
82
- # Detached HEAD state
83
- await panel(
84
- " Detached HEAD State",
85
- "You're in a detached HEAD state. TunaCode will continue without creating a branch.",
86
- border_style="yellow",
87
- )
88
- return
89
-
90
- # Check if we're already on a -tunacode branch
91
- if current_branch.endswith("-tunacode"):
92
- await ui.info(f"Already on a TunaCode branch: {current_branch}")
93
- return
94
-
95
- # Propose new branch name
96
- new_branch = f"{current_branch}-tunacode"
97
-
98
- # Check if there are uncommitted changes
99
- result = subprocess.run(
100
- ["git", "status", "--porcelain"], capture_output=True, text=True, check=True
101
- )
102
-
103
- has_changes = bool(result.stdout.strip())
104
-
105
- # Ask user if they want to create a safety branch
106
- message = (
107
- f"For safety, TunaCode can create a new branch '{new_branch}' based on '{current_branch}'.\n"
108
- f"This helps protect your work from unintended changes.\n"
109
- )
110
-
111
- if has_changes:
112
- message += "\n You have uncommitted changes that will be brought to the new branch."
113
-
114
- create_branch = await yes_no_prompt(f"{message}\n\nCreate safety branch?", default=True)
115
-
116
- if not create_branch:
117
- # User declined - show warning
118
- await panel(
119
- " Working Without Safety Branch",
120
- "You've chosen to work directly on your current branch.\n"
121
- "TunaCode will modify files in place. Make sure you have backups!",
122
- border_style="red",
123
- )
124
- # Save preference
125
- self.state_manager.session.user_config["skip_git_safety"] = True
126
- # Save the updated configuration to disk
127
- try:
128
- from tunacode.utils.user_configuration import save_config
129
-
130
- save_config(self.state_manager)
131
- except Exception as e:
132
- # Log the error but don't fail the setup process
133
- import logging
134
-
135
- logging.warning(f"Failed to save skip_git_safety preference: {e}")
136
- return
137
-
138
- # Create and checkout the new branch
139
- try:
140
- # Check if branch already exists
141
- result = subprocess.run(
142
- ["git", "show-ref", "--verify", f"refs/heads/{new_branch}"],
143
- capture_output=True,
144
- check=False,
145
- text=True,
146
- )
147
-
148
- if result.returncode == 0:
149
- # Branch exists, ask to use it
150
- use_existing = await yes_no_prompt(
151
- f"Branch '{new_branch}' already exists. Switch to it?", default=True
152
- )
153
- if use_existing:
154
- subprocess.run(["git", "checkout", new_branch], check=True)
155
- await ui.success(f"Switched to existing branch: {new_branch}")
156
- else:
157
- await ui.warning("Continuing on current branch")
158
- else:
159
- # Create new branch
160
- subprocess.run(["git", "checkout", "-b", new_branch], check=True)
161
- await ui.success(f"Created and switched to new branch: {new_branch}")
162
-
163
- except subprocess.CalledProcessError as e:
164
- await panel(
165
- " Failed to Create Branch",
166
- f"Could not create branch '{new_branch}': {str(e)}\n"
167
- "Continuing on current branch.",
168
- border_style="red",
169
- )
170
-
171
- except Exception as e:
172
- # Non-fatal error - just warn the user
173
- await panel(
174
- " Git Safety Setup Failed",
175
- f"Could not set up Git safety: {str(e)}\n"
176
- "TunaCode will continue without branch protection.",
177
- border_style="yellow",
178
- )
179
-
180
- async def validate(self) -> bool:
181
- """Validate git safety setup - always returns True as this is optional."""
182
- return True