Skip to content

feat(acp): Agent Client Protocol support for Zed editor - #338

Merged
shayne-snap merged 11 commits into
mainfrom
worktree-feat-acp-support
Jul 14, 2026
Merged

feat(acp): Agent Client Protocol support for Zed editor#338
shayne-snap merged 11 commits into
mainfrom
worktree-feat-acp-support

Conversation

@shayne-snap

Copy link
Copy Markdown
Contributor

Summary

Implement ACP v1 (Agent Client Protocol) agent that enables Whale to work as an AI coding agent inside Zed editor and other ACP-compatible clients.

Key features

  • JSON-RPC 2.0 over stdio transport with single-dispatcher architecture
  • Full ACP lifecycle: initialize, session/new, session/load, session/prompt, session/cancel, session/set_mode
  • Streaming agent_message_chunk / agent_thought_chunk / tool_call / plan updates
  • session/request_permission forwarding for editor-native approval dialogs
  • Per-session cwd with dynamic toolset root and policy workspace switching
  • Merged global → project → config.local permission policy loading via .whale/config.toml
  • Cancellation support for active prompts (including pending permission waits) and queued prompts
  • Session persistence via JSONL store with message replay on session/load
  • Integration tests with real DeepSeek API

Files changed

File Change
cmd/whale-acp/main.go New ACP entry point
internal/acp/types.go ACP v1 Go types
internal/acp/transport.go JSON-RPC stdio transport + dispatcher
internal/acp/handler.go Method routing, session mgmt, cancel handlers
internal/acp/adapter.go Whale AgentEvent → ACP SessionUpdate mapping
internal/acp/smoke_test.go Integration tests
internal/agent/agent.go +SetToolPolicy()
internal/tools/toolset.go +SetRoot()
Makefile +build-acp target
scripts/acp_smoke_test.sh Shell smoke test

How to use in Zed

Add to ~/.zed/settings.json:

{
  "agent_servers": {
    "Whale (DeepSeek)": {
      "type": "custom",
      "command": "/path/to/bin/whale-acp",
      "env": {
        "DEEPSEEK_API_KEY": "sk-..."
      }
    }
  }
}

Or run make build-acp and connect any ACP-compatible client to bin/whale-acp.

Testing

make build-acp
DEEPSEEK_API_KEY=sk-... WHALE_ACP_BIN=bin/whale-acp go test -v ./internal/acp/

Implement ACP v1 (Agent Client Protocol) agent that enables Whale
to work as an AI coding agent inside Zed editor and other ACP-compatible
clients.

Key features:
- JSON-RPC 2.0 over stdio transport with single-dispatcher architecture
- Full ACP lifecycle: initialize, session/new, session/load, session/prompt,
  session/cancel, session/set_mode
- Streaming agent_message_chunk / agent_thought_chunk / tool_call updates
- session/request_permission forwarding for editor-native approval dialogs
- Per-session cwd with dynamic toolset root / policy workspace switching
- Merged global -> project -> config.local permission policy loading
- Cancellation support for active and queued prompts
- Session persistence via JSONL store with message replay
- Integration tests with real DeepSeek API
Fixes:
- Reload per-workspace policy when switching ACP session cwd (policyLoader)
- Use pendingCancels slice for multiple queued prompt cancels
- Clear isPending flag after acquiring promptMu for proper cleanup
- Return actual session mode on session/load
- Write parse-error responses via configured t.writer instead of os.Stdout
- Set PermissionRule.Action field correctly via ParsePermissionAction
- Mutex-guard activeCancel access in CallClientMethod
@shayne-snap

Copy link
Copy Markdown
Contributor Author

Hi @lnnttoo. Would you like to review this PR?

@lnnttoo

lnnttoo commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Hi @lnnttoo. Would you like to review this PR?

Will have a look ASAP.

Cleanup:
- Simplify handler.go: remove pendingCancel slice logic, use single cancel
- Remove SetToolPolicy from agent.go (unused)
- Remove SetRoot from toolset.go (use SetWorktreeContext instead)
- Merge config layers properly in loadPermissionPolicy
Protect sctx.cancel read with mutex in notification handlers.
Replace single pendingCancel with pendingCancels slice.
Use transport writer for parse error responses.
8 insertions, 3 deletions.
- Clear isPending after acquiring promptMu\n- Write parse errors via t.writer.Encode
Protect sctx.cancel with mutex, pendingCancels slice, parse error output via t.writer.
@shayne-snap
shayne-snap merged commit 8578447 into main Jul 14, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants