diff --git a/.gitignore b/.gitignore index 78fefd3d..fac65dd9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ node_modules dist *.tsbuildinfo .DS_Store +.idea # TypeScript generated files typescript/*.js diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..cf3f1ccb --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +Read AGENTS.md before making any changes — it contains project workflow instructions, naming conventions, and required commands. diff --git a/Cargo.toml b/Cargo.toml index 86160b45..82d9e794 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ include = ["/src/**/*.rs", "/README.md", "/LICENSE", "/Cargo.toml"] unstable = [ "unstable_auth_methods", "unstable_cancel_request", + "unstable_llm_providers", "unstable_elicitation", "unstable_logout", "unstable_session_fork", @@ -29,6 +30,7 @@ unstable = [ ] unstable_auth_methods = [] unstable_cancel_request = [] +unstable_llm_providers = [] unstable_elicitation = [] unstable_logout = [] unstable_session_fork = [] diff --git a/docs/protocol/draft/schema.mdx b/docs/protocol/draft/schema.mdx index d9a81347..0ae907c3 100644 --- a/docs/protocol/draft/schema.mdx +++ b/docs/protocol/draft/schema.mdx @@ -213,6 +213,180 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/exte + +### providers/disable + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Disables a provider. + +#### DisableProvidersRequest + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Request parameters for `providers/disable`. + +**Type:** Object + +**Properties:** + + + 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) + + + + Provider id to disable. + + +#### DisableProvidersResponse + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Response to `providers/disable`. + +**Type:** Object + +**Properties:** + + + 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) + + + + +### providers/list + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Lists providers that can be configured by the client. + +#### ListProvidersRequest + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Request parameters for `providers/list`. + +**Type:** Object + +**Properties:** + + + 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) + + + +#### ListProvidersResponse + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Response to `providers/list`. + +**Type:** Object + +**Properties:** + + + 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) + + +ProviderInfo[]} required> + Configurable providers with current routing info suitable for UI display. + + + +### providers/set + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Replaces the configuration for a provider. + +#### SetProvidersRequest + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Request parameters for `providers/set`. + +Replaces the full configuration for one provider id. + +**Type:** Object + +**Properties:** + + + 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) + + +LlmProtocol} required> + Protocol type for this provider. + + + Base URL for requests sent through this provider. + + + Full headers map for this provider. +May include authorization, routing, or other integration-specific headers. + + + Provider id to configure. + + +#### SetProvidersResponse + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Response to `providers/set`. + +**Type:** Object + +**Properties:** + + + 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) + + + ### session/cancel @@ -1805,6 +1979,16 @@ Authentication-related capabilities supported by the agent. - Default: `{"audio":false,"embeddedContext":false,"image":false}` + +ProvidersCapabilities | null} > + **UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Provider configuration capabilities supported by the agent. + +By supplying `\{\}` it means that the agent supports provider configuration methods. + SessionCapabilities} > @@ -3423,6 +3607,40 @@ Schema for integer properties in an elicitation form. Optional title for the property. +## LlmProtocol + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Well-known API protocol identifiers for LLM providers. + +**Type:** Union + + + Anthropic API protocol. + + + + OpenAI API protocol. + + + + Azure OpenAI API protocol. + + + + Google Vertex AI API protocol. + + + + AWS Bedrock API protocol. + + + + Unknown or custom protocol. + + ## LogoutCapabilities **UNSTABLE** @@ -4030,6 +4248,87 @@ Non-breaking changes should be introduced via capabilities. | Minimum | `0` | | Maximum | `65535` | +## ProviderCurrentConfig + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Current effective non-secret routing configuration for a provider. + +**Type:** Object + +**Properties:** + +LlmProtocol} + required +> + Protocol currently used by this provider. + + + Base URL currently used by this provider. + + +## ProviderInfo + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Information about a configurable LLM provider. + +**Type:** Object + +**Properties:** + + + 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) + + +ProviderCurrentConfig | null} required> + Current effective non-secret routing config. +Null means provider is disabled. + + + Provider identifier, for example "main" or "openai". + + + Whether this provider is mandatory and cannot be disabled via `providers/disable`. +If true, clients must not call `providers/disable` for this id. + +LlmProtocol[]} required> + Supported protocol types for this provider. + + +## ProvidersCapabilities + +**UNSTABLE** + +This capability is not part of the spec yet, and may be removed or changed at any point. + +Provider configuration capabilities supported by the agent. + +By supplying `\{\}` it means that the agent supports provider configuration methods. + +**Type:** Object + +**Properties:** + + + 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) + + + ## RequestId JSON RPC Request Id diff --git a/schema/meta.unstable.json b/schema/meta.unstable.json index 6198214a..fbd8fc49 100644 --- a/schema/meta.unstable.json +++ b/schema/meta.unstable.json @@ -3,6 +3,9 @@ "authenticate": "authenticate", "initialize": "initialize", "logout": "logout", + "providers_disable": "providers/disable", + "providers_list": "providers/list", + "providers_set": "providers/set", "session_cancel": "session/cancel", "session_close": "session/close", "session_fork": "session/fork", diff --git a/schema/schema.unstable.json b/schema/schema.unstable.json index 081e1a1f..1cca5d17 100644 --- a/schema/schema.unstable.json +++ b/schema/schema.unstable.json @@ -69,6 +69,17 @@ }, "description": "Prompt capabilities supported by the agent." }, + "providers": { + "anyOf": [ + { + "$ref": "#/$defs/ProvidersCapabilities" + }, + { + "type": "null" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nProvider configuration capabilities supported by the agent.\n\nBy supplying `{}` it means that the agent supports provider configuration methods." + }, "sessionCapabilities": { "allOf": [ { @@ -269,6 +280,30 @@ ], "title": "AuthenticateResponse" }, + { + "allOf": [ + { + "$ref": "#/$defs/ListProvidersResponse" + } + ], + "title": "ListProvidersResponse" + }, + { + "allOf": [ + { + "$ref": "#/$defs/SetProvidersResponse" + } + ], + "title": "SetProvidersResponse" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DisableProvidersResponse" + } + ], + "title": "DisableProvidersResponse" + }, { "allOf": [ { @@ -928,6 +963,33 @@ "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": [ + { + "$ref": "#/$defs/ListProvidersRequest" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nLists providers that can be configured by the client.", + "title": "ListProvidersRequest" + }, + { + "allOf": [ + { + "$ref": "#/$defs/SetProvidersRequest" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nReplaces the configuration for a provider.", + "title": "SetProvidersRequest" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DisableProvidersRequest" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nDisables a provider.", + "title": "DisableProvidersRequest" + }, { "allOf": [ { @@ -1476,6 +1538,37 @@ "required": ["path", "newText"], "type": "object" }, + "DisableProvidersRequest": { + "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 `providers/disable`.", + "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"] + }, + "id": { + "description": "Provider id to disable.", + "type": "string" + } + }, + "required": ["id"], + "type": "object", + "x-method": "providers/disable", + "x-side": "agent" + }, + "DisableProvidersResponse": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nResponse to `providers/disable`.", + "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"] + } + }, + "type": "object", + "x-method": "providers/disable", + "x-side": "agent" + }, "ElicitationAcceptAction": { "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nThe user accepted the elicitation and provided content.", "properties": { @@ -2459,6 +2552,40 @@ "x-method": "terminal/kill", "x-side": "client" }, + "ListProvidersRequest": { + "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 `providers/list`.", + "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"] + } + }, + "type": "object", + "x-method": "providers/list", + "x-side": "agent" + }, + "ListProvidersResponse": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nResponse to `providers/list`.", + "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"] + }, + "providers": { + "description": "Configurable providers with current routing info suitable for UI display.", + "items": { + "$ref": "#/$defs/ProviderInfo" + }, + "type": "array" + } + }, + "required": ["providers"], + "type": "object", + "x-method": "providers/list", + "x-side": "agent" + }, "ListSessionsRequest": { "description": "Request parameters for listing existing sessions.\n\nOnly available if the Agent supports the `sessionCapabilities.list` capability.", "properties": { @@ -2505,6 +2632,41 @@ "x-method": "session/list", "x-side": "agent" }, + "LlmProtocol": { + "anyOf": [ + { + "const": "anthropic", + "description": "Anthropic API protocol.", + "type": "string" + }, + { + "const": "openai", + "description": "OpenAI API protocol.", + "type": "string" + }, + { + "const": "azure", + "description": "Azure OpenAI API protocol.", + "type": "string" + }, + { + "const": "vertex", + "description": "Google Vertex AI API protocol.", + "type": "string" + }, + { + "const": "bedrock", + "description": "AWS Bedrock API protocol.", + "type": "string" + }, + { + "description": "Unknown or custom protocol.", + "title": "other", + "type": "string" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nWell-known API protocol identifiers for LLM providers." + }, "LoadSessionRequest": { "description": "Request parameters for loading an existing session.\n\nOnly available if the Agent supports the `loadSession` capability.\n\nSee protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)", "properties": { @@ -3229,6 +3391,74 @@ "minimum": 0, "type": "integer" }, + "ProviderCurrentConfig": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nCurrent effective non-secret routing configuration for a provider.", + "properties": { + "apiType": { + "allOf": [ + { + "$ref": "#/$defs/LlmProtocol" + } + ], + "description": "Protocol currently used by this provider." + }, + "baseUrl": { + "description": "Base URL currently used by this provider.", + "type": "string" + } + }, + "required": ["apiType", "baseUrl"], + "type": "object" + }, + "ProviderInfo": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nInformation about a configurable LLM provider.", + "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"] + }, + "current": { + "anyOf": [ + { + "$ref": "#/$defs/ProviderCurrentConfig" + }, + { + "type": "null" + } + ], + "description": "Current effective non-secret routing config.\nNull means provider is disabled." + }, + "id": { + "description": "Provider identifier, for example \"main\" or \"openai\".", + "type": "string" + }, + "required": { + "description": "Whether this provider is mandatory and cannot be disabled via `providers/disable`.\nIf true, clients must not call `providers/disable` for this id.", + "type": "boolean" + }, + "supported": { + "description": "Supported protocol types for this provider.", + "items": { + "$ref": "#/$defs/LlmProtocol" + }, + "type": "array" + } + }, + "required": ["id", "supported", "required", "current"], + "type": "object" + }, + "ProvidersCapabilities": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nProvider configuration capabilities supported by the agent.\n\nBy supplying `{}` it means that the agent supports provider configuration methods.", + "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"] + } + }, + "type": "object" + }, "ReadTextFileRequest": { "description": "Request to read content from a text file.\n\nOnly available if the client supports the `fs.readTextFile` capability.", "properties": { @@ -4250,6 +4480,56 @@ } ] }, + "SetProvidersRequest": { + "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 `providers/set`.\n\nReplaces the full configuration for one provider id.", + "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"] + }, + "apiType": { + "allOf": [ + { + "$ref": "#/$defs/LlmProtocol" + } + ], + "description": "Protocol type for this provider." + }, + "baseUrl": { + "description": "Base URL for requests sent through this provider.", + "type": "string" + }, + "headers": { + "additionalProperties": { + "type": "string" + }, + "description": "Full headers map for this provider.\nMay include authorization, routing, or other integration-specific headers.", + "type": "object" + }, + "id": { + "description": "Provider id to configure.", + "type": "string" + } + }, + "required": ["id", "apiType", "baseUrl"], + "type": "object", + "x-method": "providers/set", + "x-side": "agent" + }, + "SetProvidersResponse": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nResponse to `providers/set`.", + "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"] + } + }, + "type": "object", + "x-method": "providers/set", + "x-side": "agent" + }, "SetSessionConfigOptionRequest": { "anyOf": [ { diff --git a/src/agent.rs b/src/agent.rs index b8ce81de..69963774 100644 --- a/src/agent.rs +++ b/src/agent.rs @@ -5,7 +5,7 @@ use std::{path::PathBuf, sync::Arc}; -#[cfg(feature = "unstable_auth_methods")] +#[cfg(any(feature = "unstable_auth_methods", feature = "unstable_llm_providers"))] use std::collections::HashMap; use derive_more::{Display, From}; @@ -3212,6 +3212,427 @@ impl SetSessionModelResponse { } } +// Providers + +/// **UNSTABLE** +/// +/// This capability is not part of the spec yet, and may be removed or changed at any point. +/// +/// Well-known API protocol identifiers for LLM providers. +#[cfg(feature = "unstable_llm_providers")] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[serde(rename_all = "snake_case")] +#[non_exhaustive] +pub enum LlmProtocol { + /// Anthropic API protocol. + Anthropic, + /// OpenAI API protocol. + Openai, + /// Azure OpenAI API protocol. + Azure, + /// Google Vertex AI API protocol. + Vertex, + /// AWS Bedrock API protocol. + Bedrock, + /// Unknown or custom protocol. + #[serde(untagged)] + Other(String), +} + +/// **UNSTABLE** +/// +/// This capability is not part of the spec yet, and may be removed or changed at any point. +/// +/// Current effective non-secret routing configuration for a provider. +#[cfg(feature = "unstable_llm_providers")] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +#[non_exhaustive] +pub struct ProviderCurrentConfig { + /// Protocol currently used by this provider. + pub api_type: LlmProtocol, + /// Base URL currently used by this provider. + pub base_url: String, +} + +#[cfg(feature = "unstable_llm_providers")] +impl ProviderCurrentConfig { + #[must_use] + pub fn new(api_type: LlmProtocol, base_url: impl Into) -> Self { + Self { + api_type, + base_url: base_url.into(), + } + } +} + +/// **UNSTABLE** +/// +/// This capability is not part of the spec yet, and may be removed or changed at any point. +/// +/// Required field wrapper for nullable provider current config. +/// +/// On the wire this is encoded exactly as `ProviderCurrentConfig | null`. +#[cfg(feature = "unstable_llm_providers")] +#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[serde(transparent)] +#[schemars(with = "Option", inline)] +#[non_exhaustive] +pub struct RequiredProviderCurrentConfig(pub Option); + +#[cfg(feature = "unstable_llm_providers")] +impl From> for RequiredProviderCurrentConfig { + fn from(value: Option) -> Self { + Self(value) + } +} + +#[cfg(feature = "unstable_llm_providers")] +impl From for RequiredProviderCurrentConfig { + fn from(value: ProviderCurrentConfig) -> Self { + Self(Some(value)) + } +} + +#[cfg(feature = "unstable_llm_providers")] +impl From for Option { + fn from(value: RequiredProviderCurrentConfig) -> Self { + value.0 + } +} + +/// **UNSTABLE** +/// +/// This capability is not part of the spec yet, and may be removed or changed at any point. +/// +/// Information about a configurable LLM provider. +#[cfg(feature = "unstable_llm_providers")] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +#[non_exhaustive] +pub struct ProviderInfo { + /// Provider identifier, for example "main" or "openai". + pub id: String, + /// Supported protocol types for this provider. + pub supported: Vec, + /// Whether this provider is mandatory and cannot be disabled via `providers/disable`. + /// If true, clients must not call `providers/disable` for this id. + pub required: bool, + /// Current effective non-secret routing config. + /// Null means provider is disabled. + pub current: RequiredProviderCurrentConfig, + /// 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) + #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")] + pub meta: Option, +} + +#[cfg(feature = "unstable_llm_providers")] +impl ProviderInfo { + #[must_use] + pub fn new(id: impl Into, supported: Vec, required: bool) -> Self { + Self { + id: id.into(), + supported, + required, + current: RequiredProviderCurrentConfig::default(), + meta: None, + } + } + + /// Current effective non-secret routing config. + /// Null means provider is disabled. + #[must_use] + pub fn current(mut self, current: impl IntoOption) -> Self { + self.current = current.into_option().into(); + self + } + + /// 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) + #[must_use] + pub fn meta(mut self, meta: impl IntoOption) -> Self { + self.meta = meta.into_option(); + self + } +} + +/// **UNSTABLE** +/// +/// This capability is not part of the spec yet, and may be removed or changed at any point. +/// +/// Request parameters for `providers/list`. +#[cfg(feature = "unstable_llm_providers")] +#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))] +#[serde(rename_all = "camelCase")] +#[non_exhaustive] +pub struct ListProvidersRequest { + /// 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) + #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")] + pub meta: Option, +} + +#[cfg(feature = "unstable_llm_providers")] +impl ListProvidersRequest { + #[must_use] + pub fn new() -> Self { + Self::default() + } + + /// 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) + #[must_use] + pub fn meta(mut self, meta: impl IntoOption) -> Self { + self.meta = meta.into_option(); + self + } +} + +/// **UNSTABLE** +/// +/// This capability is not part of the spec yet, and may be removed or changed at any point. +/// +/// Response to `providers/list`. +#[cfg(feature = "unstable_llm_providers")] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))] +#[serde(rename_all = "camelCase")] +#[non_exhaustive] +pub struct ListProvidersResponse { + /// Configurable providers with current routing info suitable for UI display. + pub providers: Vec, + /// 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) + #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")] + pub meta: Option, +} + +#[cfg(feature = "unstable_llm_providers")] +impl ListProvidersResponse { + #[must_use] + pub fn new(providers: Vec) -> Self { + Self { + providers, + meta: None, + } + } + + /// 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) + #[must_use] + pub fn meta(mut self, meta: impl IntoOption) -> Self { + self.meta = meta.into_option(); + self + } +} + +/// **UNSTABLE** +/// +/// This capability is not part of the spec yet, and may be removed or changed at any point. +/// +/// Request parameters for `providers/set`. +/// +/// Replaces the full configuration for one provider id. +#[cfg(feature = "unstable_llm_providers")] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))] +#[serde(rename_all = "camelCase")] +#[non_exhaustive] +pub struct SetProvidersRequest { + /// Provider id to configure. + pub id: String, + /// Protocol type for this provider. + pub api_type: LlmProtocol, + /// Base URL for requests sent through this provider. + pub base_url: String, + /// Full headers map for this provider. + /// May include authorization, routing, or other integration-specific headers. + #[serde(default, skip_serializing_if = "HashMap::is_empty")] + pub headers: HashMap, + /// 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) + #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")] + pub meta: Option, +} + +#[cfg(feature = "unstable_llm_providers")] +impl SetProvidersRequest { + #[must_use] + pub fn new(id: impl Into, api_type: LlmProtocol, base_url: impl Into) -> Self { + Self { + id: id.into(), + api_type, + base_url: base_url.into(), + headers: HashMap::new(), + meta: None, + } + } + + /// Full headers map for this provider. + /// May include authorization, routing, or other integration-specific headers. + #[must_use] + pub fn headers(mut self, headers: HashMap) -> Self { + self.headers = headers; + self + } + + /// 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) + #[must_use] + pub fn meta(mut self, meta: impl IntoOption) -> Self { + self.meta = meta.into_option(); + self + } +} + +/// **UNSTABLE** +/// +/// This capability is not part of the spec yet, and may be removed or changed at any point. +/// +/// Response to `providers/set`. +#[cfg(feature = "unstable_llm_providers")] +#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))] +#[serde(rename_all = "camelCase")] +#[non_exhaustive] +pub struct SetProvidersResponse { + /// 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) + #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")] + pub meta: Option, +} + +#[cfg(feature = "unstable_llm_providers")] +impl SetProvidersResponse { + #[must_use] + pub fn new() -> Self { + Self::default() + } + + /// 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) + #[must_use] + pub fn meta(mut self, meta: impl IntoOption) -> Self { + self.meta = meta.into_option(); + self + } +} + +/// **UNSTABLE** +/// +/// This capability is not part of the spec yet, and may be removed or changed at any point. +/// +/// Request parameters for `providers/disable`. +#[cfg(feature = "unstable_llm_providers")] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))] +#[serde(rename_all = "camelCase")] +#[non_exhaustive] +pub struct DisableProvidersRequest { + /// Provider id to disable. + pub id: String, + /// 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) + #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")] + pub meta: Option, +} + +#[cfg(feature = "unstable_llm_providers")] +impl DisableProvidersRequest { + #[must_use] + pub fn new(id: impl Into) -> Self { + Self { + id: id.into(), + meta: None, + } + } + + /// 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) + #[must_use] + pub fn meta(mut self, meta: impl IntoOption) -> Self { + self.meta = meta.into_option(); + self + } +} + +/// **UNSTABLE** +/// +/// This capability is not part of the spec yet, and may be removed or changed at any point. +/// +/// Response to `providers/disable`. +#[cfg(feature = "unstable_llm_providers")] +#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))] +#[serde(rename_all = "camelCase")] +#[non_exhaustive] +pub struct DisableProvidersResponse { + /// 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) + #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")] + pub meta: Option, +} + +#[cfg(feature = "unstable_llm_providers")] +impl DisableProvidersResponse { + #[must_use] + pub fn new() -> Self { + Self::default() + } + + /// 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) + #[must_use] + pub fn meta(mut self, meta: impl IntoOption) -> Self { + self.meta = meta.into_option(); + self + } +} + // Capabilities /// Capabilities supported by the agent. @@ -3243,6 +3664,16 @@ pub struct AgentCapabilities { #[cfg(feature = "unstable_logout")] #[serde(default)] pub auth: AgentAuthCapabilities, + /// **UNSTABLE** + /// + /// This capability is not part of the spec yet, and may be removed or changed at any point. + /// + /// Provider configuration capabilities supported by the agent. + /// + /// By supplying `{}` it means that the agent supports provider configuration methods. + #[cfg(feature = "unstable_llm_providers")] + #[serde(skip_serializing_if = "Option::is_none")] + pub providers: Option, /// 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. @@ -3298,6 +3729,57 @@ impl AgentCapabilities { self } + /// **UNSTABLE** + /// + /// This capability is not part of the spec yet, and may be removed or changed at any point. + /// + /// Provider configuration capabilities supported by the agent. + #[cfg(feature = "unstable_llm_providers")] + #[must_use] + pub fn providers(mut self, providers: impl IntoOption) -> Self { + self.providers = providers.into_option(); + self + } + + /// 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) + #[must_use] + pub fn meta(mut self, meta: impl IntoOption) -> Self { + self.meta = meta.into_option(); + self + } +} + +/// **UNSTABLE** +/// +/// This capability is not part of the spec yet, and may be removed or changed at any point. +/// +/// Provider configuration capabilities supported by the agent. +/// +/// By supplying `{}` it means that the agent supports provider configuration methods. +#[cfg(feature = "unstable_llm_providers")] +#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[non_exhaustive] +pub struct ProvidersCapabilities { + /// 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) + #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")] + pub meta: Option, +} + +#[cfg(feature = "unstable_llm_providers")] +impl ProvidersCapabilities { + #[must_use] + pub fn new() -> Self { + Self::default() + } + /// 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. @@ -3699,6 +4181,15 @@ pub struct AgentMethodNames { pub initialize: &'static str, /// Method for authenticating with the agent. pub authenticate: &'static str, + /// Method for listing configurable providers. + #[cfg(feature = "unstable_llm_providers")] + pub providers_list: &'static str, + /// Method for setting provider configuration. + #[cfg(feature = "unstable_llm_providers")] + pub providers_set: &'static str, + /// Method for disabling a provider. + #[cfg(feature = "unstable_llm_providers")] + pub providers_disable: &'static str, /// Method for creating a new session. pub session_new: &'static str, /// Method for loading an existing session. @@ -3734,6 +4225,12 @@ pub struct AgentMethodNames { pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames { initialize: INITIALIZE_METHOD_NAME, authenticate: AUTHENTICATE_METHOD_NAME, + #[cfg(feature = "unstable_llm_providers")] + providers_list: PROVIDERS_LIST_METHOD_NAME, + #[cfg(feature = "unstable_llm_providers")] + providers_set: PROVIDERS_SET_METHOD_NAME, + #[cfg(feature = "unstable_llm_providers")] + providers_disable: PROVIDERS_DISABLE_METHOD_NAME, session_new: SESSION_NEW_METHOD_NAME, session_load: SESSION_LOAD_METHOD_NAME, session_set_mode: SESSION_SET_MODE_METHOD_NAME, @@ -3757,6 +4254,15 @@ pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames { pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize"; /// Method name for the authenticate request. pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate"; +/// Method name for listing configurable providers. +#[cfg(feature = "unstable_llm_providers")] +pub(crate) const PROVIDERS_LIST_METHOD_NAME: &str = "providers/list"; +/// Method name for setting provider configuration. +#[cfg(feature = "unstable_llm_providers")] +pub(crate) const PROVIDERS_SET_METHOD_NAME: &str = "providers/set"; +/// Method name for disabling a provider. +#[cfg(feature = "unstable_llm_providers")] +pub(crate) const PROVIDERS_DISABLE_METHOD_NAME: &str = "providers/disable"; /// Method name for creating a new session. pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new"; /// Method name for loading an existing session. @@ -3824,6 +4330,27 @@ pub enum ClientRequest { /// /// This capability is not part of the spec yet, and may be removed or changed at any point. /// + /// Lists providers that can be configured by the client. + #[cfg(feature = "unstable_llm_providers")] + ListProvidersRequest(ListProvidersRequest), + /// **UNSTABLE** + /// + /// This capability is not part of the spec yet, and may be removed or changed at any point. + /// + /// Replaces the configuration for a provider. + #[cfg(feature = "unstable_llm_providers")] + SetProvidersRequest(SetProvidersRequest), + /// **UNSTABLE** + /// + /// This capability is not part of the spec yet, and may be removed or changed at any point. + /// + /// Disables a provider. + #[cfg(feature = "unstable_llm_providers")] + DisableProvidersRequest(DisableProvidersRequest), + /// **UNSTABLE** + /// + /// This capability is not part of the spec yet, and may be removed or changed at any point. + /// /// Logs out of the current authenticated state. /// /// After a successful logout, all new sessions will require authentication. @@ -3948,6 +4475,12 @@ impl ClientRequest { match self { Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize, Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate, + #[cfg(feature = "unstable_llm_providers")] + Self::ListProvidersRequest(_) => AGENT_METHOD_NAMES.providers_list, + #[cfg(feature = "unstable_llm_providers")] + Self::SetProvidersRequest(_) => AGENT_METHOD_NAMES.providers_set, + #[cfg(feature = "unstable_llm_providers")] + Self::DisableProvidersRequest(_) => AGENT_METHOD_NAMES.providers_disable, #[cfg(feature = "unstable_logout")] Self::LogoutRequest(_) => AGENT_METHOD_NAMES.logout, Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new, @@ -3983,6 +4516,12 @@ impl ClientRequest { pub enum AgentResponse { InitializeResponse(InitializeResponse), AuthenticateResponse(#[serde(default)] AuthenticateResponse), + #[cfg(feature = "unstable_llm_providers")] + ListProvidersResponse(ListProvidersResponse), + #[cfg(feature = "unstable_llm_providers")] + SetProvidersResponse(#[serde(default)] SetProvidersResponse), + #[cfg(feature = "unstable_llm_providers")] + DisableProvidersResponse(#[serde(default)] DisableProvidersResponse), #[cfg(feature = "unstable_logout")] LogoutResponse(#[serde(default)] LogoutResponse), NewSessionResponse(NewSessionResponse), diff --git a/src/bin/generate.rs b/src/bin/generate.rs index 3051d30f..79c67f46 100644 --- a/src/bin/generate.rs +++ b/src/bin/generate.rs @@ -1018,6 +1018,12 @@ starting with '$/' it is free to ignore the notification." match method_name { "initialize" => self.agent.get("InitializeRequest").unwrap(), "authenticate" => self.agent.get("AuthenticateRequest").unwrap(), + #[cfg(feature = "unstable_llm_providers")] + "providers/list" => self.agent.get("ListProvidersRequest").unwrap(), + #[cfg(feature = "unstable_llm_providers")] + "providers/set" => self.agent.get("SetProvidersRequest").unwrap(), + #[cfg(feature = "unstable_llm_providers")] + "providers/disable" => self.agent.get("DisableProvidersRequest").unwrap(), "session/new" => self.agent.get("NewSessionRequest").unwrap(), "session/load" => self.agent.get("LoadSessionRequest").unwrap(), "session/list" => self.agent.get("ListSessionsRequest").unwrap(), diff --git a/src/rpc.rs b/src/rpc.rs index 868087ee..0f96fb4c 100644 --- a/src/rpc.rs +++ b/src/rpc.rs @@ -284,6 +284,18 @@ impl Side for AgentSide { m if m == AGENT_METHOD_NAMES.authenticate => serde_json::from_str(params.get()) .map(ClientRequest::AuthenticateRequest) .map_err(Into::into), + #[cfg(feature = "unstable_llm_providers")] + m if m == AGENT_METHOD_NAMES.providers_list => serde_json::from_str(params.get()) + .map(ClientRequest::ListProvidersRequest) + .map_err(Into::into), + #[cfg(feature = "unstable_llm_providers")] + m if m == AGENT_METHOD_NAMES.providers_set => serde_json::from_str(params.get()) + .map(ClientRequest::SetProvidersRequest) + .map_err(Into::into), + #[cfg(feature = "unstable_llm_providers")] + m if m == AGENT_METHOD_NAMES.providers_disable => serde_json::from_str(params.get()) + .map(ClientRequest::DisableProvidersRequest) + .map_err(Into::into), #[cfg(feature = "unstable_logout")] m if m == AGENT_METHOD_NAMES.logout => serde_json::from_str(params.get()) .map(ClientRequest::LogoutRequest)