Skip to content

Commit f65295a

Browse files
authored
feat: follow 0.4.5 (#7)
* feat: bump meta and schema to 0.4.5 Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * docs: add a basic agents file for better workflow Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * chore: fix docs release and ignore local reference Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * chore: to use right version schema Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * feat: align impl with spec and tests Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * feat: better gen scripts and rename map for better dev Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * refactor: try to make examples work Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * chore: bump to 0.4.5 Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * fix: SessionUpdate5 -> ToolCallProgress Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * refactor: update the buggy examples Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * refactor(examples): make basic example better Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * fix: prevent request processing from blocking permission or cancel handling Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * docs: polish everything Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> --------- Signed-off-by: Chojan Shang <chojan.shang@vesoft.com>
1 parent ae5e795 commit f65295a

28 files changed

+1476
-817
lines changed

.github/workflows/on-release-main.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ on:
55
types: [published]
66

77
jobs:
8-
98
set-version:
109
runs-on: ubuntu-24.04
1110
steps:
@@ -63,4 +62,13 @@ jobs:
6362
uses: ./.github/actions/setup-python-env
6463

6564
- name: Deploy documentation
66-
run: uv run mkdocs gh-deploy --force
65+
env:
66+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
67+
GIT_AUTHOR_NAME: acp-bot
68+
GIT_AUTHOR_EMAIL: noreply@github.com
69+
GIT_COMMITTER_NAME: acp-bot
70+
GIT_COMMITTER_EMAIL: noreply@github.com
71+
run: |
72+
git config user.name "$GIT_AUTHOR_NAME"
73+
git config user.email "$GIT_AUTHOR_EMAIL"
74+
uv run mkdocs gh-deploy --force --remote-branch gh-pages --remote-name origin

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,10 @@ cython_debug/
209209
marimo/_static/
210210
marimo/_lsp/
211211
__marimo__/
212+
213+
# .zed
214+
.zed/
215+
216+
# others
217+
reference/
218+
.DS_Store

AGENTS.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Repository Guidelines
2+
3+
## Project Structure & Module Organization
4+
The package code lives under `src/acp`, exposing the high-level Agent, transport helpers, and generated protocol schema. Generated artifacts such as `schema/` and `src/acp/schema.py` are refreshed via `scripts/gen_all.py` against the upstream ACP schema. Integration examples are in `examples/`, including `echo_agent.py` and the mini SWE bridge. Tests reside in `tests/` with async fixtures and doctests; documentation sources live in `docs/` and publish via MkDocs. Built distributions drop into `dist/` after builds.
5+
6+
## Build, Test, and Development Commands
7+
Run `make install` to create a `uv` managed virtualenv and install pre-commit hooks. `make check` executes lock verification, Ruff linting, `ty` static checks, and deptry analysis. `make test` calls `uv run python -m pytest --doctest-modules`. For release prep use `make build` or `make build-and-publish`. `make gen-all` regenerates protocol models; export `ACP_SCHEMA_VERSION=<ref>` beforehand to fetch a specific upstream schema (defaults to the cached copy). `make docs` serves MkDocs locally; `make docs-test` ensures clean builds.
8+
9+
## Coding Style & Naming Conventions
10+
Target Python 3.10+ with type hints and 120-character lines enforced by Ruff (`pyproject.toml`). Prefer dataclasses/pydantic models from the schema modules rather than bare dicts. Tests may ignore security lint (see per-file ignores) but still follow snake_case names. Keep public API modules under `acp/*` lean; place utilities in internal `_`-prefixed modules when needed.
11+
12+
## Testing Guidelines
13+
Pytest is the main framework with `pytest-asyncio` for coroutine tests and doctests activated on modules. Name test files `test_*.py` and co-locate fixtures under `tests/conftest.py`. Aim to cover new protocol surfaces with integration-style tests using the async agent stubs. Generate coverage reports via `tox -e py310` when assessing CI parity.
14+
15+
## Commit & Pull Request Guidelines
16+
Commit history follows Conventional Commits (`feat:`, `fix:`, `docs:`). Scope commits narrowly and include context on affected protocol version or tooling. PRs should describe agent behaviors exercised, link related issues, and mention schema regeneration if applicable. Attach test output (`make check` or targeted pytest) and screenshots only when UI-adjacent docs change. Update docs/examples when altering the public agent API.
17+
18+
## Agent Integration Tips
19+
Leverage `examples/mini_swe_agent/` as a template when bridging other command executors. Use `AgentSideConnection` with `stdio_streams()` for ACP-compliant clients; document any extra environment variables in README updates.

README.md

Lines changed: 42 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,56 @@
11
# Agent Client Protocol (Python)
22

3-
A Python implementation of the Agent Client Protocol (ACP). Use it to build agents that communicate with ACP-capable clients (e.g. Zed) over stdio.
3+
Python SDK for the Agent Client Protocol (ACP). Build agents that speak ACP over stdio so tools like Zed can orchestrate them.
44

5-
- Package name: `agent-client-protocol` (import as `acp`)
6-
- Repository: https://github.com/psiace/agent-client-protocol-python
7-
- Docs: https://psiace.github.io/agent-client-protocol-python/
8-
- Featured: Listed as the first third-party SDK on the official ACP site — see https://agentclientprotocol.com/libraries/community
5+
> Each release tracks the matching ACP schema version. Contributions that improve coverage or tooling are very welcome.
6+
7+
**Highlights**
8+
9+
- Typed dataclasses generated from the upstream ACP schema (`acp.schema`)
10+
- Async agent base class plus stdio transport helpers for quick bootstrapping
11+
- Included examples that stream content updates and tool calls end-to-end
912

1013
## Install
1114

1215
```bash
1316
pip install agent-client-protocol
14-
# or
17+
# or with uv
1518
uv add agent-client-protocol
1619
```
1720

18-
## Development (contributors)
21+
## Quickstart
1922

20-
```bash
21-
make install # set up venv
22-
make check # lint + typecheck
23-
make test # run tests
24-
```
23+
1. Install the package and point your ACP-capable client at the provided echo agent:
24+
```bash
25+
pip install agent-client-protocol
26+
python examples/echo_agent.py
27+
```
28+
2. Wire it into your client (e.g. Zed → Agents panel) so stdio is connected; the SDK handles JSON-RPC framing and lifecycle messages.
2529

26-
## Minimal agent example
30+
Prefer a step-by-step walkthrough? Read the [Quickstart guide](docs/quickstart.md) or the hosted docs: https://psiace.github.io/agent-client-protocol-python/.
2731

28-
See a complete streaming echo example in [examples/echo_agent.py](examples/echo_agent.py). It streams back each text block using `session/update` and ends the turn.
32+
### Minimal agent sketch
2933

3034
```python
3135
import asyncio
3236

33-
from acp import (
34-
Agent,
35-
AgentSideConnection,
36-
InitializeRequest,
37-
InitializeResponse,
38-
NewSessionRequest,
39-
NewSessionResponse,
40-
PromptRequest,
41-
PromptResponse,
42-
SessionNotification,
43-
stdio_streams,
44-
)
45-
from acp.schema import ContentBlock1, SessionUpdate2
37+
from acp import Agent, AgentSideConnection, PromptRequest, PromptResponse, SessionNotification, stdio_streams
38+
from acp.schema import AgentMessageChunk, TextContentBlock
4639

4740

4841
class EchoAgent(Agent):
4942
def __init__(self, conn):
5043
self._conn = conn
5144

52-
async def initialize(self, params: InitializeRequest) -> InitializeResponse:
53-
return InitializeResponse(protocolVersion=params.protocolVersion)
54-
55-
async def newSession(self, params: NewSessionRequest) -> NewSessionResponse:
56-
return NewSessionResponse(sessionId="sess-1")
57-
5845
async def prompt(self, params: PromptRequest) -> PromptResponse:
5946
for block in params.prompt:
60-
text = block.get("text", "") if isinstance(block, dict) else getattr(block, "text", "")
47+
text = getattr(block, "text", "")
6148
await self._conn.sessionUpdate(
6249
SessionNotification(
6350
sessionId=params.sessionId,
64-
update=SessionUpdate2(
51+
update=AgentMessageChunk(
6552
sessionUpdate="agent_message_chunk",
66-
content=ContentBlock1(type="text", text=text),
53+
content=TextContentBlock(type="text", text=text),
6754
),
6855
)
6956
)
@@ -80,17 +67,27 @@ if __name__ == "__main__":
8067
asyncio.run(main())
8168
```
8269

83-
Run this executable from your ACP-capable client (e.g. configure Zed to launch it). The library takes care of the stdio JSON-RPC transport.
70+
Full example with streaming and lifecycle hooks lives in [examples/echo_agent.py](examples/echo_agent.py).
8471

85-
## Example: Mini SWE Agent bridge
72+
## Examples
8673

87-
A minimal ACP bridge for mini-swe-agent is provided under [`examples/mini_swe_agent`](examples/mini_swe_agent/README.md). It demonstrates:
88-
89-
- Parsing a prompt from ACP content blocks
90-
- Streaming agent output via `session/update`
91-
- Mapping command execution to `tool_call` and `tool_call_update`
74+
- `examples/mini_swe_agent`: bridges mini-swe-agent into ACP, including a duet launcher and Textual TUI client
75+
- Additional transport helpers are documented in the [Mini SWE guide](docs/mini-swe-agent.md)
9276

9377
## Documentation
9478

95-
- Quickstart: [docs/quickstart.md](docs/quickstart.md)
96-
- Mini SWE Agent example: [docs/mini-swe-agent.md](docs/mini-swe-agent.md)
79+
- Project docs (MkDocs): https://psiace.github.io/agent-client-protocol-python/
80+
- Local sources: `docs/`
81+
- [Quickstart](docs/quickstart.md)
82+
- [Mini SWE Agent bridge](docs/mini-swe-agent.md)
83+
84+
## Development workflow
85+
86+
```bash
87+
make install # create uv virtualenv and install hooks
88+
ACP_SCHEMA_VERSION=<ref> make gen-all # refresh generated schema bindings
89+
make check # lint, types, dependency analysis
90+
make test # run pytest + doctests
91+
```
92+
93+
After local changes, consider updating docs/examples if the public API surface shifts.

docs/index.md

Lines changed: 21 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,30 @@
1-
# Agent Client Protocol (Python)
1+
# Agent Client Protocol SDK (Python)
22

3-
A Python implementation of the Agent Client Protocol (ACP). Build agents that communicate with ACP-capable clients (e.g. Zed) over stdio.
3+
Welcome to the Python SDK for the Agent Client Protocol (ACP). The package ships ready-to-use transports, typed protocol models, and examples that stream messages to ACP-aware clients such as Zed.
44

5-
## Install
5+
## What you get
66

7-
```bash
8-
pip install agent-client-protocol
9-
```
7+
- Fully typed dataclasses generated from the upstream ACP schema (`acp.schema`)
8+
- Async agent base class and stdio helpers to spin up an agent in a few lines
9+
- Examples that demonstrate streaming updates and tool execution over ACP
1010

11-
## Minimal usage
11+
## Getting started
1212

13-
```python
14-
import asyncio
13+
1. Install the package:
14+
```bash
15+
pip install agent-client-protocol
16+
```
17+
2. Launch the provided echo agent to verify your setup:
18+
```bash
19+
python examples/echo_agent.py
20+
```
21+
3. Point your ACP-capable client at the running process (for Zed, configure an Agent Server entry). The SDK takes care of JSON-RPC framing and lifecycle transitions.
1522

16-
from acp import (
17-
Agent,
18-
AgentSideConnection,
19-
InitializeRequest,
20-
InitializeResponse,
21-
NewSessionRequest,
22-
NewSessionResponse,
23-
PromptRequest,
24-
PromptResponse,
25-
SessionNotification,
26-
stdio_streams,
27-
)
28-
from acp.schema import ContentBlock1, SessionUpdate2
23+
Prefer a guided tour? Head to the [Quickstart](quickstart.md) for step-by-step instructions, including how to run the agent from an editor or terminal.
2924

25+
## Documentation map
3026

31-
class EchoAgent(Agent):
32-
def __init__(self, conn):
33-
self._conn = conn
27+
- [Quickstart](quickstart.md): install, run, and extend the echo agent
28+
- [Mini SWE Agent guide](mini-swe-agent.md): bridge mini-swe-agent over ACP, including duet launcher and Textual client
3429

35-
async def initialize(self, params: InitializeRequest) -> InitializeResponse:
36-
return InitializeResponse(protocolVersion=params.protocolVersion)
37-
38-
async def newSession(self, params: NewSessionRequest) -> NewSessionResponse:
39-
return NewSessionResponse(sessionId="sess-1")
40-
41-
async def prompt(self, params: PromptRequest) -> PromptResponse:
42-
for block in params.prompt:
43-
text = block.get("text", "") if isinstance(block, dict) else getattr(block, "text", "")
44-
await self._conn.sessionUpdate(
45-
SessionNotification(
46-
sessionId=params.sessionId,
47-
update=SessionUpdate2(
48-
sessionUpdate="agent_message_chunk",
49-
content=ContentBlock1(type="text", text=text),
50-
),
51-
)
52-
)
53-
return PromptResponse(stopReason="end_turn")
54-
55-
56-
async def main() -> None:
57-
reader, writer = await stdio_streams()
58-
AgentSideConnection(lambda conn: EchoAgent(conn), writer, reader)
59-
await asyncio.Event().wait()
60-
61-
62-
if __name__ == "__main__":
63-
asyncio.run(main())
64-
```
65-
66-
- Quickstart: [quickstart.md](quickstart.md)
67-
- Mini SWE Agent example: [mini-swe-agent.md](mini-swe-agent.md)
30+
Source code lives under `src/acp/`, while tests and additional examples are available in `tests/` and `examples/`. If you plan to contribute, see the repository README for the development workflow.

docs/mini-swe-agent.md

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,54 @@
11
# Mini SWE Agent bridge
22

3-
> Just a show of the bridge in action. Not a best-effort or absolutely-correct implementation of the agent.
3+
This example wraps mini-swe-agent behind ACP so editors such as Zed can interact with it over stdio. A duet launcher is included to run a local Textual client beside the bridge for quick experimentation.
44

5-
This example wraps mini-swe-agent behind ACP so Zed can run it as an external agent over stdio. It also includes a local Textual UI client connected via a duet launcher
5+
## Overview
66

7-
## Behavior
7+
- Accepts ACP prompts, concatenates text blocks, and forwards them to mini-swe-agent
8+
- Streams language-model output via `session/update``agent_message_chunk`
9+
- Emits `tool_call` / `tool_call_update` pairs for shell execution, including stdout and return codes
10+
- Sends a final `agent_message_chunk` when mini-swe-agent prints `COMPLETE_TASK_AND_SUBMIT_FINAL_OUTPUT`
811

9-
- Prompts: text blocks are concatenated into a single task string. (Resource embedding is not used in this example.)
10-
- Streaming: only LM output is streamed via `session/update``agent_message_chunk`.
11-
- Tool calls: when the agent executes a shell command, the bridge sends:
12-
- `tool_call` with `kind=execute`, pending status, and a bash code block containing the command
13-
- `tool_call_update` upon completion, including output and a `rawOutput` object with `output` and `returncode`
14-
- Final result: on task submission (mini-swe-agent prints `COMPLETE_TASK_AND_SUBMIT_FINAL_OUTPUT` as the first line), a final `agent_message_chunk` with the submission content is sent.
12+
## Requirements
1513

16-
## Configuration
14+
- Python environment with `mini-swe-agent` installed (`pip install mini-swe-agent`)
15+
- ACP-capable client (e.g. Zed) or the bundled Textual client
16+
- Optional: `.env` file at the repo root for shared configuration when using the duet launcher
1717

18-
Environment variables control the model:
18+
If `mini-swe-agent` is missing, the bridge falls back to the reference copy at `reference/mini-swe-agent/src`.
1919

20-
- `MINI_SWE_MODEL`: model ID (e.g. `openrouter/openai/gpt-4o-mini`)
21-
- `OPENROUTER_API_KEY` for OpenRouter; or `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` for native providers
22-
- Optional `MINI_SWE_MODEL_KWARGS`: JSON, e.g. `{ "api_base": "https://openrouter.ai/api/v1" }` (auto-injected for OpenRouter if missing)
20+
## Configure models and credentials
2321

24-
Agent behavior automatically maps the appropriate API key based on the chosen model and available environment variables.
22+
Set environment variables before launching the bridge:
2523

26-
If `mini-swe-agent` is not installed in the venv, the bridge attempts to import a vendored reference copy under `reference/mini-swe-agent/src`.
24+
- `MINI_SWE_MODEL`: model identifier such as `openrouter/openai/gpt-4o-mini`
25+
- `OPENROUTER_API_KEY` for OpenRouter models, or `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` for native providers
26+
- Optional `MINI_SWE_MODEL_KWARGS`: JSON blob of extra keyword arguments (OpenRouter defaults are injected automatically when omitted)
2727

28-
## How to run
28+
The bridge selects the correct API key based on the chosen model and available variables.
2929

30-
- In Zed (editor integration): configure an agent server to launch `examples/mini_swe_agent/agent.py` and set the environment variables there. Use Zed’s “Open ACP Logs” to inspect `tool_call`/`tool_call_update` and message chunks.
31-
- In terminal (local TUI): run the duet launcher to start both the agent and the Textual client with the same environment and dedicated pipes:
30+
## Run inside Zed
31+
32+
Add an Agent Server entry targeting `examples/mini_swe_agent/agent.py` and provide the environment variables there. Use Zed’s “Open ACP Logs” panel to observe streamed message chunks and tool call events in real time.
33+
34+
## Run locally with the duet launcher
35+
36+
To pair the bridge with the Textual TUI client, run:
3237

3338
```bash
3439
python examples/mini_swe_agent/duet.py
3540
```
3641

37-
The launcher loads `.env` from the repo root (using python-dotenv) so both processes share the same configuration.
38-
39-
### TUI usage
42+
Both processes inherit settings from `.env` (thanks to `python-dotenv`) and communicate over dedicated pipes.
4043

41-
- Hotkeys: `y` → YOLO, `c` → Confirm, `u` → Human, `Enter` → Continue.
42-
- In Human mode, you’ll be prompted for a bash command; it will be executed and streamed back as a tool call.
43-
- Each executed command appears in the “TOOL CALLS” section with live status and output.
44+
**TUI shortcuts**
45+
- `y`: YOLO
46+
- `c`: Confirm
47+
- `u`: Human (prompts for a shell command and streams it back as a tool call)
48+
- `Enter`: Continue
4449

45-
## Files
50+
## Related files
4651

47-
- Agent entry: [`examples/mini_swe_agent/agent.py`](https://github.com/psiace/agent-client-protocol-python/blob/main/examples/mini_swe_agent/agent.py)
48-
- Duet launcher: [`examples/mini_swe_agent/duet.py`](https://github.com/psiace/agent-client-protocol-python/blob/main/examples/mini_swe_agent/duet.py)
49-
- Textual client: [`examples/mini_swe_agent/client.py`](https://github.com/psiace/agent-client-protocol-python/blob/main/examples/mini_swe_agent/client.py)
52+
- Agent entrypoint: `examples/mini_swe_agent/agent.py`
53+
- Duet launcher: `examples/mini_swe_agent/duet.py`
54+
- Textual client: `examples/mini_swe_agent/client.py`

0 commit comments

Comments
 (0)