Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7d946f1
fix(ai-harness): a settled operation keeps its status, a media signer…
AlemTuzlak Oct 17, 2026
3868e4f
fix(ai-harness): every plugin contribution has an owner, ctx.on clean…
AlemTuzlak Oct 17, 2026
5ce3e64
docs(ai-harness): say when capabilities report the WebSocket
AlemTuzlak Oct 17, 2026
08faf9a
feat(ai): onGuardToolCall middleware hook that runs on the final argu…
AlemTuzlak Oct 17, 2026
d6026ce
test(e2e): onGuardToolCall denies on the final args after a transform…
AlemTuzlak Oct 17, 2026
d02278c
Merge branch 'feat/harness-log-session' into feat/harness-point-bugs
AlemTuzlak Oct 17, 2026
42c8014
fix(ai-harness): tool turns take no steers, a turn keeps its config, …
AlemTuzlak Oct 17, 2026
4a43804
Merge branch 'feat/harness-log-session' into feat/harness-point-bugs
AlemTuzlak Oct 17, 2026
8afc555
Merge branch 'feat/harness-log-session' into feat/harness-point-bugs
AlemTuzlak Oct 17, 2026
07f9377
fix(ai-harness): the media signer's key check covers an empty secret
AlemTuzlak Oct 17, 2026
8942571
Merge branch 'feat/harness-reporting' into feat/harness-point-bugs
AlemTuzlak Oct 18, 2026
f1d5347
Merge branch 'feat/harness-perf' into feat/harness-point-bugs
AlemTuzlak Oct 18, 2026
5fadbfd
Merge branch 'feat/harness-perf' into feat/harness-point-bugs
AlemTuzlak Oct 18, 2026
012afa8
Merge branch 'feat/harness-perf' into feat/harness-point-bugs
AlemTuzlak Oct 18, 2026
0515997
fix(ai-harness-cli): serve signs media URLs with a key derived from t…
AlemTuzlak Oct 18, 2026
a609b81
Merge branch 'feat/harness-perf' into feat/harness-point-bugs
AlemTuzlak Oct 18, 2026
58b5cc6
feat(ai-harness, ai-mcp, ai-acp, ai-code-mode, ai-harness-cli): the f…
AlemTuzlak Oct 19, 2026
f634e4f
refactor(ai-harness): mounted plugins keep each contribution list wit…
AlemTuzlak Oct 19, 2026
8ec1658
fix(ai-harness): a plugins remove setting is rejected when a kept tur…
AlemTuzlak Oct 19, 2026
a5fa03a
fix(ai-harness): client media checks every part before it stores any,…
AlemTuzlak Oct 19, 2026
2c8d58b
fix(ai-harness): a retried client input with inline media reuses the …
AlemTuzlak Oct 19, 2026
cc1eae9
docs(ai-harness): routed root-agent turns take steers and late joins,…
AlemTuzlak Oct 19, 2026
b5e10b6
fix(ai-harness-cli): --serve signs media URLs with --media-key or HAR…
AlemTuzlak Oct 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .changeset/ai-harness-coding-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
Add coding tools in the new Node entry `@tanstack/ai-harness/plugins/coding`:

- `workspaceTools({ root })` gives `read_file` (text pages, images, PDFs), `write_file`, `edit_file` or `patch` (`editStyle`), `list_files`, `grep`, `bash` (with `background`), `webfetch`, and `websearch` (with a `SearchProvider`). With `permissions()`, edits, `bash`, and `webfetch` ask first, and the rules also apply to the real path of a link. `outside: 'ask'` makes a path outside `root` need an approval. `permissions()` decides outside paths and the real paths of links before the call runs, so a tool never asks while it runs. The `cwd` thread setting gives each thread its own working folder.
- `workspaceTools({ workspace: { bind, reattach? } })` gives each thread its own workspace. The root of the workspace is the boundary of every tool. The session log keeps where the workspace is (`harness.workspace.bound`). On another host, `reattach` gives the workspace back (for example a resumed sandbox), or `'pinned'` or `'gone'`. A gone workspace sends `tanstack/workspace-tools:stranded`.
- `workspaceTools({ workspace: { bind, reattach? } })` gives each thread its own workspace. The root of the workspace is the boundary of every tool. The session log keeps where the workspace is (`harness.workspace.bound`). On another host, `reattach` gives the workspace back (for example a resumed sandbox), or `'pinned'` or `'gone'`. A gone workspace sends `tanstack/workspace-tools:stranded`. With this plugin first, `snapshots()` and `formatter()` use the workspace of each thread, and their `root` is optional.
- `createHarnessHost({ ownership: { hostId } })` gives a host a stable id. Then a thread that uses a folder on that host is pinned to it, and other hosts refuse its tool calls. Without `hostId`, threads are not pinned.
- Commands, `rg`, `git`, and the formatters get only a short list of variables of the server process, plus the `env` of the backend call. Git runs without the hooks and the `fsmonitor` of the project.
- The tools resolve links with `realpath` under the file lock, and fail when a backend cannot resolve a path. A write fails when the file changed after the tool read it. The file locks are shared by the sessions of a host.
- Background jobs: at most 8 per session (`maxJobs`), the newest 1 MiB of output per job, and the events `tanstack/workspace-tools:job-started`, `job-output`, and `job-ended`. A job that an earlier host left running is stopped at the next tool call, with a note to the model.
- Background jobs: at most 8 per session (`maxJobs`), the newest 1 MiB of output per job, and the events `tanstack/workspace-tools:job-started`, `job-output`, and `job-ended`. A job that an earlier host left running is stopped at the next tool call, with a note to the model. The wake turn of a job runs as the user who started it. The `bash` spill file has `[redacted]` in place of each secret of the session.
- `read_file` sends images and PDFs up to 256 KB. `webfetch` gives the model the first 256 KB of a page.
- A `WorkspaceBackend` runs the tools. `hostBackend` is the default. `realpath` is required. `spawn` can give a `jobId`, and `killJob`, `binding`, and `close` are optional. On Windows, commands do not run a program from the working folder by its name.
- `snapshots()` adds `/undo` and `/redo`, which restore only the files of the turn (git 2.26 or newer), file restore for `session.revert()`, and a diff for each model step. Each thread of each tenant has its own shadow repository, which never stores `.env` files. A step keeps only the files of its own run. The steps and the undo point are in the session log, so another host with the same repository can undo. A revert uses the last 500 steps. `purgeSnapshots()` removes the repository of a thread. A failed snapshot sends `tanstack/snapshots:failed`.
- `formatter()` formats each written file with the formatter of the project. With `permissions()`, the rules decide the formatter with the call that writes, before that call runs: one approval covers both, and the formatter runs after the write.
- `snapshots()` adds `/undo` and `/redo`, which restore only the files of the turn (git 2.26 or newer), file restore for `session.revert()`, and a diff for each model step. Each thread of each tenant has its own shadow repository, which never stores `.env` files. A step keeps only the files of its own run. The steps and the undo point are in the session log, so another host with the same repository can undo. A revert uses the last 500 steps. `host.sessions.delete` removes the repository of the thread, and `purgeSnapshots()` does it from your own code. A failed snapshot sends `tanstack/snapshots:failed`.
- `formatter()` formats each written file with the formatter of the project. With `permissions()`, the rules decide the formatter with the call that writes, before that call runs: one approval covers both, and the formatter runs after the write. An `always` answer is tied to a hash of the formatter config files. A write of a formatter config below the root, or under `node_modules`, asks each time, and an `always` answer saves no rule for that formatter run.
- `WorkspaceHooks` lets other plugins run code after a read or a write.

`@vscode/ripgrep` and `turndown` are optional peer dependencies.
Loading
Loading