Skip to content

Commit 6594993

Browse files
authored
refactor: align spec to optimize the development experience (#10)
* refactor: polish all code to align spec impl Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * docs: polish docs for next release Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * fix: make gen all great Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * fix: make echo work Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * fix: correct default value Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * fix: make echo work better Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * test(golden): intro golden tests Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * feat(gemini): intro the gemini impl to showcase Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * docs: update to include gemini Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * docs: update for coding agents Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * *: update with more case and polished docs Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * feat: intro helpers Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> * docs: polish docs Signed-off-by: Chojan Shang <chojan.shang@vesoft.com> --------- Signed-off-by: Chojan Shang <chojan.shang@vesoft.com>
1 parent 1839086 commit 6594993

File tree

66 files changed

+2320
-1558
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+2320
-1558
lines changed

AGENTS.md

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,35 @@
11
# Repository Guidelines
22

33
## 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.
4+
- `src/acp/`: runtime package exposing agent/client abstractions, transports, and the generated `schema.py`.
5+
- `schema/`: upstream JSON schema sources; regenerate Python bindings with `make gen-all`.
6+
- `examples/`: runnable scripts (`echo_agent.py`, `client.py`, `gemini.py`, etc.) demonstrating stdio orchestration patterns.
7+
- `tests/`: pytest suite, including opt-in Gemini smoke checks under `tests/test_gemini_example.py`.
8+
- `docs/`: MkDocs content powering the hosted documentation.
59

610
## 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.
11+
- `make install` — provision the `uv` virtualenv and install pre-commit hooks.
12+
- `make check` — run Ruff linting/formatting, type analysis, dependency hygiene, and lock verification.
13+
- `make test` — execute `pytest` (with doctests) inside the managed environment.
14+
- `make gen-all` — refresh protocol artifacts when the ACP schema version advances (`ACP_SCHEMA_VERSION=<ref>` to pin an upstream tag).
815

916
## 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.
17+
- Target Python 3.10+ with four-space indentation and type hints on public APIs.
18+
- Ruff enforces formatting and lint rules (`uv run ruff check`, `uv run ruff format`); keep both clean before publishing.
19+
- Prefer dataclasses or generated Pydantic models from `acp.schema` over ad-hoc dicts. Place shared utilities in `_`-prefixed internal modules.
20+
- Prefer the builders in `acp.helpers` (for example `text_block`, `start_tool_call`) when constructing ACP payloads. The helpers instantiate the generated Pydantic models for you, keep literal discriminator fields out of call sites, and stay in lockstep with the schema thanks to the golden tests (`tests/test_golden.py`).
1121

1222
## 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.
23+
- Tests live in `tests/` and must be named `test_*.py`. Use `pytest.mark.asyncio` for coroutine coverage.
24+
- Run `make test` (or `uv run python -m pytest`) prior to commits; include reproducing steps for any added fixtures.
25+
- Gemini CLI coverage is disabled by default. Set `ACP_ENABLE_GEMINI_TESTS=1` (and `ACP_GEMINI_BIN=/path/to/gemini`) to exercise `tests/test_gemini_example.py`.
1426

1527
## 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.
28+
- Follow Conventional Commits (`feat:`, `fix:`, `docs:`, etc.) with succinct scopes, noting schema regenerations when applicable.
29+
- PRs should describe exercised agent behaviours, link relevant issues, and include output from `make check` or focused pytest runs.
30+
- Update documentation and examples whenever public APIs or transport behaviours change, and call out environment prerequisites for new integrations.
1731

1832
## 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.
33+
- Bootstrap agents from `examples/echo_agent.py` or `examples/agent.py`; pair with `examples/client.py` for round-trip validation.
34+
- Use `spawn_agent_process` / `spawn_client_process` to embed ACP parties directly in Python applications.
35+
- Validate new transports against `tests/test_rpc.py` and, when applicable, the Gemini example to ensure streaming updates and permission flows stay compliant.

README.md

Lines changed: 106 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
<a href="https://agentclientprotocol.com/" >
2+
<img alt="Agent Client Protocol" src="https://zed.dev/img/acp/banner-dark.webp">
3+
</a>
4+
15
# Agent Client Protocol (Python)
26

37
Python SDK for the Agent Client Protocol (ACP). Build agents that speak ACP over stdio so tools like Zed can orchestrate them.
@@ -6,9 +10,11 @@ Python SDK for the Agent Client Protocol (ACP). Build agents that speak ACP over
610
711
**Highlights**
812

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
13+
- Generated `pydantic` models that track the upstream ACP schema (`acp.schema`)
14+
- Async base classes and JSON-RPC plumbing that keep stdio agents tiny
15+
- Process helpers such as `spawn_agent_process` for embedding agents and clients directly in Python
16+
- Batteries-included examples that exercise streaming updates, file I/O, and permission flows
17+
- Optional Gemini CLI bridge (`examples/gemini.py`) for the `gemini --experimental-acp` integration
1218

1319
## Install
1420

@@ -29,29 +35,75 @@ uv add agent-client-protocol
2935

3036
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/.
3137

38+
### Launching from Python
39+
40+
Embed the agent inside another Python process without spawning your own pipes:
41+
42+
```python
43+
import asyncio
44+
import sys
45+
from pathlib import Path
46+
47+
from acp import spawn_agent_process, text_block
48+
from acp.schema import InitializeRequest, NewSessionRequest, PromptRequest
49+
50+
51+
async def main() -> None:
52+
agent_script = Path("examples/echo_agent.py")
53+
async with spawn_agent_process(lambda _agent: YourClient(), sys.executable, str(agent_script)) as (conn, _proc):
54+
await conn.initialize(InitializeRequest(protocolVersion=1))
55+
session = await conn.newSession(NewSessionRequest(cwd=str(agent_script.parent), mcpServers=[]))
56+
await conn.prompt(
57+
PromptRequest(
58+
sessionId=session.sessionId,
59+
prompt=[text_block("Hello!")],
60+
)
61+
)
62+
63+
64+
asyncio.run(main())
65+
```
66+
67+
`spawn_client_process` mirrors this pattern for the inverse direction.
68+
3269
### Minimal agent sketch
3370

3471
```python
3572
import asyncio
3673

37-
from acp import Agent, AgentSideConnection, PromptRequest, PromptResponse, SessionNotification, stdio_streams
38-
from acp.schema import AgentMessageChunk, TextContentBlock
74+
from acp import (
75+
Agent,
76+
AgentSideConnection,
77+
InitializeRequest,
78+
InitializeResponse,
79+
NewSessionRequest,
80+
NewSessionResponse,
81+
PromptRequest,
82+
PromptResponse,
83+
session_notification,
84+
stdio_streams,
85+
text_block,
86+
update_agent_message,
87+
)
3988

4089

4190
class EchoAgent(Agent):
4291
def __init__(self, conn):
4392
self._conn = conn
4493

94+
async def initialize(self, params: InitializeRequest) -> InitializeResponse:
95+
return InitializeResponse(protocolVersion=params.protocolVersion)
96+
97+
async def newSession(self, params: NewSessionRequest) -> NewSessionResponse:
98+
return NewSessionResponse(sessionId="sess-1")
99+
45100
async def prompt(self, params: PromptRequest) -> PromptResponse:
46101
for block in params.prompt:
47-
text = getattr(block, "text", "")
102+
text = block.get("text", "") if isinstance(block, dict) else getattr(block, "text", "")
48103
await self._conn.sessionUpdate(
49-
SessionNotification(
50-
sessionId=params.sessionId,
51-
update=AgentMessageChunk(
52-
sessionUpdate="agent_message_chunk",
53-
content=TextContentBlock(type="text", text=text),
54-
),
104+
session_notification(
105+
params.sessionId,
106+
update_agent_message(text_block(text)),
55107
)
56108
)
57109
return PromptResponse(stopReason="end_turn")
@@ -71,15 +123,54 @@ Full example with streaming and lifecycle hooks lives in [examples/echo_agent.py
71123

72124
## Examples
73125

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)
126+
- `examples/echo_agent.py`: the canonical streaming agent with lifecycle hooks
127+
- `examples/client.py`: interactive console client that can launch any ACP agent via stdio
128+
- `examples/agent.py`: richer agent showcasing initialization, authentication, and chunked updates
129+
- `examples/duet.py`: launches both example agent and client using `spawn_agent_process`
130+
- `examples/gemini.py`: connects to the Gemini CLI in `--experimental-acp` mode, with optional auto-approval and sandbox flags
131+
132+
## Helper APIs
133+
134+
Use `acp.helpers` to build protocol payloads without manually shaping dictionaries:
135+
136+
```python
137+
from acp import start_tool_call, text_block, tool_content, update_tool_call
138+
139+
start = start_tool_call("call-1", "Inspect config", kind="read", status="pending")
140+
update = update_tool_call(
141+
"call-1",
142+
status="completed",
143+
content=[tool_content(text_block("Inspection finished."))],
144+
)
145+
```
146+
147+
Helpers cover content blocks (`text_block`, `resource_link_block`), embedded resources, tool calls (`start_edit_tool_call`, `update_tool_call`), and session updates (`update_agent_message_text`, `session_notification`).
76148

77149
## Documentation
78150

79151
- Project docs (MkDocs): https://psiace.github.io/agent-client-protocol-python/
80152
- Local sources: `docs/`
81153
- [Quickstart](docs/quickstart.md)
82-
- [Mini SWE Agent bridge](docs/mini-swe-agent.md)
154+
- [Releasing](docs/releasing.md)
155+
156+
## Gemini CLI bridge
157+
158+
Want to exercise the `gemini` CLI over ACP? The repository includes a Python replica of the Go SDK's REPL:
159+
160+
```bash
161+
python examples/gemini.py --yolo # auto-approve permissions
162+
python examples/gemini.py --sandbox --model gemini-2.5-pro
163+
```
164+
165+
Defaults assume the CLI is discoverable via `PATH`; override with `--gemini` or `ACP_GEMINI_BIN=/path/to/gemini`.
166+
167+
The smoke test (`tests/test_gemini_example.py`) is opt-in to avoid false negatives when the CLI is unavailable or lacks credentials. Enable it locally with:
168+
169+
```bash
170+
ACP_ENABLE_GEMINI_TESTS=1 ACP_GEMINI_BIN=/path/to/gemini uv run python -m pytest tests/test_gemini_example.py
171+
```
172+
173+
The test gracefully skips when authentication prompts (e.g. missing `GOOGLE_CLOUD_PROJECT`) block the interaction.
83174

84175
## Development workflow
85176

docs/index.md

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1+
<a href="https://agentclientprotocol.com/" >
2+
<img alt="Agent Client Protocol" src="https://zed.dev/img/acp/banner-dark.webp">
3+
</a>
4+
15
# Agent Client Protocol SDK (Python)
26

37
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.
48

59
## What you get
610

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
11+
- Pydantic models generated from the upstream ACP schema (`acp.schema`)
12+
- Async agent/client wrappers with JSON-RPC task supervision built in
13+
- Process helpers (`spawn_agent_process`, `spawn_client_process`) for embedding ACP nodes inside Python applications
14+
- Helper APIs in `acp.helpers` that mirror the Go/TS SDK builders for content blocks, tool calls, and session updates. They instantiate the generated Pydantic types for you, so call sites stay concise without sacrificing validation.
15+
- Examples that showcase streaming updates, file operations, permission flows, and even a Gemini CLI bridge (`examples/gemini.py`)
1016

1117
## Getting started
1218

@@ -20,11 +26,27 @@ Welcome to the Python SDK for the Agent Client Protocol (ACP). The package ships
2026
```
2127
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.
2228

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.
29+
Prefer a guided tour? Head to the [Quickstart](quickstart.md) for terminal, editor, and programmatic launch walkthroughs.
30+
31+
## Gemini CLI bridge
32+
33+
If you have access to the Gemini CLI (`gemini --experimental-acp`), run:
34+
35+
```bash
36+
python examples/gemini.py --yolo
37+
```
38+
39+
Flags mirror the Go SDK example:
40+
41+
- `--gemini /path/to/cli` or `ACP_GEMINI_BIN` to override discovery
42+
- `--model`, `--sandbox`, `--debug` forwarded verbatim
43+
- `--yolo` auto-approves permission prompts with sensible defaults
44+
45+
An opt-in smoke test lives at `tests/test_gemini_example.py`. Enable it with `ACP_ENABLE_GEMINI_TESTS=1` (and optionally `ACP_GEMINI_TEST_ARGS`) when the CLI is authenticated; otherwise the test stays skipped.
2446

2547
## Documentation map
2648

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
49+
- [Quickstart](quickstart.md): install, run, and embed the echo agent, plus next steps for extending it
50+
- [Releasing](releasing.md): schema upgrade workflow, version bumps, and publishing checklist
2951

3052
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: 0 additions & 54 deletions
This file was deleted.

0 commit comments

Comments
 (0)