acp: pin V1 SDK and narrow acp crate features (#11289)
This commit is contained in:
+2
-2
@@ -21,9 +21,9 @@ string_slice = "warn"
|
||||
|
||||
[workspace.dependencies]
|
||||
rmcp = { version = "3.0.0", default-features = false, features = ["schemars", "auth"] }
|
||||
agent-client-protocol-schema = { version = "=1.5.0", default-features = false, features = ["unstable"] }
|
||||
agent-client-protocol-schema = { version = "=1.5.0", default-features = false }
|
||||
agent-client-protocol = { version = "2.0.0", default-features = false }
|
||||
agent-client-protocol-http = { version = "2.0.0", default-features = false, features = ["server"] }
|
||||
agent-client-protocol-http = { version = "2.0.0", default-features = false }
|
||||
arboard = { version = "3", default-features = false }
|
||||
anyhow = { version = "1.0.102", default-features = false, features = ["std"] }
|
||||
async-stream = { version = "0.3.6", default-features = false }
|
||||
|
||||
@@ -9,7 +9,7 @@ repository.workspace = true
|
||||
description = "Shared types for the Goose SDK"
|
||||
|
||||
[dependencies]
|
||||
agent-client-protocol = { workspace = true, features = ["unstable"] }
|
||||
agent-client-protocol = { workspace = true }
|
||||
agent-client-protocol-schema = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
@@ -34,7 +34,7 @@ uniffi = [
|
||||
|
||||
[dependencies]
|
||||
goose-sdk-types = { version = "0.1.0-alpha.6", path = "../goose-sdk-types" }
|
||||
agent-client-protocol = { workspace = true, features = ["unstable"] }
|
||||
agent-client-protocol = { workspace = true }
|
||||
agent-client-protocol-schema = { workspace = true }
|
||||
|
||||
uniffi = { version = "0.32", features = ["cli"], optional = true }
|
||||
|
||||
@@ -101,7 +101,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Step 1: Initialize
|
||||
eprintln!("🤝 Initializing...");
|
||||
let init_response = cx
|
||||
.send_request(InitializeRequest::new(ProtocolVersion::LATEST))
|
||||
.send_request(InitializeRequest::new(ProtocolVersion::V1))
|
||||
.block_task()
|
||||
.await?;
|
||||
eprintln!("✓ Agent initialized: {:?}", init_response.agent_info);
|
||||
|
||||
@@ -171,8 +171,12 @@ tokio-stream = { workspace = true, features = ["io-util"] }
|
||||
tempfile = { workspace = true }
|
||||
tokio-util = { workspace = true, features = ["compat"] }
|
||||
agent-client-protocol-schema = { workspace = true }
|
||||
agent-client-protocol = { workspace = true, features = ["unstable"] }
|
||||
agent-client-protocol-http = { workspace = true }
|
||||
agent-client-protocol = { workspace = true, features = [
|
||||
"unstable_elicitation",
|
||||
"unstable_end_turn_token_usage",
|
||||
"unstable_session_fork",
|
||||
] }
|
||||
agent-client-protocol-http = { workspace = true, features = ["server"] }
|
||||
unicode-normalization = { version = "0.1.22", default-features = false, features = ["std"] }
|
||||
|
||||
# For local Whisper transcription (optional, behind "local-inference" feature)
|
||||
|
||||
@@ -227,20 +227,6 @@
|
||||
],
|
||||
"description": "SSE transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.sse` is `true`."
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/McpServerAcp",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"const": "acp"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nACP transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.acp` is `true`.\nThe MCP server is provided by an ACP component and communicates over the ACP channel."
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/McpServerStdio",
|
||||
"description": "Stdio transport configuration\n\nAll Agents MUST support this transport."
|
||||
@@ -355,37 +341,6 @@
|
||||
],
|
||||
"description": "SSE transport configuration for MCP."
|
||||
},
|
||||
"McpServerAcpId": {
|
||||
"type": "string",
|
||||
"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 an MCP server using the ACP transport.\n\nThe value is opaque and generated by the ACP component providing the MCP server. It is\nused by `mcp/connect` to route connection requests back to the component that declared the\nserver."
|
||||
},
|
||||
"McpServerAcp": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Human-readable name identifying this MCP server."
|
||||
},
|
||||
"serverId": {
|
||||
"$ref": "#/$defs/McpServerAcpId",
|
||||
"description": "Unique identifier for this MCP server, generated by the component providing it.\n\nProviders MUST NOT reuse an ID for multiple ACP-transport MCP servers that are visible\non the same ACP connection."
|
||||
},
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": {},
|
||||
"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)",
|
||||
"x-deserialize-default-on-error": {}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"serverId"
|
||||
],
|
||||
"description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nACP transport configuration for MCP.\n\nThe MCP server is provided by an ACP component and communicates over the ACP channel\nusing `mcp/connect`, `mcp/message`, and `mcp/disconnect`."
|
||||
},
|
||||
"McpServerStdio": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -1243,8 +1243,7 @@ async fn handle_requests(
|
||||
let client_capabilities = ClientCapabilities::new();
|
||||
let init_response: InitializeResponse = cx
|
||||
.send_request(
|
||||
InitializeRequest::new(ProtocolVersion::LATEST)
|
||||
.client_capabilities(client_capabilities),
|
||||
InitializeRequest::new(ProtocolVersion::V1).client_capabilities(client_capabilities),
|
||||
)
|
||||
.block_task()
|
||||
.await
|
||||
|
||||
@@ -2810,8 +2810,7 @@ print(\"hello, world\")
|
||||
|
||||
#[test]
|
||||
fn test_goose_custom_notifications_capability_defaults_to_false() {
|
||||
let request =
|
||||
InitializeRequest::new(agent_client_protocol::schema::ProtocolVersion::LATEST);
|
||||
let request = InitializeRequest::new(agent_client_protocol::schema::ProtocolVersion::V1);
|
||||
let goose_client_capabilities =
|
||||
extract_client_capabilities_meta(&request).and_then(|meta| meta.goose);
|
||||
|
||||
@@ -2840,11 +2839,10 @@ print(\"hello, world\")
|
||||
let mut meta = serde_json::Map::new();
|
||||
meta.insert("goose".to_string(), serde_json::Value::Object(goose_meta));
|
||||
|
||||
let request =
|
||||
InitializeRequest::new(agent_client_protocol::schema::ProtocolVersion::LATEST)
|
||||
.client_capabilities(
|
||||
agent_client_protocol::schema::v1::ClientCapabilities::new().meta(meta),
|
||||
);
|
||||
let request = InitializeRequest::new(agent_client_protocol::schema::ProtocolVersion::V1)
|
||||
.client_capabilities(
|
||||
agent_client_protocol::schema::v1::ClientCapabilities::new().meta(meta),
|
||||
);
|
||||
let goose_client_capabilities =
|
||||
extract_client_capabilities_meta(&request).and_then(|meta| meta.goose);
|
||||
|
||||
@@ -2855,8 +2853,7 @@ print(\"hello, world\")
|
||||
|
||||
#[test]
|
||||
fn test_tool_call_label_enrichment_capability() {
|
||||
let request =
|
||||
InitializeRequest::new(agent_client_protocol::schema::ProtocolVersion::LATEST);
|
||||
let request = InitializeRequest::new(agent_client_protocol::schema::ProtocolVersion::V1);
|
||||
let goose_client_capabilities =
|
||||
extract_client_capabilities_meta(&request).and_then(|meta| meta.goose);
|
||||
assert!(!goose_client_capabilities
|
||||
@@ -2870,11 +2867,10 @@ print(\"hello, world\")
|
||||
);
|
||||
let mut meta = serde_json::Map::new();
|
||||
meta.insert("goose".to_string(), serde_json::Value::Object(goose_meta));
|
||||
let request =
|
||||
InitializeRequest::new(agent_client_protocol::schema::ProtocolVersion::LATEST)
|
||||
.client_capabilities(
|
||||
agent_client_protocol::schema::v1::ClientCapabilities::new().meta(meta),
|
||||
);
|
||||
let request = InitializeRequest::new(agent_client_protocol::schema::ProtocolVersion::V1)
|
||||
.client_capabilities(
|
||||
agent_client_protocol::schema::v1::ClientCapabilities::new().meta(meta),
|
||||
);
|
||||
let goose_client_capabilities =
|
||||
extract_client_capabilities_meta(&request).and_then(|meta| meta.goose);
|
||||
assert!(goose_client_capabilities
|
||||
|
||||
@@ -346,7 +346,7 @@ impl Connection for AcpServerConnection {
|
||||
async move |cx: ConnectionTo<Agent>| {
|
||||
let resp = cx
|
||||
.send_request(
|
||||
InitializeRequest::new(ProtocolVersion::LATEST)
|
||||
InitializeRequest::new(ProtocolVersion::V1)
|
||||
.client_capabilities(
|
||||
ClientCapabilities::new()
|
||||
.fs(fs_cap)
|
||||
@@ -356,6 +356,11 @@ impl Connection for AcpServerConnection {
|
||||
.block_task()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
resp.protocol_version,
|
||||
ProtocolVersion::V1,
|
||||
"initialize response must negotiate ACP V1"
|
||||
);
|
||||
assert_eq!(
|
||||
resp.agent_info.as_ref().map(|info| info.name.as_str()),
|
||||
Some("goose"),
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@aaif/goose-sdk": "workspace:*",
|
||||
"@agentclientprotocol/sdk": "^1.3.0",
|
||||
"@agentclientprotocol/sdk": "1.3.0",
|
||||
"@mcp-ui/client": "6.1.0",
|
||||
"@modelcontextprotocol/ext-apps": "^1.1.1",
|
||||
"@radix-ui/react-accordion": "^1.2.12",
|
||||
|
||||
@@ -76,6 +76,10 @@ describe('ACP connection ownership', () => {
|
||||
expect(first).toBe(second);
|
||||
expect(mockClientFactory.instances).toHaveLength(1);
|
||||
expect(mockClientFactory.initialize).toHaveBeenCalledTimes(1);
|
||||
expect(mockClientFactory.initialize).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
expect.objectContaining({ protocolVersion: 1 })
|
||||
);
|
||||
expect(transport.createWebSocketStream).toHaveBeenCalledWith('ws://localhost/acp', {
|
||||
protocols: [],
|
||||
});
|
||||
|
||||
@@ -26,6 +26,7 @@ type AcpRecoveryListener = (recovering: boolean) => void;
|
||||
const ACP_INITIALIZE_TIMEOUT_MS = 10_000;
|
||||
const ACP_RECONNECT_BASE_DELAY_MS = 500;
|
||||
const ACP_RECONNECT_MAX_DELAY_MS = 30_000;
|
||||
const ACP_V1_PROTOCOL_VERSION: 1 = PROTOCOL_VERSION;
|
||||
|
||||
let currentConnection: AcpConnection | null = null;
|
||||
let pendingConnection: Promise<AcpConnection> | null = null;
|
||||
@@ -139,7 +140,7 @@ async function openConnection(generation: number): Promise<AcpConnection> {
|
||||
try {
|
||||
const initializeResponse = await withTimeout(
|
||||
client.connection.agent.request(methods.agent.initialize, {
|
||||
protocolVersion: PROTOCOL_VERSION,
|
||||
protocolVersion: ACP_V1_PROTOCOL_VERSION,
|
||||
_meta: {
|
||||
'goose/useLoginShellPath': true,
|
||||
},
|
||||
|
||||
Generated
+2
-2
@@ -22,7 +22,7 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../sdk
|
||||
'@agentclientprotocol/sdk':
|
||||
specifier: ^1.3.0
|
||||
specifier: 1.3.0
|
||||
version: 1.3.0(zod@3.25.76)
|
||||
'@mcp-ui/client':
|
||||
specifier: 6.1.0
|
||||
@@ -358,7 +358,7 @@ importers:
|
||||
version: 3.25.76
|
||||
devDependencies:
|
||||
'@agentclientprotocol/sdk':
|
||||
specifier: ^1.3.0
|
||||
specifier: 1.3.0
|
||||
version: 1.3.0(zod@3.25.76)
|
||||
'@hey-api/openapi-ts':
|
||||
specifier: ^0.92.3
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@
|
||||
"@aaif/goose-binary-win32-x64": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@agentclientprotocol/sdk": "^1.3.0",
|
||||
"@agentclientprotocol/sdk": "1.3.0",
|
||||
"@hey-api/openapi-ts": "^0.92.3",
|
||||
"@types/node": "^26.1.2",
|
||||
"prettier": "^3.8.1",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -64,7 +64,7 @@ export type GooseExtension = {
|
||||
*
|
||||
* See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)
|
||||
*/
|
||||
export type McpServer = McpServerHttp | McpServerSse | McpServerAcp | McpServerStdio;
|
||||
export type McpServer = McpServerHttp | McpServerSse | McpServerStdio;
|
||||
|
||||
/**
|
||||
* An HTTP header to set when making requests to the MCP server.
|
||||
@@ -148,53 +148,6 @@ export type McpServerSse = {
|
||||
type: 'sse';
|
||||
};
|
||||
|
||||
/**
|
||||
* **UNSTABLE**
|
||||
*
|
||||
* This capability is not part of the spec yet, and may be removed or changed at any point.
|
||||
*
|
||||
* Unique identifier for an MCP server using the ACP transport.
|
||||
*
|
||||
* The value is opaque and generated by the ACP component providing the MCP server. It is
|
||||
* used by `mcp/connect` to route connection requests back to the component that declared the
|
||||
* server.
|
||||
*/
|
||||
export type McpServerAcpId = string;
|
||||
|
||||
/**
|
||||
* **UNSTABLE**
|
||||
*
|
||||
* This capability is not part of the spec yet, and may be removed or changed at any point.
|
||||
*
|
||||
* ACP transport configuration for MCP.
|
||||
*
|
||||
* The MCP server is provided by an ACP component and communicates over the ACP channel
|
||||
* using `mcp/connect`, `mcp/message`, and `mcp/disconnect`.
|
||||
*/
|
||||
export type McpServerAcp = {
|
||||
/**
|
||||
* Human-readable name identifying this MCP server.
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Unique identifier for this MCP server, generated by the component providing it.
|
||||
*
|
||||
* Providers MUST NOT reuse an ID for multiple ACP-transport MCP servers that are visible
|
||||
* on the same ACP connection.
|
||||
*/
|
||||
serverId: McpServerAcpId;
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
_meta?: {
|
||||
[key: string]: unknown;
|
||||
} | null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stdio transport configuration for MCP.
|
||||
*/
|
||||
|
||||
@@ -42,38 +42,6 @@ export const zMcpServerSse = z.object({
|
||||
type: z.literal('sse')
|
||||
});
|
||||
|
||||
/**
|
||||
* **UNSTABLE**
|
||||
*
|
||||
* This capability is not part of the spec yet, and may be removed or changed at any point.
|
||||
*
|
||||
* Unique identifier for an MCP server using the ACP transport.
|
||||
*
|
||||
* The value is opaque and generated by the ACP component providing the MCP server. It is
|
||||
* used by `mcp/connect` to route connection requests back to the component that declared the
|
||||
* server.
|
||||
*/
|
||||
export const zMcpServerAcpId = z.string();
|
||||
|
||||
/**
|
||||
* **UNSTABLE**
|
||||
*
|
||||
* This capability is not part of the spec yet, and may be removed or changed at any point.
|
||||
*
|
||||
* ACP transport configuration for MCP.
|
||||
*
|
||||
* The MCP server is provided by an ACP component and communicates over the ACP channel
|
||||
* using `mcp/connect`, `mcp/message`, and `mcp/disconnect`.
|
||||
*/
|
||||
export const zMcpServerAcp = z.object({
|
||||
name: z.string(),
|
||||
serverId: zMcpServerAcpId,
|
||||
_meta: z.union([
|
||||
z.record(z.unknown()),
|
||||
z.null()
|
||||
]).optional()
|
||||
});
|
||||
|
||||
/**
|
||||
* An environment variable to set when launching an MCP server.
|
||||
*/
|
||||
@@ -111,7 +79,6 @@ export const zMcpServerStdio = z.object({
|
||||
export const zMcpServer = z.union([
|
||||
zMcpServerHttp,
|
||||
zMcpServerSse,
|
||||
zMcpServerAcp,
|
||||
zMcpServerStdio
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user