Skip to content

Commit 571766a

Browse files
authored
feat: change field names to snake case (#31)
* feat: change field names to snake case Signed-off-by: Frost Ming <[email protected]> * fix lint errors Signed-off-by: Frost Ming <[email protected]> --------- Signed-off-by: Frost Ming <[email protected]>
1 parent e0aaa35 commit 571766a

20 files changed

+509
-347
lines changed

docs/quickstart.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ Spin up a working ACP agent/client loop in minutes. Keep this page beside the te
44

55
## Quick checklist
66

7-
| Goal | Command / Link |
8-
| --- | --- |
9-
| Install the SDK | `pip install agent-client-protocol` or `uv add agent-client-protocol` |
10-
| Run the echo agent | `python examples/echo_agent.py` |
11-
| Point Zed (or another client) at it | Update `settings.json` as shown below |
12-
| Programmatically drive an agent | Copy the `spawn_agent_process` example |
13-
| Run tests before hacking further | `make check && make test` |
7+
| Goal | Command / Link |
8+
| ----------------------------------- | --------------------------------------------------------------------- |
9+
| Install the SDK | `pip install agent-client-protocol` or `uv add agent-client-protocol` |
10+
| Run the echo agent | `python examples/echo_agent.py` |
11+
| Point Zed (or another client) at it | Update `settings.json` as shown below |
12+
| Programmatically drive an agent | Copy the `spawn_agent_process` example |
13+
| Run tests before hacking further | `make check && make test` |
1414

1515
## Before you begin
1616

@@ -84,17 +84,17 @@ class SimpleClient(Client):
8484
return {"outcome": {"outcome": "cancelled"}}
8585

8686
async def sessionUpdate(self, params: SessionNotification) -> None:
87-
print("update:", params.sessionId, params.update)
87+
print("update:", params.session_id, params.update)
8888

8989

9090
async def main() -> None:
9191
script = Path("examples/echo_agent.py")
9292
async with spawn_agent_process(lambda _agent: SimpleClient(), sys.executable, str(script)) as (conn, _proc):
93-
await conn.initialize(InitializeRequest(protocolVersion=1))
94-
session = await conn.newSession(NewSessionRequest(cwd=str(script.parent), mcpServers=[]))
93+
await conn.initialize(InitializeRequest(protocol_version=1))
94+
session = await conn.newSession(NewSessionRequest(cwd=str(script.parent), mcp_servers=[]))
9595
await conn.prompt(
9696
PromptRequest(
97-
sessionId=session.sessionId,
97+
session_id=session.session_id,
9898
prompt=[text_block("Hello from spawn!")],
9999
)
100100
)
@@ -117,7 +117,7 @@ from acp import Agent, PromptRequest, PromptResponse
117117
class MyAgent(Agent):
118118
async def prompt(self, params: PromptRequest) -> PromptResponse:
119119
# inspect params.prompt, stream updates, then finish the turn
120-
return PromptResponse(stopReason="end_turn")
120+
return PromptResponse(stop_reason="end_turn")
121121
```
122122

123123
Hook it up with `AgentSideConnection` inside an async entrypoint and wire it to your client. Refer to:

examples/agent.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,44 +40,43 @@ async def _send_agent_message(self, session_id: str, content: Any) -> None:
4040
async def initialize(self, params: InitializeRequest) -> InitializeResponse: # noqa: ARG002
4141
logging.info("Received initialize request")
4242
return InitializeResponse(
43-
protocolVersion=PROTOCOL_VERSION,
44-
agentCapabilities=AgentCapabilities(),
45-
agentInfo=Implementation(name="example-agent", title="Example Agent", version="0.1.0"),
43+
protocol_version=PROTOCOL_VERSION,
44+
agent_capabilities=AgentCapabilities(),
45+
agent_info=Implementation(name="example-agent", title="Example Agent", version="0.1.0"),
4646
)
4747

4848
async def authenticate(self, params: AuthenticateRequest) -> AuthenticateResponse | None: # noqa: ARG002
49-
logging.info("Received authenticate request %s", params.methodId)
49+
logging.info("Received authenticate request %s", params.method_id)
5050
return AuthenticateResponse()
5151

5252
async def newSession(self, params: NewSessionRequest) -> NewSessionResponse: # noqa: ARG002
5353
logging.info("Received new session request")
5454
session_id = str(self._next_session_id)
5555
self._next_session_id += 1
5656
self._sessions.add(session_id)
57-
return NewSessionResponse(sessionId=session_id, modes=None)
57+
return NewSessionResponse(session_id=session_id, modes=None)
5858

5959
async def loadSession(self, params: LoadSessionRequest) -> LoadSessionResponse | None: # noqa: ARG002
60-
logging.info("Received load session request %s", params.sessionId)
61-
self._sessions.add(params.sessionId)
60+
logging.info("Received load session request %s", params.session_id)
61+
self._sessions.add(params.session_id)
6262
return LoadSessionResponse()
6363

6464
async def setSessionMode(self, params: SetSessionModeRequest) -> SetSessionModeResponse | None: # noqa: ARG002
65-
logging.info("Received set session mode request %s -> %s", params.sessionId, params.modeId)
65+
logging.info("Received set session mode request %s -> %s", params.session_id, params.mode_id)
6666
return SetSessionModeResponse()
6767

6868
async def prompt(self, params: PromptRequest) -> PromptResponse:
69-
logging.info("Received prompt request for session %s", params.sessionId)
70-
if params.sessionId not in self._sessions:
71-
self._sessions.add(params.sessionId)
69+
logging.info("Received prompt request for session %s", params.session_id)
70+
if params.session_id not in self._sessions:
71+
self._sessions.add(params.session_id)
7272

73-
await self._send_agent_message(params.sessionId, text_block("Client sent:"))
73+
await self._send_agent_message(params.session_id, text_block("Client sent:"))
7474
for block in params.prompt:
75-
await self._send_agent_message(params.sessionId, block)
76-
77-
return PromptResponse(stopReason="end_turn")
75+
await self._send_agent_message(params.session_id, block)
76+
return PromptResponse(stop_reason="end_turn")
7877

7978
async def cancel(self, params: CancelNotification) -> None: # noqa: ARG002
80-
logging.info("Received cancel notification for session %s", params.sessionId)
79+
logging.info("Received cancel notification for session %s", params.session_id)
8180

8281
async def extMethod(self, method: str, params: dict) -> dict: # noqa: ARG002
8382
logging.info("Received extension method call: %s", method)

examples/client.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ async def interactive_loop(conn: ClientSideConnection, session_id: str) -> None:
104104
try:
105105
await conn.prompt(
106106
PromptRequest(
107-
sessionId=session_id,
107+
session_id=session_id,
108108
prompt=[text_block(line)],
109109
)
110110
)
@@ -146,14 +146,14 @@ async def main(argv: list[str]) -> int:
146146

147147
await conn.initialize(
148148
InitializeRequest(
149-
protocolVersion=PROTOCOL_VERSION,
150-
clientCapabilities=ClientCapabilities(),
151-
clientInfo=Implementation(name="example-client", title="Example Client", version="0.1.0"),
149+
protocol_version=PROTOCOL_VERSION,
150+
client_capabilities=ClientCapabilities(),
151+
client_info=Implementation(name="example-client", title="Example Client", version="0.1.0"),
152152
)
153153
)
154-
session = await conn.newSession(NewSessionRequest(mcpServers=[], cwd=os.getcwd()))
154+
session = await conn.newSession(NewSessionRequest(mcp_servers=[], cwd=os.getcwd()))
155155

156-
await interactive_loop(conn, session.sessionId)
156+
await interactive_loop(conn, session.session_id)
157157

158158
if proc.returncode is None:
159159
proc.terminate()

examples/echo_agent.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ def __init__(self, conn):
2222
self._conn = conn
2323

2424
async def initialize(self, params: InitializeRequest) -> InitializeResponse:
25-
return InitializeResponse(protocolVersion=params.protocolVersion)
25+
return InitializeResponse(protocol_version=params.protocol_version)
2626

2727
async def newSession(self, params: NewSessionRequest) -> NewSessionResponse:
28-
return NewSessionResponse(sessionId=uuid4().hex)
28+
return NewSessionResponse(session_id=uuid4().hex)
2929

3030
async def prompt(self, params: PromptRequest) -> PromptResponse:
3131
for block in params.prompt:
@@ -34,16 +34,16 @@ async def prompt(self, params: PromptRequest) -> PromptResponse:
3434
chunk.field_meta = {"echo": True}
3535
chunk.content.field_meta = {"echo": True}
3636

37-
notification = session_notification(params.sessionId, chunk)
37+
notification = session_notification(params.session_id, chunk)
3838
notification.field_meta = {"source": "echo_agent"}
3939

4040
await self._conn.sessionUpdate(notification)
41-
return PromptResponse(stopReason="end_turn")
41+
return PromptResponse(stop_reason="end_turn")
4242

4343

4444
async def main() -> None:
4545
reader, writer = await stdio_streams()
46-
AgentSideConnection(lambda conn: EchoAgent(conn), writer, reader)
46+
AgentSideConnection(EchoAgent, writer, reader)
4747
await asyncio.Event().wait()
4848

4949

examples/gemini.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ async def requestPermission(
7373
option = _pick_preferred_option(params.options)
7474
if option is None:
7575
return RequestPermissionResponse(outcome=DeniedOutcome(outcome="cancelled"))
76-
return RequestPermissionResponse(outcome=AllowedOutcome(optionId=option.optionId, outcome="selected"))
76+
return RequestPermissionResponse(outcome=AllowedOutcome(option_id=option.option_id, outcome="selected"))
7777

78-
title = params.toolCall.title or "<permission>"
78+
title = params.tool_call.title or "<permission>"
7979
if not params.options:
8080
print(f"\n🔐 Permission requested: {title} (no options, cancelling)")
8181
return RequestPermissionResponse(outcome=DeniedOutcome(outcome="cancelled"))
@@ -92,7 +92,9 @@ async def requestPermission(
9292
idx = int(choice) - 1
9393
if 0 <= idx < len(params.options):
9494
opt = params.options[idx]
95-
return RequestPermissionResponse(outcome=AllowedOutcome(optionId=opt.optionId, outcome="selected"))
95+
return RequestPermissionResponse(
96+
outcome=AllowedOutcome(option_id=opt.option_id, outcome="selected")
97+
)
9698
print("Invalid selection, try again.")
9799

98100
async def writeTextFile(
@@ -141,13 +143,13 @@ async def sessionUpdate(
141143
print(f"\n🔧 {update.title} ({update.status or 'pending'})")
142144
elif isinstance(update, ToolCallProgress):
143145
status = update.status or "in_progress"
144-
print(f"\n🔧 Tool call `{update.toolCallId}` → {status}")
146+
print(f"\n🔧 Tool call `{update.tool_call_id}` → {status}")
145147
if update.content:
146148
for item in update.content:
147149
if isinstance(item, FileEditToolCallContent):
148150
print(f" diff: {item.path}")
149151
elif isinstance(item, TerminalToolCallContent):
150-
print(f" terminal: {item.terminalId}")
152+
print(f" terminal: {item.terminal_id}")
151153
elif isinstance(item, dict):
152154
print(f" content: {json.dumps(item, indent=2)}")
153155
else:
@@ -159,7 +161,7 @@ async def createTerminal(
159161
params: CreateTerminalRequest,
160162
) -> CreateTerminalResponse: # type: ignore[override]
161163
print(f"[Client] createTerminal: {params}")
162-
return CreateTerminalResponse(terminalId="term-1")
164+
return CreateTerminalResponse(terminal_id="term-1")
163165

164166
async def terminalOutput(
165167
self,
@@ -246,13 +248,13 @@ async def interactive_loop(conn: ClientSideConnection, session_id: str) -> None:
246248
if line in {":exit", ":quit"}:
247249
break
248250
if line == ":cancel":
249-
await conn.cancel(CancelNotification(sessionId=session_id))
251+
await conn.cancel(CancelNotification(session_id=session_id))
250252
continue
251253

252254
try:
253255
await conn.prompt(
254256
PromptRequest(
255-
sessionId=session_id,
257+
session_id=session_id,
256258
prompt=[text_block(line)],
257259
)
258260
)
@@ -321,9 +323,9 @@ async def run(argv: list[str]) -> int:
321323
try:
322324
init_resp = await conn.initialize(
323325
InitializeRequest(
324-
protocolVersion=PROTOCOL_VERSION,
325-
clientCapabilities=ClientCapabilities(
326-
fs=FileSystemCapability(readTextFile=True, writeTextFile=True),
326+
protocol_version=PROTOCOL_VERSION,
327+
client_capabilities=ClientCapabilities(
328+
fs=FileSystemCapability(read_text_file=True, write_text_file=True),
327329
terminal=True,
328330
),
329331
)
@@ -337,13 +339,13 @@ async def run(argv: list[str]) -> int:
337339
await _shutdown(proc, conn)
338340
return 1
339341

340-
print(f"✅ Connected to Gemini (protocol v{init_resp.protocolVersion})")
342+
print(f"✅ Connected to Gemini (protocol v{init_resp.protocol_version})")
341343

342344
try:
343345
session = await conn.newSession(
344346
NewSessionRequest(
345347
cwd=os.getcwd(),
346-
mcpServers=[],
348+
mcp_servers=[],
347349
)
348350
)
349351
except RequestError as err:
@@ -355,10 +357,10 @@ async def run(argv: list[str]) -> int:
355357
await _shutdown(proc, conn)
356358
return 1
357359

358-
print(f"📝 Created session: {session.sessionId}")
360+
print(f"📝 Created session: {session.session_id}")
359361

360362
try:
361-
await interactive_loop(conn, session.sessionId)
363+
await interactive_loop(conn, session.session_id)
362364
finally:
363365
await _shutdown(proc, conn)
364366

scripts/gen_schema.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ def generate_schema(*, format_output: bool = True) -> None:
173173
"--output-model-type",
174174
"pydantic_v2.BaseModel",
175175
"--use-annotated",
176+
"--snake-case-field",
176177
]
177178

178179
subprocess.check_call(cmd) # noqa: S603

src/acp/agent/connection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ async def createTerminal(self, params: CreateTerminalRequest) -> TerminalHandle:
9797
params,
9898
CreateTerminalResponse,
9999
)
100-
return TerminalHandle(create_response.terminalId, params.sessionId, self._conn)
100+
return TerminalHandle(create_response.terminal_id, params.session_id, self._conn)
101101

102102
async def terminalOutput(self, params: TerminalOutputRequest) -> TerminalOutputResponse:
103103
return await request_model(

src/acp/contrib/permissions.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ def __init__(self) -> None:
2929
def default_permission_options() -> tuple[PermissionOption, PermissionOption, PermissionOption]:
3030
"""Return a standard approval/reject option set."""
3131
return (
32-
PermissionOption(optionId="approve", name="Approve", kind="allow_once"),
33-
PermissionOption(optionId="approve_for_session", name="Approve for session", kind="allow_always"),
34-
PermissionOption(optionId="reject", name="Reject", kind="reject_once"),
32+
PermissionOption(option_id="approve", name="Approve", kind="allow_once"),
33+
PermissionOption(option_id="approve_for_session", name="Approve for session", kind="allow_always"),
34+
PermissionOption(option_id="reject", name="Reject", kind="reject_once"),
3535
)
3636

3737

@@ -83,8 +83,8 @@ async def request_for(
8383
raise MissingPermissionOptionsError()
8484

8585
request = RequestPermissionRequest(
86-
sessionId=self._session_id,
87-
toolCall=tool_call,
86+
session_id=self._session_id,
87+
tool_call=tool_call,
8888
options=list(option_set),
8989
)
9090
return await self._requester(request)

src/acp/contrib/session_state.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ def apply_start(self, update: ToolCallStart) -> None:
6262
self.status = update.status
6363
self.content = _copy_model_list(update.content)
6464
self.locations = _copy_model_list(update.locations)
65-
self.raw_input = update.rawInput
66-
self.raw_output = update.rawOutput
65+
self.raw_input = update.raw_input
66+
self.raw_output = update.raw_output
6767

6868
def apply_progress(self, update: ToolCallProgress) -> None:
6969
if update.title is not None:
@@ -76,10 +76,10 @@ def apply_progress(self, update: ToolCallProgress) -> None:
7676
self.content = _copy_model_list(update.content)
7777
if update.locations is not None:
7878
self.locations = _copy_model_list(update.locations)
79-
if update.rawInput is not None:
80-
self.raw_input = update.rawInput
81-
if update.rawOutput is not None:
82-
self.raw_output = update.rawOutput
79+
if update.raw_input is not None:
80+
self.raw_input = update.raw_input
81+
if update.raw_output is not None:
82+
self.raw_output = update.raw_output
8383

8484
def snapshot(self) -> ToolCallView:
8585
return ToolCallView(
@@ -185,11 +185,11 @@ def apply(self, notification: SessionNotification) -> SessionSnapshot:
185185

186186
def _ensure_session(self, notification: SessionNotification) -> None:
187187
if self.session_id is None:
188-
self.session_id = notification.sessionId
188+
self.session_id = notification.session_id
189189
return
190190

191-
if notification.sessionId != self.session_id:
192-
self._handle_session_change(notification.sessionId)
191+
if notification.session_id != self.session_id:
192+
self._handle_session_change(notification.session_id)
193193

194194
def _handle_session_change(self, session_id: str) -> None:
195195
expected = self.session_id
@@ -206,14 +206,14 @@ def _handle_session_change(self, session_id: str) -> None:
206206
def _apply_update(self, update: Any) -> None:
207207
if isinstance(update, ToolCallStart):
208208
state = self._tool_calls.setdefault(
209-
update.toolCallId, _MutableToolCallState(tool_call_id=update.toolCallId)
209+
update.tool_call_id, _MutableToolCallState(tool_call_id=update.tool_call_id)
210210
)
211211
state.apply_start(update)
212212
return
213213

214214
if isinstance(update, ToolCallProgress):
215215
state = self._tool_calls.setdefault(
216-
update.toolCallId, _MutableToolCallState(tool_call_id=update.toolCallId)
216+
update.tool_call_id, _MutableToolCallState(tool_call_id=update.tool_call_id)
217217
)
218218
state.apply_progress(update)
219219
return
@@ -223,11 +223,11 @@ def _apply_update(self, update: Any) -> None:
223223
return
224224

225225
if isinstance(update, CurrentModeUpdate):
226-
self._current_mode_id = update.currentModeId
226+
self._current_mode_id = update.current_mode_id
227227
return
228228

229229
if isinstance(update, AvailableCommandsUpdate):
230-
self._available_commands = _copy_model_list(update.availableCommands) or []
230+
self._available_commands = _copy_model_list(update.available_commands) or []
231231
return
232232

233233
if isinstance(update, UserMessageChunk):

0 commit comments

Comments
 (0)