import asyncio import asyncio.subprocess as aio_subprocess import contextlib import logging import os import sys from pathlib import Path from typing import Any from acp import ( PROTOCOL_VERSION, Client, RequestError, connect_to_agent, text_block, ) from acp.core import ClientSideConnection from acp.schema import ( AgentMessageChunk, AgentPlanContentUpdate, AgentPlanRemovedUpdate, AgentPlanUpdate, AgentThoughtChunk, AudioContentBlock, AvailableCommandsUpdate, ClientCapabilities, ConfigOptionUpdate, CreateElicitationResponse, CreateTerminalResponse, CurrentModeUpdate, DeclineElicitationResponse, ElicitationMode, EmbeddedResourceContentBlock, EnvVariable, ImageContentBlock, Implementation, KillTerminalResponse, PermissionOption, ReadTextFileResponse, ReleaseTerminalResponse, RequestPermissionResponse, ResourceContentBlock, SessionInfoUpdate, TerminalOutputResponse, TextContentBlock, ToolCallProgress, ToolCallStart, ToolCallUpdate, UsageUpdate, UserMessageChunk, WaitForTerminalExitResponse, WriteTextFileResponse, ) class ExampleClient(Client): async def request_permission( self, session_id: str, tool_call: ToolCallUpdate, options: list[PermissionOption], **kwargs: Any ) -> RequestPermissionResponse: raise RequestError.method_not_found("session/request_permission") async def write_text_file( self, session_id: str, path: str, content: str, **kwargs: Any ) -> WriteTextFileResponse | None: raise RequestError.method_not_found("fs/write_text_file") async def read_text_file( self, session_id: str, path: str, line: int | None = None, limit: int | None = None, **kwargs: Any ) -> ReadTextFileResponse: raise RequestError.method_not_found("fs/read_text_file") async def create_terminal( self, session_id: str, command: str, args: list[str] | None = None, env: list[EnvVariable] | None = None, cwd: str | None = None, output_byte_limit: int | None = None, **kwargs: Any, ) -> CreateTerminalResponse: raise RequestError.method_not_found("terminal/create") async def terminal_output(self, session_id: str, terminal_id: str, **kwargs: Any) -> TerminalOutputResponse: raise RequestError.method_not_found("terminal/output") async def release_terminal( self, session_id: str, terminal_id: str, **kwargs: Any ) -> ReleaseTerminalResponse | None: raise RequestError.method_not_found("terminal/release") async def wait_for_terminal_exit( self, session_id: str, terminal_id: str, **kwargs: Any ) -> WaitForTerminalExitResponse: raise RequestError.method_not_found("terminal/wait_for_exit") async def kill_terminal(self, session_id: str, terminal_id: str, **kwargs: Any) -> KillTerminalResponse | None: raise RequestError.method_not_found("terminal/kill") async def create_elicitation(self, message: str, mode: ElicitationMode, **kwargs: Any) -> CreateElicitationResponse: print(f"| Agent requested input: {message} ({type(mode).__name__})") return DeclineElicitationResponse(action="decline") async def complete_elicitation(self, elicitation_id: str, **kwargs: Any) -> None: print(f"| Agent completed elicitation: {elicitation_id}") async def session_update( self, session_id: str, update: UserMessageChunk | AgentMessageChunk | AgentThoughtChunk | ToolCallStart | ToolCallProgress | AgentPlanUpdate | AgentPlanContentUpdate | AgentPlanRemovedUpdate | AvailableCommandsUpdate | CurrentModeUpdate | ConfigOptionUpdate | SessionInfoUpdate | UsageUpdate, **kwargs: Any, ) -> None: if not isinstance(update, AgentMessageChunk): return content = update.content text: str if isinstance(content, TextContentBlock): text = content.text elif isinstance(content, ImageContentBlock): text = "" elif isinstance(content, AudioContentBlock): text = "