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.
- {aru_code-0.24.2/aru_code.egg-info → aru_code-0.25.1}/PKG-INFO +2 -2
- {aru_code-0.24.2 → aru_code-0.25.1}/README.md +1 -1
- aru_code-0.25.1/aru/__init__.py +1 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/agents/base.py +54 -13
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/agents/explorer.py +16 -14
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/agents/planner.py +7 -3
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/display.py +8 -4
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/tools/codebase.py +564 -191
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/tools/gitignore.py +76 -11
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/tools/ranker.py +83 -16
- {aru_code-0.24.2 → aru_code-0.25.1/aru_code.egg-info}/PKG-INFO +2 -2
- {aru_code-0.24.2 → aru_code-0.25.1}/pyproject.toml +1 -1
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_codebase.py +68 -101
- aru_code-0.24.2/aru/__init__.py +0 -1
- {aru_code-0.24.2 → aru_code-0.25.1}/LICENSE +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/agent_factory.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/agents/__init__.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/agents/executor.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/cache_patch.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/checkpoints.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/cli.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/commands.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/completers.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/config.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/context.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/history_blocks.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/permissions.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/plugins/__init__.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/plugins/custom_tools.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/plugins/hooks.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/plugins/manager.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/plugins/tool_api.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/providers.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/runner.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/runtime.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/session.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/tools/__init__.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/tools/ast_tools.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/tools/mcp_client.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru/tools/tasklist.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru_code.egg-info/SOURCES.txt +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru_code.egg-info/dependency_links.txt +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru_code.egg-info/entry_points.txt +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru_code.egg-info/requires.txt +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/aru_code.egg-info/top_level.txt +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/setup.cfg +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_agents_base.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_checkpoints.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli_advanced.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli_base.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli_completers.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli_new.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli_run_cli.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli_session.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_cli_shell.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_confabulation_regression.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_config.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_context.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_executor.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_gitignore.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_guardrails_scenarios.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_main.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_mcp_client.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_permissions.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_planner.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_plugins.py +0 -0
- {aru_code-0.24.2 → aru_code-0.25.1}/tests/test_providers.py +0 -0
- {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.
|
|
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
|
-
- `
|
|
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
|
-
- `
|
|
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. **
|
|
70
|
-
3. **Need
|
|
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. **
|
|
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
|
-
|
|
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
|
-
`
|
|
199
|
-
|
|
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
|
-
|
|
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` / `
|
|
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
|
-
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
_read_file_tool,
|
|
24
|
+
read_files,
|
|
25
|
+
_glob_search_tool,
|
|
26
|
+
_grep_search_tool,
|
|
27
|
+
_list_directory_tool,
|
|
26
28
|
bash,
|
|
27
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
38
|
-
|
|
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
|
-
|
|
191
|
-
yield from
|
|
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
|
-
"
|
|
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
|
-
"
|
|
216
|
+
"read_files": "paths",
|
|
213
217
|
"write_file": "file_path",
|
|
214
218
|
"edit_file": "file_path",
|
|
215
219
|
"glob_search": "pattern",
|