tunacode-cli 0.0.55__py3-none-any.whl → 0.0.57__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 (47) hide show
  1. tunacode/cli/commands/implementations/plan.py +50 -0
  2. tunacode/cli/commands/registry.py +3 -0
  3. tunacode/cli/repl.py +327 -186
  4. tunacode/cli/repl_components/command_parser.py +37 -4
  5. tunacode/cli/repl_components/error_recovery.py +79 -1
  6. tunacode/cli/repl_components/output_display.py +21 -1
  7. tunacode/cli/repl_components/tool_executor.py +12 -0
  8. tunacode/configuration/defaults.py +8 -0
  9. tunacode/constants.py +10 -2
  10. tunacode/core/agents/agent_components/agent_config.py +212 -22
  11. tunacode/core/agents/agent_components/node_processor.py +46 -40
  12. tunacode/core/code_index.py +83 -29
  13. tunacode/core/state.py +44 -0
  14. tunacode/core/token_usage/usage_tracker.py +2 -2
  15. tunacode/core/tool_handler.py +20 -0
  16. tunacode/prompts/system.md +117 -490
  17. tunacode/services/mcp.py +29 -7
  18. tunacode/tools/base.py +110 -0
  19. tunacode/tools/bash.py +96 -1
  20. tunacode/tools/exit_plan_mode.py +273 -0
  21. tunacode/tools/glob.py +366 -33
  22. tunacode/tools/grep.py +226 -77
  23. tunacode/tools/grep_components/result_formatter.py +98 -4
  24. tunacode/tools/list_dir.py +132 -2
  25. tunacode/tools/present_plan.py +288 -0
  26. tunacode/tools/read_file.py +91 -0
  27. tunacode/tools/run_command.py +99 -0
  28. tunacode/tools/schema_assembler.py +167 -0
  29. tunacode/tools/todo.py +108 -1
  30. tunacode/tools/update_file.py +94 -0
  31. tunacode/tools/write_file.py +86 -0
  32. tunacode/types.py +58 -0
  33. tunacode/ui/input.py +14 -2
  34. tunacode/ui/keybindings.py +25 -4
  35. tunacode/ui/panels.py +53 -8
  36. tunacode/ui/prompt_manager.py +25 -2
  37. tunacode/ui/tool_ui.py +3 -2
  38. tunacode/utils/json_utils.py +206 -0
  39. tunacode/utils/message_utils.py +14 -4
  40. tunacode/utils/ripgrep.py +332 -9
  41. {tunacode_cli-0.0.55.dist-info → tunacode_cli-0.0.57.dist-info}/METADATA +8 -3
  42. {tunacode_cli-0.0.55.dist-info → tunacode_cli-0.0.57.dist-info}/RECORD +46 -42
  43. tunacode/tools/read_file_async_poc.py +0 -196
  44. {tunacode_cli-0.0.55.dist-info → tunacode_cli-0.0.57.dist-info}/WHEEL +0 -0
  45. {tunacode_cli-0.0.55.dist-info → tunacode_cli-0.0.57.dist-info}/entry_points.txt +0 -0
  46. {tunacode_cli-0.0.55.dist-info → tunacode_cli-0.0.57.dist-info}/licenses/LICENSE +0 -0
  47. {tunacode_cli-0.0.55.dist-info → tunacode_cli-0.0.57.dist-info}/top_level.txt +0 -0
@@ -1,47 +1,48 @@
1
1
  tunacode/__init__.py,sha256=yUul8igNYMfUrHnYfioIGAqvrH8b5BKiO_pt1wVnmd0,119
2
- tunacode/constants.py,sha256=nNS_4fOgxWjzUxnCm-FBXgfVRifwFytkt7yICn7eL1I,5968
2
+ tunacode/constants.py,sha256=ZDv1Y8WXJXKjdLvIONM-CHZkILMu7S-ACV0OxDq8Rqk,6100
3
3
  tunacode/context.py,sha256=YtfRjUiqsSkk2k9Nn_pjb_m-AXyh6XcOBOJWtFI0wVw,2405
4
4
  tunacode/exceptions.py,sha256=oDO1SVKOgjcKIylwqdbqh_g5my4roU5mB9Nv4n_Vb0s,3877
5
5
  tunacode/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  tunacode/setup.py,sha256=a5S-uGkVYoBTvH9nsqMBgAFoH4CILOgfKvgS30qGnoU,1978
7
- tunacode/types.py,sha256=bCJ0mq1iQKa42fhBN5Pimkx0FV0f2J3-qRzbMzFhmBw,8499
7
+ tunacode/types.py,sha256=Q3PeHB01qeaKteGDQf8Byx4q1XLSXVnNDG6D-WjWsBk,10157
8
8
  tunacode/cli/__init__.py,sha256=zgs0UbAck8hfvhYsWhWOfBe5oK09ug2De1r4RuQZREA,55
9
9
  tunacode/cli/main.py,sha256=4MF4nGEU-CB83ckIl85AY-015EeUJHrE_UdbuSa9wCU,2968
10
- tunacode/cli/repl.py,sha256=GMEvDW8LP1iM-bwOY83BviYk0fMngDJiZiI3f28CHwo,16327
10
+ tunacode/cli/repl.py,sha256=sQc-FBGgF1u054kXJY3GpXehd9J3u-dAG7lEnFf9DIs,21568
11
11
  tunacode/cli/commands/__init__.py,sha256=7rPwGkdYbPUgf__cPVX9oQUJOPQ18MdxDT_I64crdak,1740
12
12
  tunacode/cli/commands/base.py,sha256=Ge_lNQA-GDfcb1Ap1oznCH3UrifBiHH3bA9DNL-tCDw,2519
13
- tunacode/cli/commands/registry.py,sha256=Xmfb4qRZ1wvT-3OggGsuDxpXlCykuhOkSBberysj1SE,9345
13
+ tunacode/cli/commands/registry.py,sha256=nDEpIMGnKnKDRKc_v238b13ixrbMMSjM672FKtGfBCw,9507
14
14
  tunacode/cli/commands/template_shortcut.py,sha256=ApYTPkDVBRaLxa7rWaPrsGcJdkR7eg09k18KyTjYg_E,3447
15
15
  tunacode/cli/commands/implementations/__init__.py,sha256=DHjQm1f14OV1go0ZyqacFa3yfnGWH7LZFbZVVQZ5Iw0,1011
16
16
  tunacode/cli/commands/implementations/conversation.py,sha256=ZijCNaRi1p5v1Q-IaVHtU2_BripSW3JCVKTtqFkOUjg,4676
17
17
  tunacode/cli/commands/implementations/debug.py,sha256=ornvceGF4GbJd2OJXnnT9i9KpHBAMJUYNs9wNhzViGM,6764
18
18
  tunacode/cli/commands/implementations/development.py,sha256=I8jHgYY3VgjTU8its0D0ysruuVqKbNTBur0JjPIUIZA,2844
19
19
  tunacode/cli/commands/implementations/model.py,sha256=uthx6IX9KwgwywNTDklkJpqCbaTX9h1_p-eVmqL73WQ,2245
20
+ tunacode/cli/commands/implementations/plan.py,sha256=iZtvdGPqvGqMr8_lYil8_8NOL1iyc54Bxtb0gb9VOnw,1825
20
21
  tunacode/cli/commands/implementations/system.py,sha256=2cGw5iCJO3aNhXTFF28CgAIyLgslvHmpfyL2ZHVB6oQ,7903
21
22
  tunacode/cli/commands/implementations/template.py,sha256=YeFOjbKKfPswPCHPvlDUwXvg6J0MesyAyVsujiIgPbU,5482
22
23
  tunacode/cli/commands/implementations/todo.py,sha256=Dtz5bgcuK2VXGPWEBBZQgnWUMYkRXNzTGf_qkVPLF2U,8125
23
24
  tunacode/cli/repl_components/__init__.py,sha256=5ZjPJ3yUvZ5x6Vg9EYJ03-tdxfEEdmfradCmwSlVY3E,334
24
- tunacode/cli/repl_components/command_parser.py,sha256=SuDRP-nt8Sq5klI4-tXkllN_4nVzji5VJ-dQvbxDmDw,880
25
- tunacode/cli/repl_components/error_recovery.py,sha256=yPoWXzuMi6B_Pwlm1wnFIJV55lJEOChvHGDca4XtoVI,3064
26
- tunacode/cli/repl_components/output_display.py,sha256=SGhP7Hc1ymfZf-AvrkELgdJCZ3UVEzTx2Y6W737zdoY,816
27
- tunacode/cli/repl_components/tool_executor.py,sha256=p5oSpoO0qkiKr9fsgIQVSXCv6ZiSWk8QtPb_x7IpKhE,3147
25
+ tunacode/cli/repl_components/command_parser.py,sha256=BU_3h4aJ4MNQ0UU6_ulvK7NRTlC417soZkGGzMFy6-s,2368
26
+ tunacode/cli/repl_components/error_recovery.py,sha256=59DCv8PkWg3ZOjaNPkWmYw0u68JpPMIxUMikMiW4TjY,6176
27
+ tunacode/cli/repl_components/output_display.py,sha256=uzse2bhxSyCWnJD0Ni5lwnp0BmYDAr1tZbnlj3-x6ro,1484
28
+ tunacode/cli/repl_components/tool_executor.py,sha256=i6KB_qXaFlbdv90_3xj3TwL6alFd_JAbSS0Cdln9zfU,3767
28
29
  tunacode/configuration/__init__.py,sha256=MbVXy8bGu0yKehzgdgZ_mfWlYGvIdb1dY2Ly75nfuPE,17
29
- tunacode/configuration/defaults.py,sha256=5TUeSqMTeA7kW7gz9hND_H4s9Key0_khPvc6mNFMlZc,838
30
+ tunacode/configuration/defaults.py,sha256=Kd0uBNrURdhDad_HsLeOz3MJu1o6atLJ3vjaESQqgnw,1269
30
31
  tunacode/configuration/models.py,sha256=buH8ZquvcYI3OQBDIZeJ08cu00rSCeNABtUwl3VQS0E,4103
31
32
  tunacode/configuration/settings.py,sha256=9wtIWBlLhW_ZBlLx-GA4XDfVZyGj2Gs6Zk49vk-nHq0,1047
32
33
  tunacode/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
- tunacode/core/code_index.py,sha256=jgAx3lSWP_DwnyiP5Jkm1YvX4JJyI4teMzlNrJSpEOA,15661
34
- tunacode/core/state.py,sha256=RGBTOHTpe4z42MbIjRKhGNz9MIGyY0QbpdDJMldm53o,6284
35
- tunacode/core/tool_handler.py,sha256=FqA3w8M_fhpyOQKJIgl_8MAhSFVEguufbZH6gm_b7NI,2932
34
+ tunacode/core/code_index.py,sha256=2qxEn2eTIegV4F_gLeZO5lAOv8mkf4Y_t21whZ9F2Fk,17370
35
+ tunacode/core/state.py,sha256=aksE0mM2xG-1CkLmpi8cu1n1SOMfqpMuqMBciEVShf0,7893
36
+ tunacode/core/tool_handler.py,sha256=42yUfnq5jgk-0LK93JoJgtsXfVDTf-7hNXyKEfH2FM0,3626
36
37
  tunacode/core/agents/__init__.py,sha256=UUJiPYb91arwziSpjd7vIk7XNGA_4HQbsOIbskSqevA,149
37
38
  tunacode/core/agents/main.py,sha256=myz_K2lxqYH8pQdbw8n8bai8F40Mqfj-kTLagPR1dP4,18253
38
39
  tunacode/core/agents/utils.py,sha256=dJsdbvWs48vxQpwAtUjJLMj7_huv12Mx3E2CEgwoK94,14467
39
40
  tunacode/core/agents/agent_components/__init__.py,sha256=CL4XH47T6v_iYy7xCPYjyiEFNOFnkcKwbTuKw6IjKTs,1474
40
- tunacode/core/agents/agent_components/agent_config.py,sha256=6m2RBZ7Y-0p_KFBVmfPW4ZGLGzTAw3YFQ4i94qsqEpM,4373
41
+ tunacode/core/agents/agent_components/agent_config.py,sha256=lkq6-6p8AHVZuoebUrFXtZgmBJipK8CSD2JaBA0Am_A,11845
41
42
  tunacode/core/agents/agent_components/agent_helpers.py,sha256=G3zF5GPRzBhA3yOcsXf8gar892ackGDcwFk9wM6FA9s,8119
42
43
  tunacode/core/agents/agent_components/json_tool_parser.py,sha256=HuyNT0rs-ppx_gLAI2e0XMVGbR_F0WXZfP3sx38VoMg,3447
43
44
  tunacode/core/agents/agent_components/message_handler.py,sha256=KJGOtb9VhumgZpxxwO45HrKLhU9_MwuoWRsSQwJviNU,3704
44
- tunacode/core/agents/agent_components/node_processor.py,sha256=FmjIEJWkqc0uzRfgTINv8uJwKG7-w00mV5lgOS4Jcd8,20426
45
+ tunacode/core/agents/agent_components/node_processor.py,sha256=BAVbXy17sfW3i4LCTdJ9_MSNc7j6qz1bP3_6IhprIW4,20912
45
46
  tunacode/core/agents/agent_components/response_state.py,sha256=_C2loLeyZHMFHwjGny4h0dI02UoFJcJAVaabkh9H9JQ,343
46
47
  tunacode/core/agents/agent_components/result_wrapper.py,sha256=9CFK0wpsfZx2WT4PBHfkSv22GxL1gAQuUYVMlmYtCJU,1761
47
48
  tunacode/core/agents/agent_components/task_completion.py,sha256=BSnjNEFbxlzgzcXdjdTVGeCr1RpCiAaEp_D7f5FXa5Q,819
@@ -66,43 +67,45 @@ tunacode/core/setup/git_safety_setup.py,sha256=uBvcvw3THfduGUW51rprFt13Qw3HoekWe
66
67
  tunacode/core/setup/template_setup.py,sha256=0lDGhNVCvGN7ykqHnl3pj4CONH3I2PvMzkmIZibfSoc,2640
67
68
  tunacode/core/token_usage/api_response_parser.py,sha256=plLltHg4zGVzxjv3MFj45bbd-NOJeT_v3P0Ki4zlvn4,1831
68
69
  tunacode/core/token_usage/cost_calculator.py,sha256=RjO-O0JENBuGOrWP7QgBZlZxeXC-PAIr8tj_9p_BxOU,2058
69
- tunacode/core/token_usage/usage_tracker.py,sha256=G6lt9VXnS3JcXsiPTwuS3v1YptI_7gfV78f08jX22yU,5932
70
- tunacode/prompts/system.md,sha256=jrPtKFLu2CD6WpNNFgN1nc0p3mec4En9VYmpRQxyZi8,24080
70
+ tunacode/core/token_usage/usage_tracker.py,sha256=YUCnF-712nLrbtEvFrsC-VZuYjKUCz3hf-_do6GKSDA,6016
71
+ tunacode/prompts/system.md,sha256=c7bqedMkHpRf85djDKHwb55mkFjqVm8V6zAA8z1btLY,10721
71
72
  tunacode/services/__init__.py,sha256=w_E8QK6RnvKSvU866eDe8BCRV26rAm4d3R-Yg06OWCU,19
72
- tunacode/services/mcp.py,sha256=R48X73KQjQ9vwhBrtbWHSBl-4K99QXmbIhh5J_1Gezo,3046
73
+ tunacode/services/mcp.py,sha256=quO13skECUGt-4QE2NkWk6_8qhmZ5qjgibvw8tUOt-4,3761
73
74
  tunacode/templates/__init__.py,sha256=ssEOPrPjyCywtKI-QFcoqcWhMjlfI5TbI8Ip0_wyqGM,241
74
75
  tunacode/templates/loader.py,sha256=6_Dk4jX47_GKUAWxlHG2Mzkl9lkXFUOiAdlcJqb6rBA,6765
75
76
  tunacode/tools/__init__.py,sha256=ECBuUWWF1JjHW42CCceaPKgVTQyuljbz3RlhuA2fe2s,314
76
- tunacode/tools/base.py,sha256=DhlanZZZxU2JJaBOwwyGFKMUcoCWR_CzLuwVeSXC0Go,7297
77
- tunacode/tools/bash.py,sha256=mgZqugfDFevZ4BETuUv90pzXvtq7qKGUGFiuDxzmytk,8766
78
- tunacode/tools/glob.py,sha256=mQwVGC8dfvzwzUOeTikfnHhExnLcYnGQwDoHOWrt_fE,10342
79
- tunacode/tools/grep.py,sha256=SfpLazOMbizganPO16w7v6iHRcUn0cD6-6lyUwrl-3U,17834
80
- tunacode/tools/list_dir.py,sha256=1kNqzYCNlcA5rqXIEVqcjQy6QxlLZLj5AG6YIECfwio,7217
81
- tunacode/tools/read_file.py,sha256=z2omev9xzj4-0GG9mRssD13rj-Aa1c-pszFi2Z7Hxvk,3268
82
- tunacode/tools/read_file_async_poc.py,sha256=2v2ckLQlwahgPGWGdE2c5Es37B35Y7zWdseZwT46E1E,6453
83
- tunacode/tools/run_command.py,sha256=7UvXjFQI1Av4vceXx48MbQCTrsFNj4PlygTAAhNDYIA,4376
84
- tunacode/tools/todo.py,sha256=kHYtipmPBxBURrBMbyH92yjOE6cKvrQuq9w-gSrOaLI,13179
85
- tunacode/tools/update_file.py,sha256=bW1MhTzRjBDjJzqQ6A1yCVEbkr1oIqtEC8uqcg_rfY4,3957
86
- tunacode/tools/write_file.py,sha256=prL6u8XOi9ZyPU-YNlG9YMLbSLrDJXDRuDX73ncXh-k,2699
77
+ tunacode/tools/base.py,sha256=jQz_rz2rNZrKo2vZtyArwiHCMdAaqRYJGYtSZ27nxcU,10711
78
+ tunacode/tools/bash.py,sha256=fEjI5Vm7yqQiOzc83kFzu1n4zAPiWLQNHZYY-ORNV4Q,12437
79
+ tunacode/tools/exit_plan_mode.py,sha256=DOl_8CsY7h9N-SuCg2YgMjp8eEMuO5I8Tv8XjoJcTJ0,10597
80
+ tunacode/tools/glob.py,sha256=qnD6g-aZxoytr4PXEgrFyvhl0_lvLSkSXhfmlSFTuaI,24623
81
+ tunacode/tools/grep.py,sha256=kzP8_CMAhjZEXbJzHvMC35bKqsNqk96AiP2_CkEXC04,24142
82
+ tunacode/tools/list_dir.py,sha256=aJ2FdAUU-HxOmAwBk188KYIYB94thESIrSBflzoUlYs,12402
83
+ tunacode/tools/present_plan.py,sha256=PjpZ7Ll9T6Ij-oBNPK9iysvGJZpvKr1-lqBpURNXiLM,10856
84
+ tunacode/tools/read_file.py,sha256=Xy8vkckjq8kBNNYJMpMhq0pabVi4Kp8b57C3C3picI4,6729
85
+ tunacode/tools/run_command.py,sha256=VBFEy52y70gSkodGd0wNLrlfImgD_57Hl2h2BRn3GnE,8177
86
+ tunacode/tools/schema_assembler.py,sha256=sUePWvprfTHz9hau1q7hmWd12ew3rHdbASAGkpjBhuM,5507
87
+ tunacode/tools/todo.py,sha256=wO8Ui19Jd4r_LQ9Iirlo0WQamcxu1H6NuVWf87soKwk,18027
88
+ tunacode/tools/update_file.py,sha256=0KTbEe1awS53CZPh1G3F3-TWuemWWBuDVQhcRYwXKOg,7619
89
+ tunacode/tools/write_file.py,sha256=WHEXdUKqUHZZ8Jh1muyupJgjud-x6h99x7qAMaloLao,6021
87
90
  tunacode/tools/grep_components/__init__.py,sha256=qy3kwzxOiE6ydlRzpCC39TaIp5BJc5X_bRfXukiu4eM,266
88
91
  tunacode/tools/grep_components/file_filter.py,sha256=-XYlmVLOipjuAGdLhHDApLMKZJ1qtlzRUXvOvHc7VYU,3152
89
92
  tunacode/tools/grep_components/pattern_matcher.py,sha256=ZvEUqBZ6UWf9wZzb1DIRGSTFQuJCBV0GJG3DVG4r4Ss,5177
90
- tunacode/tools/grep_components/result_formatter.py,sha256=aa0tJitbG9IalWYWKG0nInRmZnp8HtBREOeMpAireVg,1641
93
+ tunacode/tools/grep_components/result_formatter.py,sha256=S2TKdkJ81akFWyhwico0xR4jSx4yubfqchErEW-mEDQ,5223
91
94
  tunacode/tools/grep_components/search_result.py,sha256=xzb_htSANuPIPVWViPAqIMsCCWVA8loxWdaZOA8RqMs,869
92
95
  tunacode/ui/__init__.py,sha256=aRNE2pS50nFAX6y--rSGMNYwhz905g14gRd6g4BolYU,13
93
96
  tunacode/ui/completers.py,sha256=18f1Im5210-b-qNKyCoOMnSjW99FXNoF0DtgRvEWTm0,4901
94
97
  tunacode/ui/console.py,sha256=HfE30vUy8ebXCobP7psFNJc17-dvH6APChg2tbi7aTw,2632
95
98
  tunacode/ui/constants.py,sha256=A76B_KpM8jCuBYRg4cPmhi8_j6LLyWttO7_jjv47r3w,421
96
99
  tunacode/ui/decorators.py,sha256=jJDNztO8MyX_IG1nqXAL8-sQUFjaAzBnc5BsM3ioX24,1955
97
- tunacode/ui/input.py,sha256=NCZlj5qzNPy0gsSeGKeDNdAOMKZVGph8Z-UBXhX-Sbk,3020
98
- tunacode/ui/keybindings.py,sha256=YUyi6I0xXs9mNjT0qnKh_SXsfSYb6eNUD44pV_q5TVI,1685
100
+ tunacode/ui/input.py,sha256=WcbQ93Ct-Eu5CZkzFrmIz4eIN6wDbG4iegr9N6Vjzrk,3306
101
+ tunacode/ui/keybindings.py,sha256=8j58NN432XyawffssFNe86leXaPur12qBX3O7hOOGsc,2374
99
102
  tunacode/ui/lexers.py,sha256=tmg4ic1enyTRLzanN5QPP7D_0n12YjX_8ZhsffzhXA4,1340
100
103
  tunacode/ui/logging_compat.py,sha256=5v6lcjVaG1CxdY1Zm9FAGr9H7Sy-tP6ihGfhP-5YvAY,1406
101
104
  tunacode/ui/output.py,sha256=C2LHKAZxBySsIfk9saJ-jZrsZBE7f3WeP-RHpn5TChQ,6808
102
- tunacode/ui/panels.py,sha256=wccIQ-exLs5oBedFZRU1lsY69fRqf-em_5gTTRM0Luc,11527
103
- tunacode/ui/prompt_manager.py,sha256=489r-WtuR3gdaugEr1lSV7SvtmXF2IlhDQckvzjYG2c,4676
105
+ tunacode/ui/panels.py,sha256=jsStKE618qrZjZQGYBBVL__pNIamnRgu0UvE0RG0luA,13461
106
+ tunacode/ui/prompt_manager.py,sha256=HUL6443pFPb41uDAnAKD-sZsrWd_VhWYRGwvrFH_9SI,5618
104
107
  tunacode/ui/tool_descriptions.py,sha256=vk61JPIXy7gHNfJ--77maXgK6WwNwxqY47QYsw_a2uw,4126
105
- tunacode/ui/tool_ui.py,sha256=bLydo5Y42b2gbUMP2kM6m_stIkj4Q1wbwaqO-1P6O1g,7198
108
+ tunacode/ui/tool_ui.py,sha256=MVmBLXx6OTJVFLl58SpoW0KoStOrbAY9sc6XXMKgWtQ,7216
106
109
  tunacode/ui/utils.py,sha256=yvoCTz8AOdRfV0XIqUX3sgg88g_wntV9yhnQP6WzAVs,114
107
110
  tunacode/ui/validators.py,sha256=MMIMT1I2v0l2jIy-gxX_4GSApvUTi8XWIOACr_dmoBA,758
108
111
  tunacode/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -110,17 +113,18 @@ tunacode/utils/bm25.py,sha256=fd59YQXovC8rXwZrdoqIAfFrLn_WCVjzCh0pkU22APE,1966
110
113
  tunacode/utils/diff_utils.py,sha256=V9QqQ0q4MfabVTnWptF3IXDp3estnfOKcJtDe_Sj14I,2372
111
114
  tunacode/utils/file_utils.py,sha256=84g-MQRzmBI2aG_CuXsDl2OhvvWoSL7YdL5Kz_UKSwk,979
112
115
  tunacode/utils/import_cache.py,sha256=q_xjJbtju05YbFopLDSkIo1hOtCx3DOTl3GQE5FFDgs,295
113
- tunacode/utils/message_utils.py,sha256=qb_EgPRq5a4pbQNcCLhmfcQVQ6vjekjsfgKrhIiszGQ,610
116
+ tunacode/utils/json_utils.py,sha256=cMVctSwwV9Z1c-rZdj6UuOlZwsUPSTF5oUruP6uPix0,6470
117
+ tunacode/utils/message_utils.py,sha256=V4MrZZPmwO22_MVGupMqtE5ltQEBwaSIqGD5LEb_bLw,1050
114
118
  tunacode/utils/retry.py,sha256=AHdUzY6m-mwlT4OPXdtWWMAafL_NeS7JAMORGyM8c5k,4931
115
- tunacode/utils/ripgrep.py,sha256=AXUs2FFt0A7KBV996deS8wreIlUzKOlAHJmwrcAr4No,583
119
+ tunacode/utils/ripgrep.py,sha256=VdGWYPQ1zCwUidw2QicuVmG5OiAgqI93jAsjS3y3ksE,11001
116
120
  tunacode/utils/security.py,sha256=i3eGKg4o-qY2S_ObTlEaHO93q14iBfiPXR5O7srHn58,6579
117
121
  tunacode/utils/system.py,sha256=J8KqJ4ZqQrNSnM5rrJxPeMk9z2xQQp6dWtI1SKBY1-0,11121
118
122
  tunacode/utils/text_utils.py,sha256=HAwlT4QMy41hr53cDbbNeNo05MI461TpI9b_xdIv8EY,7288
119
123
  tunacode/utils/token_counter.py,sha256=dmFuqVz4ywGFdLfAi5Mg9bAGf8v87Ek-mHU-R3fsYjI,2711
120
124
  tunacode/utils/user_configuration.py,sha256=Ilz8dpGVJDBE2iLWHAPT0xR8D51VRKV3kIbsAz8Bboc,3275
121
- tunacode_cli-0.0.55.dist-info/licenses/LICENSE,sha256=Btzdu2kIoMbdSp6OyCLupB1aRgpTCJ_szMimgEnpkkE,1056
122
- tunacode_cli-0.0.55.dist-info/METADATA,sha256=nB8M3oUVfbFFUBxldQFl86PjnnuxhhL6KGeal1iE88g,10193
123
- tunacode_cli-0.0.55.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
124
- tunacode_cli-0.0.55.dist-info/entry_points.txt,sha256=hbkytikj4dGu6rizPuAd_DGUPBGF191RTnhr9wdhORY,51
125
- tunacode_cli-0.0.55.dist-info/top_level.txt,sha256=lKy2P6BWNi5XSA4DHFvyjQ14V26lDZctwdmhEJrxQbU,9
126
- tunacode_cli-0.0.55.dist-info/RECORD,,
125
+ tunacode_cli-0.0.57.dist-info/licenses/LICENSE,sha256=Btzdu2kIoMbdSp6OyCLupB1aRgpTCJ_szMimgEnpkkE,1056
126
+ tunacode_cli-0.0.57.dist-info/METADATA,sha256=DeoLfo2hux8X_uO0axtFPP0Ejxu-_e-6y7WCK7vSf90,10926
127
+ tunacode_cli-0.0.57.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
128
+ tunacode_cli-0.0.57.dist-info/entry_points.txt,sha256=hbkytikj4dGu6rizPuAd_DGUPBGF191RTnhr9wdhORY,51
129
+ tunacode_cli-0.0.57.dist-info/top_level.txt,sha256=lKy2P6BWNi5XSA4DHFvyjQ14V26lDZctwdmhEJrxQbU,9
130
+ tunacode_cli-0.0.57.dist-info/RECORD,,
@@ -1,196 +0,0 @@
1
- """
2
- Proof of Concept: Async-optimized read_file tool
3
-
4
- This demonstrates how we can make the read_file tool truly async
5
- by using asyncio.to_thread (Python 3.9+) or run_in_executor.
6
- """
7
-
8
- import asyncio
9
- import os
10
- import sys
11
- from concurrent.futures import ThreadPoolExecutor
12
- from typing import Optional
13
-
14
- from tunacode.constants import (
15
- ERROR_FILE_DECODE,
16
- ERROR_FILE_DECODE_DETAILS,
17
- ERROR_FILE_NOT_FOUND,
18
- ERROR_FILE_TOO_LARGE,
19
- MAX_FILE_SIZE,
20
- MSG_FILE_SIZE_LIMIT,
21
- )
22
- from tunacode.exceptions import ToolExecutionError
23
- from tunacode.tools.base import FileBasedTool
24
- from tunacode.types import ToolResult
25
-
26
- # Shared thread pool for I/O operations
27
- # This avoids creating multiple thread pools
28
- _IO_THREAD_POOL: Optional[ThreadPoolExecutor] = None
29
-
30
-
31
- def get_io_thread_pool() -> ThreadPoolExecutor:
32
- """Get or create the shared I/O thread pool."""
33
- global _IO_THREAD_POOL
34
- if _IO_THREAD_POOL is None:
35
- max_workers = min(32, (os.cpu_count() or 1) * 4)
36
- _IO_THREAD_POOL = ThreadPoolExecutor(
37
- max_workers=max_workers, thread_name_prefix="tunacode-io"
38
- )
39
- return _IO_THREAD_POOL
40
-
41
-
42
- class AsyncReadFileTool(FileBasedTool):
43
- """Async-optimized tool for reading file contents."""
44
-
45
- @property
46
- def tool_name(self) -> str:
47
- return "Read"
48
-
49
- async def _execute(self, filepath: str) -> ToolResult:
50
- """Read the contents of a file asynchronously.
51
-
52
- Args:
53
- filepath: The path to the file to read.
54
-
55
- Returns:
56
- ToolResult: The contents of the file or an error message.
57
-
58
- Raises:
59
- Exception: Any file reading errors
60
- """
61
- # Check file size first (this is fast)
62
- try:
63
- file_size = os.path.getsize(filepath)
64
- except FileNotFoundError:
65
- raise FileNotFoundError(f"File not found: {filepath}")
66
-
67
- if file_size > MAX_FILE_SIZE:
68
- err_msg = ERROR_FILE_TOO_LARGE.format(filepath=filepath) + MSG_FILE_SIZE_LIMIT
69
- if self.ui:
70
- await self.ui.error(err_msg)
71
- raise ToolExecutionError(tool_name=self.tool_name, message=err_msg, original_error=None)
72
-
73
- # Read file asynchronously
74
- content = await self._read_file_async(filepath)
75
- return content
76
-
77
- async def _read_file_async(self, filepath: str) -> str:
78
- """Read file contents without blocking the event loop."""
79
-
80
- # Method 1: Using asyncio.to_thread (Python 3.9+)
81
- if sys.version_info >= (3, 9):
82
-
83
- def _read_sync():
84
- with open(filepath, "r", encoding="utf-8") as file:
85
- return file.read()
86
-
87
- try:
88
- return await asyncio.to_thread(_read_sync)
89
- except Exception:
90
- # Re-raise to be handled by _handle_error
91
- raise
92
-
93
- # Method 2: Using run_in_executor (older Python versions)
94
- else:
95
-
96
- def _read_sync(path):
97
- with open(path, "r", encoding="utf-8") as file:
98
- return file.read()
99
-
100
- loop = asyncio.get_event_loop()
101
- executor = get_io_thread_pool()
102
-
103
- try:
104
- return await loop.run_in_executor(executor, _read_sync, filepath)
105
- except Exception:
106
- # Re-raise to be handled by _handle_error
107
- raise
108
-
109
- async def _handle_error(self, error: Exception, filepath: str = None) -> ToolResult:
110
- """Handle errors with specific messages for common cases.
111
-
112
- Raises:
113
- ToolExecutionError: Always raised with structured error information
114
- """
115
- if isinstance(error, FileNotFoundError):
116
- err_msg = ERROR_FILE_NOT_FOUND.format(filepath=filepath)
117
- elif isinstance(error, UnicodeDecodeError):
118
- err_msg = (
119
- ERROR_FILE_DECODE.format(filepath=filepath)
120
- + " "
121
- + ERROR_FILE_DECODE_DETAILS.format(error=error)
122
- )
123
- else:
124
- # Use parent class handling for other errors
125
- await super()._handle_error(error, filepath)
126
- return # super() will raise, this is unreachable
127
-
128
- if self.ui:
129
- await self.ui.error(err_msg)
130
-
131
- raise ToolExecutionError(tool_name=self.tool_name, message=err_msg, original_error=error)
132
-
133
-
134
- # Create the async function that maintains the existing interface
135
- async def read_file_async(filepath: str) -> str:
136
- """
137
- Read the contents of a file asynchronously without blocking the event loop.
138
-
139
- This implementation uses thread pool execution to avoid blocking during file I/O,
140
- allowing true parallel execution of multiple file reads.
141
-
142
- Args:
143
- filepath: The path to the file to read.
144
-
145
- Returns:
146
- str: The contents of the file or an error message.
147
- """
148
- tool = AsyncReadFileTool(None) # No UI for pydantic-ai compatibility
149
- try:
150
- return await tool.execute(filepath)
151
- except ToolExecutionError as e:
152
- # Return error message for pydantic-ai compatibility
153
- return str(e)
154
-
155
-
156
- # Benchmarking utilities for testing
157
- async def benchmark_read_performance():
158
- """Benchmark the performance difference between sync and async reads."""
159
- import contextlib
160
- import tempfile
161
- import time
162
-
163
- from tunacode.tools.read_file import read_file as read_file_sync
164
-
165
- # Create some test files using tempfile for secure temporary file creation
166
- test_files = []
167
- for _ in range(10):
168
- with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".txt") as temp_file:
169
- temp_file.write("x" * 10000) # 10KB file
170
- test_files.append(temp_file.name)
171
-
172
- # Test synchronous reads (sequential)
173
- start_time = time.time()
174
- for filepath in test_files:
175
- await read_file_sync(filepath)
176
- sync_time = time.time() - start_time
177
-
178
- # Test async reads (parallel)
179
- start_time = time.time()
180
- tasks = [read_file_async(filepath) for filepath in test_files]
181
- await asyncio.gather(*tasks)
182
- async_time = time.time() - start_time
183
-
184
- # Cleanup using safe file removal
185
- for filepath in test_files:
186
- with contextlib.suppress(OSError):
187
- os.unlink(filepath)
188
-
189
- print(f"Synchronous reads: {sync_time:.3f}s")
190
- print(f"Async reads: {async_time:.3f}s")
191
- print(f"Speedup: {sync_time / async_time:.2f}x")
192
-
193
-
194
- if __name__ == "__main__":
195
- # Run benchmark when executed directly
196
- asyncio.run(benchmark_read_performance())