tunacode-cli 0.0.56__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 (45) hide show
  1. tunacode/cli/commands/implementations/plan.py +8 -8
  2. tunacode/cli/commands/registry.py +2 -2
  3. tunacode/cli/repl.py +214 -407
  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 +14 -11
  7. tunacode/cli/repl_components/tool_executor.py +7 -4
  8. tunacode/configuration/defaults.py +8 -0
  9. tunacode/constants.py +8 -2
  10. tunacode/core/agents/agent_components/agent_config.py +128 -65
  11. tunacode/core/agents/agent_components/node_processor.py +6 -2
  12. tunacode/core/code_index.py +83 -29
  13. tunacode/core/state.py +1 -1
  14. tunacode/core/token_usage/usage_tracker.py +2 -2
  15. tunacode/core/tool_handler.py +3 -3
  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 +114 -32
  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 +111 -31
  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 +10 -9
  33. tunacode/ui/input.py +1 -0
  34. tunacode/ui/keybindings.py +1 -0
  35. tunacode/ui/panels.py +49 -27
  36. tunacode/ui/prompt_manager.py +13 -7
  37. tunacode/utils/json_utils.py +206 -0
  38. tunacode/utils/ripgrep.py +332 -9
  39. {tunacode_cli-0.0.56.dist-info → tunacode_cli-0.0.57.dist-info}/METADATA +5 -1
  40. {tunacode_cli-0.0.56.dist-info → tunacode_cli-0.0.57.dist-info}/RECORD +44 -43
  41. tunacode/tools/read_file_async_poc.py +0 -196
  42. {tunacode_cli-0.0.56.dist-info → tunacode_cli-0.0.57.dist-info}/WHEEL +0 -0
  43. {tunacode_cli-0.0.56.dist-info → tunacode_cli-0.0.57.dist-info}/entry_points.txt +0 -0
  44. {tunacode_cli-0.0.56.dist-info → tunacode_cli-0.0.57.dist-info}/licenses/LICENSE +0 -0
  45. {tunacode_cli-0.0.56.dist-info → tunacode_cli-0.0.57.dist-info}/top_level.txt +0 -0
@@ -1,48 +1,48 @@
1
1
  tunacode/__init__.py,sha256=yUul8igNYMfUrHnYfioIGAqvrH8b5BKiO_pt1wVnmd0,119
2
- tunacode/constants.py,sha256=7expbYlpKFgNIAF-zkeUWQ4HBw6PQb1Lnvk0u85qleo,6077
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=9cprg2Lc9vkzRkiGQlwHwLXO09tZYaob12s6PJHxc3Y,10196
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=RVx1D3s2t9-Ur1q_-voyknFOQn4URlJExR9yceSjW8g,30745
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=OOZG51x1DTFfjIzStxBVxAOb6SOsUSh2bfIOsKY3Z1Q,9515
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=gFMcwoz9glLctvkyuNMqIkxoK6RAZA4f7JLQOBtgtqk,1865
20
+ tunacode/cli/commands/implementations/plan.py,sha256=iZtvdGPqvGqMr8_lYil8_8NOL1iyc54Bxtb0gb9VOnw,1825
21
21
  tunacode/cli/commands/implementations/system.py,sha256=2cGw5iCJO3aNhXTFF28CgAIyLgslvHmpfyL2ZHVB6oQ,7903
22
22
  tunacode/cli/commands/implementations/template.py,sha256=YeFOjbKKfPswPCHPvlDUwXvg6J0MesyAyVsujiIgPbU,5482
23
23
  tunacode/cli/commands/implementations/todo.py,sha256=Dtz5bgcuK2VXGPWEBBZQgnWUMYkRXNzTGf_qkVPLF2U,8125
24
24
  tunacode/cli/repl_components/__init__.py,sha256=5ZjPJ3yUvZ5x6Vg9EYJ03-tdxfEEdmfradCmwSlVY3E,334
25
- tunacode/cli/repl_components/command_parser.py,sha256=SuDRP-nt8Sq5klI4-tXkllN_4nVzji5VJ-dQvbxDmDw,880
26
- tunacode/cli/repl_components/error_recovery.py,sha256=yPoWXzuMi6B_Pwlm1wnFIJV55lJEOChvHGDca4XtoVI,3064
27
- tunacode/cli/repl_components/output_display.py,sha256=ry-F2fG8m_oqfWt8lhvzeEhq0XgCI_Ed4H4plibfHJ8,1437
28
- tunacode/cli/repl_components/tool_executor.py,sha256=1E8kL0eCP9f3wx2dZtNOFY0x7_B7eHdK9zYFpc11C0Y,3754
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
29
29
  tunacode/configuration/__init__.py,sha256=MbVXy8bGu0yKehzgdgZ_mfWlYGvIdb1dY2Ly75nfuPE,17
30
- tunacode/configuration/defaults.py,sha256=5TUeSqMTeA7kW7gz9hND_H4s9Key0_khPvc6mNFMlZc,838
30
+ tunacode/configuration/defaults.py,sha256=Kd0uBNrURdhDad_HsLeOz3MJu1o6atLJ3vjaESQqgnw,1269
31
31
  tunacode/configuration/models.py,sha256=buH8ZquvcYI3OQBDIZeJ08cu00rSCeNABtUwl3VQS0E,4103
32
32
  tunacode/configuration/settings.py,sha256=9wtIWBlLhW_ZBlLx-GA4XDfVZyGj2Gs6Zk49vk-nHq0,1047
33
33
  tunacode/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
- tunacode/core/code_index.py,sha256=jgAx3lSWP_DwnyiP5Jkm1YvX4JJyI4teMzlNrJSpEOA,15661
35
- tunacode/core/state.py,sha256=IDCoHOWn40BBAXnd2h8OCpMtQRpt2d95KUgX8vkHu6M,7897
36
- tunacode/core/tool_handler.py,sha256=A9wbnSpS0DsyqcOOS57I6txiuc74HEZ5mlc4qkRIgK0,3658
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
37
37
  tunacode/core/agents/__init__.py,sha256=UUJiPYb91arwziSpjd7vIk7XNGA_4HQbsOIbskSqevA,149
38
38
  tunacode/core/agents/main.py,sha256=myz_K2lxqYH8pQdbw8n8bai8F40Mqfj-kTLagPR1dP4,18253
39
39
  tunacode/core/agents/utils.py,sha256=dJsdbvWs48vxQpwAtUjJLMj7_huv12Mx3E2CEgwoK94,14467
40
40
  tunacode/core/agents/agent_components/__init__.py,sha256=CL4XH47T6v_iYy7xCPYjyiEFNOFnkcKwbTuKw6IjKTs,1474
41
- tunacode/core/agents/agent_components/agent_config.py,sha256=MwYGFvUGxgENU_IOy76EECA1TXc4Jc4-jeZctxZ8RSE,9664
41
+ tunacode/core/agents/agent_components/agent_config.py,sha256=lkq6-6p8AHVZuoebUrFXtZgmBJipK8CSD2JaBA0Am_A,11845
42
42
  tunacode/core/agents/agent_components/agent_helpers.py,sha256=G3zF5GPRzBhA3yOcsXf8gar892ackGDcwFk9wM6FA9s,8119
43
43
  tunacode/core/agents/agent_components/json_tool_parser.py,sha256=HuyNT0rs-ppx_gLAI2e0XMVGbR_F0WXZfP3sx38VoMg,3447
44
44
  tunacode/core/agents/agent_components/message_handler.py,sha256=KJGOtb9VhumgZpxxwO45HrKLhU9_MwuoWRsSQwJviNU,3704
45
- tunacode/core/agents/agent_components/node_processor.py,sha256=77XxHjBI6hFmC_c4hWguVjmHGr5o-8KA3aWHxIL6gPg,20736
45
+ tunacode/core/agents/agent_components/node_processor.py,sha256=BAVbXy17sfW3i4LCTdJ9_MSNc7j6qz1bP3_6IhprIW4,20912
46
46
  tunacode/core/agents/agent_components/response_state.py,sha256=_C2loLeyZHMFHwjGny4h0dI02UoFJcJAVaabkh9H9JQ,343
47
47
  tunacode/core/agents/agent_components/result_wrapper.py,sha256=9CFK0wpsfZx2WT4PBHfkSv22GxL1gAQuUYVMlmYtCJU,1761
48
48
  tunacode/core/agents/agent_components/task_completion.py,sha256=BSnjNEFbxlzgzcXdjdTVGeCr1RpCiAaEp_D7f5FXa5Q,819
@@ -67,43 +67,43 @@ tunacode/core/setup/git_safety_setup.py,sha256=uBvcvw3THfduGUW51rprFt13Qw3HoekWe
67
67
  tunacode/core/setup/template_setup.py,sha256=0lDGhNVCvGN7ykqHnl3pj4CONH3I2PvMzkmIZibfSoc,2640
68
68
  tunacode/core/token_usage/api_response_parser.py,sha256=plLltHg4zGVzxjv3MFj45bbd-NOJeT_v3P0Ki4zlvn4,1831
69
69
  tunacode/core/token_usage/cost_calculator.py,sha256=RjO-O0JENBuGOrWP7QgBZlZxeXC-PAIr8tj_9p_BxOU,2058
70
- tunacode/core/token_usage/usage_tracker.py,sha256=G6lt9VXnS3JcXsiPTwuS3v1YptI_7gfV78f08jX22yU,5932
71
- 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
72
72
  tunacode/services/__init__.py,sha256=w_E8QK6RnvKSvU866eDe8BCRV26rAm4d3R-Yg06OWCU,19
73
- tunacode/services/mcp.py,sha256=R48X73KQjQ9vwhBrtbWHSBl-4K99QXmbIhh5J_1Gezo,3046
73
+ tunacode/services/mcp.py,sha256=quO13skECUGt-4QE2NkWk6_8qhmZ5qjgibvw8tUOt-4,3761
74
74
  tunacode/templates/__init__.py,sha256=ssEOPrPjyCywtKI-QFcoqcWhMjlfI5TbI8Ip0_wyqGM,241
75
75
  tunacode/templates/loader.py,sha256=6_Dk4jX47_GKUAWxlHG2Mzkl9lkXFUOiAdlcJqb6rBA,6765
76
76
  tunacode/tools/__init__.py,sha256=ECBuUWWF1JjHW42CCceaPKgVTQyuljbz3RlhuA2fe2s,314
77
- tunacode/tools/base.py,sha256=DhlanZZZxU2JJaBOwwyGFKMUcoCWR_CzLuwVeSXC0Go,7297
78
- tunacode/tools/bash.py,sha256=mgZqugfDFevZ4BETuUv90pzXvtq7qKGUGFiuDxzmytk,8766
79
- tunacode/tools/exit_plan_mode.py,sha256=UCtoqBPlT7auP2VJ1_KDsPIB9FatylqwQdD7cU4kz2g,7683
80
- tunacode/tools/glob.py,sha256=mQwVGC8dfvzwzUOeTikfnHhExnLcYnGQwDoHOWrt_fE,10342
81
- tunacode/tools/grep.py,sha256=SfpLazOMbizganPO16w7v6iHRcUn0cD6-6lyUwrl-3U,17834
82
- tunacode/tools/list_dir.py,sha256=1kNqzYCNlcA5rqXIEVqcjQy6QxlLZLj5AG6YIECfwio,7217
83
- tunacode/tools/present_plan.py,sha256=dxHlFMIeiSfxuXSkox7znw4YsrteyXswWNHpcbDz8XU,7988
84
- tunacode/tools/read_file.py,sha256=z2omev9xzj4-0GG9mRssD13rj-Aa1c-pszFi2Z7Hxvk,3268
85
- tunacode/tools/read_file_async_poc.py,sha256=2v2ckLQlwahgPGWGdE2c5Es37B35Y7zWdseZwT46E1E,6453
86
- tunacode/tools/run_command.py,sha256=7UvXjFQI1Av4vceXx48MbQCTrsFNj4PlygTAAhNDYIA,4376
87
- tunacode/tools/todo.py,sha256=kHYtipmPBxBURrBMbyH92yjOE6cKvrQuq9w-gSrOaLI,13179
88
- tunacode/tools/update_file.py,sha256=bW1MhTzRjBDjJzqQ6A1yCVEbkr1oIqtEC8uqcg_rfY4,3957
89
- 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
90
90
  tunacode/tools/grep_components/__init__.py,sha256=qy3kwzxOiE6ydlRzpCC39TaIp5BJc5X_bRfXukiu4eM,266
91
91
  tunacode/tools/grep_components/file_filter.py,sha256=-XYlmVLOipjuAGdLhHDApLMKZJ1qtlzRUXvOvHc7VYU,3152
92
92
  tunacode/tools/grep_components/pattern_matcher.py,sha256=ZvEUqBZ6UWf9wZzb1DIRGSTFQuJCBV0GJG3DVG4r4Ss,5177
93
- tunacode/tools/grep_components/result_formatter.py,sha256=aa0tJitbG9IalWYWKG0nInRmZnp8HtBREOeMpAireVg,1641
93
+ tunacode/tools/grep_components/result_formatter.py,sha256=S2TKdkJ81akFWyhwico0xR4jSx4yubfqchErEW-mEDQ,5223
94
94
  tunacode/tools/grep_components/search_result.py,sha256=xzb_htSANuPIPVWViPAqIMsCCWVA8loxWdaZOA8RqMs,869
95
95
  tunacode/ui/__init__.py,sha256=aRNE2pS50nFAX6y--rSGMNYwhz905g14gRd6g4BolYU,13
96
96
  tunacode/ui/completers.py,sha256=18f1Im5210-b-qNKyCoOMnSjW99FXNoF0DtgRvEWTm0,4901
97
97
  tunacode/ui/console.py,sha256=HfE30vUy8ebXCobP7psFNJc17-dvH6APChg2tbi7aTw,2632
98
98
  tunacode/ui/constants.py,sha256=A76B_KpM8jCuBYRg4cPmhi8_j6LLyWttO7_jjv47r3w,421
99
99
  tunacode/ui/decorators.py,sha256=jJDNztO8MyX_IG1nqXAL8-sQUFjaAzBnc5BsM3ioX24,1955
100
- tunacode/ui/input.py,sha256=xnxpprr5K6Asd6vezvVhStnQEdKeY7f7pwo849X8UeE,3305
101
- tunacode/ui/keybindings.py,sha256=vyETOZiEuWnnCsrd_bmnlbon6qLD0fK6llG9oU500zY,2373
100
+ tunacode/ui/input.py,sha256=WcbQ93Ct-Eu5CZkzFrmIz4eIN6wDbG4iegr9N6Vjzrk,3306
101
+ tunacode/ui/keybindings.py,sha256=8j58NN432XyawffssFNe86leXaPur12qBX3O7hOOGsc,2374
102
102
  tunacode/ui/lexers.py,sha256=tmg4ic1enyTRLzanN5QPP7D_0n12YjX_8ZhsffzhXA4,1340
103
103
  tunacode/ui/logging_compat.py,sha256=5v6lcjVaG1CxdY1Zm9FAGr9H7Sy-tP6ihGfhP-5YvAY,1406
104
104
  tunacode/ui/output.py,sha256=C2LHKAZxBySsIfk9saJ-jZrsZBE7f3WeP-RHpn5TChQ,6808
105
- tunacode/ui/panels.py,sha256=0U63lISyrqE7FMOllaPx_Cp9hRGIR6Ra2NdGTCCR2oE,12381
106
- tunacode/ui/prompt_manager.py,sha256=ENT2eqdOO5Hlf4Ga7kXaPVS4QNjxD2E7NQN6AmHQRPM,5522
105
+ tunacode/ui/panels.py,sha256=jsStKE618qrZjZQGYBBVL__pNIamnRgu0UvE0RG0luA,13461
106
+ tunacode/ui/prompt_manager.py,sha256=HUL6443pFPb41uDAnAKD-sZsrWd_VhWYRGwvrFH_9SI,5618
107
107
  tunacode/ui/tool_descriptions.py,sha256=vk61JPIXy7gHNfJ--77maXgK6WwNwxqY47QYsw_a2uw,4126
108
108
  tunacode/ui/tool_ui.py,sha256=MVmBLXx6OTJVFLl58SpoW0KoStOrbAY9sc6XXMKgWtQ,7216
109
109
  tunacode/ui/utils.py,sha256=yvoCTz8AOdRfV0XIqUX3sgg88g_wntV9yhnQP6WzAVs,114
@@ -113,17 +113,18 @@ tunacode/utils/bm25.py,sha256=fd59YQXovC8rXwZrdoqIAfFrLn_WCVjzCh0pkU22APE,1966
113
113
  tunacode/utils/diff_utils.py,sha256=V9QqQ0q4MfabVTnWptF3IXDp3estnfOKcJtDe_Sj14I,2372
114
114
  tunacode/utils/file_utils.py,sha256=84g-MQRzmBI2aG_CuXsDl2OhvvWoSL7YdL5Kz_UKSwk,979
115
115
  tunacode/utils/import_cache.py,sha256=q_xjJbtju05YbFopLDSkIo1hOtCx3DOTl3GQE5FFDgs,295
116
+ tunacode/utils/json_utils.py,sha256=cMVctSwwV9Z1c-rZdj6UuOlZwsUPSTF5oUruP6uPix0,6470
116
117
  tunacode/utils/message_utils.py,sha256=V4MrZZPmwO22_MVGupMqtE5ltQEBwaSIqGD5LEb_bLw,1050
117
118
  tunacode/utils/retry.py,sha256=AHdUzY6m-mwlT4OPXdtWWMAafL_NeS7JAMORGyM8c5k,4931
118
- tunacode/utils/ripgrep.py,sha256=AXUs2FFt0A7KBV996deS8wreIlUzKOlAHJmwrcAr4No,583
119
+ tunacode/utils/ripgrep.py,sha256=VdGWYPQ1zCwUidw2QicuVmG5OiAgqI93jAsjS3y3ksE,11001
119
120
  tunacode/utils/security.py,sha256=i3eGKg4o-qY2S_ObTlEaHO93q14iBfiPXR5O7srHn58,6579
120
121
  tunacode/utils/system.py,sha256=J8KqJ4ZqQrNSnM5rrJxPeMk9z2xQQp6dWtI1SKBY1-0,11121
121
122
  tunacode/utils/text_utils.py,sha256=HAwlT4QMy41hr53cDbbNeNo05MI461TpI9b_xdIv8EY,7288
122
123
  tunacode/utils/token_counter.py,sha256=dmFuqVz4ywGFdLfAi5Mg9bAGf8v87Ek-mHU-R3fsYjI,2711
123
124
  tunacode/utils/user_configuration.py,sha256=Ilz8dpGVJDBE2iLWHAPT0xR8D51VRKV3kIbsAz8Bboc,3275
124
- tunacode_cli-0.0.56.dist-info/licenses/LICENSE,sha256=Btzdu2kIoMbdSp6OyCLupB1aRgpTCJ_szMimgEnpkkE,1056
125
- tunacode_cli-0.0.56.dist-info/METADATA,sha256=92Fa9XfK5XiYYOwiHlKuWHbnFkb0cGX1tAVOGwLalXQ,10773
126
- tunacode_cli-0.0.56.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
127
- tunacode_cli-0.0.56.dist-info/entry_points.txt,sha256=hbkytikj4dGu6rizPuAd_DGUPBGF191RTnhr9wdhORY,51
128
- tunacode_cli-0.0.56.dist-info/top_level.txt,sha256=lKy2P6BWNi5XSA4DHFvyjQ14V26lDZctwdmhEJrxQbU,9
129
- tunacode_cli-0.0.56.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())