Skip to content

Commit 22f9166

Browse files
ZhiXiao-Linclaude
andauthored
feat(tools): add context-efficient repository operations (#46)
* feat(tools): add context-efficient repository operations * test(mcp): remove process-group teardown race * chore(release): prepare 6.5.0 * docs: document repository-context tool modes --------- Co-authored-by: Claude <claude@anthropic.com>
1 parent 8440773 commit 22f9166

29 files changed

Lines changed: 1600 additions & 83 deletions

File tree

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [6.5.0] - 2026-07-28
11+
12+
### Added
13+
14+
- Added budget-bounded `read.files` calls for 1-32 text files with ordered
15+
per-file results, isolated member failures, and lossless continuation
16+
arguments that are included in the response budget.
17+
- Added `grep` output modes for content, paginated matching paths, paginated
18+
per-file matching-line counts, and full-scan summaries without rendering
19+
discarded match text.
20+
- Added read-only `edit` dry runs plus exact and maximum replacement-count
21+
guards so mechanical edits can be previewed and bounded before CAS writes.
22+
23+
### Changed
24+
25+
- Added explicit `glob` ordering: `sort: "path"` provides deterministic lexical
26+
order before cursor pagination, while the compatible `sort: "backend"`
27+
default retains backend relevance or recency order.
28+
- Added explicit README attribution for the FastCtx repository-tool ergonomics
29+
that informed these context-efficiency improvements.
30+
1031
## [6.4.3] - 2026-07-25
1132

1233
### Fixed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ the model.
207207

208208
| Concern | Built-in surface |
209209
| --- | --- |
210-
| Files and directories | `read`, `write`, `edit`, `patch`, `ls`, `glob`, `grep` with ranged or resumable operations and compare-and-swap mutation |
210+
| Files and directories | Budgeted single/multi-file `read`, `write`, previewable CAS `edit`, `patch`, `ls`, order-selectable paginated `glob`, and mode-selectable `grep` |
211211
| Commands and source control | Bounded `bash` plus typed `git` operations, cancellation, and Unix process-group termination |
212212
| Code intelligence | `code_symbols`, `code_navigation`, and `code_diagnostics`; source reading and mutation remain in file tools |
213213
| Web evidence | Multi-engine `web_search` and bounded `web_fetch` with structured failures, fallback, source normalization, and SSRF protections |
@@ -219,6 +219,51 @@ idempotent, resumable, cancellation-safe, paginated, output-kind, and parallel
219219
limits. `batch` parallelizes only calls that declare safe read-only behavior;
220220
mutations and unknown tools are serialized.
221221

222+
### Context-efficient repository tools
223+
224+
`read` can pack 1-32 known text files into one ordered response. The shared
225+
budget includes headers and the continuation itself, so the result reaches the
226+
model intact instead of relying on downstream truncation:
227+
228+
```json
229+
{
230+
"files": [
231+
{ "path": "src/lib.rs" },
232+
{ "path": "src/config.rs", "offset": 40, "limit": 80 }
233+
],
234+
"max_output_bytes": 65536
235+
}
236+
```
237+
238+
If the budget fills, copy `metadata.batch.continuation` back into `files`.
239+
Offsets and remaining per-file limits are advanced without repeating completed
240+
lines. One missing or unreadable member is reported in its own segment while
241+
the other files continue.
242+
243+
`grep.output_mode` controls how much evidence enters the context:
244+
245+
| Mode | Result |
246+
| --- | --- |
247+
| `content` | Matching lines with optional context (default) |
248+
| `files_with_matches` | Lexically cursor-paginated matching paths only |
249+
| `count` | Lexically cursor-paginated matching-line counts per file |
250+
| `summary` | Full-scan line and file totals without rendered matches |
251+
252+
The non-content modes ask built-in workspace backends to count matches without
253+
constructing discarded match text. `glob` retains a backend's recency or
254+
relevance order by default; request `sort: "path"` when cursor pages require
255+
stable lexical ordering.
256+
257+
Use `edit` with `dry_run: true` to receive the exact before/after diff without
258+
writing. The dry run is declared read-only and can be safely batched. Apply the
259+
result with `expected_replacements` and optionally `max_replacements` to reject
260+
stale or unexpectedly broad changes before the compare-and-swap write.
261+
262+
These repository-context ergonomics were informed by
263+
[FastCtx](https://github.com/yc-duan/fastctx). Their implementation here stays
264+
inside A3S Code's workspace abstractions, capability declarations, permission
265+
path, remote-backend contracts, and structured metadata.
266+
222267
### Sandbox and credential boundaries
223268

224269
Hosts can attach a `BashSandbox`. The fail-closed local `SrtBashSandbox` limits

core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "a3s-code-core"
3-
version = "6.4.3"
3+
version = "6.5.0"
44
edition = "2021"
55
authors = ["A3S Lab Team"]
66
license = "MIT"

core/src/mcp/transport/stdio.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ mod tests {
445445
) -> StdioTransport {
446446
let args = vec![
447447
"-c".to_string(),
448-
"touch \"$1\"; (sleep 0.30; touch \"$2\") & wait".to_string(),
448+
"(sleep 0.30; : > \"$2\") & : > \"$1\"; wait".to_string(),
449449
"mcp-process-tree-test".to_string(),
450450
started.to_string_lossy().into_owned(),
451451
leaked.to_string_lossy().into_owned(),

0 commit comments

Comments
 (0)