Removes the problematic file cache and instead builds the diff out of
the unified diff that gets returned from the edit tool already.
This should solve several error cases and provide a more reliable diff
When the ACP client persists the session id to support resuming, it has
no way to pass it back to the agent to resume an existing session as the
current implementation always creates a new id that is now shared with
Claude Code.
My client used to pass the value in the `--resume` within Claude Code
option, but `--resume` is not compatible with the new `--session-id`:
```
--session-id cannot be used with --continue or --resume.
```
Change:
When `--resume` is used, extract its value and use it as the session id.
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
There have been some issues for folks because the session id we returned
for ACP wasn't the same as the session id for Claude Code.
Now, we pass it through to the `--session-id` flag of the Claude Code
CLI, which means both ACP and Claude Code are always referring to the
same UUID. Yay!
## Summary
Follow-up to #121. The same issue (invalid locations when `file_path` is
undefined) existed in the `Read` tool case as well.
## Problem
The ACP spec requires `path` as a required field in `ToolCallLocation`.
PR #121 fixed this for `mcp__acp__Read`, but the same issue remained for
the `Read` tool case.
When Claude generates a Read tool call without `file_path`, the current
code produces an invalid notification:
```json
{
"locations": [
{
"line": 0
}
]
}
```
This causes the following error in the client:
```
Error handling notification
{code: -32602, message: 'Invalid params', data: {…}}
```
## Solution
Return an empty `locations` array when `input.file_path` is undefined,
consistent with the fix in #121.
Currently, if we get an unexpected message, we crash. While this is fine
in the world where we vendor CC (which we do by default) we also allow
users to override the executable for cases where their work needs a
wrapper.
This makes it so that we just log the event that we get, but don't crash
right away in case we can continue on.
Fixes#162:
- guard both tool callbacks so they return the host-provided error
instead of crashing on missing content
- skip writeTextFile in the edit tool when the initial read fails,
mirroring the read tool behavior
- add regression tests
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
The "status" message may say "success" but can actually have an error
which we weren't surfacing.
We should now be returning a more helpful message to the user.
Closes#161 and possibly #146
Add ability to disable built-in tools (Read, Write, Edit, Bash, etc.)
when `_meta.disableBuiltInTools` is set to true. This allows clients to
rely solely on MCP tools without the built-in tool implementations.
---
This is just my take on #157 — not necessarily the one that makes sense
/cc @benbrandt
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
🤖 Co-authored-by: Claude (Anthropic AI Assistant)
## Problem
Tool approval dialogs in ACP clients (like Emacs
[agent-shell](https://github.com/xenodium/agent-shell)) were showing up
empty because the `toolCall` object in `session/request_permission`
requests was missing the `title` field.
This caused dialogs to appear with just buttons and no description of
what tool is being approved, making it impossible for users to make
informed decisions.
## Solution
Add the `title` field to both `requestPermission` calls (lines 553 and
612) by using the existing `toolInfoFromToolUse()` function which
already generates appropriate titles for all tool types.
## Before
```
╭─
⚠ Tool Permission ⚠
Allow (y) Reject (n) Always Allow (!)
╰─
```
## After
```
╭─
⚠ Tool Permission ⚠
Write /path/to/file.txt
Allow (y) Reject (n) Always Allow (!)
╰─
```
## References
- This agent-shell.el issue shows (as has been shown above) what the
expected interaction would look like and what this changeset supports:
https://github.com/xenodium/agent-shell/issues/123
- The ACP protocol already supports the `title` field and agent-shell
displays it correctly when present (confirmed with OpenCode Agent which
does send titles)
## Testing
- **Manual testing**: Confirmed with agent-shell that permission dialogs
now show descriptive titles like "Write /path/to/file.txt"
- **Unit tests**: Added test coverage that verifies the `title` field is
present in permission request structures for multiple tool types (Write,
Bash, Read)
- **Regression testing**: Verified the new test fails when the `title`
field is omitted, confirming it catches the bug this PR fixes
- **Existing tests**: All 61 existing unit tests pass
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
We were mapping tool call rejections to actual "refusals" which isn't
quite right in ACP.
Also filters out more of these status messages that Claude is returning.
Use the `_meta` field for tool calls to forward:
- the original tool name (ie `Bash` etc)
- the structured output of the tool call
The output is received by using the `PostToolUse` hook from the SDK. The
`tool_call_update` for the tool result is now only sent when both the
hook callback and the original tool result (plain text) have been
received.
Claude Code describes [in its documentation
](https://docs.claude.com/en/api/agent-sdk/typescript#tool-output-types)the
expected structure of the output for each tools. Unfortunately those are
not part of the SDK, and [empirically I've found that there was some
differences](58c3100a36/local-server/src/server/endpoints/sendMessage/acp/clients/claudeCode/types.ts (L265)).
Still I've found that having this structured output was useful for my
client to provide a richer UX. Maybe Zed will too.
I was not sure how to add tests for this change, given the current setup