From 8509738e6581890d9d0fedf1f6ded2044d597ead Mon Sep 17 00:00:00 2001 From: stdrc Date: Wed, 31 Dec 2025 01:02:50 +0800 Subject: [PATCH 1/8] feat: bump acp schema version to 0.10.5 (#52) * feat: bump acp schema version to 0.10.5 Signed-off-by: Richard Chien * add tests and renaming Signed-off-by: Richard Chien * remove obsolete type aliases Signed-off-by: Richard Chien --------- Signed-off-by: Richard Chien --- schema/VERSION | 2 +- schema/meta.json | 1 + schema/schema.json | 356 +++++++++ scripts/gen_schema.py | 27 +- src/acp/agent/connection.py | 2 + src/acp/interfaces.py | 2 + src/acp/meta.py | 3 +- src/acp/schema.py | 681 +++++++++++------- tests/conftest.py | 2 + .../session_update_config_option_update.json | 55 ++ .../set_session_config_option_request.json | 5 + .../set_session_config_option_response.json | 20 + tests/test_golden.py | 6 + 13 files changed, 895 insertions(+), 267 deletions(-) create mode 100644 tests/golden/session_update_config_option_update.json create mode 100644 tests/golden/set_session_config_option_request.json create mode 100644 tests/golden/set_session_config_option_response.json diff --git a/schema/VERSION b/schema/VERSION index babc878..801f529 100644 --- a/schema/VERSION +++ b/schema/VERSION @@ -1 +1 @@ -refs/tags/v0.10.3 +refs/tags/v0.10.5 diff --git a/schema/meta.json b/schema/meta.json index e58853e..507c21d 100644 --- a/schema/meta.json +++ b/schema/meta.json @@ -9,6 +9,7 @@ "session_new": "session/new", "session_prompt": "session/prompt", "session_resume": "session/resume", + "session_set_config_option": "session/set_config_option", "session_set_mode": "session/set_mode", "session_set_model": "session/set_model" }, diff --git a/schema/schema.json b/schema/schema.json index 9d1f974..4f45ef0 100644 --- a/schema/schema.json +++ b/schema/schema.json @@ -225,6 +225,9 @@ { "$ref": "#/$defs/SetSessionModeResponse" }, + { + "$ref": "#/$defs/SetSessionConfigOptionResponse" + }, { "$ref": "#/$defs/PromptResponse" }, @@ -709,6 +712,14 @@ ], "description": "Sets the current mode for a session.\n\nAllows switching between different agent modes (e.g., \"ask\", \"architect\", \"code\")\nthat affect system prompts, tool availability, and permission behaviors.\n\nThe mode must be one of the modes advertised in `availableModes` during session\ncreation or loading. Agents may also change modes autonomously and notify the\nclient via `current_mode_update` notifications.\n\nThis method can be called at any time during a session, whether the Agent is\nidle or actively generating a response.\n\nSee protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)" }, + { + "allOf": [ + { + "$ref": "#/$defs/SetSessionConfigOptionRequest" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nSets the current value for a session configuration option." + }, { "allOf": [ { @@ -813,6 +824,30 @@ ], "x-docs-ignore": true }, + "ConfigOptionUpdate": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nSession configuration options have been updated.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": [ + "object", + "null" + ] + }, + "configOptions": { + "description": "The full set of configuration options and their current values.", + "items": { + "$ref": "#/$defs/SessionConfigOption" + }, + "type": "array" + } + }, + "required": [ + "configOptions" + ], + "type": "object" + }, "Content": { "description": "Standard content block (text, images, resources).", "properties": { @@ -1337,6 +1372,16 @@ "null" ] }, + "configOptions": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + "items": { + "$ref": "#/$defs/SessionConfigOption" + }, + "type": [ + "array", + "null" + ] + }, "models": { "anyOf": [ { @@ -1756,6 +1801,16 @@ "null" ] }, + "configOptions": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + "items": { + "$ref": "#/$defs/SessionConfigOption" + }, + "type": [ + "array", + "null" + ] + }, "models": { "anyOf": [ { @@ -2049,6 +2104,16 @@ "null" ] }, + "configOptions": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + "items": { + "$ref": "#/$defs/SessionConfigOption" + }, + "type": [ + "array", + "null" + ] + }, "models": { "anyOf": [ { @@ -2710,6 +2775,16 @@ "null" ] }, + "configOptions": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + "items": { + "$ref": "#/$defs/SessionConfigOption" + }, + "type": [ + "array", + "null" + ] + }, "models": { "anyOf": [ { @@ -2817,6 +2892,198 @@ }, "type": "object" }, + "SessionConfigGroupId": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nUnique identifier for a session configuration option value group.", + "type": "string" + }, + "SessionConfigId": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nUnique identifier for a session configuration option.", + "type": "string" + }, + "SessionConfigOption": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nA session configuration option selector and its current state.", + "discriminator": { + "propertyName": "type" + }, + "oneOf": [ + { + "allOf": [ + { + "$ref": "#/$defs/SessionConfigSelect" + } + ], + "description": "Single-value selector (dropdown).", + "properties": { + "type": { + "const": "select", + "type": "string" + } + }, + "required": [ + "type" + ], + "type": "object" + } + ], + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": [ + "object", + "null" + ] + }, + "description": { + "description": "Optional description for the Client to display to the user.", + "type": [ + "string", + "null" + ] + }, + "id": { + "allOf": [ + { + "$ref": "#/$defs/SessionConfigId" + } + ], + "description": "Unique identifier for the configuration option." + }, + "name": { + "description": "Human-readable label for the option.", + "type": "string" + } + }, + "required": [ + "id", + "name" + ], + "type": "object" + }, + "SessionConfigSelect": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nA single-value selector (dropdown) session configuration option payload.", + "properties": { + "currentValue": { + "allOf": [ + { + "$ref": "#/$defs/SessionConfigValueId" + } + ], + "description": "The currently selected value." + }, + "options": { + "allOf": [ + { + "$ref": "#/$defs/SessionConfigSelectOptions" + } + ], + "description": "The set of selectable options." + } + }, + "required": [ + "currentValue", + "options" + ], + "type": "object" + }, + "SessionConfigSelectGroup": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nA group of possible values for a session configuration option.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": [ + "object", + "null" + ] + }, + "group": { + "allOf": [ + { + "$ref": "#/$defs/SessionConfigGroupId" + } + ], + "description": "Unique identifier for this group." + }, + "name": { + "description": "Human-readable label for this group.", + "type": "string" + }, + "options": { + "description": "The set of option values in this group.", + "items": { + "$ref": "#/$defs/SessionConfigSelectOption" + }, + "type": "array" + } + }, + "required": [ + "group", + "name", + "options" + ], + "type": "object" + }, + "SessionConfigSelectOption": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nA possible value for a session configuration option.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": [ + "object", + "null" + ] + }, + "description": { + "description": "Optional description for this option value.", + "type": [ + "string", + "null" + ] + }, + "name": { + "description": "Human-readable label for this option value.", + "type": "string" + }, + "value": { + "allOf": [ + { + "$ref": "#/$defs/SessionConfigValueId" + } + ], + "description": "Unique identifier for this option value." + } + }, + "required": [ + "value", + "name" + ], + "type": "object" + }, + "SessionConfigSelectOptions": { + "anyOf": [ + { + "description": "A flat list of options with no grouping.", + "items": { + "$ref": "#/$defs/SessionConfigSelectOption" + }, + "type": "array" + }, + { + "description": "A list of options grouped under headers.", + "items": { + "$ref": "#/$defs/SessionConfigSelectGroup" + }, + "type": "array" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nPossible values for a session configuration option." + }, + "SessionConfigValueId": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nUnique identifier for a session configuration option value.", + "type": "string" + }, "SessionForkCapabilities": { "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nCapabilities for the `session/fork` method.\n\nBy supplying `{}` it means that the agent supports forking of sessions.", "properties": { @@ -3221,6 +3488,24 @@ ], "type": "object" }, + { + "allOf": [ + { + "$ref": "#/$defs/ConfigOptionUpdate" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nSession configuration options have been updated.", + "properties": { + "sessionUpdate": { + "const": "config_option_update", + "type": "string" + } + }, + "required": [ + "sessionUpdate" + ], + "type": "object" + }, { "allOf": [ { @@ -3241,6 +3526,77 @@ } ] }, + "SetSessionConfigOptionRequest": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nRequest parameters for setting a session configuration option.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": [ + "object", + "null" + ] + }, + "configId": { + "allOf": [ + { + "$ref": "#/$defs/SessionConfigId" + } + ], + "description": "The ID of the configuration option to set." + }, + "sessionId": { + "allOf": [ + { + "$ref": "#/$defs/SessionId" + } + ], + "description": "The ID of the session to set the configuration option for." + }, + "value": { + "allOf": [ + { + "$ref": "#/$defs/SessionConfigValueId" + } + ], + "description": "The ID of the configuration option value to set." + } + }, + "required": [ + "sessionId", + "configId", + "value" + ], + "type": "object", + "x-method": "session/set_config_option", + "x-side": "agent" + }, + "SetSessionConfigOptionResponse": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nResponse to `session/set_config_option` method.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": [ + "object", + "null" + ] + }, + "configOptions": { + "description": "The full set of configuration options and their current values.", + "items": { + "$ref": "#/$defs/SessionConfigOption" + }, + "type": "array" + } + }, + "required": [ + "configOptions" + ], + "type": "object", + "x-method": "session/set_config_option", + "x-side": "agent" + }, "SetSessionModeRequest": { "description": "Request parameters for setting a session mode.", "properties": { diff --git a/scripts/gen_schema.py b/scripts/gen_schema.py index 2a951a2..36cbda7 100644 --- a/scripts/gen_schema.py +++ b/scripts/gen_schema.py @@ -17,8 +17,6 @@ VERSION_FILE = SCHEMA_DIR / "VERSION" SCHEMA_OUT = ROOT / "src" / "acp" / "schema.py" -BACKCOMPAT_MARKER = "# Backwards compatibility aliases" - # Pattern caches used when post-processing generated schema. FIELD_DECLARATION_PATTERN = re.compile(r"[A-Za-z_][A-Za-z0-9_]*\s*:") DESCRIPTION_PATTERN = re.compile( @@ -53,6 +51,7 @@ "McpServer2": "SseMcpServer", "RequestPermissionOutcome1": "DeniedOutcome", "RequestPermissionOutcome2": "AllowedOutcome", + "SessionConfigOption1": "SessionConfigOptionSelect", "SessionUpdate1": "UserMessageChunk", "SessionUpdate2": "AgentMessageChunk", "SessionUpdate3": "AgentThoughtChunk", @@ -61,16 +60,13 @@ "SessionUpdate6": "AgentPlanUpdate", "SessionUpdate7": "AvailableCommandsUpdate", "SessionUpdate8": "CurrentModeUpdate", - "SessionUpdate9": "SessionInfoUpdate", + "SessionUpdate9": "ConfigOptionUpdate", + "SessionUpdate10": "SessionInfoUpdate", "ToolCallContent1": "ContentToolCallContent", "ToolCallContent2": "FileEditToolCallContent", "ToolCallContent3": "TerminalToolCallContent", } -ALIASES_MAP = { - "StdioMcpServer": "McpServerStdio", -} - ENUM_LITERAL_MAP: dict[str, tuple[str, ...]] = { "PermissionOptionKind": ( "allow_once", @@ -172,7 +168,6 @@ def postprocess_generated_schema(output_path: Path) -> list[str]: header_block = _build_header_block() content = _strip_existing_header(raw_content) - content = _remove_backcompat_block(content) content = _remove_unused_models(content) content, leftover_classes = _rename_numbered_models(content) @@ -189,8 +184,7 @@ def postprocess_generated_schema(output_path: Path) -> list[str]: missing_targets = _find_missing_targets(content) content = _inject_enum_aliases(content) - alias_block = _build_alias_block() - final_content = header_block + content.rstrip() + "\n\n" + alias_block + final_content = header_block + content.rstrip() + "\n" if not final_content.endswith("\n"): final_content += "\n" output_path.write_text(final_content, encoding="utf-8") @@ -222,12 +216,6 @@ def _build_header_block() -> str: return "\n".join(header_lines) + "\n\n" -def _build_alias_block() -> str: - alias_lines = [f"{old} = {new}" for old, new in sorted(RENAME_MAP.items())] - alias_lines += [f"{old} = {new}" for old, new in sorted(ALIASES_MAP.items())] - return BACKCOMPAT_MARKER + "\n" + "\n".join(alias_lines) + "\n" - - def _strip_existing_header(content: str) -> str: existing_header = re.match(r"(#.*\n)+", content) if existing_header: @@ -235,13 +223,6 @@ def _strip_existing_header(content: str) -> str: return content.lstrip("\n") -def _remove_backcompat_block(content: str) -> str: - marker_index = content.find(BACKCOMPAT_MARKER) - if marker_index != -1: - return content[:marker_index].rstrip() - return content - - def _rename_numbered_models(content: str) -> tuple[str, list[str]]: renamed = content for old, new in sorted(RENAME_MAP.items(), key=lambda item: len(item[0]), reverse=True): diff --git a/src/acp/agent/connection.py b/src/acp/agent/connection.py index 587ad43..9fc55f2 100644 --- a/src/acp/agent/connection.py +++ b/src/acp/agent/connection.py @@ -12,6 +12,7 @@ AgentPlanUpdate, AgentThoughtChunk, AvailableCommandsUpdate, + ConfigOptionUpdate, CreateTerminalRequest, CreateTerminalResponse, CurrentModeUpdate, @@ -85,6 +86,7 @@ async def session_update( | AgentPlanUpdate | AvailableCommandsUpdate | CurrentModeUpdate + | ConfigOptionUpdate | SessionInfoUpdate, **kwargs: Any, ) -> None: diff --git a/src/acp/interfaces.py b/src/acp/interfaces.py index 74c2fe5..6d143fe 100644 --- a/src/acp/interfaces.py +++ b/src/acp/interfaces.py @@ -12,6 +12,7 @@ AvailableCommandsUpdate, CancelNotification, ClientCapabilities, + ConfigOptionUpdate, CreateTerminalRequest, CreateTerminalResponse, CurrentModeUpdate, @@ -88,6 +89,7 @@ async def session_update( | AgentPlanUpdate | AvailableCommandsUpdate | CurrentModeUpdate + | ConfigOptionUpdate | SessionInfoUpdate, **kwargs: Any, ) -> None: ... diff --git a/src/acp/meta.py b/src/acp/meta.py index d5512a1..142f2f1 100644 --- a/src/acp/meta.py +++ b/src/acp/meta.py @@ -1,5 +1,5 @@ # Generated from schema/meta.json. Do not edit by hand. -# Schema ref: refs/tags/v0.10.3 +# Schema ref: refs/tags/v0.10.5 AGENT_METHODS = { "authenticate": "authenticate", "initialize": "initialize", @@ -10,6 +10,7 @@ "session_new": "session/new", "session_prompt": "session/prompt", "session_resume": "session/resume", + "session_set_config_option": "session/set_config_option", "session_set_mode": "session/set_mode", "session_set_model": "session/set_model", } diff --git a/src/acp/schema.py b/src/acp/schema.py index aaa7c6a..314ccd9 100644 --- a/src/acp/schema.py +++ b/src/acp/schema.py @@ -1,5 +1,5 @@ # Generated from schema/schema.json. Do not edit by hand. -# Schema ref: refs/tags/v0.10.3 +# Schema ref: refs/tags/v0.10.5 from __future__ import annotations @@ -651,6 +651,36 @@ class SessionInfoUpdate(_SessionInfoUpdate): session_update: Annotated[Literal["session_info_update"], Field(alias="sessionUpdate")] +class SetSessionConfigOptionRequest(BaseModel): + # The _meta property is reserved by ACP to allow clients and agents to attach additional + # metadata to their interactions. Implementations MUST NOT make assumptions about values at + # these keys. + # + # See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + field_meta: Annotated[ + Optional[Dict[str, Any]], + Field( + alias="_meta", + description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + ), + ] = None + # The ID of the configuration option to set. + config_id: Annotated[ + str, + Field(alias="configId", description="The ID of the configuration option to set."), + ] + # The ID of the session to set the configuration option for. + session_id: Annotated[ + str, + Field( + alias="sessionId", + description="The ID of the session to set the configuration option for.", + ), + ] + # The ID of the configuration option value to set. + value: Annotated[str, Field(description="The ID of the configuration option value to set.")] + + class SetSessionModeRequest(BaseModel): # The _meta property is reserved by ACP to allow clients and agents to attach additional # metadata to their interactions. Implementations MUST NOT make assumptions about values at @@ -1564,6 +1594,27 @@ class SessionCapabilities(BaseModel): ] = None +class SessionConfigSelectOption(BaseModel): + # The _meta property is reserved by ACP to allow clients and agents to attach additional + # metadata to their interactions. Implementations MUST NOT make assumptions about values at + # these keys. + # + # See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + field_meta: Annotated[ + Optional[Dict[str, Any]], + Field( + alias="_meta", + description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + ), + ] = None + # Optional description for this option value. + description: Annotated[Optional[str], Field(description="Optional description for this option value.")] = None + # Human-readable label for this option value. + name: Annotated[str, Field(description="Human-readable label for this option value.")] + # Unique identifier for this option value. + value: Annotated[str, Field(description="Unique identifier for this option value.")] + + class SessionMode(BaseModel): # The _meta property is reserved by ACP to allow clients and agents to attach additional # metadata to their interactions. Implementations MUST NOT make assumptions about values at @@ -1863,49 +1914,6 @@ class ForkSessionRequest(BaseModel): session_id: Annotated[str, Field(alias="sessionId", description="The ID of the session to fork.")] -class ForkSessionResponse(BaseModel): - # The _meta property is reserved by ACP to allow clients and agents to attach additional - # metadata to their interactions. Implementations MUST NOT make assumptions about values at - # these keys. - # - # See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) - field_meta: Annotated[ - Optional[Dict[str, Any]], - Field( - alias="_meta", - description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", - ), - ] = None - # **UNSTABLE** - # - # This capability is not part of the spec yet, and may be removed or changed at any point. - # - # Initial model state if supported by the Agent - models: Annotated[ - Optional[SessionModelState], - Field( - description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial model state if supported by the Agent" - ), - ] = None - # Initial mode state if supported by the Agent - # - # See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes) - modes: Annotated[ - Optional[SessionModeState], - Field( - description="Initial mode state if supported by the Agent\n\nSee protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)" - ), - ] = None - # Unique identifier for the newly created forked session. - session_id: Annotated[ - str, - Field( - alias="sessionId", - description="Unique identifier for the newly created forked session.", - ), - ] - - class InitializeResponse(BaseModel): # The _meta property is reserved by ACP to allow clients and agents to attach additional # metadata to their interactions. Implementations MUST NOT make assumptions about values at @@ -1987,86 +1995,6 @@ class LoadSessionRequest(BaseModel): session_id: Annotated[str, Field(alias="sessionId", description="The ID of the session to load.")] -class LoadSessionResponse(BaseModel): - # The _meta property is reserved by ACP to allow clients and agents to attach additional - # metadata to their interactions. Implementations MUST NOT make assumptions about values at - # these keys. - # - # See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) - field_meta: Annotated[ - Optional[Dict[str, Any]], - Field( - alias="_meta", - description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", - ), - ] = None - # **UNSTABLE** - # - # This capability is not part of the spec yet, and may be removed or changed at any point. - # - # Initial model state if supported by the Agent - models: Annotated[ - Optional[SessionModelState], - Field( - description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial model state if supported by the Agent" - ), - ] = None - # Initial mode state if supported by the Agent - # - # See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes) - modes: Annotated[ - Optional[SessionModeState], - Field( - description="Initial mode state if supported by the Agent\n\nSee protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)" - ), - ] = None - - -class NewSessionResponse(BaseModel): - # The _meta property is reserved by ACP to allow clients and agents to attach additional - # metadata to their interactions. Implementations MUST NOT make assumptions about values at - # these keys. - # - # See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) - field_meta: Annotated[ - Optional[Dict[str, Any]], - Field( - alias="_meta", - description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", - ), - ] = None - # **UNSTABLE** - # - # This capability is not part of the spec yet, and may be removed or changed at any point. - # - # Initial model state if supported by the Agent - models: Annotated[ - Optional[SessionModelState], - Field( - description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial model state if supported by the Agent" - ), - ] = None - # Initial mode state if supported by the Agent - # - # See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes) - modes: Annotated[ - Optional[SessionModeState], - Field( - description="Initial mode state if supported by the Agent\n\nSee protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)" - ), - ] = None - # Unique identifier for the created session. - # - # Used in all subsequent requests for this conversation. - session_id: Annotated[ - str, - Field( - alias="sessionId", - description="Unique identifier for the created session.\n\nUsed in all subsequent requests for this conversation.", - ), - ] - - class Plan(BaseModel): # The _meta property is reserved by ACP to allow clients and agents to attach additional # metadata to their interactions. Implementations MUST NOT make assumptions about values at @@ -2092,7 +2020,7 @@ class Plan(BaseModel): ] -class ResumeSessionResponse(BaseModel): +class SessionConfigSelectGroup(BaseModel): # The _meta property is reserved by ACP to allow clients and agents to attach additional # metadata to their interactions. Implementations MUST NOT make assumptions about values at # these keys. @@ -2105,26 +2033,15 @@ class ResumeSessionResponse(BaseModel): description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", ), ] = None - # **UNSTABLE** - # - # This capability is not part of the spec yet, and may be removed or changed at any point. - # - # Initial model state if supported by the Agent - models: Annotated[ - Optional[SessionModelState], - Field( - description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial model state if supported by the Agent" - ), - ] = None - # Initial mode state if supported by the Agent - # - # See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes) - modes: Annotated[ - Optional[SessionModeState], - Field( - description="Initial mode state if supported by the Agent\n\nSee protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)" - ), - ] = None + # Unique identifier for this group. + group: Annotated[str, Field(description="Unique identifier for this group.")] + # Human-readable label for this group. + name: Annotated[str, Field(description="Human-readable label for this group.")] + # The set of option values in this group. + options: Annotated[ + List[SessionConfigSelectOption], + Field(description="The set of option values in this group."), + ] class AgentPlanUpdate(Plan): @@ -2135,52 +2052,6 @@ class AvailableCommandsUpdate(_AvailableCommandsUpdate): session_update: Annotated[Literal["available_commands_update"], Field(alias="sessionUpdate")] -class AgentResponseMessage(BaseModel): - # JSON RPC Request Id - # - # An identifier established by the Client that MUST contain a String, Number, or NULL value if included. If it is not included it is assumed to be a notification. The value SHOULD normally not be Null [1] and Numbers SHOULD NOT contain fractional parts [2] - # - # The Server MUST reply with the same value in the Response object if included. This member is used to correlate the context between the two objects. - # - # [1] The use of Null as a value for the id member in a Request object is discouraged, because this specification uses a value of Null for Responses with an unknown id. Also, because JSON-RPC 1.0 uses an id value of Null for Notifications this could cause confusion in handling. - # - # [2] Fractional parts may be problematic, since many decimal fractions cannot be represented exactly as binary fractions. - id: Annotated[ - Optional[Union[int, str]], - Field( - description="JSON RPC Request Id\n\nAn identifier established by the Client that MUST contain a String, Number, or NULL value if included. If it is not included it is assumed to be a notification. The value SHOULD normally not be Null [1] and Numbers SHOULD NOT contain fractional parts [2]\n\nThe Server MUST reply with the same value in the Response object if included. This member is used to correlate the context between the two objects.\n\n[1] The use of Null as a value for the id member in a Request object is discouraged, because this specification uses a value of Null for Responses with an unknown id. Also, because JSON-RPC 1.0 uses an id value of Null for Notifications this could cause confusion in handling.\n\n[2] Fractional parts may be problematic, since many decimal fractions cannot be represented exactly as binary fractions." - ), - ] = None - # All possible responses that an agent can send to a client. - # - # This enum is used internally for routing RPC responses. You typically won't need - # to use this directly - the responses are handled automatically by the connection. - # - # These are responses to the corresponding `ClientRequest` variants. - result: Annotated[ - Union[ - InitializeResponse, - AuthenticateResponse, - NewSessionResponse, - LoadSessionResponse, - ListSessionsResponse, - ForkSessionResponse, - ResumeSessionResponse, - SetSessionModeResponse, - PromptResponse, - SetSessionModelResponse, - Any, - ], - Field( - description="All possible responses that an agent can send to a client.\n\nThis enum is used internally for routing RPC responses. You typically won't need\nto use this directly - the responses are handled automatically by the connection.\n\nThese are responses to the corresponding `ClientRequest` variants." - ), - ] - - -class AgentResponse(RootModel[Union[AgentResponseMessage, AgentErrorMessage]]): - root: Union[AgentResponseMessage, AgentErrorMessage] - - class EmbeddedResourceContentBlock(EmbeddedResource): type: Literal["resource"] @@ -2257,6 +2128,16 @@ class PromptRequest(BaseModel): ] +class SessionConfigSelect(BaseModel): + # The currently selected value. + current_value: Annotated[str, Field(alias="currentValue", description="The currently selected value.")] + # The set of selectable options. + options: Annotated[ + Union[List[SessionConfigSelectOption], List[SessionConfigSelectGroup]], + Field(description="The set of selectable options."), + ] + + class UserMessageChunk(ContentChunk): session_update: Annotated[Literal["user_message_chunk"], Field(alias="sessionUpdate")] @@ -2296,6 +2177,7 @@ class ClientRequest(BaseModel): ForkSessionRequest, ResumeSessionRequest, SetSessionModeRequest, + SetSessionConfigOptionRequest, PromptRequest, SetSessionModelRequest, Any, @@ -2325,11 +2207,7 @@ class Content(BaseModel): ] -class ContentToolCallContent(Content): - type: Literal["content"] - - -class ToolCallUpdate(BaseModel): +class SessionConfigOptionSelect(SessionConfigSelect): # The _meta property is reserved by ACP to allow clients and agents to attach additional # metadata to their interactions. Implementations MUST NOT make assumptions about values at # these keys. @@ -2342,24 +2220,91 @@ class ToolCallUpdate(BaseModel): description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", ), ] = None - # Replace the content collection. - content: Annotated[ - Optional[List[Union[ContentToolCallContent, FileEditToolCallContent, TerminalToolCallContent]]], - Field(description="Replace the content collection."), - ] = None - # Update the tool kind. - kind: Annotated[Optional[ToolKind], Field(description="Update the tool kind.")] = None - # Replace the locations collection. - locations: Annotated[ - Optional[List[ToolCallLocation]], - Field(description="Replace the locations collection."), + # Optional description for the Client to display to the user. + description: Annotated[ + Optional[str], + Field(description="Optional description for the Client to display to the user."), ] = None - # Update the raw input. - raw_input: Annotated[Optional[Any], Field(alias="rawInput", description="Update the raw input.")] = None - # Update the raw output. - raw_output: Annotated[Optional[Any], Field(alias="rawOutput", description="Update the raw output.")] = None - # Update the execution status. - status: Annotated[Optional[ToolCallStatus], Field(description="Update the execution status.")] = None + # Unique identifier for the configuration option. + id: Annotated[str, Field(description="Unique identifier for the configuration option.")] + # Human-readable label for the option. + name: Annotated[str, Field(description="Human-readable label for the option.")] + type: Literal["select"] + + +class SessionConfigOption(RootModel[SessionConfigOptionSelect]): + # **UNSTABLE** + # + # This capability is not part of the spec yet, and may be removed or changed at any point. + # + # A session configuration option selector and its current state. + root: Annotated[ + SessionConfigOptionSelect, + Field( + description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nA session configuration option selector and its current state.", + discriminator="type", + ), + ] + + +class SetSessionConfigOptionResponse(BaseModel): + # The _meta property is reserved by ACP to allow clients and agents to attach additional + # metadata to their interactions. Implementations MUST NOT make assumptions about values at + # these keys. + # + # See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + field_meta: Annotated[ + Optional[Dict[str, Any]], + Field( + alias="_meta", + description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + ), + ] = None + # The full set of configuration options and their current values. + config_options: Annotated[ + List[SessionConfigOption], + Field( + alias="configOptions", + description="The full set of configuration options and their current values.", + ), + ] + + +class ContentToolCallContent(Content): + type: Literal["content"] + + +class ToolCallUpdate(BaseModel): + # The _meta property is reserved by ACP to allow clients and agents to attach additional + # metadata to their interactions. Implementations MUST NOT make assumptions about values at + # these keys. + # + # See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + field_meta: Annotated[ + Optional[Dict[str, Any]], + Field( + alias="_meta", + description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + ), + ] = None + # Replace the content collection. + content: Annotated[ + Optional[List[Union[ContentToolCallContent, FileEditToolCallContent, TerminalToolCallContent]]], + Field(description="Replace the content collection."), + ] = None + # Update the tool kind. + kind: Annotated[Optional[ToolKind], Field(description="Update the tool kind.")] = None + # Replace the locations collection. + locations: Annotated[ + Optional[List[ToolCallLocation]], + Field(description="Replace the locations collection."), + ] = None + # Update the raw input. + raw_input: Annotated[Optional[Any], Field(alias="rawInput", description="Update the raw input.")] = None + # Update the raw output. + raw_output: Annotated[Optional[Any], Field(alias="rawOutput", description="Update the raw output.")] = None + # Update the execution status. + status: Annotated[Optional[ToolCallStatus], Field(description="Update the execution status.")] = None # Update the human-readable title. title: Annotated[Optional[str], Field(description="Update the human-readable title.")] = None # The ID of the tool call being updated. @@ -2369,6 +2314,188 @@ class ToolCallUpdate(BaseModel): ] +class _ConfigOptionUpdate(BaseModel): + # The _meta property is reserved by ACP to allow clients and agents to attach additional + # metadata to their interactions. Implementations MUST NOT make assumptions about values at + # these keys. + # + # See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + field_meta: Annotated[ + Optional[Dict[str, Any]], + Field( + alias="_meta", + description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + ), + ] = None + # The full set of configuration options and their current values. + config_options: Annotated[ + List[SessionConfigOption], + Field( + alias="configOptions", + description="The full set of configuration options and their current values.", + ), + ] + + +class ForkSessionResponse(BaseModel): + # The _meta property is reserved by ACP to allow clients and agents to attach additional + # metadata to their interactions. Implementations MUST NOT make assumptions about values at + # these keys. + # + # See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + field_meta: Annotated[ + Optional[Dict[str, Any]], + Field( + alias="_meta", + description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + ), + ] = None + # **UNSTABLE** + # + # This capability is not part of the spec yet, and may be removed or changed at any point. + # + # Initial session configuration options if supported by the Agent. + config_options: Annotated[ + Optional[List[SessionConfigOption]], + Field( + alias="configOptions", + description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + ), + ] = None + # **UNSTABLE** + # + # This capability is not part of the spec yet, and may be removed or changed at any point. + # + # Initial model state if supported by the Agent + models: Annotated[ + Optional[SessionModelState], + Field( + description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial model state if supported by the Agent" + ), + ] = None + # Initial mode state if supported by the Agent + # + # See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes) + modes: Annotated[ + Optional[SessionModeState], + Field( + description="Initial mode state if supported by the Agent\n\nSee protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)" + ), + ] = None + # Unique identifier for the newly created forked session. + session_id: Annotated[ + str, + Field( + alias="sessionId", + description="Unique identifier for the newly created forked session.", + ), + ] + + +class LoadSessionResponse(BaseModel): + # The _meta property is reserved by ACP to allow clients and agents to attach additional + # metadata to their interactions. Implementations MUST NOT make assumptions about values at + # these keys. + # + # See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + field_meta: Annotated[ + Optional[Dict[str, Any]], + Field( + alias="_meta", + description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + ), + ] = None + # **UNSTABLE** + # + # This capability is not part of the spec yet, and may be removed or changed at any point. + # + # Initial session configuration options if supported by the Agent. + config_options: Annotated[ + Optional[List[SessionConfigOption]], + Field( + alias="configOptions", + description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + ), + ] = None + # **UNSTABLE** + # + # This capability is not part of the spec yet, and may be removed or changed at any point. + # + # Initial model state if supported by the Agent + models: Annotated[ + Optional[SessionModelState], + Field( + description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial model state if supported by the Agent" + ), + ] = None + # Initial mode state if supported by the Agent + # + # See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes) + modes: Annotated[ + Optional[SessionModeState], + Field( + description="Initial mode state if supported by the Agent\n\nSee protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)" + ), + ] = None + + +class NewSessionResponse(BaseModel): + # The _meta property is reserved by ACP to allow clients and agents to attach additional + # metadata to their interactions. Implementations MUST NOT make assumptions about values at + # these keys. + # + # See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + field_meta: Annotated[ + Optional[Dict[str, Any]], + Field( + alias="_meta", + description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + ), + ] = None + # **UNSTABLE** + # + # This capability is not part of the spec yet, and may be removed or changed at any point. + # + # Initial session configuration options if supported by the Agent. + config_options: Annotated[ + Optional[List[SessionConfigOption]], + Field( + alias="configOptions", + description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + ), + ] = None + # **UNSTABLE** + # + # This capability is not part of the spec yet, and may be removed or changed at any point. + # + # Initial model state if supported by the Agent + models: Annotated[ + Optional[SessionModelState], + Field( + description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial model state if supported by the Agent" + ), + ] = None + # Initial mode state if supported by the Agent + # + # See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes) + modes: Annotated[ + Optional[SessionModeState], + Field( + description="Initial mode state if supported by the Agent\n\nSee protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)" + ), + ] = None + # Unique identifier for the created session. + # + # Used in all subsequent requests for this conversation. + session_id: Annotated[ + str, + Field( + alias="sessionId", + description="Unique identifier for the created session.\n\nUsed in all subsequent requests for this conversation.", + ), + ] + + class RequestPermissionRequest(BaseModel): # The _meta property is reserved by ACP to allow clients and agents to attach additional # metadata to their interactions. Implementations MUST NOT make assumptions about values at @@ -2399,10 +2526,61 @@ class RequestPermissionRequest(BaseModel): ] +class ResumeSessionResponse(BaseModel): + # The _meta property is reserved by ACP to allow clients and agents to attach additional + # metadata to their interactions. Implementations MUST NOT make assumptions about values at + # these keys. + # + # See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + field_meta: Annotated[ + Optional[Dict[str, Any]], + Field( + alias="_meta", + description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + ), + ] = None + # **UNSTABLE** + # + # This capability is not part of the spec yet, and may be removed or changed at any point. + # + # Initial session configuration options if supported by the Agent. + config_options: Annotated[ + Optional[List[SessionConfigOption]], + Field( + alias="configOptions", + description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + ), + ] = None + # **UNSTABLE** + # + # This capability is not part of the spec yet, and may be removed or changed at any point. + # + # Initial model state if supported by the Agent + models: Annotated[ + Optional[SessionModelState], + Field( + description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial model state if supported by the Agent" + ), + ] = None + # Initial mode state if supported by the Agent + # + # See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes) + modes: Annotated[ + Optional[SessionModeState], + Field( + description="Initial mode state if supported by the Agent\n\nSee protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)" + ), + ] = None + + class ToolCallProgress(ToolCallUpdate): session_update: Annotated[Literal["tool_call_update"], Field(alias="sessionUpdate")] +class ConfigOptionUpdate(_ConfigOptionUpdate): + session_update: Annotated[Literal["config_option_update"], Field(alias="sessionUpdate")] + + class ToolCall(BaseModel): # The _meta property is reserved by ACP to allow clients and agents to attach additional # metadata to their interactions. Implementations MUST NOT make assumptions about values at @@ -2494,6 +2672,53 @@ class AgentRequest(BaseModel): ] = None +class AgentResponseMessage(BaseModel): + # JSON RPC Request Id + # + # An identifier established by the Client that MUST contain a String, Number, or NULL value if included. If it is not included it is assumed to be a notification. The value SHOULD normally not be Null [1] and Numbers SHOULD NOT contain fractional parts [2] + # + # The Server MUST reply with the same value in the Response object if included. This member is used to correlate the context between the two objects. + # + # [1] The use of Null as a value for the id member in a Request object is discouraged, because this specification uses a value of Null for Responses with an unknown id. Also, because JSON-RPC 1.0 uses an id value of Null for Notifications this could cause confusion in handling. + # + # [2] Fractional parts may be problematic, since many decimal fractions cannot be represented exactly as binary fractions. + id: Annotated[ + Optional[Union[int, str]], + Field( + description="JSON RPC Request Id\n\nAn identifier established by the Client that MUST contain a String, Number, or NULL value if included. If it is not included it is assumed to be a notification. The value SHOULD normally not be Null [1] and Numbers SHOULD NOT contain fractional parts [2]\n\nThe Server MUST reply with the same value in the Response object if included. This member is used to correlate the context between the two objects.\n\n[1] The use of Null as a value for the id member in a Request object is discouraged, because this specification uses a value of Null for Responses with an unknown id. Also, because JSON-RPC 1.0 uses an id value of Null for Notifications this could cause confusion in handling.\n\n[2] Fractional parts may be problematic, since many decimal fractions cannot be represented exactly as binary fractions." + ), + ] = None + # All possible responses that an agent can send to a client. + # + # This enum is used internally for routing RPC responses. You typically won't need + # to use this directly - the responses are handled automatically by the connection. + # + # These are responses to the corresponding `ClientRequest` variants. + result: Annotated[ + Union[ + InitializeResponse, + AuthenticateResponse, + NewSessionResponse, + LoadSessionResponse, + ListSessionsResponse, + ForkSessionResponse, + ResumeSessionResponse, + SetSessionModeResponse, + SetSessionConfigOptionResponse, + PromptResponse, + SetSessionModelResponse, + Any, + ], + Field( + description="All possible responses that an agent can send to a client.\n\nThis enum is used internally for routing RPC responses. You typically won't need\nto use this directly - the responses are handled automatically by the connection.\n\nThese are responses to the corresponding `ClientRequest` variants." + ), + ] + + +class AgentResponse(RootModel[Union[AgentResponseMessage, AgentErrorMessage]]): + root: Union[AgentResponseMessage, AgentErrorMessage] + + class ToolCallStart(ToolCall): session_update: Annotated[Literal["tool_call"], Field(alias="sessionUpdate")] @@ -2530,6 +2755,7 @@ class SessionNotification(BaseModel): AgentPlanUpdate, AvailableCommandsUpdate, CurrentModeUpdate, + ConfigOptionUpdate, SessionInfoUpdate, ], Field(description="The actual update content.", discriminator="session_update"), @@ -2539,32 +2765,3 @@ class SessionNotification(BaseModel): class AgentNotification(BaseModel): method: str params: Optional[Union[SessionNotification, Any]] = None - - -# Backwards compatibility aliases -AgentResponse1 = AgentResponseMessage -AgentResponse2 = AgentErrorMessage -ClientResponse1 = ClientResponseMessage -ClientResponse2 = ClientErrorMessage -ContentBlock1 = TextContentBlock -ContentBlock2 = ImageContentBlock -ContentBlock3 = AudioContentBlock -ContentBlock4 = ResourceContentBlock -ContentBlock5 = EmbeddedResourceContentBlock -McpServer1 = HttpMcpServer -McpServer2 = SseMcpServer -RequestPermissionOutcome1 = DeniedOutcome -RequestPermissionOutcome2 = AllowedOutcome -SessionUpdate1 = UserMessageChunk -SessionUpdate2 = AgentMessageChunk -SessionUpdate3 = AgentThoughtChunk -SessionUpdate4 = ToolCallStart -SessionUpdate5 = ToolCallProgress -SessionUpdate6 = AgentPlanUpdate -SessionUpdate7 = AvailableCommandsUpdate -SessionUpdate8 = CurrentModeUpdate -SessionUpdate9 = SessionInfoUpdate -ToolCallContent1 = ContentToolCallContent -ToolCallContent2 = FileEditToolCallContent -ToolCallContent3 = TerminalToolCallContent -StdioMcpServer = McpServerStdio diff --git a/tests/conftest.py b/tests/conftest.py index 654b8d1..6cce0b1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -34,6 +34,7 @@ AudioContentBlock, AvailableCommandsUpdate, ClientCapabilities, + ConfigOptionUpdate, CurrentModeUpdate, DeniedOutcome, EmbeddedResourceContentBlock, @@ -173,6 +174,7 @@ async def session_update( | AgentPlanUpdate | AvailableCommandsUpdate | CurrentModeUpdate + | ConfigOptionUpdate | SessionInfoUpdate, **kwargs: Any, ) -> None: diff --git a/tests/golden/session_update_config_option_update.json b/tests/golden/session_update_config_option_update.json new file mode 100644 index 0000000..84fb2b8 --- /dev/null +++ b/tests/golden/session_update_config_option_update.json @@ -0,0 +1,55 @@ +{ + "sessionUpdate": "config_option_update", + "configOptions": [ + { + "type": "select", + "id": "model", + "name": "Model", + "description": "Choose a model", + "currentValue": "gpt-4o-mini", + "options": [ + { + "name": "GPT-4o Mini", + "value": "gpt-4o-mini" + }, + { + "name": "GPT-4o", + "value": "gpt-4o", + "description": "Highest quality" + } + ] + }, + { + "type": "select", + "id": "mode", + "name": "Mode", + "currentValue": "fast", + "options": [ + { + "group": "speed", + "name": "Speed", + "options": [ + { + "name": "Fast", + "value": "fast" + }, + { + "name": "Balanced", + "value": "balanced" + } + ] + }, + { + "group": "quality", + "name": "Quality", + "options": [ + { + "name": "High", + "value": "high" + } + ] + } + ] + } + ] +} diff --git a/tests/golden/set_session_config_option_request.json b/tests/golden/set_session_config_option_request.json new file mode 100644 index 0000000..fddd447 --- /dev/null +++ b/tests/golden/set_session_config_option_request.json @@ -0,0 +1,5 @@ +{ + "sessionId": "sess-123", + "configId": "model", + "value": "gpt-4o-mini" +} diff --git a/tests/golden/set_session_config_option_response.json b/tests/golden/set_session_config_option_response.json new file mode 100644 index 0000000..9c6564d --- /dev/null +++ b/tests/golden/set_session_config_option_response.json @@ -0,0 +1,20 @@ +{ + "configOptions": [ + { + "type": "select", + "id": "mode", + "name": "Mode", + "currentValue": "balanced", + "options": [ + { + "name": "Fast", + "value": "fast" + }, + { + "name": "Balanced", + "value": "balanced" + } + ] + } + ] +} diff --git a/tests/test_golden.py b/tests/test_golden.py index 430bd04..181945f 100644 --- a/tests/test_golden.py +++ b/tests/test_golden.py @@ -35,6 +35,7 @@ AllowedOutcome, AudioContentBlock, CancelNotification, + ConfigOptionUpdate, ContentToolCallContent, DeniedOutcome, EmbeddedResourceContentBlock, @@ -50,6 +51,8 @@ RequestPermissionRequest, RequestPermissionResponse, ResourceContentBlock, + SetSessionConfigOptionRequest, + SetSessionConfigOptionResponse, TerminalToolCallContent, TextContentBlock, ToolCallLocation, @@ -84,6 +87,7 @@ "request_permission_response_selected": RequestPermissionResponse, "session_update_agent_message_chunk": AgentMessageChunk, "session_update_agent_thought_chunk": AgentThoughtChunk, + "session_update_config_option_update": ConfigOptionUpdate, "session_update_plan": AgentPlanUpdate, "session_update_tool_call": ToolCallStart, "session_update_tool_call_edit": ToolCallStart, @@ -92,6 +96,8 @@ "session_update_tool_call_update_content": ToolCallProgress, "session_update_tool_call_update_more_fields": ToolCallProgress, "session_update_user_message_chunk": UserMessageChunk, + "set_session_config_option_request": SetSessionConfigOptionRequest, + "set_session_config_option_response": SetSessionConfigOptionResponse, "tool_content_content_text": ContentToolCallContent, "tool_content_diff": FileEditToolCallContent, "tool_content_diff_no_old": FileEditToolCallContent, From a7aa7c310ceb0ba9e6dffa03408d7271f9e5803a Mon Sep 17 00:00:00 2001 From: Frost Ming Date: Thu, 8 Jan 2026 13:57:39 +0800 Subject: [PATCH 2/8] fix: remove TerminalHandle (#56) fix: Eliminate the usage of type casting by making Agent/Client side connection fully compatible with the protocol. Signed-off-by: Frost Ming --- src/acp/__init__.py | 2 -- src/acp/agent/connection.py | 16 +++++---- src/acp/client/connection.py | 10 ++++-- src/acp/core.py | 2 -- src/acp/interfaces.py | 3 +- src/acp/terminal.py | 69 ------------------------------------ 6 files changed, 19 insertions(+), 83 deletions(-) delete mode 100644 src/acp/terminal.py diff --git a/src/acp/__init__.py b/src/acp/__init__.py index 71a693f..2d09a7d 100644 --- a/src/acp/__init__.py +++ b/src/acp/__init__.py @@ -4,7 +4,6 @@ Agent, Client, RequestError, - TerminalHandle, connect_to_agent, run_agent, ) @@ -133,7 +132,6 @@ "RequestError", "Agent", "Client", - "TerminalHandle", # stdio helper "stdio_streams", "spawn_stdio_connection", diff --git a/src/acp/agent/connection.py b/src/acp/agent/connection.py index 9fc55f2..30b1092 100644 --- a/src/acp/agent/connection.py +++ b/src/acp/agent/connection.py @@ -39,7 +39,6 @@ WriteTextFileRequest, WriteTextFileResponse, ) -from ..terminal import TerminalHandle from ..utils import compatible_class, notify_model, param_model, request_model, request_optional_model from .router import build_agent_router @@ -50,7 +49,9 @@ @final @compatible_class class AgentSideConnection: - """Agent-side connection wrapper that dispatches JSON-RPC messages to a Client implementation.""" + """Agent-side connection wrapper that dispatches JSON-RPC messages to a Client implementation. + The agent can use this connection to communicate with the Client so it behaves like a Client. + """ def __init__( self, @@ -62,7 +63,7 @@ def __init__( use_unstable_protocol: bool = False, **connection_kwargs: Any, ) -> None: - agent = to_agent(cast(Client, self)) if callable(to_agent) else to_agent + agent = to_agent(self) if callable(to_agent) else to_agent if not isinstance(input_stream, asyncio.StreamWriter) or not isinstance(output_stream, asyncio.StreamReader): raise TypeError(_AGENT_CONNECTION_ERROR) handler = build_agent_router(cast(Agent, agent), use_unstable_protocol=use_unstable_protocol) @@ -141,8 +142,8 @@ async def create_terminal( env: list[EnvVariable] | None = None, output_byte_limit: int | None = None, **kwargs: Any, - ) -> TerminalHandle: - create_response = await request_model( + ) -> CreateTerminalResponse: + return await request_model( self._conn, CLIENT_METHODS["terminal_create"], CreateTerminalRequest( @@ -156,7 +157,6 @@ async def create_terminal( ), CreateTerminalResponse, ) - return TerminalHandle(create_response.terminal_id, session_id, self._conn) @param_model(TerminalOutputRequest) async def terminal_output(self, session_id: str, terminal_id: str, **kwargs: Any) -> TerminalOutputResponse: @@ -214,3 +214,7 @@ async def __aenter__(self) -> AgentSideConnection: async def __aexit__(self, exc_type, exc, tb) -> None: await self.close() + + def on_connect(self, conn: Agent) -> None: + # A dummy method to match the Client protocol + pass diff --git a/src/acp/client/connection.py b/src/acp/client/connection.py index 7a5cdcb..c71da96 100644 --- a/src/acp/client/connection.py +++ b/src/acp/client/connection.py @@ -50,7 +50,9 @@ @final @compatible_class class ClientSideConnection: - """Client-side connection wrapper that dispatches JSON-RPC messages to an Agent implementation.""" + """Client-side connection wrapper that dispatches JSON-RPC messages to an Agent implementation. + The client can use this connection to communicate with the Agent so it behaves like an Agent. + """ def __init__( self, @@ -63,7 +65,7 @@ def __init__( ) -> None: if not isinstance(input_stream, asyncio.StreamWriter) or not isinstance(output_stream, asyncio.StreamReader): raise TypeError(_CLIENT_CONNECTION_ERROR) - client = to_client(cast(Agent, self)) if callable(to_client) else to_client + client = to_client(self) if callable(to_client) else to_client handler = build_client_router(cast(Client, client), use_unstable_protocol=use_unstable_protocol) self._conn = Connection(handler, input_stream, output_stream, **connection_kwargs) if on_connect := getattr(client, "on_connect", None): @@ -221,3 +223,7 @@ async def __aenter__(self) -> ClientSideConnection: async def __aexit__(self, exc_type, exc, tb) -> None: await self.close() + + def on_connect(self, conn: Client) -> None: + # A dummy method to match the Agent protocol + pass diff --git a/src/acp/core.py b/src/acp/core.py index 1d440de..42632f6 100644 --- a/src/acp/core.py +++ b/src/acp/core.py @@ -14,7 +14,6 @@ from .connection import Connection, JsonValue, MethodHandler from .exceptions import RequestError from .interfaces import Agent, Client -from .terminal import TerminalHandle __all__ = [ "Agent", @@ -25,7 +24,6 @@ "JsonValue", "MethodHandler", "RequestError", - "TerminalHandle", "connect_to_agent", "run_agent", ] diff --git a/src/acp/interfaces.py b/src/acp/interfaces.py index 6d143fe..5cc45ff 100644 --- a/src/acp/interfaces.py +++ b/src/acp/interfaces.py @@ -65,7 +65,6 @@ WriteTextFileRequest, WriteTextFileResponse, ) -from .terminal import TerminalHandle from .utils import param_model __all__ = ["Agent", "Client"] @@ -114,7 +113,7 @@ async def create_terminal( env: list[EnvVariable] | None = None, output_byte_limit: int | None = None, **kwargs: Any, - ) -> CreateTerminalResponse | TerminalHandle: ... + ) -> CreateTerminalResponse: ... @param_model(TerminalOutputRequest) async def terminal_output(self, session_id: str, terminal_id: str, **kwargs: Any) -> TerminalOutputResponse: ... diff --git a/src/acp/terminal.py b/src/acp/terminal.py deleted file mode 100644 index fdc4777..0000000 --- a/src/acp/terminal.py +++ /dev/null @@ -1,69 +0,0 @@ -from __future__ import annotations - -from contextlib import suppress - -from .connection import Connection -from .meta import CLIENT_METHODS -from .schema import ( - KillTerminalCommandResponse, - ReleaseTerminalResponse, - TerminalOutputResponse, - WaitForTerminalExitResponse, -) - -__all__ = ["TerminalHandle"] - - -class TerminalHandle: - def __init__(self, terminal_id: str, session_id: str, conn: Connection) -> None: - self.id = terminal_id - self._session_id = session_id - self._conn = conn - - @property - def terminal_id(self) -> str: - return self.id - - async def current_output(self) -> TerminalOutputResponse: - response = await self._conn.send_request( - CLIENT_METHODS["terminal_output"], - {"sessionId": self._session_id, "terminalId": self.id}, - ) - return TerminalOutputResponse.model_validate(response) - - async def wait_for_exit(self) -> WaitForTerminalExitResponse: - response = await self._conn.send_request( - CLIENT_METHODS["terminal_wait_for_exit"], - {"sessionId": self._session_id, "terminalId": self.id}, - ) - return WaitForTerminalExitResponse.model_validate(response) - - async def kill(self) -> KillTerminalCommandResponse: - response = await self._conn.send_request( - CLIENT_METHODS["terminal_kill"], - {"sessionId": self._session_id, "terminalId": self.id}, - ) - payload = response if isinstance(response, dict) else {} - return KillTerminalCommandResponse.model_validate(payload) - - async def release(self) -> ReleaseTerminalResponse: - response = await self._conn.send_request( - CLIENT_METHODS["terminal_release"], - {"sessionId": self._session_id, "terminalId": self.id}, - ) - payload = response if isinstance(response, dict) else {} - return ReleaseTerminalResponse.model_validate(payload) - - async def aclose(self) -> None: - """Release the terminal, ignoring errors that occur during shutdown.""" - with suppress(Exception): - await self.release() - - async def close(self) -> None: - await self.aclose() - - async def __aenter__(self) -> TerminalHandle: - return self - - async def __aexit__(self, exc_type, exc, tb) -> None: - await self.aclose() From adaff6dd58e989b48ed715f450f1089566037ec5 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Sun, 11 Jan 2026 10:24:56 -0800 Subject: [PATCH 3/8] docs: update settings.json in ACP quickstart (#57) --- docs/quickstart.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/quickstart.md b/docs/quickstart.md index e26563d..401b7d5 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -50,6 +50,7 @@ Add an Agent Server entry in `settings.json` (Zed → Settings → Agents panel) { "agent_servers": { "Echo Agent (Python)": { + "type": "custom", "command": "/abs/path/to/python", "args": [ "/abs/path/to/agentclientprotocol/python-sdk/examples/echo_agent.py" @@ -59,6 +60,21 @@ Add an Agent Server entry in `settings.json` (Zed → Settings → Agents panel) } ``` +Or, if using `uv`: + +```json +{ + "agent_servers": { + "type": "custom", + "command": "uv", + "args": [ + "run", + "/abs/path/to/agentclientprotocol/python-sdk/examples/echo_agent.py" + ], + } +} +``` + Open the Agents panel and start the session. Each message you send should be echoed back via streamed `session/update` notifications. ### Other clients From 5510db24a0b3ac1a85514ec7bb6cc7dee01c93c8 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Fri, 30 Jan 2026 20:05:56 -0800 Subject: [PATCH 4/8] feat: Increase default stdio buffer limit and allow configuration (#59) * Increase default stdio buffer limit and allow configuration * Format * Lint --- src/acp/core.py | 9 ++++- tests/real_user/test_stdio_limits.py | 59 ++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/acp/core.py b/src/acp/core.py index 42632f6..75ab987 100644 --- a/src/acp/core.py +++ b/src/acp/core.py @@ -16,6 +16,7 @@ from .interfaces import Agent, Client __all__ = [ + "DEFAULT_STDIO_BUFFER_LIMIT_BYTES", "Agent", "AgentSideConnection", "Client", @@ -28,6 +29,11 @@ "run_agent", ] +# Default to 50MB for agent/client data transfer. +# The original stdio_streams default is 64KB, which is not large +# enough for multimodal use-cases. +DEFAULT_STDIO_BUFFER_LIMIT_BYTES = 50 * 1024 * 1024 + async def run_agent( agent: Agent, @@ -35,6 +41,7 @@ async def run_agent( output_stream: Any = None, *, use_unstable_protocol: bool = False, + stdio_buffer_limit_bytes: int = DEFAULT_STDIO_BUFFER_LIMIT_BYTES, **connection_kwargs: Any, ) -> None: """Run an ACP agent over the given input/output streams. @@ -53,7 +60,7 @@ async def run_agent( from .stdio import stdio_streams if input_stream is None and output_stream is None: - output_stream, input_stream = await stdio_streams() + output_stream, input_stream = await stdio_streams(limit=stdio_buffer_limit_bytes) conn = AgentSideConnection( agent, input_stream, diff --git a/tests/real_user/test_stdio_limits.py b/tests/real_user/test_stdio_limits.py index eb9be15..f972a8f 100644 --- a/tests/real_user/test_stdio_limits.py +++ b/tests/real_user/test_stdio_limits.py @@ -1,4 +1,7 @@ +import os +import subprocess import sys +import tempfile import textwrap import pytest @@ -39,3 +42,59 @@ async def test_spawn_stdio_transport_custom_limit_handles_large_line() -> None: ) as (reader, _writer, _process): line = await reader.readline() assert len(line) == LARGE_LINE_SIZE + 1 + + +@pytest.mark.asyncio +async def test_run_agent_stdio_buffer_limit() -> None: + """Test that run_agent with different buffer limits can handle appropriately sized messages.""" + with tempfile.TemporaryDirectory() as tmpdir: + # Test 1: Small buffer (1KB) fails with large message (70KB) + small_agent = os.path.join(tmpdir, "small_agent.py") + with open(small_agent, "w") as f: + f.write(""" +import asyncio +from acp.core import run_agent +from acp.interfaces import Agent + +class TestAgent(Agent): + async def list_capabilities(self): + return {"capabilities": {}} + +asyncio.run(run_agent(TestAgent(), stdio_buffer_limit_bytes=1024)) +""") + + # Send a 70KB message - should fail with 1KB buffer + large_msg = '{"jsonrpc":"2.0","method":"test","params":{"data":"' + "X" * LARGE_LINE_SIZE + '"}}\n' + result = subprocess.run( # noqa: S603 + [sys.executable, small_agent], input=large_msg, capture_output=True, text=True, timeout=2 + ) + + # Should have errors in stderr about the buffer limit + assert "Error" in result.stderr or result.returncode != 0, ( + f"Expected error with small buffer, got: {result.stderr}" + ) + + # Test 2: Large buffer (200KB) succeeds with large message (70KB) + large_agent = os.path.join(tmpdir, "large_agent.py") + with open(large_agent, "w") as f: + f.write(f""" +import asyncio +from acp.core import run_agent +from acp.interfaces import Agent + +class TestAgent(Agent): + async def list_capabilities(self): + return {{"capabilities": {{}}}} + +asyncio.run(run_agent(TestAgent(), stdio_buffer_limit_bytes={LARGE_LINE_SIZE * 3})) +""") + + # Same message, but with a buffer 3x the size - should handle it + result = subprocess.run( # noqa: S603 + [sys.executable, large_agent], input=large_msg, capture_output=True, text=True, timeout=2 + ) + + # With a large enough buffer, the agent should at least start successfully + # (it may have other errors from invalid JSON-RPC, but not buffer overrun) + if "LimitOverrunError" in result.stderr or "buffer" in result.stderr.lower(): + pytest.fail(f"Large buffer still hit limit error: {result.stderr}") From e63a9970f225bb433d818a8c75a09bfc807e84d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=8D=9A=E4=BC=9F?= Date: Sat, 7 Feb 2026 23:13:24 +0800 Subject: [PATCH 5/8] fix: Add SessionInfoUpdate to SessionUpdate type in helpers (#61) * fix: Add SessionInfoUpdate to ToolCallContentVariant * fix: add miss import Signed-off-by: Chojan Shang --------- Signed-off-by: Chojan Shang Co-authored-by: Chojan Shang --- src/acp/helpers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/acp/helpers.py b/src/acp/helpers.py index 701cda7..8830c43 100644 --- a/src/acp/helpers.py +++ b/src/acp/helpers.py @@ -20,6 +20,7 @@ PlanEntryPriority, PlanEntryStatus, ResourceContentBlock, + SessionInfoUpdate, SessionNotification, TerminalToolCallContent, TextContentBlock, @@ -45,6 +46,7 @@ | UserMessageChunk | ToolCallStart | ToolCallProgress + | SessionInfoUpdate ) ToolCallContentVariant = ContentToolCallContent | FileEditToolCallContent | TerminalToolCallContent From b4f253c9506610798ed51f296d244cba8bc94c85 Mon Sep 17 00:00:00 2001 From: Chojan Shang Date: Sat, 7 Feb 2026 23:44:05 +0800 Subject: [PATCH 6/8] feat: bump agentclientprotocol to 0.10.8 (#63) * feat: bump agentclientprotocol to 0.10.8 Signed-off-by: Chojan Shang * fix: minor fix Signed-off-by: Chojan Shang --------- Signed-off-by: Chojan Shang --- schema/VERSION | 2 +- schema/schema.json | 523 ++++++++++++++++++++++++++++++----- scripts/gen_schema.py | 1 + src/acp/agent/connection.py | 5 +- src/acp/client/connection.py | 1 - src/acp/interfaces.py | 4 +- src/acp/meta.py | 2 +- src/acp/schema.py | 126 +++++++-- 8 files changed, 558 insertions(+), 106 deletions(-) diff --git a/schema/VERSION b/schema/VERSION index 801f529..3222b17 100644 --- a/schema/VERSION +++ b/schema/VERSION @@ -1 +1 @@ -refs/tags/v0.10.5 +refs/tags/v0.10.8 diff --git a/schema/schema.json b/schema/schema.json index 4f45ef0..ba61b43 100644 --- a/schema/schema.json +++ b/schema/schema.json @@ -67,7 +67,8 @@ "$ref": "#/$defs/SessionNotification" } ], - "description": "Handles session update notifications from the agent.\n\nThis is a notification endpoint (no response expected) that receives\nreal-time updates about session progress, including message chunks,\ntool calls, and execution plans.\n\nNote: Clients SHOULD continue accepting tool call updates even after\nsending a `session/cancel` notification, as the agent may send final\nupdates before responding with the cancelled stop reason.\n\nSee protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)" + "description": "Handles session update notifications from the agent.\n\nThis is a notification endpoint (no response expected) that receives\nreal-time updates about session progress, including message chunks,\ntool calls, and execution plans.\n\nNote: Clients SHOULD continue accepting tool call updates even after\nsending a `session/cancel` notification, as the agent may send final\nupdates before responding with the cancelled stop reason.\n\nSee protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)", + "title": "SessionNotification" }, { "allOf": [ @@ -75,7 +76,8 @@ "$ref": "#/$defs/ExtNotification" } ], - "description": "Handles extension notifications from the agent.\n\nAllows the Agent to send an arbitrary notification that is not part of the ACP spec.\nExtension notifications provide a way to send one-way messages for custom functionality\nwhile maintaining protocol compatibility.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + "description": "Handles extension notifications from the agent.\n\nAllows the Agent to send an arbitrary notification that is not part of the ACP spec.\nExtension notifications provide a way to send one-way messages for custom functionality\nwhile maintaining protocol compatibility.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "title": "ExtNotification" } ], "description": "All possible notifications that an agent can send to a client.\n\nThis enum is used internally for routing RPC notifications. You typically won't need\nto use this directly - use the notification methods on the [`Client`] trait instead.\n\nNotifications do not expect a response." @@ -110,7 +112,8 @@ "$ref": "#/$defs/WriteTextFileRequest" } ], - "description": "Writes content to a text file in the client's file system.\n\nOnly available if the client advertises the `fs.writeTextFile` capability.\nAllows the agent to create or modify files within the client's environment.\n\nSee protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client)" + "description": "Writes content to a text file in the client's file system.\n\nOnly available if the client advertises the `fs.writeTextFile` capability.\nAllows the agent to create or modify files within the client's environment.\n\nSee protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client)", + "title": "WriteTextFileRequest" }, { "allOf": [ @@ -118,7 +121,8 @@ "$ref": "#/$defs/ReadTextFileRequest" } ], - "description": "Reads content from a text file in the client's file system.\n\nOnly available if the client advertises the `fs.readTextFile` capability.\nAllows the agent to access file contents within the client's environment.\n\nSee protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client)" + "description": "Reads content from a text file in the client's file system.\n\nOnly available if the client advertises the `fs.readTextFile` capability.\nAllows the agent to access file contents within the client's environment.\n\nSee protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client)", + "title": "ReadTextFileRequest" }, { "allOf": [ @@ -126,7 +130,8 @@ "$ref": "#/$defs/RequestPermissionRequest" } ], - "description": "Requests permission from the user for a tool call operation.\n\nCalled by the agent when it needs user authorization before executing\na potentially sensitive operation. The client should present the options\nto the user and return their decision.\n\nIf the client cancels the prompt turn via `session/cancel`, it MUST\nrespond to this request with `RequestPermissionOutcome::Cancelled`.\n\nSee protocol docs: [Requesting Permission](https://agentclientprotocol.com/protocol/tool-calls#requesting-permission)" + "description": "Requests permission from the user for a tool call operation.\n\nCalled by the agent when it needs user authorization before executing\na potentially sensitive operation. The client should present the options\nto the user and return their decision.\n\nIf the client cancels the prompt turn via `session/cancel`, it MUST\nrespond to this request with `RequestPermissionOutcome::Cancelled`.\n\nSee protocol docs: [Requesting Permission](https://agentclientprotocol.com/protocol/tool-calls#requesting-permission)", + "title": "RequestPermissionRequest" }, { "allOf": [ @@ -134,7 +139,8 @@ "$ref": "#/$defs/CreateTerminalRequest" } ], - "description": "Executes a command in a new terminal\n\nOnly available if the `terminal` Client capability is set to `true`.\n\nReturns a `TerminalId` that can be used with other terminal methods\nto get the current output, wait for exit, and kill the command.\n\nThe `TerminalId` can also be used to embed the terminal in a tool call\nby using the `ToolCallContent::Terminal` variant.\n\nThe Agent is responsible for releasing the terminal by using the `terminal/release`\nmethod.\n\nSee protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)" + "description": "Executes a command in a new terminal\n\nOnly available if the `terminal` Client capability is set to `true`.\n\nReturns a `TerminalId` that can be used with other terminal methods\nto get the current output, wait for exit, and kill the command.\n\nThe `TerminalId` can also be used to embed the terminal in a tool call\nby using the `ToolCallContent::Terminal` variant.\n\nThe Agent is responsible for releasing the terminal by using the `terminal/release`\nmethod.\n\nSee protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)", + "title": "CreateTerminalRequest" }, { "allOf": [ @@ -142,7 +148,8 @@ "$ref": "#/$defs/TerminalOutputRequest" } ], - "description": "Gets the terminal output and exit status\n\nReturns the current content in the terminal without waiting for the command to exit.\nIf the command has already exited, the exit status is included.\n\nSee protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)" + "description": "Gets the terminal output and exit status\n\nReturns the current content in the terminal without waiting for the command to exit.\nIf the command has already exited, the exit status is included.\n\nSee protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)", + "title": "TerminalOutputRequest" }, { "allOf": [ @@ -150,7 +157,8 @@ "$ref": "#/$defs/ReleaseTerminalRequest" } ], - "description": "Releases a terminal\n\nThe command is killed if it hasn't exited yet. Use `terminal/wait_for_exit`\nto wait for the command to exit before releasing the terminal.\n\nAfter release, the `TerminalId` can no longer be used with other `terminal/*` methods,\nbut tool calls that already contain it, continue to display its output.\n\nThe `terminal/kill` method can be used to terminate the command without releasing\nthe terminal, allowing the Agent to call `terminal/output` and other methods.\n\nSee protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)" + "description": "Releases a terminal\n\nThe command is killed if it hasn't exited yet. Use `terminal/wait_for_exit`\nto wait for the command to exit before releasing the terminal.\n\nAfter release, the `TerminalId` can no longer be used with other `terminal/*` methods,\nbut tool calls that already contain it, continue to display its output.\n\nThe `terminal/kill` method can be used to terminate the command without releasing\nthe terminal, allowing the Agent to call `terminal/output` and other methods.\n\nSee protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)", + "title": "ReleaseTerminalRequest" }, { "allOf": [ @@ -158,7 +166,8 @@ "$ref": "#/$defs/WaitForTerminalExitRequest" } ], - "description": "Waits for the terminal command to exit and return its exit status\n\nSee protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)" + "description": "Waits for the terminal command to exit and return its exit status\n\nSee protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)", + "title": "WaitForTerminalExitRequest" }, { "allOf": [ @@ -166,7 +175,8 @@ "$ref": "#/$defs/KillTerminalCommandRequest" } ], - "description": "Kills the terminal command without releasing the terminal\n\nWhile `terminal/release` will also kill the command, this method will keep\nthe `TerminalId` valid so it can be used with other methods.\n\nThis method can be helpful when implementing command timeouts which terminate\nthe command as soon as elapsed, and then get the final output so it can be sent\nto the model.\n\nNote: `terminal/release` when `TerminalId` is no longer needed.\n\nSee protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)" + "description": "Kills the terminal command without releasing the terminal\n\nWhile `terminal/release` will also kill the command, this method will keep\nthe `TerminalId` valid so it can be used with other methods.\n\nThis method can be helpful when implementing command timeouts which terminate\nthe command as soon as elapsed, and then get the final output so it can be sent\nto the model.\n\nNote: `terminal/release` when `TerminalId` is no longer needed.\n\nSee protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)", + "title": "KillTerminalCommandRequest" }, { "allOf": [ @@ -174,7 +184,8 @@ "$ref": "#/$defs/ExtRequest" } ], - "description": "Handles extension method requests from the agent.\n\nAllows the Agent to send an arbitrary request that is not part of the ACP spec.\nExtension methods provide a way to add custom functionality while maintaining\nprotocol compatibility.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + "description": "Handles extension method requests from the agent.\n\nAllows the Agent to send an arbitrary request that is not part of the ACP spec.\nExtension methods provide a way to add custom functionality while maintaining\nprotocol compatibility.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "title": "ExtMethodRequest" } ], "description": "All possible requests that an agent can send to a client.\n\nThis enum is used internally for routing RPC requests. You typically won't need\nto use this directly - instead, use the methods on the [`Client`] trait.\n\nThis enum encompasses all method calls from agent to client." @@ -202,40 +213,100 @@ "result": { "anyOf": [ { - "$ref": "#/$defs/InitializeResponse" + "allOf": [ + { + "$ref": "#/$defs/InitializeResponse" + } + ], + "title": "InitializeResponse" }, { - "$ref": "#/$defs/AuthenticateResponse" + "allOf": [ + { + "$ref": "#/$defs/AuthenticateResponse" + } + ], + "title": "AuthenticateResponse" }, { - "$ref": "#/$defs/NewSessionResponse" + "allOf": [ + { + "$ref": "#/$defs/NewSessionResponse" + } + ], + "title": "NewSessionResponse" }, { - "$ref": "#/$defs/LoadSessionResponse" + "allOf": [ + { + "$ref": "#/$defs/LoadSessionResponse" + } + ], + "title": "LoadSessionResponse" }, { - "$ref": "#/$defs/ListSessionsResponse" + "allOf": [ + { + "$ref": "#/$defs/ListSessionsResponse" + } + ], + "title": "ListSessionsResponse" }, { - "$ref": "#/$defs/ForkSessionResponse" + "allOf": [ + { + "$ref": "#/$defs/ForkSessionResponse" + } + ], + "title": "ForkSessionResponse" }, { - "$ref": "#/$defs/ResumeSessionResponse" + "allOf": [ + { + "$ref": "#/$defs/ResumeSessionResponse" + } + ], + "title": "ResumeSessionResponse" }, { - "$ref": "#/$defs/SetSessionModeResponse" + "allOf": [ + { + "$ref": "#/$defs/SetSessionModeResponse" + } + ], + "title": "SetSessionModeResponse" }, { - "$ref": "#/$defs/SetSessionConfigOptionResponse" + "allOf": [ + { + "$ref": "#/$defs/SetSessionConfigOptionResponse" + } + ], + "title": "SetSessionConfigOptionResponse" }, { - "$ref": "#/$defs/PromptResponse" + "allOf": [ + { + "$ref": "#/$defs/PromptResponse" + } + ], + "title": "PromptResponse" }, { - "$ref": "#/$defs/SetSessionModelResponse" + "allOf": [ + { + "$ref": "#/$defs/SetSessionModelResponse" + } + ], + "title": "SetSessionModelResponse" }, { - "$ref": "#/$defs/ExtResponse" + "allOf": [ + { + "$ref": "#/$defs/ExtResponse" + } + ], + "title": "ExtMethodResponse" } ], "description": "All possible responses that an agent can send to a client.\n\nThis enum is used internally for routing RPC responses. You typically won't need\nto use this directly - the responses are handled automatically by the connection.\n\nThese are responses to the corresponding `ClientRequest` variants." @@ -245,6 +316,7 @@ "id", "result" ], + "title": "Result", "type": "object" }, { @@ -260,6 +332,7 @@ "id", "error" ], + "title": "Error", "type": "object" } ], @@ -452,7 +525,8 @@ "$ref": "#/$defs/UnstructuredCommandInput" } ], - "description": "All text that was typed after the command name is provided as input." + "description": "All text that was typed after the command name is provided as input.", + "title": "unstructured" } ], "description": "The input specification for a command." @@ -611,7 +685,8 @@ "$ref": "#/$defs/CancelNotification" } ], - "description": "Cancels ongoing operations for a session.\n\nThis is a notification sent by the client to cancel an ongoing prompt turn.\n\nUpon receiving this notification, the Agent SHOULD:\n- Stop all language model requests as soon as possible\n- Abort all tool call invocations in progress\n- Send any pending `session/update` notifications\n- Respond to the original `session/prompt` request with `StopReason::Cancelled`\n\nSee protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)" + "description": "Cancels ongoing operations for a session.\n\nThis is a notification sent by the client to cancel an ongoing prompt turn.\n\nUpon receiving this notification, the Agent SHOULD:\n- Stop all language model requests as soon as possible\n- Abort all tool call invocations in progress\n- Send any pending `session/update` notifications\n- Respond to the original `session/prompt` request with `StopReason::Cancelled`\n\nSee protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)", + "title": "CancelNotification" }, { "allOf": [ @@ -619,7 +694,8 @@ "$ref": "#/$defs/ExtNotification" } ], - "description": "Handles extension notifications from the client.\n\nExtension notifications provide a way to send one-way messages for custom functionality\nwhile maintaining protocol compatibility.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + "description": "Handles extension notifications from the client.\n\nExtension notifications provide a way to send one-way messages for custom functionality\nwhile maintaining protocol compatibility.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "title": "ExtNotification" } ], "description": "All possible notifications that a client can send to an agent.\n\nThis enum is used internally for routing RPC notifications. You typically won't need\nto use this directly - use the notification methods on the [`Agent`] trait instead.\n\nNotifications do not expect a response." @@ -654,7 +730,8 @@ "$ref": "#/$defs/InitializeRequest" } ], - "description": "Establishes the connection with a client and negotiates protocol capabilities.\n\nThis method is called once at the beginning of the connection to:\n- Negotiate the protocol version to use\n- Exchange capability information between client and agent\n- Determine available authentication methods\n\nThe agent should respond with its supported protocol version and capabilities.\n\nSee protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)" + "description": "Establishes the connection with a client and negotiates protocol capabilities.\n\nThis method is called once at the beginning of the connection to:\n- Negotiate the protocol version to use\n- Exchange capability information between client and agent\n- Determine available authentication methods\n\nThe agent should respond with its supported protocol version and capabilities.\n\nSee protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)", + "title": "InitializeRequest" }, { "allOf": [ @@ -662,7 +739,8 @@ "$ref": "#/$defs/AuthenticateRequest" } ], - "description": "Authenticates the client using the specified authentication method.\n\nCalled when the agent requires authentication before allowing session creation.\nThe client provides the authentication method ID that was advertised during initialization.\n\nAfter successful authentication, the client can proceed to create sessions with\n`new_session` without receiving an `auth_required` error.\n\nSee protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)" + "description": "Authenticates the client using the specified authentication method.\n\nCalled when the agent requires authentication before allowing session creation.\nThe client provides the authentication method ID that was advertised during initialization.\n\nAfter successful authentication, the client can proceed to create sessions with\n`new_session` without receiving an `auth_required` error.\n\nSee protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)", + "title": "AuthenticateRequest" }, { "allOf": [ @@ -670,7 +748,8 @@ "$ref": "#/$defs/NewSessionRequest" } ], - "description": "Creates a new conversation session with the agent.\n\nSessions represent independent conversation contexts with their own history and state.\n\nThe agent should:\n- Create a new session context\n- Connect to any specified MCP servers\n- Return a unique session ID for future requests\n\nMay return an `auth_required` error if the agent requires authentication.\n\nSee protocol docs: [Session Setup](https://agentclientprotocol.com/protocol/session-setup)" + "description": "Creates a new conversation session with the agent.\n\nSessions represent independent conversation contexts with their own history and state.\n\nThe agent should:\n- Create a new session context\n- Connect to any specified MCP servers\n- Return a unique session ID for future requests\n\nMay return an `auth_required` error if the agent requires authentication.\n\nSee protocol docs: [Session Setup](https://agentclientprotocol.com/protocol/session-setup)", + "title": "NewSessionRequest" }, { "allOf": [ @@ -678,7 +757,8 @@ "$ref": "#/$defs/LoadSessionRequest" } ], - "description": "Loads an existing session to resume a previous conversation.\n\nThis method is only available if the agent advertises the `loadSession` capability.\n\nThe agent should:\n- Restore the session context and conversation history\n- Connect to the specified MCP servers\n- Stream the entire conversation history back to the client via notifications\n\nSee protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)" + "description": "Loads an existing session to resume a previous conversation.\n\nThis method is only available if the agent advertises the `loadSession` capability.\n\nThe agent should:\n- Restore the session context and conversation history\n- Connect to the specified MCP servers\n- Stream the entire conversation history back to the client via notifications\n\nSee protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)", + "title": "LoadSessionRequest" }, { "allOf": [ @@ -686,7 +766,8 @@ "$ref": "#/$defs/ListSessionsRequest" } ], - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nLists existing sessions known to the agent.\n\nThis method is only available if the agent advertises the `listSessions` capability.\n\nThe agent should return metadata about sessions with optional filtering and pagination support." + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nLists existing sessions known to the agent.\n\nThis method is only available if the agent advertises the `listSessions` capability.\n\nThe agent should return metadata about sessions with optional filtering and pagination support.", + "title": "ListSessionsRequest" }, { "allOf": [ @@ -694,7 +775,8 @@ "$ref": "#/$defs/ForkSessionRequest" } ], - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nForks an existing session to create a new independent session.\n\nThis method is only available if the agent advertises the `session.fork` capability.\n\nThe agent should create a new session with the same conversation context as the\noriginal, allowing operations like generating summaries without affecting the\noriginal session's history." + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nForks an existing session to create a new independent session.\n\nThis method is only available if the agent advertises the `session.fork` capability.\n\nThe agent should create a new session with the same conversation context as the\noriginal, allowing operations like generating summaries without affecting the\noriginal session's history.", + "title": "ForkSessionRequest" }, { "allOf": [ @@ -702,7 +784,8 @@ "$ref": "#/$defs/ResumeSessionRequest" } ], - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nResumes an existing session without returning previous messages.\n\nThis method is only available if the agent advertises the `session.resume` capability.\n\nThe agent should resume the session context, allowing the conversation to continue\nwithout replaying the message history (unlike `session/load`)." + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nResumes an existing session without returning previous messages.\n\nThis method is only available if the agent advertises the `session.resume` capability.\n\nThe agent should resume the session context, allowing the conversation to continue\nwithout replaying the message history (unlike `session/load`).", + "title": "ResumeSessionRequest" }, { "allOf": [ @@ -710,7 +793,8 @@ "$ref": "#/$defs/SetSessionModeRequest" } ], - "description": "Sets the current mode for a session.\n\nAllows switching between different agent modes (e.g., \"ask\", \"architect\", \"code\")\nthat affect system prompts, tool availability, and permission behaviors.\n\nThe mode must be one of the modes advertised in `availableModes` during session\ncreation or loading. Agents may also change modes autonomously and notify the\nclient via `current_mode_update` notifications.\n\nThis method can be called at any time during a session, whether the Agent is\nidle or actively generating a response.\n\nSee protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)" + "description": "Sets the current mode for a session.\n\nAllows switching between different agent modes (e.g., \"ask\", \"architect\", \"code\")\nthat affect system prompts, tool availability, and permission behaviors.\n\nThe mode must be one of the modes advertised in `availableModes` during session\ncreation or loading. Agents may also change modes autonomously and notify the\nclient via `current_mode_update` notifications.\n\nThis method can be called at any time during a session, whether the Agent is\nidle or actively generating a response.\n\nSee protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)", + "title": "SetSessionModeRequest" }, { "allOf": [ @@ -718,7 +802,8 @@ "$ref": "#/$defs/SetSessionConfigOptionRequest" } ], - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nSets the current value for a session configuration option." + "description": "Sets the current value for a session configuration option.", + "title": "SetSessionConfigOptionRequest" }, { "allOf": [ @@ -726,7 +811,8 @@ "$ref": "#/$defs/PromptRequest" } ], - "description": "Processes a user prompt within a session.\n\nThis method handles the whole lifecycle of a prompt:\n- Receives user messages with optional context (files, images, etc.)\n- Processes the prompt using language models\n- Reports language model content and tool calls to the Clients\n- Requests permission to run tools\n- Executes any requested tool calls\n- Returns when the turn is complete with a stop reason\n\nSee protocol docs: [Prompt Turn](https://agentclientprotocol.com/protocol/prompt-turn)" + "description": "Processes a user prompt within a session.\n\nThis method handles the whole lifecycle of a prompt:\n- Receives user messages with optional context (files, images, etc.)\n- Processes the prompt using language models\n- Reports language model content and tool calls to the Clients\n- Requests permission to run tools\n- Executes any requested tool calls\n- Returns when the turn is complete with a stop reason\n\nSee protocol docs: [Prompt Turn](https://agentclientprotocol.com/protocol/prompt-turn)", + "title": "PromptRequest" }, { "allOf": [ @@ -734,7 +820,8 @@ "$ref": "#/$defs/SetSessionModelRequest" } ], - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nSelect a model for a given session." + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nSelect a model for a given session.", + "title": "SetSessionModelRequest" }, { "allOf": [ @@ -742,7 +829,8 @@ "$ref": "#/$defs/ExtRequest" } ], - "description": "Handles extension method requests from the client.\n\nExtension methods provide a way to add custom functionality while maintaining\nprotocol compatibility.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + "description": "Handles extension method requests from the client.\n\nExtension methods provide a way to add custom functionality while maintaining\nprotocol compatibility.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "title": "ExtMethodRequest" } ], "description": "All possible requests that a client can send to an agent.\n\nThis enum is used internally for routing RPC requests. You typically won't need\nto use this directly - instead, use the methods on the [`Agent`] trait.\n\nThis enum encompasses all method calls from client to agent." @@ -770,31 +858,76 @@ "result": { "anyOf": [ { - "$ref": "#/$defs/WriteTextFileResponse" + "allOf": [ + { + "$ref": "#/$defs/WriteTextFileResponse" + } + ], + "title": "WriteTextFileResponse" }, { - "$ref": "#/$defs/ReadTextFileResponse" + "allOf": [ + { + "$ref": "#/$defs/ReadTextFileResponse" + } + ], + "title": "ReadTextFileResponse" }, { - "$ref": "#/$defs/RequestPermissionResponse" + "allOf": [ + { + "$ref": "#/$defs/RequestPermissionResponse" + } + ], + "title": "RequestPermissionResponse" }, { - "$ref": "#/$defs/CreateTerminalResponse" + "allOf": [ + { + "$ref": "#/$defs/CreateTerminalResponse" + } + ], + "title": "CreateTerminalResponse" }, { - "$ref": "#/$defs/TerminalOutputResponse" + "allOf": [ + { + "$ref": "#/$defs/TerminalOutputResponse" + } + ], + "title": "TerminalOutputResponse" }, { - "$ref": "#/$defs/ReleaseTerminalResponse" + "allOf": [ + { + "$ref": "#/$defs/ReleaseTerminalResponse" + } + ], + "title": "ReleaseTerminalResponse" }, { - "$ref": "#/$defs/WaitForTerminalExitResponse" + "allOf": [ + { + "$ref": "#/$defs/WaitForTerminalExitResponse" + } + ], + "title": "WaitForTerminalExitResponse" }, { - "$ref": "#/$defs/KillTerminalCommandResponse" + "allOf": [ + { + "$ref": "#/$defs/KillTerminalCommandResponse" + } + ], + "title": "KillTerminalResponse" }, { - "$ref": "#/$defs/ExtResponse" + "allOf": [ + { + "$ref": "#/$defs/ExtResponse" + } + ], + "title": "ExtMethodResponse" } ], "description": "All possible responses that a client can send to an agent.\n\nThis enum is used internally for routing RPC responses. You typically won't need\nto use this directly - the responses are handled automatically by the connection.\n\nThese are responses to the corresponding `AgentRequest` variants." @@ -804,6 +937,7 @@ "id", "result" ], + "title": "Result", "type": "object" }, { @@ -819,13 +953,14 @@ "id", "error" ], + "title": "Error", "type": "object" } ], "x-docs-ignore": true }, "ConfigOptionUpdate": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nSession configuration options have been updated.", + "description": "Session configuration options have been updated.", "properties": { "_meta": { "additionalProperties": true, @@ -996,6 +1131,25 @@ ], "type": "object" }, + "Cost": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nCost information for a session.", + "properties": { + "amount": { + "description": "Total cumulative cost for session.", + "format": "double", + "type": "number" + }, + "currency": { + "description": "ISO 4217 currency code (e.g., \"USD\", \"EUR\").", + "type": "string" + } + }, + "required": [ + "amount", + "currency" + ], + "type": "object" + }, "CreateTerminalRequest": { "description": "Request to create a new terminal and execute a command.", "properties": { @@ -1172,10 +1326,20 @@ "EmbeddedResourceResource": { "anyOf": [ { - "$ref": "#/$defs/TextResourceContents" + "allOf": [ + { + "$ref": "#/$defs/TextResourceContents" + } + ], + "title": "TextResourceContents" }, { - "$ref": "#/$defs/BlobResourceContents" + "allOf": [ + { + "$ref": "#/$defs/BlobResourceContents" + } + ], + "title": "BlobResourceContents" } ], "description": "Resource content that can be embedded in a message." @@ -1237,53 +1401,62 @@ "const": -32700, "description": "**Parse error**: Invalid JSON was received by the server.\nAn error occurred on the server while parsing the JSON text.", "format": "int32", + "title": "Parse error", "type": "integer" }, { "const": -32600, "description": "**Invalid request**: The JSON sent is not a valid Request object.", "format": "int32", + "title": "Invalid request", "type": "integer" }, { "const": -32601, "description": "**Method not found**: The method does not exist or is not available.", "format": "int32", + "title": "Method not found", "type": "integer" }, { "const": -32602, "description": "**Invalid params**: Invalid method parameter(s).", "format": "int32", + "title": "Invalid params", "type": "integer" }, { "const": -32603, "description": "**Internal error**: Internal JSON-RPC error.\nReserved for implementation-defined server errors.", "format": "int32", + "title": "Internal error", "type": "integer" }, { "const": -32800, "description": "**Request cancelled**: **UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nExecution of the method was aborted either due to a cancellation request from the caller or\nbecause of resource constraints or shutdown.", "format": "int32", + "title": "Request cancelled", "type": "integer" }, { "const": -32000, "description": "**Authentication required**: Authentication is required before this operation can be performed.", "format": "int32", + "title": "Authentication required", "type": "integer" }, { "const": -32002, "description": "**Resource not found**: A given resource, such as a file, was not found.", "format": "int32", + "title": "Resource not found", "type": "integer" }, { "description": "Other undefined error code.", "format": "int32", + "title": "Other", "type": "integer" } ], @@ -1373,7 +1546,7 @@ ] }, "configOptions": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + "description": "Initial session configuration options if supported by the Agent.", "items": { "$ref": "#/$defs/SessionConfigOption" }, @@ -1802,7 +1975,7 @@ ] }, "configOptions": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + "description": "Initial session configuration options if supported by the Agent.", "items": { "$ref": "#/$defs/SessionConfigOption" }, @@ -1906,7 +2079,8 @@ "$ref": "#/$defs/McpServerStdio" } ], - "description": "Stdio transport configuration\n\nAll Agents MUST support this transport." + "description": "Stdio transport configuration\n\nAll Agents MUST support this transport.", + "title": "stdio" } ], "description": "Configuration for connecting to an MCP (Model Context Protocol) server.\n\nMCP servers provide tools and context that the agent can use when\nprocessing prompts.\n\nSee protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)" @@ -2105,7 +2279,7 @@ ] }, "configOptions": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + "description": "Initial session configuration options if supported by the Agent.", "items": { "$ref": "#/$defs/SessionConfigOption" }, @@ -2405,6 +2579,17 @@ } ], "description": "Indicates why the agent stopped processing the turn." + }, + "usage": { + "anyOf": [ + { + "$ref": "#/$defs/Usage" + }, + { + "type": "null" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nToken usage for this turn (optional)." } }, "required": [ @@ -2544,13 +2729,16 @@ "RequestId": { "anyOf": [ { + "title": "Null", "type": "null" }, { "format": "int64", + "title": "Number", "type": "integer" }, { + "title": "Str", "type": "string" } ], @@ -2776,7 +2964,7 @@ ] }, "configOptions": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + "description": "Initial session configuration options if supported by the Agent.", "items": { "$ref": "#/$defs/SessionConfigOption" }, @@ -2893,15 +3081,15 @@ "type": "object" }, "SessionConfigGroupId": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nUnique identifier for a session configuration option value group.", + "description": "Unique identifier for a session configuration option value group.", "type": "string" }, "SessionConfigId": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nUnique identifier for a session configuration option.", + "description": "Unique identifier for a session configuration option.", "type": "string" }, "SessionConfigOption": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nA session configuration option selector and its current state.", + "description": "A session configuration option selector and its current state.", "discriminator": { "propertyName": "type" }, @@ -2934,6 +3122,17 @@ "null" ] }, + "category": { + "anyOf": [ + { + "$ref": "#/$defs/SessionConfigOptionCategory" + }, + { + "type": "null" + } + ], + "description": "Optional semantic category for this option (UX only)." + }, "description": { "description": "Optional description for the Client to display to the user.", "type": [ @@ -2960,8 +3159,33 @@ ], "type": "object" }, + "SessionConfigOptionCategory": { + "anyOf": [ + { + "const": "mode", + "description": "Session mode selector.", + "type": "string" + }, + { + "const": "model", + "description": "Model selector.", + "type": "string" + }, + { + "const": "thought_level", + "description": "Thought/reasoning level selector.", + "type": "string" + }, + { + "description": "Unknown / uncategorized selector.", + "title": "other", + "type": "string" + } + ], + "description": "Semantic category for a session configuration option.\n\nThis is intended to help Clients distinguish broadly common selectors (e.g. model selector vs\nsession mode selector vs thought/reasoning level) for UX purposes (keyboard shortcuts, icons,\nplacement). It MUST NOT be required for correctness. Clients MUST handle missing or unknown\ncategories gracefully.\n\nCategory names beginning with `_` are free for custom use, like other ACP extension methods.\nCategory names that do not begin with `_` are reserved for the ACP spec." + }, "SessionConfigSelect": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nA single-value selector (dropdown) session configuration option payload.", + "description": "A single-value selector (dropdown) session configuration option payload.", "properties": { "currentValue": { "allOf": [ @@ -2987,7 +3211,7 @@ "type": "object" }, "SessionConfigSelectGroup": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nA group of possible values for a session configuration option.", + "description": "A group of possible values for a session configuration option.", "properties": { "_meta": { "additionalProperties": true, @@ -3025,7 +3249,7 @@ "type": "object" }, "SessionConfigSelectOption": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nA possible value for a session configuration option.", + "description": "A possible value for a session configuration option.", "properties": { "_meta": { "additionalProperties": true, @@ -3068,6 +3292,7 @@ "items": { "$ref": "#/$defs/SessionConfigSelectOption" }, + "title": "Ungrouped", "type": "array" }, { @@ -3075,13 +3300,14 @@ "items": { "$ref": "#/$defs/SessionConfigSelectGroup" }, + "title": "Grouped", "type": "array" } ], - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nPossible values for a session configuration option." + "description": "Possible values for a session configuration option." }, "SessionConfigValueId": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nUnique identifier for a session configuration option value.", + "description": "Unique identifier for a session configuration option value.", "type": "string" }, "SessionForkCapabilities": { @@ -3494,7 +3720,7 @@ "$ref": "#/$defs/ConfigOptionUpdate" } ], - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nSession configuration options have been updated.", + "description": "Session configuration options have been updated.", "properties": { "sessionUpdate": { "const": "config_option_update", @@ -3523,11 +3749,29 @@ "sessionUpdate" ], "type": "object" + }, + { + "allOf": [ + { + "$ref": "#/$defs/UsageUpdate" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nContext window and cost update for the session.", + "properties": { + "sessionUpdate": { + "const": "usage_update", + "type": "string" + } + }, + "required": [ + "sessionUpdate" + ], + "type": "object" } ] }, "SetSessionConfigOptionRequest": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nRequest parameters for setting a session configuration option.", + "description": "Request parameters for setting a session configuration option.", "properties": { "_meta": { "additionalProperties": true, @@ -3572,7 +3816,7 @@ "x-side": "agent" }, "SetSessionConfigOptionResponse": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nResponse to `session/set_config_option` method.", + "description": "Response to `session/set_config_option` method.", "properties": { "_meta": { "additionalProperties": true, @@ -4254,6 +4498,103 @@ ], "type": "object" }, + "Usage": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nToken usage information for a prompt turn.", + "properties": { + "cachedReadTokens": { + "description": "Total cache read tokens.", + "format": "uint64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "cachedWriteTokens": { + "description": "Total cache write tokens.", + "format": "uint64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "inputTokens": { + "description": "Total input tokens across all turns.", + "format": "uint64", + "minimum": 0, + "type": "integer" + }, + "outputTokens": { + "description": "Total output tokens across all turns.", + "format": "uint64", + "minimum": 0, + "type": "integer" + }, + "thoughtTokens": { + "description": "Total thought/reasoning tokens", + "format": "uint64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "totalTokens": { + "description": "Sum of all token types across session.", + "format": "uint64", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "totalTokens", + "inputTokens", + "outputTokens" + ], + "type": "object" + }, + "UsageUpdate": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nContext window and cost update for a session.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": [ + "object", + "null" + ] + }, + "cost": { + "anyOf": [ + { + "$ref": "#/$defs/Cost" + }, + { + "type": "null" + } + ], + "description": "Cumulative session cost (optional)." + }, + "size": { + "description": "Total context window size in tokens.", + "format": "uint64", + "minimum": 0, + "type": "integer" + }, + "used": { + "description": "Tokens currently in context.", + "format": "uint64", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "used", + "size" + ], + "type": "object" + }, "WaitForTerminalExitRequest": { "description": "Request to wait for a terminal command to exit.", "properties": { @@ -4377,13 +4718,28 @@ { "anyOf": [ { - "$ref": "#/$defs/AgentRequest" + "allOf": [ + { + "$ref": "#/$defs/AgentRequest" + } + ], + "title": "Request" }, { - "$ref": "#/$defs/AgentResponse" + "allOf": [ + { + "$ref": "#/$defs/AgentResponse" + } + ], + "title": "Response" }, { - "$ref": "#/$defs/AgentNotification" + "allOf": [ + { + "$ref": "#/$defs/AgentNotification" + } + ], + "title": "Notification" } ], "description": "A message (request, response, or notification) with `\"jsonrpc\": \"2.0\"` specified as\n[required by JSON-RPC 2.0 Specification][1].\n\n[1]: https://www.jsonrpc.org/specification#compatibility", @@ -4398,18 +4754,34 @@ "required": [ "jsonrpc" ], + "title": "Agent", "type": "object" }, { "anyOf": [ { - "$ref": "#/$defs/ClientRequest" + "allOf": [ + { + "$ref": "#/$defs/ClientRequest" + } + ], + "title": "Request" }, { - "$ref": "#/$defs/ClientResponse" + "allOf": [ + { + "$ref": "#/$defs/ClientResponse" + } + ], + "title": "Response" }, { - "$ref": "#/$defs/ClientNotification" + "allOf": [ + { + "$ref": "#/$defs/ClientNotification" + } + ], + "title": "Notification" } ], "description": "A message (request, response, or notification) with `\"jsonrpc\": \"2.0\"` specified as\n[required by JSON-RPC 2.0 Specification][1].\n\n[1]: https://www.jsonrpc.org/specification#compatibility", @@ -4424,6 +4796,7 @@ "required": [ "jsonrpc" ], + "title": "Client", "type": "object" }, { @@ -4434,10 +4807,12 @@ "$ref": "#/$defs/CancelRequestNotification" } ], - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or\nchanged at any point.\n\nCancels an ongoing request.\n\nThis is a notification sent by the the side that sent a request to cancel that request.\n\nUpon receiving this notification, the receiver:\n\n1. MUST cancel the corresponding request activity and all nested activities\n2. MAY send any pending notifications.\n3. MUST send one of these responses for the original request:\n - Valid response with appropriate data (partial results or cancellation marker)\n - Error response with code `-32800` (Cancelled)\n\nSee protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/cancellation)" + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or\nchanged at any point.\n\nCancels an ongoing request.\n\nThis is a notification sent by the the side that sent a request to cancel that request.\n\nUpon receiving this notification, the receiver:\n\n1. MUST cancel the corresponding request activity and all nested activities\n2. MAY send any pending notifications.\n3. MUST send one of these responses for the original request:\n - Valid response with appropriate data (partial results or cancellation marker)\n - Error response with code `-32800` (Cancelled)\n\nSee protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/cancellation)", + "title": "CancelRequestNotification" } ], - "description": "General protocol-level notifications that all sides are expected to\nimplement.\n\nNotifications whose methods start with '$/' are messages which\nare protocol implementation dependent and might not be implementable in all\nclients or agents. For example if the implementation uses a single threaded\nsynchronous programming language then there is little it can do to react to\na `$/cancel_request` notification. If an agent or client receives\nnotifications starting with '$/' it is free to ignore the notification.\n\nNotifications do not expect a response." + "description": "General protocol-level notifications that all sides are expected to\nimplement.\n\nNotifications whose methods start with '$/' are messages which\nare protocol implementation dependent and might not be implementable in all\nclients or agents. For example if the implementation uses a single threaded\nsynchronous programming language then there is little it can do to react to\na `$/cancel_request` notification. If an agent or client receives\nnotifications starting with '$/' it is free to ignore the notification.\n\nNotifications do not expect a response.", + "title": "ProtocolLevel" } ], "title": "Agent Client Protocol" diff --git a/scripts/gen_schema.py b/scripts/gen_schema.py index 36cbda7..74a8790 100644 --- a/scripts/gen_schema.py +++ b/scripts/gen_schema.py @@ -62,6 +62,7 @@ "SessionUpdate8": "CurrentModeUpdate", "SessionUpdate9": "ConfigOptionUpdate", "SessionUpdate10": "SessionInfoUpdate", + "SessionUpdate11": "UsageUpdate", "ToolCallContent1": "ContentToolCallContent", "ToolCallContent2": "FileEditToolCallContent", "ToolCallContent3": "TerminalToolCallContent", diff --git a/src/acp/agent/connection.py b/src/acp/agent/connection.py index 30b1092..b3b0351 100644 --- a/src/acp/agent/connection.py +++ b/src/acp/agent/connection.py @@ -33,6 +33,7 @@ ToolCallProgress, ToolCallStart, ToolCallUpdate, + UsageUpdate, UserMessageChunk, WaitForTerminalExitRequest, WaitForTerminalExitResponse, @@ -88,7 +89,8 @@ async def session_update( | AvailableCommandsUpdate | CurrentModeUpdate | ConfigOptionUpdate - | SessionInfoUpdate, + | SessionInfoUpdate + | UsageUpdate, **kwargs: Any, ) -> None: await notify_model( @@ -216,5 +218,4 @@ async def __aexit__(self, exc_type, exc, tb) -> None: await self.close() def on_connect(self, conn: Agent) -> None: - # A dummy method to match the Client protocol pass diff --git a/src/acp/client/connection.py b/src/acp/client/connection.py index c71da96..ac0d34f 100644 --- a/src/acp/client/connection.py +++ b/src/acp/client/connection.py @@ -225,5 +225,4 @@ async def __aexit__(self, exc_type, exc, tb) -> None: await self.close() def on_connect(self, conn: Client) -> None: - # A dummy method to match the Agent protocol pass diff --git a/src/acp/interfaces.py b/src/acp/interfaces.py index 5cc45ff..457dfe7 100644 --- a/src/acp/interfaces.py +++ b/src/acp/interfaces.py @@ -59,6 +59,7 @@ ToolCallProgress, ToolCallStart, ToolCallUpdate, + UsageUpdate, UserMessageChunk, WaitForTerminalExitRequest, WaitForTerminalExitResponse, @@ -89,7 +90,8 @@ async def session_update( | AvailableCommandsUpdate | CurrentModeUpdate | ConfigOptionUpdate - | SessionInfoUpdate, + | SessionInfoUpdate + | UsageUpdate, **kwargs: Any, ) -> None: ... diff --git a/src/acp/meta.py b/src/acp/meta.py index 142f2f1..82aae7e 100644 --- a/src/acp/meta.py +++ b/src/acp/meta.py @@ -1,5 +1,5 @@ # Generated from schema/meta.json. Do not edit by hand. -# Schema ref: refs/tags/v0.10.5 +# Schema ref: refs/tags/v0.10.8 AGENT_METHODS = { "authenticate": "authenticate", "initialize": "initialize", diff --git a/src/acp/schema.py b/src/acp/schema.py index 314ccd9..e449e4a 100644 --- a/src/acp/schema.py +++ b/src/acp/schema.py @@ -1,5 +1,5 @@ # Generated from schema/schema.json. Do not edit by hand. -# Schema ref: refs/tags/v0.10.5 +# Schema ref: refs/tags/v0.10.8 from __future__ import annotations @@ -111,6 +111,13 @@ class BlobResourceContents(BaseModel): uri: str +class Cost(BaseModel): + # Total cumulative cost for session. + amount: Annotated[float, Field(description="Total cumulative cost for session.")] + # ISO 4217 currency code (e.g., "USD", "EUR"). + currency: Annotated[str, Field(description='ISO 4217 currency code (e.g., "USD", "EUR").')] + + class CreateTerminalResponse(BaseModel): # The _meta property is reserved by ACP to allow clients and agents to attach additional # metadata to their interactions. Implementations MUST NOT make assumptions about values at @@ -900,6 +907,72 @@ class UnstructuredCommandInput(BaseModel): ] +class Usage(BaseModel): + # Total cache read tokens. + cached_read_tokens: Annotated[ + Optional[int], + Field(alias="cachedReadTokens", description="Total cache read tokens.", ge=0), + ] = None + # Total cache write tokens. + cached_write_tokens: Annotated[ + Optional[int], + Field(alias="cachedWriteTokens", description="Total cache write tokens.", ge=0), + ] = None + # Total input tokens across all turns. + input_tokens: Annotated[ + int, + Field( + alias="inputTokens", + description="Total input tokens across all turns.", + ge=0, + ), + ] + # Total output tokens across all turns. + output_tokens: Annotated[ + int, + Field( + alias="outputTokens", + description="Total output tokens across all turns.", + ge=0, + ), + ] + # Total thought/reasoning tokens + thought_tokens: Annotated[ + Optional[int], + Field(alias="thoughtTokens", description="Total thought/reasoning tokens", ge=0), + ] = None + # Sum of all token types across session. + total_tokens: Annotated[ + int, + Field( + alias="totalTokens", + description="Sum of all token types across session.", + ge=0, + ), + ] + + +class _UsageUpdate(BaseModel): + # The _meta property is reserved by ACP to allow clients and agents to attach additional + # metadata to their interactions. Implementations MUST NOT make assumptions about values at + # these keys. + # + # See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + field_meta: Annotated[ + Optional[Dict[str, Any]], + Field( + alias="_meta", + description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + ), + ] = None + # Cumulative session cost (optional). + cost: Annotated[Optional[Cost], Field(description="Cumulative session cost (optional).")] = None + # Total context window size in tokens. + size: Annotated[int, Field(description="Total context window size in tokens.", ge=0)] + # Tokens currently in context. + used: Annotated[int, Field(description="Tokens currently in context.", ge=0)] + + class WaitForTerminalExitRequest(BaseModel): # The _meta property is reserved by ACP to allow clients and agents to attach additional # metadata to their interactions. Implementations MUST NOT make assumptions about values at @@ -1423,6 +1496,17 @@ class PromptResponse(BaseModel): description="Indicates why the agent stopped processing the turn.", ), ] + # **UNSTABLE** + # + # This capability is not part of the spec yet, and may be removed or changed at any point. + # + # Token usage for this turn (optional). + usage: Annotated[ + Optional[Usage], + Field( + description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nToken usage for this turn (optional)." + ), + ] = None class ReadTextFileRequest(BaseModel): @@ -1666,6 +1750,10 @@ class CurrentModeUpdate(_CurrentModeUpdate): session_update: Annotated[Literal["current_mode_update"], Field(alias="sessionUpdate")] +class UsageUpdate(_UsageUpdate): + session_update: Annotated[Literal["usage_update"], Field(alias="sessionUpdate")] + + class TextContent(BaseModel): # The _meta property is reserved by ACP to allow clients and agents to attach additional # metadata to their interactions. Implementations MUST NOT make assumptions about values at @@ -2220,6 +2308,11 @@ class SessionConfigOptionSelect(SessionConfigSelect): description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", ), ] = None + # Optional semantic category for this option (UX only). + category: Annotated[ + Optional[str], + Field(description="Optional semantic category for this option (UX only)."), + ] = None # Optional description for the Client to display to the user. description: Annotated[ Optional[str], @@ -2233,15 +2326,11 @@ class SessionConfigOptionSelect(SessionConfigSelect): class SessionConfigOption(RootModel[SessionConfigOptionSelect]): - # **UNSTABLE** - # - # This capability is not part of the spec yet, and may be removed or changed at any point. - # # A session configuration option selector and its current state. root: Annotated[ SessionConfigOptionSelect, Field( - description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nA session configuration option selector and its current state.", + description="A session configuration option selector and its current state.", discriminator="type", ), ] @@ -2350,16 +2439,12 @@ class ForkSessionResponse(BaseModel): description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", ), ] = None - # **UNSTABLE** - # - # This capability is not part of the spec yet, and may be removed or changed at any point. - # # Initial session configuration options if supported by the Agent. config_options: Annotated[ Optional[List[SessionConfigOption]], Field( alias="configOptions", - description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + description="Initial session configuration options if supported by the Agent.", ), ] = None # **UNSTABLE** @@ -2405,16 +2490,12 @@ class LoadSessionResponse(BaseModel): description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", ), ] = None - # **UNSTABLE** - # - # This capability is not part of the spec yet, and may be removed or changed at any point. - # # Initial session configuration options if supported by the Agent. config_options: Annotated[ Optional[List[SessionConfigOption]], Field( alias="configOptions", - description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + description="Initial session configuration options if supported by the Agent.", ), ] = None # **UNSTABLE** @@ -2452,16 +2533,12 @@ class NewSessionResponse(BaseModel): description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", ), ] = None - # **UNSTABLE** - # - # This capability is not part of the spec yet, and may be removed or changed at any point. - # # Initial session configuration options if supported by the Agent. config_options: Annotated[ Optional[List[SessionConfigOption]], Field( alias="configOptions", - description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + description="Initial session configuration options if supported by the Agent.", ), ] = None # **UNSTABLE** @@ -2539,16 +2616,12 @@ class ResumeSessionResponse(BaseModel): description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", ), ] = None - # **UNSTABLE** - # - # This capability is not part of the spec yet, and may be removed or changed at any point. - # # Initial session configuration options if supported by the Agent. config_options: Annotated[ Optional[List[SessionConfigOption]], Field( alias="configOptions", - description="**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInitial session configuration options if supported by the Agent.", + description="Initial session configuration options if supported by the Agent.", ), ] = None # **UNSTABLE** @@ -2757,6 +2830,7 @@ class SessionNotification(BaseModel): CurrentModeUpdate, ConfigOptionUpdate, SessionInfoUpdate, + UsageUpdate, ], Field(description="The actual update content.", discriminator="session_update"), ] From e21d8d0acd16e31992361b1d79c3fdd06cbdd9f3 Mon Sep 17 00:00:00 2001 From: Chojan Shang Date: Sun, 8 Feb 2026 00:29:47 +0800 Subject: [PATCH 7/8] fix: allow omitting mcpServers in session requests (#58) * fix: allow omitting mcpServers in session requests * fix: warn on positional load_session session_id * Revert "fix: warn on positional load_session session_id" This reverts commit 1f21da8d68fa73bc49a0c2c4bc78d3cc60063907. * Revert "fix: allow omitting mcpServers in session requests" This reverts commit 73499a8f2ef7a0f32a0cf89e9aa6f973d66b976c. * fix: default mcpServers to empty list --- scripts/gen_signature.py | 30 +++++++-- src/acp/client/connection.py | 16 +++-- src/acp/interfaces.py | 8 ++- tests/real_user/test_mcp_servers_optional.py | 68 ++++++++++++++++++++ 4 files changed, 109 insertions(+), 13 deletions(-) create mode 100644 tests/real_user/test_mcp_servers_optional.py diff --git a/scripts/gen_signature.py b/scripts/gen_signature.py index b3a7add..b435e2c 100644 --- a/scripts/gen_signature.py +++ b/scripts/gen_signature.py @@ -9,6 +9,11 @@ from acp import schema +SIGNATURE_OPTIONAL_FIELDS: set[tuple[str, str]] = { + ("LoadSessionRequest", "mcp_servers"), + ("NewSessionRequest", "mcp_servers"), +} + class NodeTransformer(ast.NodeTransformer): def __init__(self) -> None: @@ -16,6 +21,7 @@ def __init__(self) -> None: self._schema_import_node: ast.ImportFrom | None = None self._should_rewrite = False self._literals = {name: value for name, value in schema.__dict__.items() if t.get_origin(value) is t.Literal} + self._current_model_name: str | None = None def _add_typing_import(self, name: str) -> None: if not self._type_import_node: @@ -71,9 +77,13 @@ def visit_func(self, node: ast.FunctionDef | ast.AsyncFunctionDef) -> ast.AST: self._should_rewrite = True model_name = t.cast(ast.Name, decorator.args[0]).id model = t.cast(type[schema.BaseModel], getattr(schema, model_name)) - param_defaults = [ - self._to_param_def(name, field) for name, field in model.model_fields.items() if name != "field_meta" - ] + self._current_model_name = model_name + try: + param_defaults = [ + self._to_param_def(name, field) for name, field in model.model_fields.items() if name != "field_meta" + ] + finally: + self._current_model_name = None param_defaults.sort(key=lambda x: x[1] is not None) node.args.args[1:] = [param for param, _ in param_defaults] node.args.defaults = [default for _, default in param_defaults if default is not None] @@ -84,12 +94,18 @@ def visit_func(self, node: ast.FunctionDef | ast.AsyncFunctionDef) -> ast.AST: def _to_param_def(self, name: str, field: FieldInfo) -> tuple[ast.arg, ast.expr | None]: arg = ast.arg(arg=name) ann = field.annotation - if field.default is PydanticUndefined: - default = None - elif isinstance(field.default, dict | BaseModel): + override_optional = (self._current_model_name, name) in SIGNATURE_OPTIONAL_FIELDS + if override_optional: + if ann is not None: + ann = ann | None default = ast.Constant(None) else: - default = ast.Constant(value=field.default) + if field.default is PydanticUndefined: + default = None + elif isinstance(field.default, dict | BaseModel): + default = ast.Constant(None) + else: + default = ast.Constant(value=field.default) if ann is not None: arg.annotation = self._format_annotation(ann) return arg, default diff --git a/src/acp/client/connection.py b/src/acp/client/connection.py index ac0d34f..9831d7e 100644 --- a/src/acp/client/connection.py +++ b/src/acp/client/connection.py @@ -93,23 +93,31 @@ async def initialize( @param_model(NewSessionRequest) async def new_session( - self, cwd: str, mcp_servers: list[HttpMcpServer | SseMcpServer | McpServerStdio], **kwargs: Any + self, cwd: str, mcp_servers: list[HttpMcpServer | SseMcpServer | McpServerStdio] | None = None, **kwargs: Any ) -> NewSessionResponse: + resolved_mcp_servers = mcp_servers or [] return await request_model( self._conn, AGENT_METHODS["session_new"], - NewSessionRequest(cwd=cwd, mcp_servers=mcp_servers, field_meta=kwargs or None), + NewSessionRequest(cwd=cwd, mcp_servers=resolved_mcp_servers, field_meta=kwargs or None), NewSessionResponse, ) @param_model(LoadSessionRequest) async def load_session( - self, cwd: str, mcp_servers: list[HttpMcpServer | SseMcpServer | McpServerStdio], session_id: str, **kwargs: Any + self, + cwd: str, + session_id: str, + mcp_servers: list[HttpMcpServer | SseMcpServer | McpServerStdio] | None = None, + **kwargs: Any, ) -> LoadSessionResponse: + resolved_mcp_servers = mcp_servers or [] return await request_model_from_dict( self._conn, AGENT_METHODS["session_load"], - LoadSessionRequest(cwd=cwd, mcp_servers=mcp_servers, session_id=session_id, field_meta=kwargs or None), + LoadSessionRequest( + cwd=cwd, mcp_servers=resolved_mcp_servers, session_id=session_id, field_meta=kwargs or None + ), LoadSessionResponse, ) diff --git a/src/acp/interfaces.py b/src/acp/interfaces.py index 457dfe7..55c00f3 100644 --- a/src/acp/interfaces.py +++ b/src/acp/interfaces.py @@ -154,12 +154,16 @@ async def initialize( @param_model(NewSessionRequest) async def new_session( - self, cwd: str, mcp_servers: list[HttpMcpServer | SseMcpServer | McpServerStdio], **kwargs: Any + self, cwd: str, mcp_servers: list[HttpMcpServer | SseMcpServer | McpServerStdio] | None = None, **kwargs: Any ) -> NewSessionResponse: ... @param_model(LoadSessionRequest) async def load_session( - self, cwd: str, mcp_servers: list[HttpMcpServer | SseMcpServer | McpServerStdio], session_id: str, **kwargs: Any + self, + cwd: str, + session_id: str, + mcp_servers: list[HttpMcpServer | SseMcpServer | McpServerStdio] | None = None, + **kwargs: Any, ) -> LoadSessionResponse | None: ... @param_model(ListSessionsRequest) diff --git a/tests/real_user/test_mcp_servers_optional.py b/tests/real_user/test_mcp_servers_optional.py new file mode 100644 index 0000000..96aae75 --- /dev/null +++ b/tests/real_user/test_mcp_servers_optional.py @@ -0,0 +1,68 @@ +import asyncio +from typing import Any + +import pytest + +from acp import InitializeResponse, LoadSessionResponse, NewSessionResponse +from acp.core import AgentSideConnection, ClientSideConnection +from acp.schema import HttpMcpServer, McpServerStdio, SseMcpServer +from tests.conftest import TestAgent, TestClient + + +class McpOptionalAgent(TestAgent): + def __init__(self) -> None: + super().__init__() + self.seen_new_session: tuple[str, Any] | None = None + self.seen_load_session: tuple[str, str, Any] | None = None + + async def new_session( + self, + cwd: str, + mcp_servers: list[HttpMcpServer | SseMcpServer | McpServerStdio] | None = None, + **kwargs: Any, + ) -> NewSessionResponse: + resolved_mcp_servers = mcp_servers or [] + self.seen_new_session = (cwd, resolved_mcp_servers) + return await super().new_session(cwd=cwd, mcp_servers=resolved_mcp_servers, **kwargs) + + async def load_session( + self, + cwd: str, + session_id: str, + mcp_servers: list[HttpMcpServer | SseMcpServer | McpServerStdio] | None = None, + **kwargs: Any, + ) -> LoadSessionResponse | None: + resolved_mcp_servers = mcp_servers or [] + self.seen_load_session = (cwd, session_id, resolved_mcp_servers) + return await super().load_session(cwd=cwd, session_id=session_id, mcp_servers=resolved_mcp_servers, **kwargs) + + +@pytest.mark.asyncio +async def test_session_requests_default_empty_mcp_servers(server) -> None: + client = TestClient() + captured_agent: list[McpOptionalAgent] = [] + + agent_conn = ClientSideConnection(client, server._client_writer, server._client_reader) # type: ignore[arg-type] + _agent_side = AgentSideConnection( + lambda _conn: captured_agent.append(McpOptionalAgent()) or captured_agent[-1], + server._server_writer, + server._server_reader, + listening=True, + ) + + init = await asyncio.wait_for(agent_conn.initialize(protocol_version=1), timeout=1.0) + assert isinstance(init, InitializeResponse) + + new_session = await asyncio.wait_for(agent_conn.new_session(cwd="/workspace"), timeout=1.0) + assert isinstance(new_session, NewSessionResponse) + + load_session = await asyncio.wait_for( + agent_conn.load_session(cwd="/workspace", session_id=new_session.session_id), + timeout=1.0, + ) + assert isinstance(load_session, LoadSessionResponse) + + assert captured_agent, "Agent was not constructed" + [agent] = captured_agent + assert agent.seen_new_session == ("/workspace", []) + assert agent.seen_load_session == ("/workspace", new_session.session_id, []) From a1d2ae8e9070763f575dc9a628ea76ecf49cef2e Mon Sep 17 00:00:00 2001 From: Chojan Shang Date: Sun, 8 Feb 2026 01:07:01 +0800 Subject: [PATCH 8/8] chore: prepare 0.8.0 release (#64) * chore: prepare 0.8.0 release * chore: bump to 0.8.0 --- .github/workflows/on-release-main.yml | 40 +++++++++++++++++++-------- docs/migration-guide-0.8.md | 37 +++++++++++++++++++++++++ mkdocs.yml | 1 + pyproject.toml | 2 +- uv.lock | 2 +- 5 files changed, 68 insertions(+), 14 deletions(-) create mode 100644 docs/migration-guide-0.8.md diff --git a/.github/workflows/on-release-main.yml b/.github/workflows/on-release-main.yml index 5e1bba1..620606a 100644 --- a/.github/workflows/on-release-main.yml +++ b/.github/workflows/on-release-main.yml @@ -4,6 +4,15 @@ on: release: types: [published] +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: true + jobs: set-version: runs-on: ubuntu-24.04 @@ -51,7 +60,7 @@ jobs: env: UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }} - deploy-docs: + build-docs: needs: publish runs-on: ubuntu-latest steps: @@ -61,14 +70,21 @@ jobs: - name: Set up the environment uses: ./.github/actions/setup-python-env - - name: Deploy documentation - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GIT_AUTHOR_NAME: acp-bot - GIT_AUTHOR_EMAIL: noreply@github.com - GIT_COMMITTER_NAME: acp-bot - GIT_COMMITTER_EMAIL: noreply@github.com - run: | - git config user.name "$GIT_AUTHOR_NAME" - git config user.email "$GIT_AUTHOR_EMAIL" - uv run mkdocs gh-deploy --force --remote-branch gh-pages --remote-name origin + - name: Build site + run: uv run mkdocs build -f mkdocs.yml --clean + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 + with: + path: site + + deploy-docs: + needs: build-docs + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 diff --git a/docs/migration-guide-0.8.md b/docs/migration-guide-0.8.md new file mode 100644 index 0000000..efb1d61 --- /dev/null +++ b/docs/migration-guide-0.8.md @@ -0,0 +1,37 @@ +# Migrating to ACP Python SDK 0.8 + +ACP 0.8 keeps the 0.7 public surface but aligns the SDK with the latest ACP schema and tightens a few runtime behaviors. Most teams only need to review the updated schema and terminal helpers. This guide calls out the changes that can affect downstream agents, clients, and tests. + +## 1. ACP schema bumped to 0.10.8 + +- Regenerate any internal copies of ACP schema-derived artifacts against 0.10.8. +- If you vendor schema types, run `make gen-all` or your equivalent pipeline. +- Helper types now include `SessionInfoUpdate` in the `SessionUpdate` union, so downstream code that exhaustively matches update variants should include it. + +## 2. `TerminalHandle` removal + +`TerminalHandle` is no longer part of the public API. If you referenced it directly, switch to the request/response models and terminal IDs returned by `CreateTerminalRequest`/`CreateTerminalResponse`. + +Typical adjustment: + +```python +# Before (0.7.x) +handle = await conn.create_terminal(...) +await conn.terminal_output(session_id=..., terminal_id=handle.id) + +# After (0.8.x) +resp = await conn.create_terminal(...) +await conn.terminal_output(session_id=..., terminal_id=resp.terminal_id) +``` + +## 3. Larger default stdio buffer limits + +The default stdio reader limit is now 50MB to support multimodal payloads. If you run in memory-constrained environments, explicitly set `stdio_buffer_limit_bytes` when calling `run_agent`. + +```python +await run_agent(agent, stdio_buffer_limit_bytes=2 * 1024 * 1024) +``` + +## 4. Documentation and quickstart updates + +Docs and settings examples have been refreshed for ACP 0.10.8. If you maintain internal onboarding material, sync it with the latest docs in `docs/`. diff --git a/mkdocs.yml b/mkdocs.yml index e74cd49..6a7a76e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -14,6 +14,7 @@ nav: - Experimental Contrib: contrib.md - Releasing: releasing.md - 0.7 Migration Guide: migration-guide-0.7.md + - 0.8 Migration Guide: migration-guide-0.8.md plugins: - search - mkdocstrings: diff --git a/pyproject.toml b/pyproject.toml index c31938f..fc62423 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "agent-client-protocol" -version = "0.7.1" +version = "0.8.0" description = "A Python implement of Agent Client Protocol (ACP, by Zed Industries)" authors = [ { name = "Chojan Shang", email = "psiace@apache.org" }, diff --git a/uv.lock b/uv.lock index 3bc3ea2..ad9247d 100644 --- a/uv.lock +++ b/uv.lock @@ -4,7 +4,7 @@ requires-python = ">=3.10, <3.15" [[package]] name = "agent-client-protocol" -version = "0.7.1" +version = "0.8.0" source = { editable = "." } dependencies = [ { name = "pydantic" },