aru-code 0.24.2__tar.gz → 0.25.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. {aru_code-0.24.2/aru_code.egg-info → aru_code-0.25.1}/PKG-INFO +2 -2
  2. {aru_code-0.24.2 → aru_code-0.25.1}/README.md +1 -1
  3. aru_code-0.25.1/aru/__init__.py +1 -0
  4. {aru_code-0.24.2 → aru_code-0.25.1}/aru/agents/base.py +54 -13
  5. {aru_code-0.24.2 → aru_code-0.25.1}/aru/agents/explorer.py +16 -14
  6. {aru_code-0.24.2 → aru_code-0.25.1}/aru/agents/planner.py +7 -3
  7. {aru_code-0.24.2 → aru_code-0.25.1}/aru/display.py +8 -4
  8. {aru_code-0.24.2 → aru_code-0.25.1}/aru/tools/codebase.py +564 -191
  9. {aru_code-0.24.2 → aru_code-0.25.1}/aru/tools/gitignore.py +76 -11
  10. {aru_code-0.24.2 → aru_code-0.25.1}/aru/tools/ranker.py +83 -16
  11. {aru_code-0.24.2 → aru_code-0.25.1/aru_code.egg-info}/PKG-INFO +2 -2
  12. {aru_code-0.24.2 → aru_code-0.25.1}/pyproject.toml +1 -1
  13. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_codebase.py +68 -101
  14. aru_code-0.24.2/aru/__init__.py +0 -1
  15. {aru_code-0.24.2 → aru_code-0.25.1}/LICENSE +0 -0
  16. {aru_code-0.24.2 → aru_code-0.25.1}/aru/agent_factory.py +0 -0
  17. {aru_code-0.24.2 → aru_code-0.25.1}/aru/agents/__init__.py +0 -0
  18. {aru_code-0.24.2 → aru_code-0.25.1}/aru/agents/executor.py +0 -0
  19. {aru_code-0.24.2 → aru_code-0.25.1}/aru/cache_patch.py +0 -0
  20. {aru_code-0.24.2 → aru_code-0.25.1}/aru/checkpoints.py +0 -0
  21. {aru_code-0.24.2 → aru_code-0.25.1}/aru/cli.py +0 -0
  22. {aru_code-0.24.2 → aru_code-0.25.1}/aru/commands.py +0 -0
  23. {aru_code-0.24.2 → aru_code-0.25.1}/aru/completers.py +0 -0
  24. {aru_code-0.24.2 → aru_code-0.25.1}/aru/config.py +0 -0
  25. {aru_code-0.24.2 → aru_code-0.25.1}/aru/context.py +0 -0
  26. {aru_code-0.24.2 → aru_code-0.25.1}/aru/history_blocks.py +0 -0
  27. {aru_code-0.24.2 → aru_code-0.25.1}/aru/permissions.py +0 -0
  28. {aru_code-0.24.2 → aru_code-0.25.1}/aru/plugins/__init__.py +0 -0
  29. {aru_code-0.24.2 → aru_code-0.25.1}/aru/plugins/custom_tools.py +0 -0
  30. {aru_code-0.24.2 → aru_code-0.25.1}/aru/plugins/hooks.py +0 -0
  31. {aru_code-0.24.2 → aru_code-0.25.1}/aru/plugins/manager.py +0 -0
  32. {aru_code-0.24.2 → aru_code-0.25.1}/aru/plugins/tool_api.py +0 -0
  33. {aru_code-0.24.2 → aru_code-0.25.1}/aru/providers.py +0 -0
  34. {aru_code-0.24.2 → aru_code-0.25.1}/aru/runner.py +0 -0
  35. {aru_code-0.24.2 → aru_code-0.25.1}/aru/runtime.py +0 -0
  36. {aru_code-0.24.2 → aru_code-0.25.1}/aru/session.py +0 -0
  37. {aru_code-0.24.2 → aru_code-0.25.1}/aru/tools/__init__.py +0 -0
  38. {aru_code-0.24.2 → aru_code-0.25.1}/aru/tools/ast_tools.py +0 -0
  39. {aru_code-0.24.2 → aru_code-0.25.1}/aru/tools/mcp_client.py +0 -0
  40. {aru_code-0.24.2 → aru_code-0.25.1}/aru/tools/tasklist.py +0 -0
  41. {aru_code-0.24.2 → aru_code-0.25.1}/aru_code.egg-info/SOURCES.txt +0 -0
  42. {aru_code-0.24.2 → aru_code-0.25.1}/aru_code.egg-info/dependency_links.txt +0 -0
  43. {aru_code-0.24.2 → aru_code-0.25.1}/aru_code.egg-info/entry_points.txt +0 -0
  44. {aru_code-0.24.2 → aru_code-0.25.1}/aru_code.egg-info/requires.txt +0 -0
  45. {aru_code-0.24.2 → aru_code-0.25.1}/aru_code.egg-info/top_level.txt +0 -0
  46. {aru_code-0.24.2 → aru_code-0.25.1}/setup.cfg +0 -0
  47. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_agents_base.py +0 -0
  48. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_checkpoints.py +0 -0
  49. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli.py +0 -0
  50. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli_advanced.py +0 -0
  51. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli_base.py +0 -0
  52. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli_completers.py +0 -0
  53. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli_new.py +0 -0
  54. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli_run_cli.py +0 -0
  55. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli_session.py +0 -0
  56. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli_shell.py +0 -0
  57. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_confabulation_regression.py +0 -0
  58. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_config.py +0 -0
  59. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_context.py +0 -0
  60. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_executor.py +0 -0
  61. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_gitignore.py +0 -0
  62. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_guardrails_scenarios.py +0 -0
  63. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_main.py +0 -0
  64. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_mcp_client.py +0 -0
  65. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_permissions.py +0 -0
  66. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_planner.py +0 -0
  67. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_plugins.py +0 -0
  68. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_providers.py +0 -0
  69. {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_ranker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aru-code
3
- Version: 0.24.2
3
+ Version: 0.25.1
4
4
  Summary: A Claude Code clone built with Agno agents
5
5
  Author-email: Estevao <estevaofon@gmail.com>
6
6
  License-Expression: MIT
@@ -519,7 +519,7 @@ Aru can load tools from MCP servers. Configure in `.aru/mcp_config.json`:
519
519
 
520
520
  ### File Operations
521
521
  - `read_file` — Reads files with line range support and binary detection
522
- - `read_file_smart` — Answers specific questions about a file without returning raw content
522
+ - `read_files` — Reads multiple files in parallel (single batched call)
523
523
  - `write_file` — Writes content to files, creating directories as needed
524
524
  - `edit_file` — Find-and-replace edits on files
525
525
 
@@ -472,7 +472,7 @@ Aru can load tools from MCP servers. Configure in `.aru/mcp_config.json`:
472
472
 
473
473
  ### File Operations
474
474
  - `read_file` — Reads files with line range support and binary detection
475
- - `read_file_smart` — Answers specific questions about a file without returning raw content
475
+ - `read_files` — Reads multiple files in parallel (single batched call)
476
476
  - `write_file` — Writes content to files, creating directories as needed
477
477
  - `edit_file` — Find-and-replace edits on files
478
478
 
@@ -0,0 +1 @@
1
+ __version__ = "0.25.1"
@@ -66,8 +66,8 @@ Every tool call accumulates its result in your context window. Use the minimum n
66
66
 
67
67
  1. **Find files/patterns** → `grep_search(pattern, file_glob="*.py")` or `glob_search`. \
68
68
  Default shows 10 lines of context — use `context_lines=30` for full function bodies.
69
- 2. **Understand a file** → `read_file_smart(file_path, query)` — returns a concise answer, not raw content
70
- 3. **Need raw content** → `read_file(file_path)` — returns first chunk + outline for large files
69
+ 2. **Need raw content** → `read_file(file_path)` — returns first chunk + outline for large files
70
+ 3. **Need several files at once** → `read_files(paths)` — parallel batch read
71
71
 
72
72
  **Batch independent tool calls**: When you need answers from multiple independent sources, \
73
73
  emit ALL those tool calls in a single response.
@@ -139,19 +139,40 @@ split into subtasks grouped by concern (e.g. "Create model files", "Create route
139
139
  - Read files before editing them
140
140
  - Use edit_file for targeted changes (preferred over rewriting entire files)
141
141
  - Use write_file only for new files or complete rewrites
142
- - Run existing tests after changes when applicable
143
- - **When adding or modifying unit tests, ALWAYS run them to verify they pass before finishing.**
144
142
  - Keep changes minimal and focused on the task
145
143
  - Do not add unnecessary comments, docstrings, or refactoring beyond what was asked
146
144
  - **One ask = one deliverable.** If asked for one function, write one function. \
147
145
  Helper functions are NOT implicit — do not add them unless explicitly requested.
148
146
 
147
+ ## Verification — run it before claiming done
148
+
149
+ Never mark a task done on faith. Prove the change works by running something that \
150
+ exercises it — invoke the function, trigger the code path, fire the test, and read \
151
+ what comes back. Editing a file is not the same as confirming the edit is correct. \
152
+ When running something is genuinely impossible (no runnable harness, sandbox blocks \
153
+ execution, external service unreachable), state that limitation plainly instead of \
154
+ calling the work done.
155
+
156
+ Concrete patterns:
157
+ - **After a bug fix**: reproduce the failing case and confirm it now passes.
158
+ - **After writing a plugin/tool/module**: invoke it inline with a realistic input and \
159
+ inspect the output — don't stop at "it imports". Use `bash` to run a one-shot probe, \
160
+ e.g. `python -c "from mod import fn; print(repr(fn(<realistic input>)))"`, read the \
161
+ `repr()`, and iterate until it matches expectations.
162
+ - **After a refactor**: run the existing test suite — or if none exists, exercise the \
163
+ changed path manually and read the result.
164
+ - **After adding or modifying unit tests**: ALWAYS run them before finishing.
165
+
166
+ A good colleague doesn't stop at "it compiles" — they run it, read the output, and fix \
167
+ the gap between what they wrote and what they meant. Each bug surfaced by a 10-second \
168
+ inline probe is a bug the user never has to report.
169
+
149
170
  ## Reading strategy — read, edit, test
150
171
 
151
- 1. **Know the file + have a question?** → `read_file_smart(file_path, query)`
152
- 2. **Need a specific pattern?** → `grep_search(pattern, file_glob="*.py")` — default 10 lines context. \
172
+ 1. **Need a specific pattern?** → `grep_search(pattern, file_glob="*.py")` — default 10 lines context. \
153
173
  Use `context_lines=30` for full function bodies.
154
- 3. **Need lines for editing?** → `read_file(file_path, start_line=N, end_line=M)` using line numbers from grep
174
+ 2. **Need lines for editing?** → `read_file(file_path, start_line=N, end_line=M)` using line numbers from grep
175
+ 3. **Need several files at once?** → `read_files(paths)` — parallel batch read
155
176
  4. **Need the whole file?** → `read_file(file_path)` — returns first chunk + outline for large files
156
177
  5. **Need the COMPLETE file (>60KB)?** → `read_file(file_path, max_size=0)` — reads in chunks. Use rarely.
157
178
 
@@ -194,10 +215,9 @@ Skip exploration when the task is clear and the relevant files are obvious.
194
215
 
195
216
  Every tool call accumulates its result in your context window. Use the minimum needed:
196
217
 
197
- 1. **Don't know which file?** → `grep_search` / `glob_search` for patterns, \
198
- `read_file_smart(file_path, query)` when you know the file.
199
- 2. **Know the file + have a question?** → `read_file_smart(file_path, query)`
200
- 3. **Need specific lines?** → `read_file(file_path, start_line=N, end_line=M)`
218
+ 1. **Don't know which file?** → `grep_search` / `glob_search` for patterns.
219
+ 2. **Need specific lines?** → `read_file(file_path, start_line=N, end_line=M)`
220
+ 3. **Need several files at once?** → `read_files(paths)` — parallel batch read.
201
221
  4. **Need the whole file?** → `read_file(file_path)` — returns first chunk + outline for large files.
202
222
 
203
223
  **NEVER read the same file twice.** Check if you already have the content in context.
@@ -209,7 +229,28 @@ Every tool call accumulates its result in your context window. Use the minimum n
209
229
  **Stop early**: Once you have enough information to act, stop exploring and start working. \
210
230
  Batch what you need upfront, then execute.
211
231
 
212
- **When adding or modifying unit tests, ALWAYS run them to verify they pass before finishing.**
232
+ ## Verification run it before claiming done
233
+
234
+ Never mark a task done on faith. Prove the change works by running something that \
235
+ exercises it — invoke the function, trigger the code path, fire the test, and read \
236
+ what comes back. Editing a file is not the same as confirming the edit is correct. \
237
+ When running something is genuinely impossible (no runnable harness, sandbox blocks \
238
+ execution, external service unreachable), state that limitation plainly instead of \
239
+ calling the work done.
240
+
241
+ Concrete patterns:
242
+ - **After a bug fix**: reproduce the failing case and confirm it now passes.
243
+ - **After writing a plugin/tool/module**: invoke it inline with a realistic input and \
244
+ inspect the output — don't stop at "it imports". Use `bash` to run a one-shot probe, \
245
+ e.g. `python -c "from mod import fn; print(repr(fn(<realistic input>)))"`, read the \
246
+ `repr()`, and iterate until it matches expectations.
247
+ - **After a refactor**: run the existing test suite — or if none exists, exercise the \
248
+ changed path manually and read the result.
249
+ - **After adding or modifying unit tests**: ALWAYS run them before finishing.
250
+
251
+ A good colleague doesn't stop at "it compiles" — they run it, read the output, and fix \
252
+ the gap between what they wrote and what they meant. Each bug surfaced by a 10-second \
253
+ inline probe is a bug the user never has to report.
213
254
 
214
255
  ## Delegation strategy — CRITICAL for context efficiency
215
256
 
@@ -218,7 +259,7 @@ For simple, directed lookups (one known file, one specific symbol) use \
218
259
 
219
260
  For **anything broader** — understanding a system, researching before implementing, \
220
261
  analyzing multiple files, writing specs or documentation — **always use explorer agents**. \
221
- Every `read_file` / `read_file_smart` / `grep_search` result you call directly accumulates \
262
+ Every `read_file` / `read_files` / `grep_search` result you call directly accumulates \
222
263
  in YOUR context window and stays there forever. Explorer agents read files in their own \
223
264
  isolated context and return only a concise summary. This is critical: \
224
265
  **3 explorer summaries < 8 raw file reads** in context cost.
@@ -7,24 +7,26 @@ from agno.agent import Agent
7
7
  from aru.providers import create_model
8
8
  from aru.runtime import get_ctx
9
9
  from aru.tools.codebase import (
10
+ _glob_search_tool,
11
+ _grep_search_tool,
12
+ _list_directory_tool,
13
+ _rank_files_tool,
14
+ _read_file_tool,
10
15
  bash,
11
- glob_search,
12
- grep_search,
13
- list_directory,
14
- rank_files,
15
- read_file,
16
- read_file_smart,
16
+ read_files,
17
17
  )
18
18
 
19
- # Read-only tools only — no write/edit/delegate (prevents recursion and mutations)
19
+ # Read-only tools only — no write/edit/delegate (prevents recursion and mutations).
20
+ # All wrappers are async so the Explorer's "multi-parallel tool calls" prompt
21
+ # actually matches runtime behavior — Agno can await them concurrently.
20
22
  EXPLORER_TOOLS = [
21
- read_file,
22
- read_file_smart,
23
- glob_search,
24
- grep_search,
25
- list_directory,
23
+ _read_file_tool,
24
+ read_files,
25
+ _glob_search_tool,
26
+ _grep_search_tool,
27
+ _list_directory_tool,
26
28
  bash,
27
- rank_files,
29
+ _rank_files_tool,
28
30
  ]
29
31
 
30
32
  EXPLORER_ROLE = """\
@@ -52,7 +54,7 @@ Guidelines:
52
54
  - Use glob_search for broad file pattern matching
53
55
  - Use grep_search for searching file contents with regex
54
56
  - Use read_file when you know the specific file path you need to read
55
- - Use read_file_smart when you know the file and have a specific question about it
57
+ - Use read_files (batch) when you need to pull several files at once
56
58
  - Use bash ONLY for read-only operations (ls, git status, git log, git diff, find, cat, head, tail)
57
59
  - NEVER use bash for: mkdir, touch, rm, cp, mv, git add, git commit, npm install, pip install, \
58
60
  or any file creation/modification
@@ -6,7 +6,11 @@ from agno.compression.manager import CompressionManager
6
6
  from aru.agents.base import build_instructions
7
7
  from aru.providers import create_model
8
8
  from aru.tools.codebase import (
9
- glob_search, grep_search, list_directory, read_file, read_file_smart,
9
+ _glob_search_tool,
10
+ _grep_search_tool,
11
+ _list_directory_tool,
12
+ _read_file_tool,
13
+ read_files,
10
14
  )
11
15
  from aru.runtime import get_ctx
12
16
 
@@ -34,8 +38,8 @@ Return ONLY the markdown plan. No explanation, no preamble.\
34
38
 
35
39
  # Planner uses read-only tools only — no write/edit/bash
36
40
  PLANNER_TOOLS = [
37
- read_file, read_file_smart,
38
- glob_search, grep_search, list_directory,
41
+ _read_file_tool, read_files,
42
+ _glob_search_tool, _grep_search_tool, _list_directory_tool,
39
43
  ]
40
44
 
41
45
 
@@ -161,6 +161,10 @@ class StatusBar:
161
161
  self._index = 0
162
162
  self._last_switch = time.monotonic()
163
163
  self._override: str | None = None
164
+ # A single persistent Spinner — Rich's Spinner tracks frames via
165
+ # (time - start_time), so instantiating a new one per render would
166
+ # reset start_time each frame and make the animation look frozen.
167
+ self._spinner = Spinner("dots", text="", style="cyan")
164
168
 
165
169
  @property
166
170
  def current_text(self) -> str:
@@ -187,8 +191,8 @@ class StatusBar:
187
191
 
188
192
  def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderResult:
189
193
  self._maybe_rotate()
190
- spinner = Spinner("dots", text=f"[dim]{self.current_text}[/dim]", style="cyan")
191
- yield from spinner.__rich_console__(console, options)
194
+ self._spinner.update(text=Text(self.current_text, style="dim"))
195
+ yield from self._spinner.__rich_console__(console, options)
192
196
 
193
197
  def __rich_measure__(self, console: Console, options: ConsoleOptions) -> Measurement:
194
198
  return Measurement(1, options.max_width)
@@ -196,7 +200,7 @@ class StatusBar:
196
200
 
197
201
  TOOL_DISPLAY_NAMES = {
198
202
  "read_file": "Read",
199
- "read_file_smart": "ReadSmart",
203
+ "read_files": "ReadBatch",
200
204
  "write_file": "Write",
201
205
  "edit_file": "Edit",
202
206
  "glob_search": "Glob",
@@ -209,7 +213,7 @@ TOOL_DISPLAY_NAMES = {
209
213
 
210
214
  TOOL_PRIMARY_ARG = {
211
215
  "read_file": "file_path",
212
- "read_file_smart": "file_path",
216
+ "read_files": "paths",
213
217
  "write_file": "file_path",
214
218
  "edit_file": "file_path",
215
219
  "glob_search": "pattern",