janito 1.6.0__py3-none-any.whl → 1.8.0__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.
Files changed (117) hide show
  1. janito/__init__.py +1 -1
  2. janito/agent/config.py +3 -3
  3. janito/agent/config_defaults.py +3 -2
  4. janito/agent/conversation.py +73 -27
  5. janito/agent/conversation_api.py +104 -4
  6. janito/agent/conversation_exceptions.py +6 -0
  7. janito/agent/conversation_tool_calls.py +17 -3
  8. janito/agent/event.py +24 -0
  9. janito/agent/event_dispatcher.py +24 -0
  10. janito/agent/event_handler_protocol.py +5 -0
  11. janito/agent/event_system.py +15 -0
  12. janito/agent/message_handler.py +4 -1
  13. janito/agent/message_handler_protocol.py +5 -0
  14. janito/agent/openai_client.py +5 -6
  15. janito/agent/openai_schema_generator.py +23 -4
  16. janito/agent/platform_discovery.py +90 -0
  17. janito/agent/profile_manager.py +34 -110
  18. janito/agent/queued_message_handler.py +22 -3
  19. janito/agent/rich_message_handler.py +3 -1
  20. janito/agent/templates/profiles/system_prompt_template_base.txt.j2 +14 -0
  21. janito/agent/templates/profiles/system_prompt_template_base_pt.txt.j2 +13 -0
  22. janito/agent/test_handler_protocols.py +47 -0
  23. janito/agent/tests/__init__.py +1 -0
  24. janito/agent/tool_base.py +1 -1
  25. janito/agent/tool_executor.py +109 -0
  26. janito/agent/tool_registry.py +3 -75
  27. janito/agent/tool_use_tracker.py +46 -0
  28. janito/agent/tools/__init__.py +11 -8
  29. janito/agent/tools/ask_user.py +26 -12
  30. janito/agent/tools/create_directory.py +50 -18
  31. janito/agent/tools/create_file.py +60 -29
  32. janito/agent/tools/dir_walk_utils.py +16 -0
  33. janito/agent/tools/fetch_url.py +10 -11
  34. janito/agent/tools/find_files.py +49 -40
  35. janito/agent/tools/get_lines.py +60 -25
  36. janito/agent/tools/memory.py +48 -0
  37. janito/agent/tools/move_file.py +72 -23
  38. janito/agent/tools/outline_file/__init__.py +85 -0
  39. janito/agent/tools/outline_file/formatting.py +20 -0
  40. janito/agent/tools/outline_file/markdown_outline.py +14 -0
  41. janito/agent/tools/outline_file/python_outline.py +71 -0
  42. janito/agent/tools/present_choices.py +62 -0
  43. janito/agent/tools/present_choices_test.py +18 -0
  44. janito/agent/tools/remove_directory.py +31 -26
  45. janito/agent/tools/remove_file.py +31 -13
  46. janito/agent/tools/replace_text_in_file.py +135 -36
  47. janito/agent/tools/run_bash_command.py +113 -97
  48. janito/agent/tools/run_powershell_command.py +169 -0
  49. janito/agent/tools/run_python_command.py +53 -29
  50. janito/agent/tools/search_outline.py +17 -0
  51. janito/agent/tools/search_text.py +208 -0
  52. janito/agent/tools/tools_utils.py +47 -4
  53. janito/agent/tools/utils.py +14 -15
  54. janito/agent/tools/validate_file_syntax.py +163 -0
  55. janito/cli/_print_config.py +1 -1
  56. janito/cli/arg_parser.py +36 -4
  57. janito/cli/config_commands.py +1 -1
  58. janito/cli/logging_setup.py +7 -2
  59. janito/cli/main.py +97 -3
  60. janito/cli/runner/__init__.py +0 -2
  61. janito/cli/runner/_termweb_log_utils.py +17 -0
  62. janito/cli/runner/cli_main.py +121 -89
  63. janito/cli/runner/config.py +6 -4
  64. janito/cli/termweb_starter.py +73 -0
  65. janito/cli_chat_shell/chat_loop.py +52 -13
  66. janito/cli_chat_shell/chat_state.py +1 -1
  67. janito/cli_chat_shell/chat_ui.py +2 -3
  68. janito/cli_chat_shell/commands/__init__.py +17 -6
  69. janito/cli_chat_shell/commands/{history_reset.py → history_start.py} +13 -5
  70. janito/cli_chat_shell/commands/lang.py +16 -0
  71. janito/cli_chat_shell/commands/prompt.py +42 -0
  72. janito/cli_chat_shell/commands/session_control.py +36 -1
  73. janito/cli_chat_shell/commands/sum.py +49 -0
  74. janito/cli_chat_shell/commands/termweb_log.py +86 -0
  75. janito/cli_chat_shell/commands/utility.py +5 -2
  76. janito/cli_chat_shell/commands/verbose.py +29 -0
  77. janito/cli_chat_shell/load_prompt.py +47 -8
  78. janito/cli_chat_shell/session_manager.py +9 -1
  79. janito/cli_chat_shell/shell_command_completer.py +20 -0
  80. janito/cli_chat_shell/ui.py +110 -93
  81. janito/i18n/__init__.py +35 -0
  82. janito/i18n/messages.py +23 -0
  83. janito/i18n/pt.py +46 -0
  84. janito/rich_utils.py +43 -43
  85. janito/termweb/app.py +95 -0
  86. janito/termweb/static/editor.html +238 -0
  87. janito/termweb/static/editor.html.bak +238 -0
  88. janito/termweb/static/explorer.html.bak +59 -0
  89. janito/termweb/static/favicon.ico +0 -0
  90. janito/termweb/static/favicon.ico.bak +0 -0
  91. janito/termweb/static/index.html +55 -0
  92. janito/termweb/static/index.html.bak +55 -0
  93. janito/termweb/static/index.html.bak.bak +175 -0
  94. janito/termweb/static/landing.html.bak +36 -0
  95. janito/termweb/static/termicon.svg +1 -0
  96. janito/termweb/static/termweb.css +235 -0
  97. janito/termweb/static/termweb.css.bak +286 -0
  98. janito/termweb/static/termweb.js +187 -0
  99. janito/termweb/static/termweb.js.bak +187 -0
  100. janito/termweb/static/termweb.js.bak.bak +157 -0
  101. janito/termweb/static/termweb_quickopen.js +135 -0
  102. janito/termweb/static/termweb_quickopen.js.bak +125 -0
  103. janito/web/app.py +10 -13
  104. {janito-1.6.0.dist-info → janito-1.8.0.dist-info}/METADATA +73 -32
  105. janito-1.8.0.dist-info/RECORD +127 -0
  106. {janito-1.6.0.dist-info → janito-1.8.0.dist-info}/WHEEL +1 -1
  107. janito/agent/tool_registry_core.py +0 -2
  108. janito/agent/tools/get_file_outline.py +0 -117
  109. janito/agent/tools/py_compile_file.py +0 -40
  110. janito/agent/tools/replace_file.py +0 -51
  111. janito/agent/tools/search_files.py +0 -71
  112. janito/cli/runner/scan.py +0 -44
  113. janito/cli_chat_shell/commands/system.py +0 -73
  114. janito-1.6.0.dist-info/RECORD +0 -81
  115. {janito-1.6.0.dist-info → janito-1.8.0.dist-info}/entry_points.txt +0 -0
  116. {janito-1.6.0.dist-info → janito-1.8.0.dist-info}/licenses/LICENSE +0 -0
  117. {janito-1.6.0.dist-info → janito-1.8.0.dist-info}/top_level.txt +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: janito
3
- Version: 1.6.0
4
- Summary: A Natural Language Programming Agent,
3
+ Version: 1.8.0
4
+ Summary: Natural Language Coding Agent,
5
5
  Author-email: João Pinto <joao.pinto@gmail.com>
6
- License: MIT
7
- Project-URL: homepage, https://github.com/joaompinto/janito
6
+ License-Expression: MIT
7
+ Project-URL: homepage, https://janito.dev
8
8
  Project-URL: repository, https://github.com/joaompinto/janito
9
9
  Keywords: agent,framework,tools,automation
10
10
  Classifier: Programming Language :: Python :: 3.10
@@ -21,19 +21,60 @@ Requires-Dist: pathspec
21
21
  Requires-Dist: prompt_toolkit
22
22
  Requires-Dist: requests
23
23
  Requires-Dist: rich
24
+ Requires-Dist: toml
25
+ Provides-Extra: docs
26
+ Requires-Dist: mkdocs>=1.5.3; extra == "docs"
27
+ Requires-Dist: mkdocs-material>=9.4.8; extra == "docs"
24
28
  Dynamic: license-file
25
29
 
26
- # 🚀 Janito: Natural Language Programming Agent
30
+ # 🚀 Janito: Natural Language Coding Agent
27
31
 
28
- **Current Version: 1.6.0**
29
- See [CHANGELOG.md](./CHANGELOG.md) and [RELEASE_NOTES_1.6.md](./RELEASE_NOTES_1.6.md) for details on the latest release.
32
+ **Current Version: 1.7.0**
33
+ See [CHANGELOG.md](./CHANGELOG.md) for details on the latest release.
30
34
 
31
35
  Janito is an AI-powered assistant for the command line and web that interprets natural language system_prompt_template to edit code, manage files, and analyze projects using patterns and tools designed by experienced software engineers. It prioritizes transparency, interactive clarification, and precise, reviewable changes.
32
36
 
33
- For a technical overview, see the [Architecture Guide](docs/ARCHITECTURE.md).
37
+ For a technical overview, see the [Architecture Guide](docs/reference/architecture.md).
38
+
39
+ ## 🧪 Experimental Feature: Liteweb File Viewer
40
+
41
+ Janito now includes an experimental lightweight web file viewer for use with the CLI chat shell. This feature allows you to click on file paths in the terminal (when using a Rich-compatible terminal) and instantly preview file contents in your browser—no full IDE required!
42
+
43
+ ### How to Use
44
+
45
+ - Start the CLI chat shell with the `--termweb` flag:
46
+ ```bash
47
+ janito --termweb
48
+ ```
49
+ - By default, the viewer runs at http://localhost:8088 (or the next available port up to 8100).
50
+ - To specify a port, use `--termweb-port 8090`.
51
+ - File paths in CLI output become clickable links that open the file in your browser.
52
+
53
+ **Note:** This feature is experimental. It is intended for quick file previews and review, not for editing or production use. Feedback is welcome!
54
+
55
+ ### Why is this useful?
56
+ - Enables instant file previews from the CLI without a full IDE.
57
+ - Works with all Janito file tools and outputs that display file paths.
58
+ - Uses the Rich library’s link markup for clickable terminal links.
59
+
60
+ ---
61
+
62
+ ## 📖 Full Documentation & Overview
63
+ - For structured and in-depth guides, visit the [Janito Documentation Site](https://docs.janito.dev).
64
+ - For a high-level, user-friendly overview, see [janito.dev](https://janito.dev).
34
65
 
35
66
  ---
36
67
 
68
+ ## Listing Available Tools
69
+
70
+ To list all registered tools on the command line, use the option:
71
+
72
+ ```sh
73
+ janito --list-tools
74
+ ```
75
+
76
+ This will display a colorful table with the name, description, and parameters of each available tool.
77
+
37
78
  ## ⚡ Quick Start
38
79
 
39
80
  ## 🖥️ Supported Human Interfaces
@@ -81,7 +122,7 @@ janito --web
81
122
  - 📁 **File & Directory Management:** Navigate, create, move, or remove files and folders.
82
123
  - 🧠 **Context-Aware:** Understands your project structure for precise edits.
83
124
  - 💬 **Interactive User Prompts:** Asks for clarification when needed.
84
- - 🧩 **Extensible Tooling:** Built-in tools for file operations, shell commands, directory and file management, Python code execution and validation, text replacement, and more.
125
+ - 🛠️ **Extensible Tooling:** Built-in tools for file operations, shell commands, directory and file management, Python code execution and validation, text replacement, and more.
85
126
  - See [janito/agent/tools/README.md](janito/agent/tools/README.md) for the full list of built-in tools and their usage details. For the message handler model, see [docs/MESSAGE_HANDLER_MODEL.md](docs/MESSAGE_HANDLER_MODEL.md).
86
127
  - 🌐 **Web Interface (In Development):** Simple web UI for streaming responses and tool progress.
87
128
 
@@ -93,7 +134,7 @@ janito --web
93
134
 
94
135
  ### Contributing & Developer Guide
95
136
 
96
- If you want to extend Janito or add new tools, see the [Developer Guide](docs/README_DEV.md) for system_prompt_template, tool registration requirements, and code style guidelines. For the full list of built-in tools and their usage, see the [Tools Reference](janito/agent/tools/README.md).
137
+ If you want to extend Janito or add new tools, see the [Developer Guide](docs/README_DEV.md) for system_prompt_template, tool registration requirements, and code profile guidelines. For the full list of built-in tools and their usage, see the [Tools Reference](janito/agent/tools/README.md).
97
138
 
98
139
 
99
140
 
@@ -130,12 +171,12 @@ For details on using models hosted on Azure OpenAI, see [docs/AZURE_OPENAI.md](d
130
171
 
131
172
  ---
132
173
 
133
- ## 🧩 System Prompt & Role
174
+ ## 🧑‍💻 System Prompt & Role
134
175
 
135
- Janito operates using a system prompt template that defines its behavior, communication style, and capabilities. By default, Janito assumes the role of a "software engineer"—this means its responses and actions are tailored to the expectations and best practices of professional software engineering.
176
+ Janito operates using a system prompt template that defines its behavior, communication profile, and capabilities. By default, Janito assumes the role of a "software engineer"—this means its responses and actions are tailored to the expectations and best practices of professional software engineering.
136
177
 
137
178
  - **Role:** You can customize the agent's role (e.g., "data scientist", "DevOps engineer") using the `--role` flag or config. The default is `software engineer`.
138
- - **System Prompt Template:** The system prompt is rendered from a Jinja2 template (see `janito/agent/templates/system_prompt_template.j2`). This template governs how the agent interprets system_prompt_template, interacts with files, and communicates with users.
179
+ - **System Prompt Template:** The system prompt is rendered from a Jinja2 template (see `janito/agent/templates/prompt_prompt_template.j2`). This template governs how the agent interprets system_prompt_template, interacts with files, and communicates with users.
139
180
  - **Customization & Precedence:** Advanced users can override the system prompt with the `--system` flag (raw string), or point to a custom file using `--system-file`. The precedence is: `--system-file` > `--system`/config > default template.
140
181
 
141
182
  The default template ensures the agent:
@@ -144,7 +185,7 @@ The default template ensures the agent:
144
185
  - Provides concise plans before taking action
145
186
  - Documents any changes made
146
187
 
147
- For more details or to customize the prompt, see the template file at `janito/agent/templates/system_prompt_template.j2` and the architecture overview in [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).
188
+ For more details or to customize the prompt, see the template file at `janito/agent/templates/prompt_prompt_template.j2` and the architecture overview in [docs/reference/architecture.md](docs/reference/architecture.md).
148
189
 
149
190
  ---
150
191
 
@@ -176,18 +217,18 @@ Vanilla mode is ideal for:
176
217
 
177
218
  > Note: Vanilla mode is a runtime switch and does not change the Agent API or class signatures. It is controlled via CLI/config only.
178
219
 
179
- ## 🧑‍💻 AgentProfileManager: Profile, Role, and Prompt Management
220
+ ## 👨‍💻 AgentProfileManager: Profile, Role, and Prompt Management
180
221
 
181
- Janito now uses a dedicated `AgentProfileManager` class to manage user profiles, roles, interaction styles, and system prompt selection. This manager:
182
- - Stores the current role (e.g., "software engineer") and interaction style (e.g., "default", "technical").
183
- - Renders the system prompt from the appropriate template based on interaction style.
222
+ Janito now uses a dedicated `AgentProfileManager` class to manage user profiles, roles, interaction profiles, and system prompt selection. This manager:
223
+ - Stores the current role (e.g., "software engineer") and interaction profile (e.g., "default", "technical").
224
+ - Renders the system prompt from the appropriate template based on interaction profile.
184
225
  - Instantiates and manages the low-level LLM Agent, passing the correct prompt.
185
- - Provides methods to update the role, interaction style, and refresh the prompt at runtime.
226
+ - Provides methods to update the role, interaction profile, and refresh the prompt at runtime.
186
227
 
187
228
  ### Multiple System Prompt Templates
188
- - The system prompt template is now selected based on the interaction style (e.g., `default` or `technical`).
229
+ - The system prompt template is now selected based on the interaction profile (e.g., `default` or `technical`).
189
230
  - Templates are located in `janito/agent/templates/` (see `system_prompt_template.j2` and `system_prompt_template_technical.j2`).
190
- - You can switch interaction styles at runtime using the profile manager, enabling different agent behaviors for different user needs.
231
+ - You can switch interaction profiles at runtime using the profile manager, enabling different agent behaviors for different user needs.
191
232
 
192
233
  This separation ensures that the LLM Agent remains focused on language model interaction and tool execution, while all profile, role, and prompt logic is managed at a higher level.
193
234
 
@@ -195,45 +236,45 @@ See `janito/agent/profile_manager.py` for implementation details.
195
236
 
196
237
  ### Agent Interaction Style
197
238
 
198
- You can control the agent's behavior and prompt style globally or per-project using the `interaction_style` config key. Supported values:
239
+ You can control the agent's behavior and prompt profile globally or per-project using the `profile` config key. See [Prompt Profiles Guide](docs/guides/prompt_profiles.md) for all available styles and combinations.
199
240
  - `default`: Concise, general-purpose agent (default)
200
241
  - `technical`: Strict, workflow-oriented for technical/developer use
201
242
 
202
243
  Set globally:
203
244
  ```bash
204
- janito --set-global-config interaction_style=technical
245
+ janito --set-global-config profile=technical
205
246
  ```
206
247
  Or per-project (in your project root):
207
248
  ```bash
208
- janito --set-local-config interaction_style=technical
249
+ janito --set-local-config profile=technical
209
250
  ```
210
251
 
211
252
  You can also override for a session with the CLI flag:
212
253
  ```bash
213
- janito --style technical
254
+ janito --profile technical
214
255
  ```
215
256
 
216
257
  See [docs/CONFIGURATION.md](docs/CONFIGURATION.md) for full details.
217
258
 
218
- ## 🧩 Combinatorial Style System
259
+ ## 🧑‍💻 Combinatorial Style System
219
260
 
220
- Janito now supports combinatorial styles for system prompts, allowing you to combine a main style (such as `default` or `technical`) with one or more feature extensions (such as `commit_all`).
261
+ Janito now supports combinatorial profiles for system prompts, allowing you to combine a main profile (such as `default` or `technical`) with one or more feature extensions (such as `commit_all`).
221
262
 
222
- - **Main style:** The base agent behavior and workflow (e.g., `default`, `technical`).
223
- - **Feature extensions:** Optional features that override or extend the main style (e.g., `commit_all`).
263
+ - **Main profile:** The base agent behavior and workflow (e.g., `default`, `technical`).
264
+ - **Feature extensions:** Optional features that override or extend the main profile (e.g., `commit_all`).
224
265
  - **Syntax:** Use a hyphen to combine, e.g., `technical-commit_all`.
225
266
 
226
267
  **How it works:**
227
- - The main style template is loaded first.
268
+ - The main profile template is loaded first.
228
269
  - Each feature extension template is layered on top, overriding or extending specific blocks in the main template.
229
270
  - Feature templates must use `{% extends parent_template %}` for dynamic inheritance.
230
271
 
231
272
  **Example usage:**
232
273
  ```bash
233
- janito --style technical-commit_all
274
+ janito --profile technical-commit_all
234
275
  ```
235
276
 
236
- This will apply the `technical` style with the `commit_all` feature enabled in the agent's system prompt.
277
+ This will apply the `technical` profile with the `commit_all` feature enabled in the agent's system prompt.
237
278
 
238
279
  See `janito/render_prompt.py` and `janito/agent/templates/` for implementation details and to create your own feature extensions.
239
280
 
@@ -0,0 +1,127 @@
1
+ janito/__init__.py,sha256=TEX5rBxpQQMGbHlz1RNwQDTVirV3Dy0Px6DtRIL00_0,23
2
+ janito/__main__.py,sha256=KKIoPBE9xPcb54PRYO2UOt0ti04iAwLeJlg8YY36vew,76
3
+ janito/rich_utils.py,sha256=FZEwrRnd_G9dnhBpUus5c40dDs-XDr0tTnIoctZAEME,1128
4
+ janito/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ janito/agent/config.py,sha256=SMpyt9k1LhLn8DimhHcaOFmyk_iexEPnOREM1tWcMow,4616
6
+ janito/agent/config_defaults.py,sha256=mSS_NHNH8FrZOoX61ED8LktfOEUYT84Rfek0Oaue3MA,517
7
+ janito/agent/config_utils.py,sha256=UmvR236wDrMc-aTy9LxVbop6YeoJaaPb1d2DBMlkSRg,254
8
+ janito/agent/content_handler.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ janito/agent/conversation.py,sha256=8i6pm1gsOiE2y__nzBjt7LaigRRrqTtHkx3-SwyX_UE,7326
10
+ janito/agent/conversation_api.py,sha256=q6ZqbHdyo5vkHmXeu51Yfqf6cEjELUUAazew_IxGrHg,8200
11
+ janito/agent/conversation_exceptions.py,sha256=Aw7PRLb3eUfyDOGynKds5F48dgjyiOrTCEcWSprYC58,381
12
+ janito/agent/conversation_tool_calls.py,sha256=CJateY04z27ZHMorb5I4DpaeqFnjhX25uBjg1Foxpb0,1459
13
+ janito/agent/conversation_ui.py,sha256=y4f0IoJQoWGrFMB3yi7uIwXokuTjhFtJGK_R7zcTv3w,397
14
+ janito/agent/event.py,sha256=1jcua88NT-T4jA0mGIyIF1LvqXKu2GDT8NMjlelWmCI,517
15
+ janito/agent/event_dispatcher.py,sha256=eFNDfGY8o63yNLFdMe82LqfmDyGWjrAw9CpyUAcLJAM,856
16
+ janito/agent/event_handler_protocol.py,sha256=uIIf9u82BWm8pha4sZxydeEwgbxDoiWVSyplBPI0knE,130
17
+ janito/agent/event_system.py,sha256=QxPSQ2XeTyiWV6ejcmS8kTqTBrs7fLHRVXdhyeVHpas,608
18
+ janito/agent/message_handler.py,sha256=oZJ2u0C7OewHiHwlJslT2o3RPlvY2HhPXPoRcSsBv4M,856
19
+ janito/agent/message_handler_protocol.py,sha256=E8PLl9ucNvPK_xmhLEkV-vhQzfO_P_BMvzpqDvUkcVY,150
20
+ janito/agent/openai_client.py,sha256=oPbDFQoYzzD7XWw9E_4C_eqERc3Y5DkWyUcYRl7L8cs,4638
21
+ janito/agent/openai_schema_generator.py,sha256=WIE2kQYB0bPe_0IV3vA6OJHoW-uJr5ezHENNkmbH8bg,5762
22
+ janito/agent/platform_discovery.py,sha256=yp6KTvc-_u22Dr8-J4cdjVMUS8HkCf343aeSGRu2wek,2712
23
+ janito/agent/profile_manager.py,sha256=B-bwo1ZhtD2DaVPAfn0bNv1_inoduZhKGd694Pfy5GM,3231
24
+ janito/agent/queued_message_handler.py,sha256=sjsZneGWkqvfuJNac9QERdHasp9lWZvNcow8dul7tVU,1844
25
+ janito/agent/rich_live.py,sha256=NKWU89hRakiJ-0N6FPg40bYREOxQizqicbDv9eUfsKs,927
26
+ janito/agent/rich_message_handler.py,sha256=cSeTvdgHAPoSDddd5kFQNG2RnGj9kYMfuq6nzhtyJuE,2401
27
+ janito/agent/runtime_config.py,sha256=xSx0-RD-WVA9niSCEmEn2ZPLFbQfRhPwwGIa8tid_v8,901
28
+ janito/agent/test_handler_protocols.py,sha256=4o1IitFDUN1fdw48oQCRizKWahahumdmEZ4URHrlmiY,1404
29
+ janito/agent/tool_base.py,sha256=rf88iEX_uZ7MwkeDl4gGMtHeESg0dlFKUo2Jr_ZqDTY,1900
30
+ janito/agent/tool_executor.py,sha256=ltYdegI2-xpFZXVqclh3-Dv-yJEv3vIIuxZjirJovfI,4246
31
+ janito/agent/tool_registry.py,sha256=FlZ8YEoHdk2n7t8vZ26bVbu-fi4UeSE_yu2mZq8pusU,1594
32
+ janito/agent/tool_use_tracker.py,sha256=WJ1Pi5VlzDLrh-iDL3hNTC9IBfqr2QRPaz3n9w32q3o,1546
33
+ janito/agent/templates/profiles/system_prompt_template_base.txt.j2,sha256=-cSdepK7LC-d7iCFOreRnA5aYiaFuUvfrOSMWfz0_4s,676
34
+ janito/agent/templates/profiles/system_prompt_template_base_pt.txt.j2,sha256=FX8piXbR9XNOEKkOSMt4ieZ2wn5fzQlffeQFf8d7gIc,723
35
+ janito/agent/tests/__init__.py,sha256=QuXHKEzUJ_DooaKqenv_tKuNH-HabuIVZhvW5JNaeIc,52
36
+ janito/agent/tools/__init__.py,sha256=ulJfUtzEJFp8iPkpF6wSkNjSwqOZzePPuTY4WuFvIWE,1063
37
+ janito/agent/tools/ask_user.py,sha256=DL-jBU-njSjwhNSbgi23RZCrRBt5beDgZq_PG4yzbWM,3217
38
+ janito/agent/tools/create_directory.py,sha256=KQKt4o9pRu3ruDO9hDOxkcpzuyqxUqKlez5YFudKuXw,2481
39
+ janito/agent/tools/create_file.py,sha256=cmPhLIl_MozLIQZM38yQHC1a5R_jjFh8ZeqlFuWnETQ,3524
40
+ janito/agent/tools/dir_walk_utils.py,sha256=aE2UjCmmpJckcBKujq-1dGUGLWu7ryyAA7EzIbXPVtw,656
41
+ janito/agent/tools/fetch_url.py,sha256=ZJJXk-6avQUX7ezT982LuwrnU0R0Lryo1g1M6_fs3V8,2131
42
+ janito/agent/tools/find_files.py,sha256=n8k1US3_T23uZzXVD5Zx2t_wre1uiLnqUzQMEpGLzh4,3156
43
+ janito/agent/tools/get_lines.py,sha256=rYl9E6w3WKDrO3nhxLofWgYrLjncfD2R6dwUwuF-M6o,5148
44
+ janito/agent/tools/gitignore_utils.py,sha256=fDLyRZmCu6Hqhp1BEN8hs7oG0FtA-1SM9TGDz4g0lbw,1470
45
+ janito/agent/tools/memory.py,sha256=vvFGGTHJkh_SuLIrd1yzrEyGg_jfytVrKNhUhvUpYyA,1745
46
+ janito/agent/tools/move_file.py,sha256=rkiw4sSlhn9DmUcKadg9oMVvjl2jPqNRn-qXSe1zBt0,4339
47
+ janito/agent/tools/present_choices.py,sha256=e7SpOs3RIUXL6zi6PoeFc64akTVVuiQe2yLrm0rKpNs,2327
48
+ janito/agent/tools/present_choices_test.py,sha256=YYFki84vV1FT4MKnBgiwamjZyxUb2g5RDFQKmFF8Vdc,625
49
+ janito/agent/tools/remove_directory.py,sha256=aDNhXkUGHQU8bXIoIXjytYhODQFysjUerApBOOOa-1Y,2409
50
+ janito/agent/tools/remove_file.py,sha256=B5HOFCDhB8AgHgcgzMz_0y10yzPV7BSDrMwVYuMg1i4,2336
51
+ janito/agent/tools/replace_text_in_file.py,sha256=AZGPf4pjgAGqKlvvNdnbVTKZZkOgvyFEokg-5yPYE-w,9435
52
+ janito/agent/tools/rich_live.py,sha256=KpAN-dF0h9LZnYvSK-UKR_sbDnnDw0jUxY3cj_EW_wQ,1215
53
+ janito/agent/tools/run_bash_command.py,sha256=zJ08AC7oRMOTaRs34IVsGw3DuFM_KFicSkxWo6y86dU,7556
54
+ janito/agent/tools/run_powershell_command.py,sha256=Vgy4eghQ_x0AFvzj7n_-scOCzsATBpUAfa9SnIfUSjc,7863
55
+ janito/agent/tools/run_python_command.py,sha256=3cI7Vb63Aeogb0zp5AKqwNF4CysrDSMVXCaBGpeqdqs,7041
56
+ janito/agent/tools/search_outline.py,sha256=ubSvovxCRszrmSZ3NTgrbqadJ_lEAO8ohq910iyd7zw,698
57
+ janito/agent/tools/search_text.py,sha256=eYk70KW24syvdPtFku1-_dpdcM2vgmcu-B37XlcMJ1U,9240
58
+ janito/agent/tools/tools_utils.py,sha256=NNKRfzFpqUR7gS4RKmigO7PM9WAw_M6mkQH1c4rHKDg,2090
59
+ janito/agent/tools/utils.py,sha256=igD1FBUFCmzSxt8WQRbLEYqXngupXrhfdzquYaWv4ng,932
60
+ janito/agent/tools/validate_file_syntax.py,sha256=ngxkb85YwDbraiJXiWwPCA3wTZJTv_KgBu8uv0KuBHY,7558
61
+ janito/agent/tools/outline_file/__init__.py,sha256=Y3UK2zE8UnZyM9mOIKHMr38_8x1BhtYWWsg4luRmOVQ,3315
62
+ janito/agent/tools/outline_file/formatting.py,sha256=AB44kMT6LRVW2fNqX2u2Re7B1Dy3qqObfQHRhcDd9Ow,913
63
+ janito/agent/tools/outline_file/markdown_outline.py,sha256=bXEBg0D93tEBDNy8t-wh4i7WxsxfpQ2C3dX1_rmtj08,434
64
+ janito/agent/tools/outline_file/python_outline.py,sha256=8Y6UYRSSrFmhndwGUTQacVIvFZvPVu8B91oqZhia4q8,2571
65
+ janito/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
+ janito/cli/_print_config.py,sha256=C_27QdwzhqorzeJflBFK0f46zTUtqqmdYe3EBurjOOE,3574
67
+ janito/cli/_utils.py,sha256=tRAUMDWKczd81ZvKYkwpsHWSeLzQoVlOoQ-lOw9Iujw,291
68
+ janito/cli/arg_parser.py,sha256=fnR9hKmQn_aIZz4hT8kr7tq31KDjkkFW-boNsrcPau8,6873
69
+ janito/cli/config_commands.py,sha256=vfU7XciVMRNR5kDvn6tnCo1PLvSEXg0Y0PzLcDEFI9w,8539
70
+ janito/cli/logging_setup.py,sha256=_KLF69xqq1xLPIfkXxy0EIewO-Ef2eYoxNVjqjsC0vc,1361
71
+ janito/cli/main.py,sha256=Njsvs-x22p4WumR0Z4lpG3KwRz18hoSQBdiGAW9Tces,5312
72
+ janito/cli/termweb_starter.py,sha256=Ky9qJPQ8nY3TOeDHmq-IZvWNZa4m68IVeCZqNTQ9RFY,2795
73
+ janito/cli/runner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
74
+ janito/cli/runner/_termweb_log_utils.py,sha256=QpH40uxPhksrJHWqthW4cR7BhcSSYakpza_qTeFGABs,722
75
+ janito/cli/runner/cli_main.py,sha256=Y74v_F39XCCkrv0aAJTXXNZQfdBjoISZYGkefrZNJf8,6880
76
+ janito/cli/runner/config.py,sha256=Nzam25C8P55dFlT_f6IlEj2ZvFwS63AAbnkIWe3oNsg,1702
77
+ janito/cli/runner/formatting.py,sha256=k0mtHoglqR8fKcebSK81iWTT_EL-gDl7eNfjlFZRY6g,287
78
+ janito/cli_chat_shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
79
+ janito/cli_chat_shell/chat_loop.py,sha256=DNuM2VM6FOjcY-2017HCiGeX6hO_9f0iBqlrTO-FpXo,5832
80
+ janito/cli_chat_shell/chat_state.py,sha256=Gf8gyh60SYdD_G5rSwJTKto96UHVaPrQlkRcceoN8yU,1221
81
+ janito/cli_chat_shell/chat_ui.py,sha256=3cw2Mu4u0T60malPy-SXFA3vW0MtGMCQcHAZYO-Irfw,1272
82
+ janito/cli_chat_shell/config_shell.py,sha256=sG04S_z27wI7nXKMaVDcwDpBCuo6Cvd4uhutUQesJKo,3807
83
+ janito/cli_chat_shell/load_prompt.py,sha256=gHedc5TtaFBKiGgwRM_u9nVnBuLHDTSa8VPlPOtoMEA,2125
84
+ janito/cli_chat_shell/session_manager.py,sha256=J3K5fzObwjIDSUfyKOdr8Db2jcoFGf1M4nmtYhQXpq4,2365
85
+ janito/cli_chat_shell/shell_command_completer.py,sha256=bEpfHlMqmGlTeV2wzl0xSungEl1_2eo488qxx5_ia1w,764
86
+ janito/cli_chat_shell/ui.py,sha256=6wqKFSJyILPLnzwoAVpkqFc95Mh8HkLr9DN3Sl6mC-k,7213
87
+ janito/cli_chat_shell/commands/__init__.py,sha256=3rpT6fFPP50qEePRQNOIQmmuU0U7bKRK9DnHZ0pNkNU,1777
88
+ janito/cli_chat_shell/commands/config.py,sha256=JTQwIuSBunxDwvGsU_Cu78GkQNYCtDFTPZ7HOxNOZCY,945
89
+ janito/cli_chat_shell/commands/history_start.py,sha256=JUwxaKatqMWWn0yCC5S2YDVVTfAQCpJG6oPBuW4nYWo,1139
90
+ janito/cli_chat_shell/commands/lang.py,sha256=cG_gX61LUgzv_Bxk-UPTTNF1JQFfcUVaYBnPovUylNw,521
91
+ janito/cli_chat_shell/commands/prompt.py,sha256=YVW1uHfYVPPNvcGoQeHWOwyfpGhCAgSmv670xjRnLs4,1713
92
+ janito/cli_chat_shell/commands/session.py,sha256=64H9UYB-LRSWzMar_C7iNM06MqrKmpRm_Dk9XXIMCiM,1739
93
+ janito/cli_chat_shell/commands/session_control.py,sha256=m4SolmEi7RMHe4WZiUlHQfTIzS0KDT_PYqvnetEm4fs,1398
94
+ janito/cli_chat_shell/commands/sum.py,sha256=S_46ubHUnGoLNwL5_0VeDmA5YYo99aX8baZuBdU1gZ8,1829
95
+ janito/cli_chat_shell/commands/termweb_log.py,sha256=6hU2K-cZUHCC1-l7bBMjyB6illSX_eB28opdGa9dz6g,3219
96
+ janito/cli_chat_shell/commands/utility.py,sha256=PdCkb4UpvyE5jr5o_zZpgfiCXzH4ma_3FjAl2_y0qsU,1145
97
+ janito/cli_chat_shell/commands/verbose.py,sha256=woN1-suIGBnoxTzkoZomOrK6KEl64mDPc0bgO3ToBOI,997
98
+ janito/i18n/__init__.py,sha256=7HYvwOTTf51pVm4adU79rl1FCtAjgOy6GzeShfYCdQY,970
99
+ janito/i18n/messages.py,sha256=fBuwOTFoygyHPkYphm6Y0r1iE8497Z4iryVAmPhMEkg,1851
100
+ janito/i18n/pt.py,sha256=52-ENCIrPW4A1tXFRT28xA8TwuUFoihs6ezJj-m3-Y4,4260
101
+ janito/termweb/app.py,sha256=TO_oWHGqrud4Fhf4DcExc40hCHzyO3P99pZm4oA5INM,3374
102
+ janito/termweb/static/editor.html,sha256=T5IeILW4yFIm5ZbNTqUJjqDldv7ACIdHF8AsZdv7T9M,8859
103
+ janito/termweb/static/editor.html.bak,sha256=rFm5Y_-Rh_03Hs19gzfVu3IBmljIsuPduen2gDKQEyg,8862
104
+ janito/termweb/static/explorer.html.bak,sha256=PM1fcbaQJm545WT94mVEekUNW3jduBAHOz6rwJBR1FA,2568
105
+ janito/termweb/static/favicon.ico,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
106
+ janito/termweb/static/favicon.ico.bak,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
107
+ janito/termweb/static/index.html,sha256=MCCF7ncTEBsE-c829jy3UnkVsIKmnfm0vt3s54cmwcQ,3124
108
+ janito/termweb/static/index.html.bak,sha256=SB6bQFktnZpJzMeo1CzlC82XkYpLcpLnjv1uMS-11FQ,3123
109
+ janito/termweb/static/index.html.bak.bak,sha256=dsKoC2lE0oJCGUUDTWcnIQE3s5Uoqd12WoTkWEwbH_c,6626
110
+ janito/termweb/static/landing.html.bak,sha256=JGwIcATj0B8MhHXLoXg2clypqsKJwi54NtW-rRDUsMs,1403
111
+ janito/termweb/static/termicon.svg,sha256=vc2Z3q-ADVK3pLzE3wnw_qpR6vDguWKEdH_pWObPjbw,229
112
+ janito/termweb/static/termweb.css,sha256=9AxhC2R8CzS82NHg9bk0GD-kxKt_NeRSRFGgTyi-3zI,4870
113
+ janito/termweb/static/termweb.css.bak,sha256=PICa5u6RgaXDg47EGOEn1Yt63k7Wm8mW1vc3zSUU-hs,6004
114
+ janito/termweb/static/termweb.js,sha256=SgXq3FWGl4ltUeQeamT6YRQJ7RFdy9EPaD6iSvq1uSs,9093
115
+ janito/termweb/static/termweb.js.bak,sha256=Y62Uew5kb3I6Fs5hZBcREArymigU7NHHrKdoaswqjyc,9131
116
+ janito/termweb/static/termweb.js.bak.bak,sha256=SQeqc9YwdreCmFJ7LtCYlHOjRHi8rsoW_fZ3x5WroWQ,7692
117
+ janito/termweb/static/termweb_quickopen.js,sha256=HNT85JjWAvjI5ROwukOU-oI4ZVVjCO6yg5IT115pdXI,5379
118
+ janito/termweb/static/termweb_quickopen.js.bak,sha256=sk_zbEw6HJt1iZSAYlaW0qAhq0to-KcBsOKx0AZqkKA,4814
119
+ janito/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
120
+ janito/web/__main__.py,sha256=5Ck6okOZmxKYkQ-ir4mxXDH7XWMNR-9szgsm0UyQLE0,734
121
+ janito/web/app.py,sha256=NarccXYgeYEMvws1lQSGZtArrzJIvw94LSNR0rW9Dq4,7331
122
+ janito-1.8.0.dist-info/licenses/LICENSE,sha256=sHBqv0bvtrb29H7WRR-Z603YHm9pLtJIo3nHU_9cmgE,1091
123
+ janito-1.8.0.dist-info/METADATA,sha256=3F51ULeTzBgxUVFZs5cemk1bX1ZFUfRfzpFr6V0WTK8,12479
124
+ janito-1.8.0.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
125
+ janito-1.8.0.dist-info/entry_points.txt,sha256=wIo5zZxbmu4fC-ZMrsKD0T0vq7IqkOOLYhrqRGypkx4,48
126
+ janito-1.8.0.dist-info/top_level.txt,sha256=m0NaVCq0-ivxbazE2-ND0EA9Hmuijj_OGkmCbnBcCig,7
127
+ janito-1.8.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (79.0.0)
2
+ Generator: setuptools (80.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,2 +0,0 @@
1
- # This file is now unused. All tool registry logic has been consolidated into tool_registry.py.
2
- # Kept for backward compatibility only. Do not use.
@@ -1,117 +0,0 @@
1
- from janito.agent.tool_base import ToolBase
2
- from janito.agent.tool_registry import register_tool
3
- import os
4
- import re
5
- from typing import List
6
-
7
-
8
- @register_tool(name="get_file_outline")
9
- class GetFileOutlineTool(ToolBase):
10
- """
11
- Get an outline of a file's structure.
12
-
13
- Note:
14
- The outline extraction for Python files is based on regular expression (regex) pattern matching for class and function definitions.
15
- This approach may not capture all edge cases or non-standard code structures. For complex files, further examination or more advanced parsing may be required.
16
-
17
- Args:
18
- file_path (str): Path to the file.
19
- Returns:
20
- str: Outline of the file's structure, starting with a summary line. Example:
21
- - "Outline: 5 items (python)\n| Type | Name | Start | End | Parent |\n|---------|-------------|-------|-----|----------|\n| class | MyClass | 1 | 20 | |\n| method | my_method | 3 | 10 | MyClass |\n| function| my_func | 22 | 30 | |\n..."
22
- - "Outline: 100 lines (default)\nFile has 100 lines."
23
- - "Error reading file: <error message>"
24
- """
25
-
26
- def call(self, file_path: str) -> str:
27
- from janito.agent.tools.tools_utils import display_path
28
-
29
- disp_path = display_path(file_path)
30
- self.report_info(f"📄 Getting outline for: {disp_path}")
31
-
32
- try:
33
- ext = os.path.splitext(file_path)[1].lower()
34
- with open(file_path, "r", encoding="utf-8", errors="replace") as f:
35
- lines = f.readlines()
36
- if ext == ".py":
37
- outline_items = self._parse_python_outline(lines)
38
- outline_type = "python"
39
- table = self._format_outline_table(outline_items)
40
- self.report_success(f"✅ {len(outline_items)} items ({outline_type})")
41
- return f"Outline: {len(outline_items)} items ({outline_type})\n" + table
42
- else:
43
- outline_type = "default"
44
- self.report_success(f"✅ {len(lines)} lines ({outline_type})")
45
- return f"Outline: {len(lines)} lines ({outline_type})\nFile has {len(lines)} lines."
46
- except Exception as e:
47
- self.report_error(f"❌ Error reading file: {e}")
48
- return f"Error reading file: {e}"
49
-
50
- def _parse_python_outline(self, lines: List[str]):
51
- # Regex for class, function, and method definitions
52
- class_pat = re.compile(r"^(\s*)class\s+(\w+)")
53
- func_pat = re.compile(r"^(\s*)def\s+(\w+)")
54
- outline = []
55
- stack = [] # (name, type, indent, start, parent)
56
- for idx, line in enumerate(lines):
57
- class_match = class_pat.match(line)
58
- func_match = func_pat.match(line)
59
- indent = len(line) - len(line.lstrip())
60
- if class_match:
61
- name = class_match.group(2)
62
- parent = stack[-1][1] if stack and stack[-1][0] == "class" else ""
63
- stack.append(("class", name, indent, idx + 1, parent))
64
- elif func_match:
65
- name = func_match.group(2)
66
- parent = (
67
- stack[-1][1]
68
- if stack
69
- and stack[-1][0] in ("class", "function")
70
- and indent > stack[-1][2]
71
- else ""
72
- )
73
- stack.append(("function", name, indent, idx + 1, parent))
74
- # Pop stack if indentation decreases
75
- while stack and indent < stack[-1][2]:
76
- popped = stack.pop()
77
- outline.append(
78
- {
79
- "type": (
80
- popped[0]
81
- if popped[0] != "function" or popped[3] == 1
82
- else ("method" if popped[4] else "function")
83
- ),
84
- "name": popped[1],
85
- # Add end line for popped item
86
- "start": popped[3],
87
- "end": idx,
88
- "parent": popped[4],
89
- }
90
- )
91
- # Pop any remaining items in the stack at EOF
92
- for popped in stack:
93
- outline.append(
94
- {
95
- "type": (
96
- popped[0]
97
- if popped[0] != "function" or popped[3] == 1
98
- else ("method" if popped[4] else "function")
99
- ),
100
- "name": popped[1],
101
- "start": popped[3],
102
- "end": len(lines),
103
- "parent": popped[4],
104
- }
105
- )
106
- return outline
107
-
108
- def _format_outline_table(self, outline_items):
109
- if not outline_items:
110
- return "No classes or functions found."
111
- header = "| Type | Name | Start | End | Parent |\n|---------|-------------|-------|-----|----------|"
112
- rows = []
113
- for item in outline_items:
114
- rows.append(
115
- f"| {item['type']:<7} | {item['name']:<11} | {item['start']:<5} | {item['end']:<3} | {item['parent']:<8} |"
116
- )
117
- return header + "\n" + "\n".join(rows)
@@ -1,40 +0,0 @@
1
- from janito.agent.tool_base import ToolBase
2
- from janito.agent.tool_registry import register_tool
3
-
4
- from typing import Optional
5
- import py_compile
6
-
7
-
8
- @register_tool(name="py_compile_file")
9
- class PyCompileFileTool(ToolBase):
10
- """
11
- Validate a Python file by compiling it with py_compile.
12
- Useful to validate python files after changing them, especially after import changes.
13
-
14
- Args:
15
- file_path (str): Path to the Python file to compile.
16
- doraise (bool, optional): Whether to raise exceptions on compilation errors. Defaults to True.
17
- Returns:
18
- str: Compilation status message. Example:
19
- - "✅ Compiled"
20
- - "Compile error: <error message>"
21
- - "Error: <error message>"
22
- """
23
-
24
- def call(self, file_path: str, doraise: Optional[bool] = True) -> str:
25
- self.report_info(f"🛠️ Compiling Python file: {file_path}")
26
-
27
- if not (file_path.endswith(".py") or file_path.endswith(".pyw")):
28
- msg = f"Error: {file_path} is not a Python (.py/.pyw) file."
29
- self.report_error(f" [py_compile_file] {msg}")
30
- return msg
31
- try:
32
- py_compile.compile(file_path, doraise=doraise)
33
- self.report_success(" ✅ Compiled")
34
- return "✅ Compiled"
35
- except py_compile.PyCompileError as e:
36
- self.report_error(f" [py_compile_file] Compile error: {e}")
37
- return f"Compile error: {e}"
38
- except Exception as e:
39
- self.report_error(f" [py_compile_file] Error: {e}")
40
- return f"Error: {e}"
@@ -1,51 +0,0 @@
1
- import os
2
- import shutil
3
- from janito.agent.tool_registry import register_tool
4
- from janito.agent.tools.utils import expand_path, display_path
5
- from janito.agent.tool_base import ToolBase
6
-
7
-
8
- @register_tool(name="replace_file")
9
- class ReplaceFileTool(ToolBase):
10
- """
11
- Overwrite (replace) a file with the given content. Creates the file if it does not exist.
12
-
13
- Args:
14
- path (str): Path to the file to overwrite or create.
15
- content (str): Content to write to the file.
16
- backup (bool, optional): If True, create a backup (.bak) before replacing if the file exists. Recommend using backup=True only in the first call to avoid redundant backups. Defaults to False.
17
- Returns:
18
- str: Status message indicating the result. Example:
19
- - "\u2705 Successfully replaced the file at ..."
20
- - "\u2705 Successfully created the file at ..."
21
- """
22
-
23
- def call(self, path: str, content: str, backup: bool = False) -> str:
24
- original_path = path
25
- path = expand_path(path)
26
- disp_path = display_path(original_path, path)
27
- updating = os.path.exists(path) and not os.path.isdir(path)
28
- if os.path.exists(path) and os.path.isdir(path):
29
- self.report_error("\u274c Error: is a directory")
30
- return (
31
- f"\u274c Cannot replace file: '{disp_path}' is an existing directory."
32
- )
33
- # Ensure parent directories exist
34
- dir_name = os.path.dirname(path)
35
- if dir_name:
36
- os.makedirs(dir_name, exist_ok=True)
37
- if backup and os.path.exists(path) and not os.path.isdir(path):
38
- shutil.copy2(path, path + ".bak")
39
- with open(path, "w", encoding="utf-8", errors="replace") as f:
40
- f.write(content)
41
- new_lines = content.count("\n") + 1 if content else 0
42
- if updating:
43
- self.report_success(
44
- f"\u2705 Successfully replaced the file at '{disp_path}' ({new_lines} lines)."
45
- )
46
- return f"\u2705 Successfully replaced the file at '{disp_path}' ({new_lines} lines)."
47
- else:
48
- self.report_success(
49
- f"\u2705 Successfully created the file at '{disp_path}' ({new_lines} lines)."
50
- )
51
- return f"\u2705 Successfully created the file at '{disp_path}' ({new_lines} lines)."
@@ -1,71 +0,0 @@
1
- from janito.agent.tool_base import ToolBase
2
- from janito.agent.tool_registry import register_tool
3
- from janito.agent.tools.tools_utils import pluralize
4
-
5
- import os
6
- from janito.agent.tools.gitignore_utils import filter_ignored
7
-
8
-
9
- @register_tool(name="search_files")
10
- class SearchFilesTool(ToolBase):
11
- """
12
- Search for a text pattern in all files within a directory and return matching lines. Respects .gitignore.
13
-
14
- Args:
15
- directories (list[str]): List of directories to search in.
16
- pattern (str): Plain text substring to search for in files. (Not a regular expression or glob pattern.)
17
- recursive (bool): Whether to search recursively in subdirectories. Defaults to True.
18
- max_depth (int, optional): Maximum directory depth to search (0 = only top-level). If None, unlimited. Defaults to None.
19
- Returns:
20
- str: Matching lines from files as a newline-separated string, each formatted as 'filepath:lineno: line'. Example:
21
- - "/path/to/file.py:10: def my_function():"
22
- - "Warning: Empty search pattern provided. Operation skipped."
23
- """
24
-
25
- def call(
26
- self,
27
- directories: list[str],
28
- pattern: str,
29
- recursive: bool = True,
30
- max_depth: int = None,
31
- ) -> str:
32
- if not pattern:
33
- self.report_warning(
34
- "⚠️ Warning: Empty search pattern provided. Operation skipped."
35
- )
36
- return "Warning: Empty search pattern provided. Operation skipped."
37
- output = []
38
- for directory in directories:
39
- info_str = f"🔎 Searching for text '{pattern}' in '{directory}'"
40
- if recursive is False:
41
- info_str += f" (recursive={recursive})"
42
- self.report_info(info_str)
43
- if recursive:
44
- walker = os.walk(directory)
45
- else:
46
- # Only the top directory, not recursive
47
- dirs, files = filter_ignored(
48
- directory, *os.walk(directory).__next__()[1:]
49
- )
50
- walker = [(directory, dirs, files)]
51
- for root, dirs, files in walker:
52
- # Calculate depth
53
- rel_path = os.path.relpath(root, directory)
54
- depth = 0 if rel_path == "." else rel_path.count(os.sep) + 1
55
- if max_depth is not None and depth > max_depth:
56
- dirs[:] = []
57
- continue
58
- if not recursive and depth > 0:
59
- break
60
- dirs, files = filter_ignored(root, dirs, files)
61
- for filename in files:
62
- path = os.path.join(root, filename)
63
- try:
64
- with open(path, "r", encoding="utf-8", errors="ignore") as f:
65
- for lineno, line in enumerate(f, 1):
66
- if pattern in line:
67
- output.append(f"{path}:{lineno}: {line.strip()}")
68
- except Exception:
69
- continue
70
- self.report_success(f" ✅ {len(output)} {pluralize('line', len(output))} found")
71
- return "\n".join(output)