v1.1.0: native diff card client, 200-line paging for read/grep/glob, guard rule against shell edits/reads/searches

This commit is contained in:
Agent committed 2026-10-11 00:10:19 +00:00
1 parent 71953ffb8f
commit 0dae0ee53d
5 files changed
+364 -22

No files matched your search

+41 -2
View File
@@ -62,6 +62,40 @@ Every tagged `read`/`grep`/`edit` records a snapshot. When the file changed sinc
A tag that was never issued for that file (e.g. copied from another file) is rejected with a hint.
## Paging: read, grep and glob
Like oh-my-pi, outputs are cut into pages so the model never pulls a whole file or huge search into context at once:
- **`read`**: at most **200 lines** per call (`limit` above 200 is capped); the footer gives the `offset` to continue.
- **`grep`**: at most **200 matches** per call, grouped under `[PATH#TAG]` headers. Pass `offset` for the next page (`… call grep again with offset=200`).
- **`glob`**: at most **200 paths** per call, with the same `offset` cursor.
Change the page size with `pageLines`.
## Guard rule
A `tools/pre-execute` listener makes the agent use these tools instead of working around them through the shell. Denied calls get a short reason that names the right tool.
| Denied | Use instead |
| --- | --- |
| `sed -i`, `perl -i`, `ed`/`ex`, `tee`, `>`/`>>` into files, heredocs, `truncate`/`dd`, `python -c`/`node -e`… | `edit` (hashline) |
| `cat`/`head`/`tail`/`less`/`bat`/`nl FILE`, `sed -n`, `awk` | `read` (paged) |
| `grep`/`rg`/`ag`/`ack` over files | `grep` (paged, tagged) |
| `find`/`fd`/`locate`, `ls -R` | `glob` |
| `str_replace_editor`, `apply_patch` tools; `write` on an **existing** file | `edit` (`write` stays allowed for brand-new files) |
What stays allowed:
- Text inside quotes is ignored (`git commit -m "fix > bug"`).
- Redirection to `/dev/null` is fine.
- Filters on piped output keep working (`npm test 2>&1 | tail -5`, `ps aux | grep node`).
If the guard can't check whether a path exists, `write` is denied rather than allowed (it fails closed).
Turn the guard off with `guard: false`, or change the list of blocked tools with `guardTools`.
## Diff cards in the Web UI
The plugin ships a web client (`client.js`) that registers an `edit` tool view. Hashline, sloppy and apply_patch calls then render as DSH's native green/red diff card (from the applied hunks in `meta.diffs`), with `+N -M` counts, instead of raw patch text.
## Edit modes
`mode` picks the wire format of the replacement `edit` tool:
@@ -130,19 +164,24 @@ Set options in the `config` of the row in `~/.dsh/profiles/web/cordis.patch.yml`
replaceRead: true
replaceGrep: true
fuzzy: true # replace mode fuzzy matching
replaceGlob: true
pageLines: 200 # read/grep/glob page size
guard: true # deny shell edits/reads/searches and non-hashline write tools
guardTools: [write, str_replace_editor, apply_patch] # write: only existing files are denied
```
## Tests
```bash
npm test # node --test test/*.test.mjs — 32 tests (engine + integration on the real DSH fs-local backend)
npm test # node --test test/*.test.mjs — 34 tests (engine + integration on the real DSH fs-local backend)
```
## Files
| File | Role |
| --- | --- |
| `index.js` | DSH plugin: per-agent tool registration, mode selection, fs policy, diff cards |
| `index.js` | DSH plugin: per-agent tool registration, mode selection, fs policy, paging, guard rule |
| `client.js` | Web client: `edit` tool view rendering hashline/patch results as the native diff card |
| `lib/hashline.js` | Hashline parser and applier |
| `lib/block.js` | `N*` block resolution (brackets, indentation, Markdown, decorators) |
| `lib/store.js` | Session snapshot store, Myers line diff, stale-tag rebase |