From 048e89f7e2a90e8565574fa9318ebbc0b8940bc1 Mon Sep 17 00:00:00 2001 From: Ben Brandt Date: Fri, 17 Apr 2026 20:01:25 +0200 Subject: [PATCH] feat: Migrate to new SDK design --- Cargo.lock | 497 +-------- Cargo.toml | 17 +- .../Cargo.toml | 4 +- src/agent-client-protocol-conductor/README.md | 2 +- .../src/conductor.rs | 112 +- .../src/conductor/mcp_bridge.rs | 17 +- .../src/conductor/mcp_bridge/actor.rs | 12 +- .../src/conductor/mcp_bridge/http.rs | 93 +- .../src/conductor/mcp_bridge/stdio.rs | 10 +- .../src/lib.rs | 19 +- .../src/mcp_bridge.rs | 6 +- .../src/snoop.rs | 24 +- .../src/trace.rs | 12 +- .../tests/arrow_proxy_eliza.rs | 10 +- .../tests/empty_conductor_eliza.rs | 14 +- .../tests/initialization_sequence.rs | 74 +- .../tests/mcp-integration.rs | 48 +- .../tests/mcp_integration/proxy.rs | 10 +- .../tests/mcp_server_handler_chain.rs | 48 +- .../tests/nested_arrow_proxy.rs | 10 +- .../tests/nested_conductor.rs | 27 +- .../tests/scoped_mcp_server.rs | 22 +- .../tests/standalone_mcp_server.rs | 49 +- .../tests/test_mcp_tool_output_types.rs | 16 +- .../tests/test_session_id_in_mcp_tools.rs | 16 +- .../tests/test_tool_enable_disable.rs | 40 +- .../tests/test_tool_fn.rs | 10 +- .../tests/test_util.rs | 8 +- .../tests/trace_client_mcp_server.rs | 16 +- .../tests/trace_generation.rs | 8 +- .../tests/trace_mcp_tool_call.rs | 28 +- .../tests/trace_snapshot.rs | 6 +- src/agent-client-protocol-cookbook/Cargo.toml | 4 +- src/agent-client-protocol-cookbook/src/lib.rs | 218 ++-- src/agent-client-protocol-core/CHANGELOG.md | 2 - src/agent-client-protocol-core/Cargo.toml | 68 -- src/agent-client-protocol-core/README.md | 50 - src/agent-client-protocol-core/src/lib.rs | 210 ---- src/agent-client-protocol-derive/Cargo.toml | 2 +- src/agent-client-protocol-derive/src/lib.rs | 8 +- src/agent-client-protocol-rmcp/Cargo.toml | 4 +- src/agent-client-protocol-rmcp/README.md | 10 +- .../examples/with_mcp_server.rs | 4 +- src/agent-client-protocol-rmcp/src/lib.rs | 14 +- src/agent-client-protocol-test/Cargo.toml | 4 +- .../examples/arrow_proxy.rs | 2 +- .../src/arrow_proxy.rs | 8 +- .../src/bin/testy.rs | 2 +- src/agent-client-protocol-test/src/lib.rs | 4 +- src/agent-client-protocol-test/src/testy.rs | 14 +- src/agent-client-protocol-tokio/Cargo.toml | 4 +- src/agent-client-protocol-tokio/README.md | 6 +- .../src/acp_agent.rs | 98 +- src/agent-client-protocol-tokio/src/lib.rs | 6 +- .../tests/debug_logging.rs | 20 +- .../Cargo.toml | 2 +- src/agent-client-protocol/Cargo.toml | 67 +- src/agent-client-protocol/README.md | 55 +- src/agent-client-protocol/examples/agent.rs | 198 ---- src/agent-client-protocol/examples/client.rs | 173 --- .../examples/simple_agent.rs | 17 +- .../examples/yolo_one_shot_client.rs | 14 +- .../src/acp.rs | 0 src/agent-client-protocol/src/agent.rs | 372 ------- .../src/capabilities.rs | 4 +- src/agent-client-protocol/src/client.rs | 260 ----- .../src/component.rs | 8 +- .../src/concepts/acp_basics.rs | 0 .../src/concepts/callbacks.rs | 34 +- .../src/concepts/connections.rs | 18 +- .../src/concepts/error_handling.rs | 30 +- .../src/concepts/mod.rs | 4 +- .../src/concepts/ordering.rs | 14 +- .../src/concepts/peers.rs | 16 +- .../src/concepts/proxies.rs | 26 +- .../src/concepts/sessions.rs | 26 +- .../src/cookbook.rs | 2 +- .../src/handler.rs | 0 .../src/jsonrpc.rs | 208 ++-- .../src/jsonrpc/connection.rs | 0 .../src/jsonrpc/dynamic_handler.rs | 0 .../src/jsonrpc/handlers.rs | 0 .../src/jsonrpc/incoming_actor.rs | 0 .../src/jsonrpc/outgoing_actor.rs | 0 .../src/jsonrpc/run.rs | 0 .../src/jsonrpc/task_actor.rs | 0 .../src/jsonrpc/transport_actor.rs | 0 src/agent-client-protocol/src/lib.rs | 881 ++++------------ .../src/mcp_server/active_session.rs | 0 .../src/mcp_server/builder.rs | 2 +- .../src/mcp_server/connect.rs | 4 +- .../src/mcp_server/context.rs | 0 .../src/mcp_server/mod.rs | 6 +- .../src/mcp_server/responder.rs | 0 .../src/mcp_server/server.rs | 0 .../src/mcp_server/tool.rs | 6 +- .../src/role.rs | 0 .../src/role/acp.rs | 0 .../src/role/mcp.rs | 0 src/agent-client-protocol/src/rpc.rs | 380 ------- src/agent-client-protocol/src/rpc_tests.rs | 984 ------------------ .../src/schema/agent_to_client/mod.rs | 0 .../schema/agent_to_client/notifications.rs | 0 .../src/schema/agent_to_client/requests.rs | 0 .../src/schema/client_to_agent/mod.rs | 0 .../schema/client_to_agent/notifications.rs | 0 .../src/schema/client_to_agent/requests.rs | 0 .../src/schema/enum_impls.rs | 0 .../src/schema/mod.rs | 0 .../src/schema/proxy_protocol.rs | 0 .../src/session.rs | 16 +- .../src/stream_broadcast.rs | 300 ------ .../src/typed.rs | 0 .../src/util.rs | 0 .../src/util/typed.rs | 34 +- .../tests/derive_macros.rs | 6 +- .../tests/jsonrpc_advanced.rs | 74 +- .../tests/jsonrpc_connection_builder.rs | 166 ++- .../tests/jsonrpc_edge_cases.rs | 65 +- .../tests/jsonrpc_error_handling.rs | 111 +- .../tests/jsonrpc_hello.rs | 83 +- .../tests/match_dispatch.rs | 53 +- src/yopo/Cargo.toml | 4 +- src/yopo/src/lib.rs | 44 +- 124 files changed, 1412 insertions(+), 5402 deletions(-) delete mode 100644 src/agent-client-protocol-core/CHANGELOG.md delete mode 100644 src/agent-client-protocol-core/Cargo.toml delete mode 100644 src/agent-client-protocol-core/README.md delete mode 100644 src/agent-client-protocol-core/src/lib.rs delete mode 100644 src/agent-client-protocol/examples/agent.rs delete mode 100644 src/agent-client-protocol/examples/client.rs rename src/{agent-client-protocol-core => agent-client-protocol}/examples/simple_agent.rs (61%) rename src/{agent-client-protocol-core => agent-client-protocol}/examples/yolo_one_shot_client.rs (93%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/acp.rs (100%) delete mode 100644 src/agent-client-protocol/src/agent.rs rename src/{agent-client-protocol-core => agent-client-protocol}/src/capabilities.rs (97%) delete mode 100644 src/agent-client-protocol/src/client.rs rename src/{agent-client-protocol-core => agent-client-protocol}/src/component.rs (97%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/concepts/acp_basics.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/concepts/callbacks.rs (79%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/concepts/connections.rs (87%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/concepts/error_handling.rs (80%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/concepts/mod.rs (92%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/concepts/ordering.rs (93%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/concepts/peers.rs (86%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/concepts/proxies.rs (84%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/concepts/sessions.rs (82%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/cookbook.rs (94%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/handler.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/jsonrpc.rs (94%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/jsonrpc/connection.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/jsonrpc/dynamic_handler.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/jsonrpc/handlers.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/jsonrpc/incoming_actor.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/jsonrpc/outgoing_actor.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/jsonrpc/run.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/jsonrpc/task_actor.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/jsonrpc/transport_actor.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/mcp_server/active_session.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/mcp_server/builder.rs (99%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/mcp_server/connect.rs (93%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/mcp_server/context.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/mcp_server/mod.rs (86%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/mcp_server/responder.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/mcp_server/server.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/mcp_server/tool.rs (90%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/role.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/role/acp.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/role/mcp.rs (100%) delete mode 100644 src/agent-client-protocol/src/rpc.rs delete mode 100644 src/agent-client-protocol/src/rpc_tests.rs rename src/{agent-client-protocol-core => agent-client-protocol}/src/schema/agent_to_client/mod.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/schema/agent_to_client/notifications.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/schema/agent_to_client/requests.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/schema/client_to_agent/mod.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/schema/client_to_agent/notifications.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/schema/client_to_agent/requests.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/schema/enum_impls.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/schema/mod.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/schema/proxy_protocol.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/session.rs (98%) delete mode 100644 src/agent-client-protocol/src/stream_broadcast.rs rename src/{agent-client-protocol-core => agent-client-protocol}/src/typed.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/util.rs (100%) rename src/{agent-client-protocol-core => agent-client-protocol}/src/util/typed.rs (96%) rename src/{agent-client-protocol-core => agent-client-protocol}/tests/derive_macros.rs (95%) rename src/{agent-client-protocol-core => agent-client-protocol}/tests/jsonrpc_advanced.rs (82%) rename src/{agent-client-protocol-core => agent-client-protocol}/tests/jsonrpc_connection_builder.rs (79%) rename src/{agent-client-protocol-core => agent-client-protocol}/tests/jsonrpc_edge_cases.rs (83%) rename src/{agent-client-protocol-core => agent-client-protocol}/tests/jsonrpc_error_handling.rs (86%) rename src/{agent-client-protocol-core => agent-client-protocol}/tests/jsonrpc_hello.rs (80%) rename src/{agent-client-protocol-core => agent-client-protocol}/tests/match_dispatch.rs (82%) diff --git a/Cargo.lock b/Cargo.lock index 85dcffe..76d2a3b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,29 +6,34 @@ version = 4 name = "agent-client-protocol" version = "0.10.4" dependencies = [ + "agent-client-protocol-derive", "agent-client-protocol-schema", + "agent-client-protocol-test", "anyhow", - "async-broadcast", - "async-trait", - "derive_more", - "env_logger", + "boxfnonce", + "clap", + "expect-test", "futures", - "futures-util", - "log", - "piper", - "pretty_assertions", - "rustyline", + "futures-concurrency", + "jsonrpcmsg", + "rmcp", + "rustc-hash", + "schemars", "serde", "serde_json", + "shell-words", + "thiserror", "tokio", "tokio-util", + "tracing", + "uuid", ] [[package]] name = "agent-client-protocol-conductor" -version = "0.1.0" +version = "0.11.0" dependencies = [ - "agent-client-protocol-core", + "agent-client-protocol", "agent-client-protocol-schema", "agent-client-protocol-test", "agent-client-protocol-tokio", @@ -63,10 +68,10 @@ dependencies = [ [[package]] name = "agent-client-protocol-cookbook" -version = "0.1.0" +version = "0.11.0" dependencies = [ + "agent-client-protocol", "agent-client-protocol-conductor", - "agent-client-protocol-core", "agent-client-protocol-rmcp", "agent-client-protocol-tokio", "rmcp", @@ -77,36 +82,9 @@ dependencies = [ "tracing", ] -[[package]] -name = "agent-client-protocol-core" -version = "0.1.0" -dependencies = [ - "agent-client-protocol-derive", - "agent-client-protocol-schema", - "agent-client-protocol-test", - "anyhow", - "boxfnonce", - "clap", - "expect-test", - "futures", - "futures-concurrency", - "jsonrpcmsg", - "rmcp", - "rustc-hash", - "schemars", - "serde", - "serde_json", - "shell-words", - "thiserror", - "tokio", - "tokio-util", - "tracing", - "uuid", -] - [[package]] name = "agent-client-protocol-derive" -version = "0.1.0" +version = "0.11.0" dependencies = [ "proc-macro2", "quote", @@ -115,9 +93,9 @@ dependencies = [ [[package]] name = "agent-client-protocol-rmcp" -version = "0.1.0" +version = "0.11.0" dependencies = [ - "agent-client-protocol-core", + "agent-client-protocol", "futures", "futures-concurrency", "rmcp", @@ -145,9 +123,9 @@ dependencies = [ [[package]] name = "agent-client-protocol-test" -version = "0.1.0" +version = "0.11.0" dependencies = [ - "agent-client-protocol-core", + "agent-client-protocol", "agent-client-protocol-tokio", "agent-client-protocol-yopo", "anyhow", @@ -165,9 +143,9 @@ dependencies = [ [[package]] name = "agent-client-protocol-tokio" -version = "0.1.0" +version = "0.11.0" dependencies = [ - "agent-client-protocol-core", + "agent-client-protocol", "agent-client-protocol-test", "expect-test", "futures", @@ -180,7 +158,7 @@ dependencies = [ [[package]] name = "agent-client-protocol-trace-viewer" -version = "0.1.0" +version = "0.11.0" dependencies = [ "anyhow", "axum", @@ -195,9 +173,9 @@ dependencies = [ [[package]] name = "agent-client-protocol-yopo" -version = "0.1.0" +version = "0.11.0" dependencies = [ - "agent-client-protocol-core", + "agent-client-protocol", "agent-client-protocol-tokio", "clap", "tokio", @@ -259,7 +237,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -270,7 +248,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -279,18 +257,6 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" -[[package]] -name = "async-broadcast" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" -dependencies = [ - "event-listener", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - [[package]] name = "async-stream" version = "0.3.6" @@ -494,30 +460,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" -[[package]] -name = "clipboard-win" -version = "5.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" -dependencies = [ - "error-code", -] - [[package]] name = "colorchoice" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "convert_case" version = "0.10.0" @@ -614,12 +562,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "diff" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" - [[package]] name = "displaydoc" version = "0.2.5" @@ -643,35 +585,6 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" -[[package]] -name = "endian-type" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" - -[[package]] -name = "env_filter" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "jiff", - "log", -] - [[package]] name = "equivalent" version = "1.0.2" @@ -685,34 +598,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "error-code" -version = "3.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" - -[[package]] -name = "event-listener" -version = "5.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" -dependencies = [ - "event-listener", - "pin-project-lite", + "windows-sys", ] [[package]] @@ -731,17 +617,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" -[[package]] -name = "fd-lock" -version = "4.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" -dependencies = [ - "cfg-if", - "rustix", - "windows-sys 0.59.0", -] - [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -917,15 +792,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "home" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" -dependencies = [ - "windows-sys 0.61.2", -] - [[package]] name = "http" version = "1.4.0" @@ -1218,30 +1084,6 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" -[[package]] -name = "jiff" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" -dependencies = [ - "jiff-static", - "log", - "portable-atomic", - "portable-atomic-util", - "serde_core", -] - -[[package]] -name = "jiff-static" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "js-sys" version = "0.3.94" @@ -1282,12 +1124,6 @@ version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" -[[package]] -name = "linux-raw-sys" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" - [[package]] name = "litemap" version = "0.8.1" @@ -1354,28 +1190,7 @@ checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "wasi", - "windows-sys 0.61.2", -] - -[[package]] -name = "nibble_vec" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" -dependencies = [ - "smallvec", -] - -[[package]] -name = "nix" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags", - "cfg-if", - "cfg_aliases", - "libc", + "windows-sys", ] [[package]] @@ -1396,7 +1211,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -1510,32 +1325,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" -[[package]] -name = "piper" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - -[[package]] -name = "portable-atomic" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" - -[[package]] -name = "portable-atomic-util" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" -dependencies = [ - "portable-atomic", -] - [[package]] name = "potential_utf" version = "0.1.4" @@ -1551,16 +1340,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" -[[package]] -name = "pretty_assertions" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" -dependencies = [ - "diff", - "yansi", -] - [[package]] name = "prettyplease" version = "0.2.37" @@ -1588,7 +1367,7 @@ checksum = "2e842efad9119158434d193c6682e2ebee4b44d6ad801d7b349623b3f57cdf55" dependencies = [ "futures", "indexmap", - "nix 0.31.2", + "nix", "tokio", "tracing", "windows", @@ -1609,16 +1388,6 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" -[[package]] -name = "radix_trie" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" -dependencies = [ - "endian-type", - "nibble_vec", -] - [[package]] name = "redox_syscall" version = "0.5.18" @@ -1766,47 +1535,12 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.61.2", -] - [[package]] name = "rustversion" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" -[[package]] -name = "rustyline" -version = "17.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e902948a25149d50edc1a8e0141aad50f54e22ba83ff988cf8f7c9ef07f50564" -dependencies = [ - "bitflags", - "cfg-if", - "clipboard-win", - "fd-lock", - "home", - "libc", - "log", - "memchr", - "nix 0.30.1", - "radix_trie", - "unicode-segmentation", - "unicode-width", - "utf8parse", - "windows-sys 0.60.2", -] - [[package]] name = "ryu" version = "1.0.23" @@ -1978,7 +1712,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -2151,7 +1885,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -2357,12 +2091,6 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" -[[package]] -name = "unicode-width" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" - [[package]] name = "unicode-xid" version = "0.2.6" @@ -2665,24 +2393,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -2692,39 +2402,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - [[package]] name = "windows-threading" version = "0.2.1" @@ -2734,102 +2411,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "wit-bindgen" version = "0.51.0" @@ -2924,12 +2505,6 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" -[[package]] -name = "yansi" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" - [[package]] name = "yoke" version = "0.8.1" diff --git a/Cargo.toml b/Cargo.toml index c7958e0..15abe75 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,6 @@ members = [ "src/agent-client-protocol", "src/agent-client-protocol-conductor", "src/agent-client-protocol-cookbook", - "src/agent-client-protocol-core", "src/agent-client-protocol-derive", "src/agent-client-protocol-rmcp", "src/agent-client-protocol-test", @@ -22,14 +21,14 @@ homepage = "https://github.com/agentclientprotocol/rust-sdk" [workspace.dependencies] # Internal crates -agent-client-protocol-conductor = { path = "src/agent-client-protocol-conductor", version = "0.1.0" } -agent-client-protocol-core = { path = "src/agent-client-protocol-core", version = "0.1.0" } -agent-client-protocol-derive = { path = "src/agent-client-protocol-derive", version = "0.1.0" } -agent-client-protocol-rmcp = { path = "src/agent-client-protocol-rmcp", version = "0.1.0" } -agent-client-protocol-test = { path = "src/agent-client-protocol-test", version = "0.1.0" } -agent-client-protocol-tokio = { path = "src/agent-client-protocol-tokio", version = "0.1.0" } -agent-client-protocol-trace-viewer = { path = "src/agent-client-protocol-trace-viewer", version = "0.1.0" } -yopo = { package = "agent-client-protocol-yopo", path = "src/yopo", version = "0.1.0" } +agent-client-protocol = { path = "src/agent-client-protocol", version = "0.10.4" } +agent-client-protocol-conductor = { path = "src/agent-client-protocol-conductor", version = "0.11.0" } +agent-client-protocol-derive = { path = "src/agent-client-protocol-derive", version = "0.11.0" } +agent-client-protocol-rmcp = { path = "src/agent-client-protocol-rmcp", version = "0.11.0" } +agent-client-protocol-test = { path = "src/agent-client-protocol-test", version = "0.11.0" } +agent-client-protocol-tokio = { path = "src/agent-client-protocol-tokio", version = "0.11.0" } +agent-client-protocol-trace-viewer = { path = "src/agent-client-protocol-trace-viewer", version = "0.11.0" } +yopo = { package = "agent-client-protocol-yopo", path = "src/yopo", version = "0.11.0" } # Core async runtime tokio = { version = "1.48", features = ["full"] } diff --git a/src/agent-client-protocol-conductor/Cargo.toml b/src/agent-client-protocol-conductor/Cargo.toml index d3da12d..5f35da6 100644 --- a/src/agent-client-protocol-conductor/Cargo.toml +++ b/src/agent-client-protocol-conductor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "agent-client-protocol-conductor" -version = "0.1.0" +version = "0.11.0" edition.workspace = true authors.workspace = true license.workspace = true @@ -18,7 +18,7 @@ path = "src/main.rs" test-support = [] [dependencies] -agent-client-protocol-core.workspace = true +agent-client-protocol.workspace = true agent-client-protocol-schema.workspace = true agent-client-protocol-tokio.workspace = true agent-client-protocol-trace-viewer.workspace = true diff --git a/src/agent-client-protocol-conductor/README.md b/src/agent-client-protocol-conductor/README.md index 8b3e62c..f94965b 100644 --- a/src/agent-client-protocol-conductor/README.md +++ b/src/agent-client-protocol-conductor/README.md @@ -64,7 +64,7 @@ Binary will be at `target/release/agent-client-protocol-conductor`. ## Related Crates -- **[agent-client-protocol-core](../agent-client-protocol-core/)** — Core ACP protocol types and traits +- **[agent-client-protocol](../agent-client-protocol/)** — Core ACP protocol types and traits - **[agent-client-protocol-tokio](../agent-client-protocol-tokio/)** — Tokio utilities for process spawning - **[agent-client-protocol-trace-viewer](../agent-client-protocol-trace-viewer/)** — Interactive trace visualization diff --git a/src/agent-client-protocol-conductor/src/conductor.rs b/src/agent-client-protocol-conductor/src/conductor.rs index 9ca1641..4bc2557 100644 --- a/src/agent-client-protocol-conductor/src/conductor.rs +++ b/src/agent-client-protocol-conductor/src/conductor.rs @@ -112,19 +112,19 @@ use std::{collections::HashMap, sync::Arc}; -use agent_client_protocol_core::{ +use agent_client_protocol::{ Agent, BoxFuture, Client, Conductor, ConnectTo, Dispatch, DynConnectTo, Error, JsonRpcMessage, Proxy, Role, RunWithConnectionTo, role::HasPeer, util::MatchDispatch, }; -use agent_client_protocol_core::{ +use agent_client_protocol::{ Builder, ConnectionTo, JsonRpcNotification, JsonRpcRequest, SentRequest, UntypedMessage, }; -use agent_client_protocol_core::{ +use agent_client_protocol::{ HandleDispatchFrom, schema::{InitializeProxyRequest, InitializeRequest, NewSessionRequest}, util::MatchDispatchFrom, }; -use agent_client_protocol_core::{ +use agent_client_protocol::{ Handled, schema::{ McpConnectRequest, McpConnectResponse, McpDisconnectNotification, McpOverAcpMessage, @@ -226,12 +226,12 @@ impl ConductorImpl { pub async fn run( self, transport: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { let (conductor_tx, conductor_rx) = mpsc::channel(128 /* chosen arbitrarily */); // Set up tracing if enabled - spawn writer task and get handle let trace_handle; - let trace_future: BoxFuture<'static, Result<(), agent_client_protocol_core::Error>>; + let trace_future: BoxFuture<'static, Result<(), agent_client_protocol::Error>>; if let Some((h, f)) = self.trace_writer.map(super::trace::TraceWriter::spawn) { trace_handle = Some(h); trace_future = Box::pin(f); @@ -248,7 +248,7 @@ impl ConductorImpl { bridge_connections: HashMap::default(), mcp_bridge_mode: self.mcp_bridge_mode, proxies: Vec::default(), - successor: Arc::new(agent_client_protocol_core::util::internal_error( + successor: Arc::new(agent_client_protocol::util::internal_error( "successor not initialized", )), trace_handle, @@ -272,27 +272,27 @@ impl ConductorImpl { async fn incoming_message_from_client( conductor_tx: &mut mpsc::Sender, message: Dispatch, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { conductor_tx .send(ConductorMessage::LeftToRight { target_component_index: 0, message, }) .await - .map_err(agent_client_protocol_core::util::internal_error) + .map_err(agent_client_protocol::util::internal_error) } async fn incoming_message_from_agent( conductor_tx: &mut mpsc::Sender, message: Dispatch, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { conductor_tx .send(ConductorMessage::RightToLeft { source_component_index: SourceComponentIndex::Successor, message, }) .await - .map_err(agent_client_protocol_core::util::internal_error) + .map_err(agent_client_protocol::util::internal_error) } } @@ -300,7 +300,7 @@ impl ConnectTo for ConductorImpl, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { self.run(client).await } } @@ -316,9 +316,8 @@ impl HandleDispatchFrom async fn handle_dispatch_from( &mut self, message: Dispatch, - connection: agent_client_protocol_core::ConnectionTo, - ) -> Result, agent_client_protocol_core::Error> - { + connection: agent_client_protocol::ConnectionTo, + ) -> Result, agent_client_protocol::Error> { self.host .handle_dispatch(message, connection, &mut self.conductor_tx) .await @@ -397,7 +396,7 @@ where async fn run_with_connection_to( mut self, connection: ConnectionTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { // Components are now spawned lazily in forward_initialize_request // when the first Initialize request is received. @@ -446,7 +445,7 @@ where &mut self, client: ConnectionTo, message: ConductorMessage, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { tracing::debug!(?message, "handle_conductor_message"); match message { @@ -502,7 +501,7 @@ where connection, }) .await - .map_err(|_| agent_client_protocol_core::Error::internal_error()), + .map_err(|_| agent_client_protocol::Error::internal_error()), Err(_) => { // Error occurred, just drop the connection. Ok(()) @@ -582,7 +581,7 @@ where client: ConnectionTo, source_component_index: SourceComponentIndex, message: Dispatch, - ) -> Result<(), agent_client_protocol_core::Error> + ) -> Result<(), agent_client_protocol::Error> where Req::Response: Send, { @@ -635,7 +634,7 @@ where client: ConnectionTo, source_component_index: usize, notification: N, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { tracing::debug!( source_component_index, proxies_len = self.proxies.len(), @@ -665,7 +664,7 @@ where target_component_index: usize, message: Dispatch, client: ConnectionTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { tracing::trace!( target_component_index, ?message, @@ -739,7 +738,7 @@ where &mut self, client: ConnectionTo, proxy_components: Vec>, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { assert!(self.proxies.is_empty()); let num_proxies = proxy_components.len(); @@ -838,7 +837,7 @@ where message: dispatch.map(|r, cx| (r.message, cx), |n| n.message), }) .await - .map_err(agent_client_protocol_core::util::internal_error) + .map_err(agent_client_protocol::util::internal_error) }) .await .otherwise(async |dispatch| { @@ -865,11 +864,11 @@ where conductor_tx .send(message) .await - .map_err(agent_client_protocol_core::util::internal_error) + .map_err(agent_client_protocol::util::internal_error) }) .await }, - agent_client_protocol_core::on_receive_dispatch!(), + agent_client_protocol::on_receive_dispatch!(), ) } @@ -877,13 +876,13 @@ where &mut self, target_component_index: usize, message: Dispatch, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { tracing::debug!(?message, "forward_message_to_proxy"); MatchDispatch::new(message) .if_request(async |_request: InitializeProxyRequest, responder| { responder.respond_with_error( - agent_client_protocol_core::Error::invalid_request() + agent_client_protocol::Error::invalid_request() .data("initialize/proxy requests are only sent by the conductor"), ) }) @@ -924,7 +923,7 @@ where MatchDispatch::new(message) .if_request(async |_request: InitializeProxyRequest, responder| { responder.respond_with_error( - agent_client_protocol_core::Error::invalid_request() + agent_client_protocol::Error::invalid_request() .data("initialize/proxy requests are only sent by the conductor"), ) }) @@ -958,7 +957,7 @@ where self.bridge_connections .get_mut(&connection_id) .ok_or_else(|| { - agent_client_protocol_core::util::internal_error(format!( + agent_client_protocol::util::internal_error(format!( "unknown connection id: {connection_id}" )) })? @@ -976,7 +975,7 @@ where self.bridge_connections .get_mut(&connection_id) .ok_or_else(|| { - agent_client_protocol_core::util::internal_error(format!( + agent_client_protocol::util::internal_error(format!( "unknown connection id: {connection_id}" )) })? @@ -1056,10 +1055,7 @@ pub trait InstantiateProxies: Send { req: InitializeRequest, ) -> futures::future::BoxFuture< 'static, - Result< - (InitializeRequest, Vec>), - agent_client_protocol_core::Error, - >, + Result<(InitializeRequest, Vec>), agent_client_protocol::Error>, >; } @@ -1075,10 +1071,7 @@ where req: InitializeRequest, ) -> futures::future::BoxFuture< 'static, - Result< - (InitializeRequest, Vec>), - agent_client_protocol_core::Error, - >, + Result<(InitializeRequest, Vec>), agent_client_protocol::Error>, > { Box::pin(async move { let components: Vec> = @@ -1095,7 +1088,7 @@ where Fut: std::future::Future< Output = Result< (InitializeRequest, Vec>), - agent_client_protocol_core::Error, + agent_client_protocol::Error, >, > + Send + 'static, @@ -1105,10 +1098,7 @@ where req: InitializeRequest, ) -> futures::future::BoxFuture< 'static, - Result< - (InitializeRequest, Vec>), - agent_client_protocol_core::Error, - >, + Result<(InitializeRequest, Vec>), agent_client_protocol::Error>, > { Box::pin(async move { (*self)(req).await }) } @@ -1135,7 +1125,7 @@ pub trait InstantiateProxiesAndAgent: Send { Vec>, DynConnectTo, ), - agent_client_protocol_core::Error, + agent_client_protocol::Error, >, >; } @@ -1156,7 +1146,7 @@ impl + 'static> InstantiateProxiesAndAgent for AgentOnly Vec>, DynConnectTo, ), - agent_client_protocol_core::Error, + agent_client_protocol::Error, >, > { Box::pin(async move { Ok((req, Vec::new(), DynConnectTo::new(self.0))) }) @@ -1218,7 +1208,7 @@ impl InstantiateProxiesAndAgent for ProxiesAndAgent { Vec>, DynConnectTo, ), - agent_client_protocol_core::Error, + agent_client_protocol::Error, >, > { Box::pin(async move { Ok((req, self.proxies, self.agent)) }) @@ -1236,7 +1226,7 @@ where Vec>, DynConnectTo, ), - agent_client_protocol_core::Error, + agent_client_protocol::Error, >, > + Send + 'static, @@ -1252,7 +1242,7 @@ where Vec>, DynConnectTo, ), - agent_client_protocol_core::Error, + agent_client_protocol::Error, >, > { Box::pin(async move { (*self)(req).await }) @@ -1350,7 +1340,7 @@ pub trait ConductorHostRole: Role> { connection: ConnectionTo, instantiator: Self::Instantiator, responder: &mut ConductorResponder, - ) -> impl Future> + Send; + ) -> impl Future> + Send; /// Handle an incoming message from the client or conductor, depending on `Self` fn handle_dispatch( @@ -1358,7 +1348,7 @@ pub trait ConductorHostRole: Role> { message: Dispatch, connection: ConnectionTo, conductor_tx: &mut mpsc::Sender, - ) -> impl Future, agent_client_protocol_core::Error>> + Send; + ) -> impl Future, agent_client_protocol::Error>> + Send; } /// Conductor acting as an agent @@ -1371,7 +1361,7 @@ impl ConductorHostRole for Agent { client_connection: ConnectionTo, instantiator: Self::Instantiator, responder: &mut ConductorResponder, - ) -> Result { + ) -> Result { let invalid_request = || Error::invalid_request().data("expected `initialize` request"); // Not yet initialized - expect an initialize request. @@ -1417,10 +1407,10 @@ impl ConductorHostRole for Agent { message: dispatch, }) .await - .map_err(agent_client_protocol_core::util::internal_error) + .map_err(agent_client_protocol::util::internal_error) } }, - agent_client_protocol_core::on_receive_dispatch!(), + agent_client_protocol::on_receive_dispatch!(), ), agent_component, )?; @@ -1440,7 +1430,7 @@ impl ConductorHostRole for Agent { message: Dispatch, client_connection: ConnectionTo, conductor_tx: &mut mpsc::Sender, - ) -> Result, agent_client_protocol_core::Error> { + ) -> Result, agent_client_protocol::Error> { tracing::debug!( method = ?message.method(), "ConductorToClient::handle_dispatch" @@ -1469,7 +1459,7 @@ impl ConductorHostRole for Proxy { client_connection: ConnectionTo, instantiator: Self::Instantiator, responder: &mut ConductorResponder, - ) -> Result { + ) -> Result { let invalid_request = || Error::invalid_request().data("expected `initialize` request"); // Not yet initialized - expect an InitializeProxy request. @@ -1514,7 +1504,7 @@ impl ConductorHostRole for Proxy { message: Dispatch, client_connection: ConnectionTo, conductor_tx: &mut mpsc::Sender, - ) -> Result, agent_client_protocol_core::Error> { + ) -> Result, agent_client_protocol::Error> { tracing::debug!( method = ?message.method(), ?message, @@ -1557,16 +1547,16 @@ pub trait ConductorSuccessor: Send + Sync + 'static { message: Dispatch, connection_to_conductor: ConnectionTo, responder: &'a mut ConductorResponder, - ) -> BoxFuture<'a, Result<(), agent_client_protocol_core::Error>>; + ) -> BoxFuture<'a, Result<(), agent_client_protocol::Error>>; } -impl ConductorSuccessor for agent_client_protocol_core::Error { +impl ConductorSuccessor for agent_client_protocol::Error { fn send_message<'a>( &self, #[expect(unused_variables)] message: Dispatch, #[expect(unused_variables)] connection_to_conductor: ConnectionTo, #[expect(unused_variables)] responder: &'a mut ConductorResponder, - ) -> BoxFuture<'a, Result<(), agent_client_protocol_core::Error>> { + ) -> BoxFuture<'a, Result<(), agent_client_protocol::Error>> { let error = self.clone(); Box::pin(std::future::ready(Err(error))) } @@ -1590,7 +1580,7 @@ impl ConductorSuccessor for GrandSuccessor { message: Dispatch, connection: ConnectionTo, _responder: &'a mut ConductorResponder, - ) -> BoxFuture<'a, Result<(), agent_client_protocol_core::Error>> { + ) -> BoxFuture<'a, Result<(), agent_client_protocol::Error>> { Box::pin(async move { debug!("Proxy mode: forwarding successor message to conductor's successor"); connection.send_proxied_message_to(Agent, message) @@ -1607,7 +1597,7 @@ impl ConductorSuccessor for ConnectionTo { message: Dispatch, connection: ConnectionTo, responder: &'a mut ConductorResponder, - ) -> BoxFuture<'a, Result<(), agent_client_protocol_core::Error>> { + ) -> BoxFuture<'a, Result<(), agent_client_protocol::Error>> { let connection_to_agent = self.clone(); Box::pin(async move { debug!("Proxy mode: forwarding successor message to conductor's successor"); diff --git a/src/agent-client-protocol-conductor/src/conductor/mcp_bridge.rs b/src/agent-client-protocol-conductor/src/conductor/mcp_bridge.rs index 4e9dae5..ed4b07a 100644 --- a/src/agent-client-protocol-conductor/src/conductor/mcp_bridge.rs +++ b/src/agent-client-protocol-conductor/src/conductor/mcp_bridge.rs @@ -5,8 +5,8 @@ pub mod stdio; use std::collections::HashMap; use std::path::PathBuf; -use agent_client_protocol_core::schema::{McpServer, McpServerHttp, McpServerStdio}; -use agent_client_protocol_core::{ConnectionTo, Dispatch, Role}; +use agent_client_protocol::schema::{McpServer, McpServerHttp, McpServerStdio}; +use agent_client_protocol::{ConnectionTo, Dispatch, Role}; use futures::{SinkExt, channel::mpsc}; use tokio::net::TcpListener; use tracing::info; @@ -40,14 +40,11 @@ impl McpBridgeConnection { Self { to_mcp_client_tx } } - pub async fn send( - &mut self, - message: Dispatch, - ) -> Result<(), agent_client_protocol_core::Error> { + pub async fn send(&mut self, message: Dispatch) -> Result<(), agent_client_protocol::Error> { self.to_mcp_client_tx .send(message) .await - .map_err(|_| agent_client_protocol_core::Error::internal_error()) + .map_err(|_| agent_client_protocol::Error::internal_error()) } } @@ -66,8 +63,8 @@ impl McpBridgeListeners { mcp_server: &mut McpServer, conductor_tx: &mpsc::Sender, mcp_bridge_mode: &crate::McpBridgeMode, - ) -> Result<(), agent_client_protocol_core::Error> { - use agent_client_protocol_core::schema::McpServer; + ) -> Result<(), agent_client_protocol::Error> { + use agent_client_protocol::schema::McpServer; let McpServer::Http(http) = mcp_server else { return Ok(()); @@ -78,7 +75,7 @@ impl McpBridgeListeners { } if !http.headers.is_empty() { - return Err(agent_client_protocol_core::Error::internal_error()); + return Err(agent_client_protocol::Error::internal_error()); } let name = &http.name; diff --git a/src/agent-client-protocol-conductor/src/conductor/mcp_bridge/actor.rs b/src/agent-client-protocol-conductor/src/conductor/mcp_bridge/actor.rs index 2c15ad9..557e08c 100644 --- a/src/agent-client-protocol-conductor/src/conductor/mcp_bridge/actor.rs +++ b/src/agent-client-protocol-conductor/src/conductor/mcp_bridge/actor.rs @@ -1,4 +1,4 @@ -use agent_client_protocol_core::{ +use agent_client_protocol::{ ConnectTo, Dispatch, DynConnectTo, role::mcp, schema::McpDisconnectNotification, }; use futures::{SinkExt as _, StreamExt as _, channel::mpsc}; @@ -34,7 +34,7 @@ impl McpBridgeConnectionActor { } } - pub async fn run(self, connection_id: String) -> Result<(), agent_client_protocol_core::Error> { + pub async fn run(self, connection_id: String) -> Result<(), agent_client_protocol::Error> { info!(connection_id, "MCP bridge connected"); let McpBridgeConnectionActor { @@ -51,17 +51,17 @@ impl McpBridgeConnectionActor { { let mut conductor_tx = conductor_tx.clone(); let connection_id = connection_id.clone(); - async move |message: agent_client_protocol_core::Dispatch, _cx| { + async move |message: agent_client_protocol::Dispatch, _cx| { conductor_tx .send(ConductorMessage::McpClientToMcpServer { connection_id: connection_id.clone(), message, }) .await - .map_err(|_| agent_client_protocol_core::Error::internal_error()) + .map_err(|_| agent_client_protocol::Error::internal_error()) } }, - agent_client_protocol_core::on_receive_dispatch!(), + agent_client_protocol::on_receive_dispatch!(), ) // When we receive messages from the conductor, forward them to the MCP client .connect_with(transport, async move |mcp_connection_to_client| { @@ -81,7 +81,7 @@ impl McpBridgeConnectionActor { }, }) .await - .map_err(|_| agent_client_protocol_core::Error::internal_error())?; + .map_err(|_| agent_client_protocol::Error::internal_error())?; result } diff --git a/src/agent-client-protocol-conductor/src/conductor/mcp_bridge/http.rs b/src/agent-client-protocol-conductor/src/conductor/mcp_bridge/http.rs index 2b90998..9ea579d 100644 --- a/src/agent-client-protocol-conductor/src/conductor/mcp_bridge/http.rs +++ b/src/agent-client-protocol-conductor/src/conductor/mcp_bridge/http.rs @@ -1,4 +1,4 @@ -use agent_client_protocol_core::{BoxFuture, Channel, ConnectTo, jsonrpcmsg::Message, role::mcp}; +use agent_client_protocol::{BoxFuture, Channel, ConnectTo, jsonrpcmsg::Message, role::mcp}; use axum::{ Router, extract::State, @@ -27,7 +27,7 @@ pub async fn run_http_listener( tcp_listener: TcpListener, acp_url: String, mut conductor_tx: mpsc::Sender, -) -> Result<(), agent_client_protocol_core::Error> { +) -> Result<(), agent_client_protocol::Error> { let (to_mcp_client_tx, to_mcp_client_rx) = mpsc::channel(128); // When we send this message to the conductor, @@ -45,7 +45,7 @@ pub async fn run_http_listener( connection: McpBridgeConnection::new(to_mcp_client_tx), }) .await - .map_err(|_| agent_client_protocol_core::Error::internal_error())?; + .map_err(|_| agent_client_protocol::Error::internal_error())?; Ok(()) } @@ -66,7 +66,7 @@ impl ConnectTo for HttpMcpBridge { async fn connect_to( self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { let (channel, serve_self) = self.into_channel_and_future(); match futures::future::select(pin!(client.connect_to(channel)), serve_self).await { Either::Left((result, _)) | Either::Right((result, _)) => result, @@ -77,7 +77,7 @@ impl ConnectTo for HttpMcpBridge { self, ) -> ( Channel, - BoxFuture<'static, Result<(), agent_client_protocol_core::Error>>, + BoxFuture<'static, Result<(), agent_client_protocol::Error>>, ) where Self: Sized, @@ -90,11 +90,11 @@ impl ConnectTo for HttpMcpBridge { /// Error type that we use to respond to malformed HTTP requests. #[derive(Debug, thiserror::Error)] #[error(transparent)] -struct HttpError(#[from] agent_client_protocol_core::Error); +struct HttpError(#[from] agent_client_protocol::Error); impl From for HttpError { fn from(error: axum::Error) -> Self { - HttpError(agent_client_protocol_core::util::internal_error(error)) + HttpError(agent_client_protocol::util::internal_error(error)) } } @@ -107,10 +107,7 @@ impl IntoResponse for HttpError { /// Run a webserver listening on `listener` for HTTP requests at `/` /// and communicating those requests over `channel` to the JSON-RPC server. -async fn run( - listener: TcpListener, - channel: Channel, -) -> Result<(), agent_client_protocol_core::Error> { +async fn run(listener: TcpListener, channel: Channel) -> Result<(), agent_client_protocol::Error> { let (registration_tx, registration_rx) = mpsc::unbounded(); let state = BridgeState { registration_tx }; @@ -135,7 +132,7 @@ async fn run( axum::serve(listener, app) .await - .map_err(agent_client_protocol_core::util::internal_error) + .map_err(agent_client_protocol::util::internal_error) } .race(RunningServer::new().run(channel, registration_rx)) .await @@ -153,27 +150,27 @@ enum HttpMessage { /// A JSON-RPC request (has an id, expects a response via the channel) Request { http_request_id: uuid::Uuid, - request: agent_client_protocol_core::jsonrpcmsg::Request, - response_tx: mpsc::UnboundedSender, + request: agent_client_protocol::jsonrpcmsg::Request, + response_tx: mpsc::UnboundedSender, }, /// A JSON-RPC notification (no id, no response expected) Notification { http_request_id: uuid::Uuid, - request: agent_client_protocol_core::jsonrpcmsg::Request, + request: agent_client_protocol::jsonrpcmsg::Request, }, /// A JSON-RPC response from the client Response { http_request_id: uuid::Uuid, - response: agent_client_protocol_core::jsonrpcmsg::Response, + response: agent_client_protocol::jsonrpcmsg::Response, }, /// A GET request to open an SSE stream for server-initiated messages Get { http_request_id: uuid::Uuid, - response_tx: mpsc::UnboundedSender, + response_tx: mpsc::UnboundedSender, }, } -/// Clone of `agent_client_protocol_core::jsonrpcmsg::Id` since for unfathomable reasons that does not impl Hash +/// Clone of `agent_client_protocol::jsonrpcmsg::Id` since for unfathomable reasons that does not impl Hash #[derive(Eq, PartialEq, PartialOrd, Ord, Hash, Debug, Clone)] enum JsonRpcId { /// String identifier @@ -184,12 +181,12 @@ enum JsonRpcId { Null, } -impl From for JsonRpcId { - fn from(id: agent_client_protocol_core::jsonrpcmsg::Id) -> Self { +impl From for JsonRpcId { + fn from(id: agent_client_protocol::jsonrpcmsg::Id) -> Self { match id { - agent_client_protocol_core::jsonrpcmsg::Id::String(s) => JsonRpcId::String(s), - agent_client_protocol_core::jsonrpcmsg::Id::Number(n) => JsonRpcId::Number(n), - agent_client_protocol_core::jsonrpcmsg::Id::Null => JsonRpcId::Null, + agent_client_protocol::jsonrpcmsg::Id::String(s) => JsonRpcId::String(s), + agent_client_protocol::jsonrpcmsg::Id::Number(n) => JsonRpcId::Number(n), + agent_client_protocol::jsonrpcmsg::Id::Null => JsonRpcId::Null, } } } @@ -197,7 +194,7 @@ impl From for JsonRpcId { struct RunningServer { waiting_sessions: FxHashMap, general_sessions: Vec, - message_deque: VecDeque, + message_deque: VecDeque, } impl RunningServer { @@ -219,15 +216,12 @@ impl RunningServer { mut self, mut channel: Channel, http_rx: mpsc::UnboundedReceiver, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { #[derive(Debug)] enum MultiplexMessage { FromHttpToChannel(HttpMessage), FromChannelToHttp( - Result< - agent_client_protocol_core::jsonrpcmsg::Message, - agent_client_protocol_core::Error, - >, + Result, ), } @@ -245,9 +239,9 @@ impl RunningServer { MultiplexMessage::FromChannelToHttp(message) => { let message = message.unwrap_or_else(|err| { - agent_client_protocol_core::jsonrpcmsg::Message::Response( - agent_client_protocol_core::jsonrpcmsg::Response::error( - agent_client_protocol_core::util::into_jsonrpc_error(err), + agent_client_protocol::jsonrpcmsg::Message::Response( + agent_client_protocol::jsonrpcmsg::Response::error( + agent_client_protocol::util::into_jsonrpc_error(err), None, ), ) @@ -274,12 +268,9 @@ impl RunningServer { &mut self, message: HttpMessage, channel_tx: &mut mpsc::UnboundedSender< - Result< - agent_client_protocol_core::jsonrpcmsg::Message, - agent_client_protocol_core::Error, - >, + Result, >, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { match message { HttpMessage::Request { http_request_id, @@ -292,7 +283,7 @@ impl RunningServer { // Send to the JSON-RPC server channel_tx .unbounded_send(Ok(Message::Request(request))) - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; // Register to receive the response let session = RegisteredSession::new(response_tx); @@ -314,7 +305,7 @@ impl RunningServer { // Just forward to the server, no response tracking needed channel_tx .unbounded_send(Ok(Message::Request(request))) - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; } HttpMessage::Response { @@ -325,7 +316,7 @@ impl RunningServer { // Forward to the server channel_tx .unbounded_send(Ok(Message::Response(response))) - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; } HttpMessage::Get { @@ -389,8 +380,8 @@ impl RunningServer { /// If there is no place to send it, returns `Some(message)`. fn try_dispatch_jsonrpc_message( &mut self, - mut message: agent_client_protocol_core::jsonrpcmsg::Message, - ) -> Option { + mut message: agent_client_protocol::jsonrpcmsg::Message, + ) -> Option { // Extract the id of the message we are replying to, if any let message_id = match &message { Message::Response(response) => response.id.as_ref().map(|v| v.clone().into()), @@ -467,13 +458,11 @@ impl RunningServer { struct RegisteredSession { id: uuid::Uuid, - outgoing_tx: mpsc::UnboundedSender, + outgoing_tx: mpsc::UnboundedSender, } impl RegisteredSession { - fn new( - outgoing_tx: mpsc::UnboundedSender, - ) -> Self { + fn new(outgoing_tx: mpsc::UnboundedSender) -> Self { Self { id: uuid::Uuid::new_v4(), outgoing_tx, @@ -491,8 +480,8 @@ async fn handle_post( let http_request_id = uuid::Uuid::new_v4(); // Parse incoming JSON-RPC message - let message: agent_client_protocol_core::jsonrpcmsg::Message = - serde_json::from_str(&body).map_err(agent_client_protocol_core::util::parse_error)?; + let message: agent_client_protocol::jsonrpcmsg::Message = + serde_json::from_str(&body).map_err(agent_client_protocol::util::parse_error)?; match message { Message::Request(request) if request.id.is_some() => { @@ -506,7 +495,7 @@ async fn handle_post( request, response_tx: tx, }) - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; let stream = async_stream::stream! { while let Some(message) = rx.next().await { @@ -530,7 +519,7 @@ async fn handle_post( http_request_id, request, }) - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; Ok(StatusCode::ACCEPTED.into_response()) } @@ -543,7 +532,7 @@ async fn handle_post( http_request_id, response, }) - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; Ok(StatusCode::ACCEPTED.into_response()) } } @@ -564,7 +553,7 @@ async fn handle_get( http_request_id, response_tx: tx, }) - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; let stream = async_stream::stream! { while let Some(message) = rx.next().await { diff --git a/src/agent-client-protocol-conductor/src/conductor/mcp_bridge/stdio.rs b/src/agent-client-protocol-conductor/src/conductor/mcp_bridge/stdio.rs index 3b15c64..fd85ee4 100644 --- a/src/agent-client-protocol-conductor/src/conductor/mcp_bridge/stdio.rs +++ b/src/agent-client-protocol-conductor/src/conductor/mcp_bridge/stdio.rs @@ -1,4 +1,4 @@ -use agent_client_protocol_core::Dispatch; +use agent_client_protocol::Dispatch; use futures::{SinkExt, channel::mpsc}; use tokio::net::{TcpListener, TcpStream}; use tokio_util::compat::{TokioAsyncReadCompatExt as _, TokioAsyncWriteCompatExt as _}; @@ -16,13 +16,13 @@ pub async fn run_tcp_listener( tcp_listener: TcpListener, acp_url: String, mut conductor_tx: mpsc::Sender, -) -> Result<(), agent_client_protocol_core::Error> { +) -> Result<(), agent_client_protocol::Error> { // Accept connections loop { let (stream, _addr) = tcp_listener .accept() .await - .map_err(agent_client_protocol_core::Error::into_internal_error)?; + .map_err(agent_client_protocol::Error::into_internal_error)?; let (to_mcp_client_tx, to_mcp_client_rx) = mpsc::channel(128); @@ -33,7 +33,7 @@ pub async fn run_tcp_listener( connection: McpBridgeConnection::new(to_mcp_client_tx), }) .await - .map_err(|_| agent_client_protocol_core::Error::internal_error())?; + .map_err(|_| agent_client_protocol::Error::internal_error())?; } } @@ -48,7 +48,7 @@ fn make_stdio_actor( // The bridge will send MCP requests (tools/call, etc.) to the conductor // The conductor can also send responses back let transport = - agent_client_protocol_core::ByteStreams::new(write_half.compat_write(), read_half.compat()); + agent_client_protocol::ByteStreams::new(write_half.compat_write(), read_half.compat()); McpBridgeConnectionActor::new(transport, conductor_tx, to_mcp_client_rx) } diff --git a/src/agent-client-protocol-conductor/src/lib.rs b/src/agent-client-protocol-conductor/src/lib.rs index f1ecba0..1878c73 100644 --- a/src/agent-client-protocol-conductor/src/lib.rs +++ b/src/agent-client-protocol-conductor/src/lib.rs @@ -71,7 +71,7 @@ //! ## Related Crates //! //! - **[agent-client-protocol-proxy](https://crates.io/crates/agent-client-protocol-proxy)** - Framework for building proxy components -//! - **[agent-client-protocol-core](https://crates.io/crates/agent-client-protocol-core)** - Core ACP SDK +//! - **[agent-client-protocol](https://crates.io/crates/agent-client-protocol)** - Core ACP SDK //! - **[agent-client-protocol-tokio](https://crates.io/crates/agent-client-protocol-tokio)** - Tokio utilities for process spawning use std::path::PathBuf; @@ -91,7 +91,7 @@ pub use self::conductor::*; use clap::{Parser, Subcommand}; -use agent_client_protocol_core::{Client, Conductor, DynConnectTo, schema::InitializeRequest}; +use agent_client_protocol::{Client, Conductor, DynConnectTo, schema::InitializeRequest}; use agent_client_protocol_tokio::{AcpAgent, Stdio}; use tracing::Instrument; use tracing_subscriber::{EnvFilter, layer::SubscriberExt, util::SubscriberInitExt}; @@ -111,10 +111,7 @@ impl InstantiateProxies for CommandLineComponents { req: InitializeRequest, ) -> futures::future::BoxFuture< 'static, - Result< - (InitializeRequest, Vec>), - agent_client_protocol_core::Error, - >, + Result<(InitializeRequest, Vec>), agent_client_protocol::Error>, > { Box::pin(async move { let proxies = self.0.into_iter().map(DynConnectTo::new).collect(); @@ -135,7 +132,7 @@ impl InstantiateProxiesAndAgent for CommandLineComponents { Vec>, DynConnectTo, ), - agent_client_protocol_core::Error, + agent_client_protocol::Error, >, > { Box::pin(async move { @@ -153,7 +150,7 @@ impl InstantiateProxiesAndAgent for CommandLineComponents { } } - Err(agent_client_protocol_core::util::internal_error( + Err(agent_client_protocol::util::internal_error( "no agent component in list", )) }) @@ -329,7 +326,7 @@ impl ConductorArgs { self, debug_logger: Option<&debug_logger::DebugLogger>, trace_writer: Option, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { match self.command { ConductorCommand::Agent { name, components } => { initialize_conductor( @@ -366,7 +363,7 @@ async fn initialize_conductor( CommandLineComponents, crate::McpBridgeMode, ) -> ConductorImpl, -) -> Result<(), agent_client_protocol_core::Error> { +) -> Result<(), agent_client_protocol::Error> { // Parse agents and optionally wrap with debug callbacks let providers: Vec = components .into_iter() @@ -378,7 +375,7 @@ async fn initialize_conductor( } Ok(agent) }) - .collect::, agent_client_protocol_core::Error>>()?; + .collect::, agent_client_protocol::Error>>()?; // Create Stdio component with optional debug logging let stdio = if let Some(logger) = debug_logger { diff --git a/src/agent-client-protocol-conductor/src/mcp_bridge.rs b/src/agent-client-protocol-conductor/src/mcp_bridge.rs index d6b3ca0..9d60825 100644 --- a/src/agent-client-protocol-conductor/src/mcp_bridge.rs +++ b/src/agent-client-protocol-conductor/src/mcp_bridge.rs @@ -15,7 +15,7 @@ use tokio::net::TcpStream; /// /// Reads MCP JSON-RPC messages from stdin, forwards to TCP connection. /// Reads responses from TCP, writes to stdout. -pub async fn run_mcp_bridge(port: u16) -> Result<(), agent_client_protocol_core::Error> { +pub async fn run_mcp_bridge(port: u16) -> Result<(), agent_client_protocol::Error> { tracing::info!("MCP bridge starting, connecting to localhost:{}", port); // Connect to the main conductor via TCP @@ -92,7 +92,7 @@ pub async fn run_mcp_bridge(port: u16) -> Result<(), agent_client_protocol_core: } /// Connect to TCP port with retry logic -async fn connect_with_retry(port: u16) -> Result { +async fn connect_with_retry(port: u16) -> Result { let max_retries = 10; let mut retry_delay_ms = 50; @@ -113,7 +113,7 @@ async fn connect_with_retry(port: u16) -> Result { - return Err(agent_client_protocol_core::Error::into_internal_error(e)); + return Err(agent_client_protocol::Error::into_internal_error(e)); } } } diff --git a/src/agent-client-protocol-conductor/src/snoop.rs b/src/agent-client-protocol-conductor/src/snoop.rs index 455fd32..2c61c04 100644 --- a/src/agent-client-protocol-conductor/src/snoop.rs +++ b/src/agent-client-protocol-conductor/src/snoop.rs @@ -1,33 +1,25 @@ -use agent_client_protocol_core::{Channel, ConnectTo, DynConnectTo, Role, jsonrpcmsg}; +use agent_client_protocol::{Channel, ConnectTo, DynConnectTo, Role, jsonrpcmsg}; use futures::StreamExt; use futures_concurrency::future::TryJoin; pub struct SnooperComponent { base_component: DynConnectTo, incoming_message: Box< - dyn FnMut(&jsonrpcmsg::Message) -> Result<(), agent_client_protocol_core::Error> - + Send - + Sync, + dyn FnMut(&jsonrpcmsg::Message) -> Result<(), agent_client_protocol::Error> + Send + Sync, >, outgoing_message: Box< - dyn FnMut(&jsonrpcmsg::Message) -> Result<(), agent_client_protocol_core::Error> - + Send - + Sync, + dyn FnMut(&jsonrpcmsg::Message) -> Result<(), agent_client_protocol::Error> + Send + Sync, >, } impl SnooperComponent { pub fn new( base_component: impl ConnectTo, - incoming_message: impl FnMut( - &jsonrpcmsg::Message, - ) -> Result<(), agent_client_protocol_core::Error> + incoming_message: impl FnMut(&jsonrpcmsg::Message) -> Result<(), agent_client_protocol::Error> + Send + Sync + 'static, - outgoing_message: impl FnMut( - &jsonrpcmsg::Message, - ) -> Result<(), agent_client_protocol_core::Error> + outgoing_message: impl FnMut(&jsonrpcmsg::Message) -> Result<(), agent_client_protocol::Error> + Send + Sync + 'static, @@ -44,7 +36,7 @@ impl ConnectTo for SnooperComponent { async fn connect_to( mut self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { let (client_a, mut client_b) = Channel::duplex(); let client_future = client.connect_to(client_a); @@ -62,7 +54,7 @@ impl ConnectTo for SnooperComponent { base_channel .tx .unbounded_send(msg) - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; } Ok(()) }; @@ -78,7 +70,7 @@ impl ConnectTo for SnooperComponent { client_b .tx .unbounded_send(msg) - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; } Ok(()) }; diff --git a/src/agent-client-protocol-conductor/src/trace.rs b/src/agent-client-protocol-conductor/src/trace.rs index 2573ca9..7b10ba4 100644 --- a/src/agent-client-protocol-conductor/src/trace.rs +++ b/src/agent-client-protocol-conductor/src/trace.rs @@ -9,8 +9,8 @@ use std::io::{BufWriter, Write}; use std::path::Path; use std::time::Instant; -use agent_client_protocol_core::schema::{McpOverAcpMessage, SuccessorMessage}; -use agent_client_protocol_core::{DynConnectTo, JsonRpcMessage, Role, UntypedMessage, jsonrpcmsg}; +use agent_client_protocol::schema::{McpOverAcpMessage, SuccessorMessage}; +use agent_client_protocol::{DynConnectTo, JsonRpcMessage, Role, UntypedMessage, jsonrpcmsg}; use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; @@ -388,7 +388,7 @@ impl TraceWriter { mut self: TraceWriter, ) -> ( TraceHandle, - impl std::future::Future>, + impl std::future::Future>, ) { use futures::StreamExt; @@ -421,7 +421,7 @@ impl TraceHandle { successor_index: ComponentIndex, incoming: Incoming, message: &jsonrpcmsg::Message, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { self.tx .unbounded_send(TracedMessage { component_index, @@ -429,7 +429,7 @@ impl TraceHandle { incoming, message: message.clone(), }) - .map_err(agent_client_protocol_core::util::internal_error) + .map_err(agent_client_protocol::util::internal_error) } /// Create a tracing bridge that wraps a proxy component. @@ -450,7 +450,7 @@ impl TraceHandle { &self, proxy_index: ComponentIndex, successor_index: ComponentIndex, - proxy: impl agent_client_protocol_core::ConnectTo, + proxy: impl agent_client_protocol::ConnectTo, ) -> DynConnectTo { DynConnectTo::new(SnooperComponent::new( proxy, diff --git a/src/agent-client-protocol-conductor/tests/arrow_proxy_eliza.rs b/src/agent-client-protocol-conductor/tests/arrow_proxy_eliza.rs index 5f6328d..1b465a8 100644 --- a/src/agent-client-protocol-conductor/tests/arrow_proxy_eliza.rs +++ b/src/agent-client-protocol-conductor/tests/arrow_proxy_eliza.rs @@ -15,8 +15,8 @@ use tokio::io::duplex; use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; #[tokio::test] -async fn test_conductor_with_arrow_proxy_and_test_agent() --> Result<(), agent_client_protocol_core::Error> { +async fn test_conductor_with_arrow_proxy_and_test_agent() -> Result<(), agent_client_protocol::Error> +{ // Create the component chain: arrow_proxy -> test_agent // Uses pre-built binaries to avoid cargo run races during `cargo test --all` let arrow_proxy_agent = @@ -34,7 +34,7 @@ async fn test_conductor_with_arrow_proxy_and_test_agent() ProxiesAndAgent::new(test_agent).proxy(arrow_proxy_agent), McpBridgeMode::default(), ) - .run(agent_client_protocol_core::ByteStreams::new( + .run(agent_client_protocol::ByteStreams::new( conductor_write.compat_write(), conductor_read.compat(), )) @@ -44,7 +44,7 @@ async fn test_conductor_with_arrow_proxy_and_test_agent() // Wait for editor to complete and get the result let result = tokio::time::timeout(std::time::Duration::from_secs(30), async move { let result = yopo::prompt( - agent_client_protocol_core::ByteStreams::new( + agent_client_protocol::ByteStreams::new( editor_write.compat_write(), editor_read.compat(), ), @@ -59,7 +59,7 @@ async fn test_conductor_with_arrow_proxy_and_test_agent() "Expected response to start with '>' from arrow proxy, got: {result}" ); - Ok::(result) + Ok::(result) }) .await .expect("Test timed out") diff --git a/src/agent-client-protocol-conductor/tests/empty_conductor_eliza.rs b/src/agent-client-protocol-conductor/tests/empty_conductor_eliza.rs index 495faf4..c1f87a8 100644 --- a/src/agent-client-protocol-conductor/tests/empty_conductor_eliza.rs +++ b/src/agent-client-protocol-conductor/tests/empty_conductor_eliza.rs @@ -6,8 +6,8 @@ //! 3. Messages flow correctly through the empty conductor to the agent //! 4. The full chain works end-to-end +use agent_client_protocol::{Conductor, ConnectTo, Proxy}; use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; -use agent_client_protocol_core::{Conductor, ConnectTo, Proxy}; use agent_client_protocol_test::testy::{Testy, TestyCommand}; use tokio::io::duplex; use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; @@ -20,9 +20,9 @@ impl ConnectTo for MockEmptyConductor { async fn connect_to( self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { // Create an empty conductor with no components - it should act as a passthrough - let empty_components: Vec> = vec![]; + let empty_components: Vec> = vec![]; ConnectTo::::connect_to( ConductorImpl::new_proxy( "empty-conductor".to_string(), @@ -37,7 +37,7 @@ impl ConnectTo for MockEmptyConductor { #[tokio::test] async fn test_conductor_with_empty_conductor_and_test_agent() --> Result<(), agent_client_protocol_core::Error> { +-> Result<(), agent_client_protocol::Error> { // Initialize tracing for debugging drop( tracing_subscriber::fmt() @@ -59,7 +59,7 @@ async fn test_conductor_with_empty_conductor_and_test_agent() ProxiesAndAgent::new(Testy::new()).proxy(MockEmptyConductor), McpBridgeMode::default(), ) - .run(agent_client_protocol_core::ByteStreams::new( + .run(agent_client_protocol::ByteStreams::new( conductor_write.compat_write(), conductor_read.compat(), )) @@ -69,7 +69,7 @@ async fn test_conductor_with_empty_conductor_and_test_agent() // Wait for editor to complete and get the result let result = tokio::time::timeout(std::time::Duration::from_secs(30), async move { let result = yopo::prompt( - agent_client_protocol_core::ByteStreams::new( + agent_client_protocol::ByteStreams::new( editor_write.compat_write(), editor_read.compat(), ), @@ -85,7 +85,7 @@ async fn test_conductor_with_empty_conductor_and_test_agent() "#]] .assert_debug_eq(&result); - Ok::(result) + Ok::(result) }) .await .expect("Test timed out") diff --git a/src/agent-client-protocol-conductor/tests/initialization_sequence.rs b/src/agent-client-protocol-conductor/tests/initialization_sequence.rs index 004c7ad..dcf0a5a 100644 --- a/src/agent-client-protocol-conductor/tests/initialization_sequence.rs +++ b/src/agent-client-protocol-conductor/tests/initialization_sequence.rs @@ -5,12 +5,12 @@ //! 2. Multi-component chains: proxies receive `InitializeProxyRequest` //! 3. Last component (agent) receives `InitializeRequest` -use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; -use agent_client_protocol_core::schema::{ +use agent_client_protocol::schema::{ AgentCapabilities, InitializeProxyRequest, InitializeRequest, InitializeResponse, ProtocolVersion, }; -use agent_client_protocol_core::{Agent, Client, Conductor, ConnectTo, DynConnectTo, Proxy}; +use agent_client_protocol::{Agent, Client, Conductor, ConnectTo, DynConnectTo, Proxy}; +use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; use agent_client_protocol_test::testy::Testy; use std::sync::Arc; use std::sync::Mutex; @@ -19,16 +19,16 @@ use tokio::io::duplex; use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; /// Test helper to receive a JSON-RPC response -async fn recv( - response: agent_client_protocol_core::SentRequest, -) -> Result { +async fn recv( + response: agent_client_protocol::SentRequest, +) -> Result { let (tx, rx) = tokio::sync::oneshot::channel(); response.on_receiving_result(async move |result| { tx.send(result) - .map_err(|_| agent_client_protocol_core::Error::internal_error()) + .map_err(|_| agent_client_protocol::Error::internal_error()) })?; rx.await - .map_err(|_| agent_client_protocol_core::Error::internal_error())? + .map_err(|_| agent_client_protocol::Error::internal_error())? } /// Tracks what type of initialization request was received @@ -74,7 +74,7 @@ impl ConnectTo for InitComponent { async fn connect_to( self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { let config = self.config; let config2 = Arc::clone(&config); @@ -89,13 +89,13 @@ impl ConnectTo for InitComponent { Some(InitRequestType::InitializeProxy); // Forward InitializeRequest (not InitializeProxyRequest) to successor - cx.send_request_to(agent_client_protocol_core::Agent, request.initialize) + cx.send_request_to(agent_client_protocol::Agent, request.initialize) .on_receiving_result(async move |response| { let response: InitializeResponse = response?; responder.respond(response) }) }, - agent_client_protocol_core::on_receive_request!(), + agent_client_protocol::on_receive_request!(), ) // Handle InitializeRequest (we're the agent) .on_receive_request_from( @@ -110,7 +110,7 @@ impl ConnectTo for InitComponent { responder.respond(response) }, - agent_client_protocol_core::on_receive_request!(), + agent_client_protocol::on_receive_request!(), ) .connect_to(client) .await @@ -120,17 +120,17 @@ impl ConnectTo for InitComponent { async fn run_test_with_components( proxies: Vec, editor_task: impl AsyncFnOnce( - agent_client_protocol_core::ConnectionTo, - ) -> Result<(), agent_client_protocol_core::Error>, -) -> Result<(), agent_client_protocol_core::Error> { + agent_client_protocol::ConnectionTo, + ) -> Result<(), agent_client_protocol::Error>, +) -> Result<(), agent_client_protocol::Error> { // Set up editor <-> conductor communication let (editor_out, conductor_in) = duplex(1024); let (conductor_out, editor_in) = duplex(1024); let transport = - agent_client_protocol_core::ByteStreams::new(editor_out.compat_write(), editor_in.compat()); + agent_client_protocol::ByteStreams::new(editor_out.compat_write(), editor_in.compat()); - agent_client_protocol_core::Client + agent_client_protocol::Client .builder() .name("editor-to-connector") .with_spawned(|_cx| async move { @@ -139,7 +139,7 @@ async fn run_test_with_components( ProxiesAndAgent::new(Testy::new()).proxies(proxies), McpBridgeMode::default(), ) - .run(agent_client_protocol_core::ByteStreams::new( + .run(agent_client_protocol::ByteStreams::new( conductor_out.compat_write(), conductor_in.compat(), )) @@ -150,8 +150,8 @@ async fn run_test_with_components( } #[tokio::test] -async fn test_single_component_gets_initialize_request() --> Result<(), agent_client_protocol_core::Error> { +async fn test_single_component_gets_initialize_request() -> Result<(), agent_client_protocol::Error> +{ // Single component (agent) should receive InitializeRequest - we use ElizaAgent // which properly handles InitializeRequest run_test_with_components(vec![], async |connection_to_editor| { @@ -165,7 +165,7 @@ async fn test_single_component_gets_initialize_request() "Initialize should succeed: {init_response:?}" ); - Ok::<(), agent_client_protocol_core::Error>(()) + Ok::<(), agent_client_protocol::Error>(()) }) .await?; @@ -174,7 +174,7 @@ async fn test_single_component_gets_initialize_request() #[tokio::test] async fn test_two_components_proxy_gets_initialize_proxy() --> Result<(), agent_client_protocol_core::Error> { +-> Result<(), agent_client_protocol::Error> { // First component (proxy) gets InitializeProxyRequest // Second component (agent, ElizaAgent) gets InitializeRequest let component1 = InitConfig::new(); @@ -192,7 +192,7 @@ async fn test_two_components_proxy_gets_initialize_proxy() "Initialize should succeed: {init_response:?}" ); - Ok::<(), agent_client_protocol_core::Error>(()) + Ok::<(), agent_client_protocol::Error>(()) }, ) .await?; @@ -211,7 +211,7 @@ async fn test_two_components_proxy_gets_initialize_proxy() #[tokio::test] async fn test_three_components_all_proxies_get_initialize_proxy() --> Result<(), agent_client_protocol_core::Error> { +-> Result<(), agent_client_protocol::Error> { // First two components (proxies) get InitializeProxyRequest // Third component (agent, ElizaAgent) gets InitializeRequest let component1 = InitConfig::new(); @@ -233,7 +233,7 @@ async fn test_three_components_all_proxies_get_initialize_proxy() "Initialize should succeed: {init_response:?}" ); - Ok::<(), agent_client_protocol_core::Error>(()) + Ok::<(), agent_client_protocol::Error>(()) }, ) .await?; @@ -263,7 +263,7 @@ impl ConnectTo for BadProxy { async fn connect_to( self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { Proxy .builder() .name("bad-proxy") @@ -277,7 +277,7 @@ impl ConnectTo for BadProxy { responder.respond(response) }) }, - agent_client_protocol_core::on_receive_request!(), + agent_client_protocol::on_receive_request!(), ) .connect_to(client) .await @@ -289,16 +289,16 @@ async fn run_bad_proxy_test( proxies: Vec>, agent: DynConnectTo, editor_task: impl AsyncFnOnce( - agent_client_protocol_core::ConnectionTo, - ) -> Result<(), agent_client_protocol_core::Error>, -) -> Result<(), agent_client_protocol_core::Error> { + agent_client_protocol::ConnectionTo, + ) -> Result<(), agent_client_protocol::Error>, +) -> Result<(), agent_client_protocol::Error> { let (editor_out, conductor_in) = duplex(1024); let (conductor_out, editor_in) = duplex(1024); let transport = - agent_client_protocol_core::ByteStreams::new(editor_out.compat_write(), editor_in.compat()); + agent_client_protocol::ByteStreams::new(editor_out.compat_write(), editor_in.compat()); - agent_client_protocol_core::Client + agent_client_protocol::Client .builder() .name("editor-to-connector") .with_spawned(|_cx| async move { @@ -307,7 +307,7 @@ async fn run_bad_proxy_test( ProxiesAndAgent::new(agent).proxies(proxies), McpBridgeMode::default(), ) - .run(agent_client_protocol_core::ByteStreams::new( + .run(agent_client_protocol::ByteStreams::new( conductor_out.compat_write(), conductor_in.compat(), )) @@ -319,7 +319,7 @@ async fn run_bad_proxy_test( #[tokio::test] async fn test_conductor_rejects_initialize_proxy_forwarded_to_agent() --> Result<(), agent_client_protocol_core::Error> { +-> Result<(), agent_client_protocol::Error> { // BadProxy incorrectly forwards InitializeProxyRequest to the agent. // The conductor should reject this with an error. let result = run_bad_proxy_test( @@ -338,7 +338,7 @@ async fn test_conductor_rejects_initialize_proxy_forwarded_to_agent() ); } - Ok::<(), agent_client_protocol_core::Error>(()) + Ok::<(), agent_client_protocol::Error>(()) }, ) .await; @@ -358,7 +358,7 @@ async fn test_conductor_rejects_initialize_proxy_forwarded_to_agent() #[tokio::test] async fn test_conductor_rejects_initialize_proxy_forwarded_to_proxy() --> Result<(), agent_client_protocol_core::Error> { +-> Result<(), agent_client_protocol::Error> { // BadProxy incorrectly forwards InitializeProxyRequest to another proxy. // The conductor should reject this with an error. let result = run_bad_proxy_test( @@ -381,7 +381,7 @@ async fn test_conductor_rejects_initialize_proxy_forwarded_to_proxy() ); } - Ok::<(), agent_client_protocol_core::Error>(()) + Ok::<(), agent_client_protocol::Error>(()) }, ) .await; diff --git a/src/agent-client-protocol-conductor/tests/mcp-integration.rs b/src/agent-client-protocol-conductor/tests/mcp-integration.rs index 2ab5407..174f0b9 100644 --- a/src/agent-client-protocol-conductor/tests/mcp-integration.rs +++ b/src/agent-client-protocol-conductor/tests/mcp-integration.rs @@ -7,12 +7,12 @@ mod mcp_integration; -use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; -use agent_client_protocol_core::Agent; -use agent_client_protocol_core::schema::{ +use agent_client_protocol::Agent; +use agent_client_protocol::schema::{ ContentBlock, InitializeRequest, NewSessionRequest, PromptRequest, ProtocolVersion, SessionNotification, TextContent, }; +use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; use agent_client_protocol_test::test_binaries; use agent_client_protocol_test::testy::{Testy, TestyCommand}; use futures::{SinkExt, StreamExt, channel::mpsc}; @@ -21,16 +21,16 @@ use tokio::io::duplex; use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; /// Test helper to receive a JSON-RPC response -async fn recv( - response: agent_client_protocol_core::SentRequest, -) -> Result { +async fn recv( + response: agent_client_protocol::SentRequest, +) -> Result { let (tx, rx) = tokio::sync::oneshot::channel(); response.on_receiving_result(async move |result| { tx.send(result) - .map_err(|_| agent_client_protocol_core::Error::internal_error()) + .map_err(|_| agent_client_protocol::Error::internal_error()) })?; rx.await - .map_err(|_| agent_client_protocol_core::Error::internal_error())? + .map_err(|_| agent_client_protocol::Error::internal_error())? } fn conductor_command() -> Vec { @@ -42,9 +42,9 @@ async fn run_test_with_mode( mode: McpBridgeMode, components: ProxiesAndAgent, editor_task: impl AsyncFnOnce( - agent_client_protocol_core::ConnectionTo, - ) -> Result<(), agent_client_protocol_core::Error>, -) -> Result<(), agent_client_protocol_core::Error> { + agent_client_protocol::ConnectionTo, + ) -> Result<(), agent_client_protocol::Error>, +) -> Result<(), agent_client_protocol::Error> { // Initialize tracing for debug output drop( tracing_subscriber::fmt() @@ -58,14 +58,14 @@ async fn run_test_with_mode( let (conductor_out, editor_in) = duplex(1024); let transport = - agent_client_protocol_core::ByteStreams::new(editor_out.compat_write(), editor_in.compat()); + agent_client_protocol::ByteStreams::new(editor_out.compat_write(), editor_in.compat()); - agent_client_protocol_core::Client + agent_client_protocol::Client .builder() .name("editor-to-connector") .with_spawned(|_cx| async move { ConductorImpl::new_agent("conductor".to_string(), components, mode) - .run(agent_client_protocol_core::ByteStreams::new( + .run(agent_client_protocol::ByteStreams::new( conductor_out.compat_write(), conductor_in.compat(), )) @@ -77,7 +77,7 @@ async fn run_test_with_mode( /// Test that proxy-provided MCP tools work with stdio bridge mode #[tokio::test] -async fn test_proxy_provides_mcp_tools_stdio() -> Result<(), agent_client_protocol_core::Error> { +async fn test_proxy_provides_mcp_tools_stdio() -> Result<(), agent_client_protocol::Error> { run_test_with_mode( McpBridgeMode::Stdio { conductor_command: conductor_command(), @@ -121,7 +121,7 @@ async fn test_proxy_provides_mcp_tools_stdio() -> Result<(), agent_client_protoc /// Test that proxy-provided MCP tools work with HTTP bridge mode #[tokio::test] -async fn test_proxy_provides_mcp_tools_http() -> Result<(), agent_client_protocol_core::Error> { +async fn test_proxy_provides_mcp_tools_http() -> Result<(), agent_client_protocol::Error> { run_test_with_mode( McpBridgeMode::Http, ProxiesAndAgent::new(Testy::new()).proxy(mcp_integration::proxy::ProxyComponent), @@ -162,7 +162,7 @@ async fn test_proxy_provides_mcp_tools_http() -> Result<(), agent_client_protoco } #[tokio::test] -async fn test_agent_handles_prompt() -> Result<(), agent_client_protocol_core::Error> { +async fn test_agent_handles_prompt() -> Result<(), agent_client_protocol::Error> { // Initialize tracing for debug output drop( tracing_subscriber::fmt() @@ -185,7 +185,7 @@ async fn test_agent_handles_prompt() -> Result<(), agent_client_protocol_core::E ProxiesAndAgent::new(Testy::new()).proxy(mcp_integration::proxy::ProxyComponent), McpBridgeMode::default(), ) - .run(agent_client_protocol_core::ByteStreams::new( + .run(agent_client_protocol::ByteStreams::new( conductor_write.compat_write(), conductor_read.compat(), )) @@ -193,25 +193,25 @@ async fn test_agent_handles_prompt() -> Result<(), agent_client_protocol_core::E }); // Run the client - let result = agent_client_protocol_core::Client + let result = agent_client_protocol::Client .builder() .name("editor-to-connector") .on_receive_notification( { let mut log_tx = log_tx.clone(); async move |notification: SessionNotification, - _cx: agent_client_protocol_core::ConnectionTo| { + _cx: agent_client_protocol::ConnectionTo| { // Log the notification in debug format log_tx .send(format!("{notification:?}")) .await - .map_err(|_| agent_client_protocol_core::Error::internal_error()) + .map_err(|_| agent_client_protocol::Error::internal_error()) } }, - agent_client_protocol_core::on_receive_notification!(), + agent_client_protocol::on_receive_notification!(), ) .connect_with( - agent_client_protocol_core::ByteStreams::new( + agent_client_protocol::ByteStreams::new( client_write.compat_write(), client_read.compat(), ), @@ -247,7 +247,7 @@ async fn test_agent_handles_prompt() -> Result<(), agent_client_protocol_core::E log_tx .send(format!("{prompt_response:?}")) .await - .map_err(|_| agent_client_protocol_core::Error::internal_error())?; + .map_err(|_| agent_client_protocol::Error::internal_error())?; Ok(()) }, diff --git a/src/agent-client-protocol-conductor/tests/mcp_integration/proxy.rs b/src/agent-client-protocol-conductor/tests/mcp_integration/proxy.rs index 6daaa75..1359cf1 100644 --- a/src/agent-client-protocol-conductor/tests/mcp_integration/proxy.rs +++ b/src/agent-client-protocol-conductor/tests/mcp_integration/proxy.rs @@ -1,7 +1,7 @@ //! Proxy component that provides MCP tools -use agent_client_protocol_core::mcp_server::McpServer; -use agent_client_protocol_core::{Conductor, ConnectTo, Proxy}; +use agent_client_protocol::mcp_server::McpServer; +use agent_client_protocol::{Conductor, ConnectTo, Proxy}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -25,7 +25,7 @@ impl ConnectTo for ProxyComponent { async fn connect_to( self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { let test_server = McpServer::builder("test") .instructions("A simple test MCP server with an echo tool") .tool_fn_mut( @@ -36,11 +36,11 @@ impl ConnectTo for ProxyComponent { result: format!("Echo: {}", params.message), }) }, - agent_client_protocol_core::tool_fn_mut!(), + agent_client_protocol::tool_fn_mut!(), ) .build(); - agent_client_protocol_core::Proxy + agent_client_protocol::Proxy .builder() .name("proxy-component") .with_mcp_server(test_server) diff --git a/src/agent-client-protocol-conductor/tests/mcp_server_handler_chain.rs b/src/agent-client-protocol-conductor/tests/mcp_server_handler_chain.rs index 3ddd232..c2b1f9c 100644 --- a/src/agent-client-protocol-conductor/tests/mcp_server_handler_chain.rs +++ b/src/agent-client-protocol-conductor/tests/mcp_server_handler_chain.rs @@ -5,13 +5,13 @@ //! `Handled::No`, which prevented downstream `.on_receive_request_from()` handlers //! from being invoked. -use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; -use agent_client_protocol_core::mcp_server::McpServer; -use agent_client_protocol_core::schema::{ +use agent_client_protocol::mcp_server::McpServer; +use agent_client_protocol::schema::{ AgentCapabilities, InitializeRequest, InitializeResponse, NewSessionRequest, NewSessionResponse, ProtocolVersion, SessionId, }; -use agent_client_protocol_core::{Agent, Client, Conductor, ConnectTo, DynConnectTo, Proxy}; +use agent_client_protocol::{Agent, Client, Conductor, ConnectTo, DynConnectTo, Proxy}; +use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::path::PathBuf; @@ -34,16 +34,16 @@ struct EchoOutput { } /// Test helper to receive a JSON-RPC response -async fn recv( - response: agent_client_protocol_core::SentRequest, -) -> Result { +async fn recv( + response: agent_client_protocol::SentRequest, +) -> Result { let (tx, rx) = tokio::sync::oneshot::channel(); response.on_receiving_result(async move |result| { tx.send(result) - .map_err(|_| agent_client_protocol_core::Error::internal_error()) + .map_err(|_| agent_client_protocol::Error::internal_error()) })?; rx.await - .map_err(|_| agent_client_protocol_core::Error::internal_error())? + .map_err(|_| agent_client_protocol::Error::internal_error())? } /// Tracks whether the NewSessionRequest handler was invoked @@ -73,7 +73,7 @@ impl ConnectTo for ProxyWithMcpAndHandler { async fn connect_to( self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { let config = Arc::clone(&self.config); // Create an MCP server with a simple tool @@ -87,11 +87,11 @@ impl ConnectTo for ProxyWithMcpAndHandler { result: format!("Echo: {}", params.message), }) }, - agent_client_protocol_core::tool_fn_mut!(), + agent_client_protocol::tool_fn_mut!(), ) .build(); - agent_client_protocol_core::Proxy + agent_client_protocol::Proxy .builder() .name("proxy-with-mcp-and-handler") // Add the MCP server @@ -112,7 +112,7 @@ impl ConnectTo for ProxyWithMcpAndHandler { responder.respond(response) }) }, - agent_client_protocol_core::on_receive_request!(), + agent_client_protocol::on_receive_request!(), ) .connect_to(client) .await @@ -126,7 +126,7 @@ impl ConnectTo for SimpleAgent { async fn connect_to( self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { Agent .builder() .name("simple-agent") @@ -137,7 +137,7 @@ impl ConnectTo for SimpleAgent { .agent_capabilities(AgentCapabilities::new()), ) }, - agent_client_protocol_core::on_receive_request!(), + agent_client_protocol::on_receive_request!(), ) .on_receive_request( async |_request: NewSessionRequest, responder, _cx| { @@ -145,7 +145,7 @@ impl ConnectTo for SimpleAgent { uuid::Uuid::new_v4().to_string(), ))) }, - agent_client_protocol_core::on_receive_request!(), + agent_client_protocol::on_receive_request!(), ) .connect_to(client) .await @@ -156,16 +156,16 @@ async fn run_test( proxies: Vec>, agent: DynConnectTo, editor_task: impl AsyncFnOnce( - agent_client_protocol_core::ConnectionTo, - ) -> Result<(), agent_client_protocol_core::Error>, -) -> Result<(), agent_client_protocol_core::Error> { + agent_client_protocol::ConnectionTo, + ) -> Result<(), agent_client_protocol::Error>, +) -> Result<(), agent_client_protocol::Error> { let (editor_out, conductor_in) = duplex(1024); let (conductor_out, editor_in) = duplex(1024); let transport = - agent_client_protocol_core::ByteStreams::new(editor_out.compat_write(), editor_in.compat()); + agent_client_protocol::ByteStreams::new(editor_out.compat_write(), editor_in.compat()); - agent_client_protocol_core::Client + agent_client_protocol::Client .builder() .name("editor-to-conductor") .with_spawned(|_cx| async move { @@ -174,7 +174,7 @@ async fn run_test( ProxiesAndAgent::new(agent).proxies(proxies), McpBridgeMode::default(), ) - .run(agent_client_protocol_core::ByteStreams::new( + .run(agent_client_protocol::ByteStreams::new( conductor_out.compat_write(), conductor_in.compat(), )) @@ -187,7 +187,7 @@ async fn run_test( /// Regression test: NewSessionRequest handler should be invoked even when MCP server is present #[tokio::test] async fn test_new_session_handler_invoked_with_mcp_server() --> Result<(), agent_client_protocol_core::Error> { +-> Result<(), agent_client_protocol::Error> { let handler_config = HandlerConfig::new(); let handler_config_clone = Arc::clone(&handler_config); @@ -214,7 +214,7 @@ async fn test_new_session_handler_invoked_with_mcp_server() "Should receive a valid session ID" ); - Ok::<(), agent_client_protocol_core::Error>(()) + Ok::<(), agent_client_protocol::Error>(()) }) .await?; diff --git a/src/agent-client-protocol-conductor/tests/nested_arrow_proxy.rs b/src/agent-client-protocol-conductor/tests/nested_arrow_proxy.rs index 3bb91ed..42a7ac2 100644 --- a/src/agent-client-protocol-conductor/tests/nested_arrow_proxy.rs +++ b/src/agent-client-protocol-conductor/tests/nested_arrow_proxy.rs @@ -22,8 +22,8 @@ use tokio::io::duplex; use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; #[tokio::test] -async fn test_conductor_with_two_external_arrow_proxies() --> Result<(), agent_client_protocol_core::Error> { +async fn test_conductor_with_two_external_arrow_proxies() -> Result<(), agent_client_protocol::Error> +{ // Create the component chain: arrow_proxy1 -> arrow_proxy2 -> test_agent // Uses pre-built binaries to avoid cargo run races during `cargo test --all` let arrow_proxy1 = AcpAgent::from_args([arrow_proxy_example().to_string_lossy().to_string()])?; @@ -43,7 +43,7 @@ async fn test_conductor_with_two_external_arrow_proxies() .proxy(arrow_proxy2), McpBridgeMode::default(), ) - .run(agent_client_protocol_core::ByteStreams::new( + .run(agent_client_protocol::ByteStreams::new( conductor_write.compat_write(), conductor_read.compat(), )) @@ -53,7 +53,7 @@ async fn test_conductor_with_two_external_arrow_proxies() // Wait for editor to complete and get the result let result = tokio::time::timeout(std::time::Duration::from_secs(30), async move { let result = yopo::prompt( - agent_client_protocol_core::ByteStreams::new( + agent_client_protocol::ByteStreams::new( editor_write.compat_write(), editor_read.compat(), ), @@ -66,7 +66,7 @@ async fn test_conductor_with_two_external_arrow_proxies() "#]] .assert_debug_eq(&result); - Ok::(result) + Ok::(result) }) .await .expect("Test timed out") diff --git a/src/agent-client-protocol-conductor/tests/nested_conductor.rs b/src/agent-client-protocol-conductor/tests/nested_conductor.rs index 1a53620..2d03436 100644 --- a/src/agent-client-protocol-conductor/tests/nested_conductor.rs +++ b/src/agent-client-protocol-conductor/tests/nested_conductor.rs @@ -19,8 +19,8 @@ //! //! Run `just prep-tests` before running these tests. +use agent_client_protocol::{Conductor, ConnectTo, DynConnectTo}; use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; -use agent_client_protocol_core::{Conductor, ConnectTo, DynConnectTo}; use agent_client_protocol_test::arrow_proxy::run_arrow_proxy; use agent_client_protocol_test::test_binaries::{arrow_proxy_example, conductor_binary, testy}; use agent_client_protocol_test::testy::{Testy, TestyCommand}; @@ -35,8 +35,8 @@ struct MockArrowProxy; impl ConnectTo for MockArrowProxy { async fn connect_to( self, - client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + client: impl ConnectTo, + ) -> Result<(), agent_client_protocol::Error> { run_arrow_proxy(client).await } } @@ -56,8 +56,8 @@ impl MockInnerConductor { impl ConnectTo for MockInnerConductor { async fn connect_to( self, - client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + client: impl ConnectTo, + ) -> Result<(), agent_client_protocol::Error> { // Create mock arrow proxy components for the inner conductor // This conductor is ONLY proxies - no actual agent // Use Serve::serve instead of .run() to get the Serve impl @@ -79,8 +79,7 @@ impl ConnectTo for MockInnerConductor { } #[tokio::test] -async fn test_nested_conductor_with_arrow_proxies() -> Result<(), agent_client_protocol_core::Error> -{ +async fn test_nested_conductor_with_arrow_proxies() -> Result<(), agent_client_protocol::Error> { // Create the nested component chain using mock components // Inner conductor will manage: arrow_proxy1 -> arrow_proxy2 -> eliza // Outer conductor will manage: inner_conductor only @@ -96,7 +95,7 @@ async fn test_nested_conductor_with_arrow_proxies() -> Result<(), agent_client_p ProxiesAndAgent::new(Testy::new()).proxy(MockInnerConductor::new(2)), McpBridgeMode::default(), ) - .run(agent_client_protocol_core::ByteStreams::new( + .run(agent_client_protocol::ByteStreams::new( conductor_write.compat_write(), conductor_read.compat(), )) @@ -106,7 +105,7 @@ async fn test_nested_conductor_with_arrow_proxies() -> Result<(), agent_client_p // Wait for editor to complete and get the result let result = tokio::time::timeout(std::time::Duration::from_secs(30), async move { let result = yopo::prompt( - agent_client_protocol_core::ByteStreams::new( + agent_client_protocol::ByteStreams::new( editor_write.compat_write(), editor_read.compat(), ), @@ -121,7 +120,7 @@ async fn test_nested_conductor_with_arrow_proxies() -> Result<(), agent_client_p "#]] .assert_debug_eq(&result); - Ok::(result) + Ok::(result) }) .await .expect("Test timed out") @@ -139,7 +138,7 @@ async fn test_nested_conductor_with_arrow_proxies() -> Result<(), agent_client_p #[tokio::test] async fn test_nested_conductor_with_external_arrow_proxies() --> Result<(), agent_client_protocol_core::Error> { +-> Result<(), agent_client_protocol::Error> { // Create the nested component chain using external processes // Inner conductor spawned as a separate process with two arrow proxies // Outer conductor manages: inner_conductor -> test agent (both as external processes) @@ -165,7 +164,7 @@ async fn test_nested_conductor_with_external_arrow_proxies() ProxiesAndAgent::new(agent).proxy(inner_conductor), McpBridgeMode::default(), ) - .run(agent_client_protocol_core::ByteStreams::new( + .run(agent_client_protocol::ByteStreams::new( conductor_write.compat_write(), conductor_read.compat(), )) @@ -175,7 +174,7 @@ async fn test_nested_conductor_with_external_arrow_proxies() // Wait for editor to complete and get the result let result = tokio::time::timeout(std::time::Duration::from_secs(30), async move { let result = yopo::prompt( - agent_client_protocol_core::ByteStreams::new( + agent_client_protocol::ByteStreams::new( editor_write.compat_write(), editor_read.compat(), ), @@ -190,7 +189,7 @@ async fn test_nested_conductor_with_external_arrow_proxies() "#]] .assert_debug_eq(&result); - Ok::(result) + Ok::(result) }) .await .expect("Test timed out") diff --git a/src/agent-client-protocol-conductor/tests/scoped_mcp_server.rs b/src/agent-client-protocol-conductor/tests/scoped_mcp_server.rs index dc2836a..adb1f07 100644 --- a/src/agent-client-protocol-conductor/tests/scoped_mcp_server.rs +++ b/src/agent-client-protocol-conductor/tests/scoped_mcp_server.rs @@ -4,9 +4,9 @@ //! can capture references to stack-local data (like a Vec) and push to it //! when the tool is invoked. +use agent_client_protocol::mcp_server::McpServer; +use agent_client_protocol::{Agent, Conductor, ConnectTo, Proxy, Role, RunWithConnectionTo}; use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; -use agent_client_protocol_core::mcp_server::McpServer; -use agent_client_protocol_core::{Agent, Conductor, ConnectTo, Proxy, Role, RunWithConnectionTo}; use agent_client_protocol_test::testy::{Testy, TestyCommand}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -17,7 +17,7 @@ use std::sync::Mutex; /// This validates the scoped lifetime feature - the tool closure captures /// a reference to `collected_values` which lives on the stack. #[tokio::test] -async fn test_scoped_mcp_server_through_proxy() -> Result<(), agent_client_protocol_core::Error> { +async fn test_scoped_mcp_server_through_proxy() -> Result<(), agent_client_protocol::Error> { let conductor = ConductorImpl::new_agent( "conductor".to_string(), ProxiesAndAgent::new(Testy::new()).proxy(ScopedProxy), @@ -48,9 +48,9 @@ async fn test_scoped_mcp_server_through_proxy() -> Result<(), agent_client_proto /// The MCP server captures a reference to stack-local data that lives for /// the duration of the session. #[tokio::test] -async fn test_scoped_mcp_server_through_session() -> Result<(), agent_client_protocol_core::Error> { +async fn test_scoped_mcp_server_through_session() -> Result<(), agent_client_protocol::Error> { // Run the client - agent_client_protocol_core::Client.builder() + agent_client_protocol::Client.builder() .connect_with( ConductorImpl::new_agent( "conductor".to_string(), @@ -59,8 +59,8 @@ async fn test_scoped_mcp_server_through_session() -> Result<(), agent_client_pro ), async |cx| { // Initialize first - cx.send_request(agent_client_protocol_core::schema::InitializeRequest::new( - agent_client_protocol_core::schema::ProtocolVersion::LATEST, + cx.send_request(agent_client_protocol::schema::InitializeRequest::new( + agent_client_protocol::schema::ProtocolVersion::LATEST, )) .block_task() .await?; @@ -113,7 +113,7 @@ fn make_mcp_server( values.extend(input.elements); Ok(values.len()) }, - agent_client_protocol_core::tool_fn_mut!(), + agent_client_protocol::tool_fn_mut!(), ) .tool_fn_mut( "get", @@ -122,7 +122,7 @@ fn make_mcp_server( let values = values.lock().expect("not poisoned"); Ok(values.clone()) }, - agent_client_protocol_core::tool_fn_mut!(), + agent_client_protocol::tool_fn_mut!(), ) .build() } @@ -131,12 +131,12 @@ impl ConnectTo for ScopedProxy { async fn connect_to( self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { // Stack-local data that the MCP tool will push to let values: Mutex> = Mutex::new(Vec::new()); // Build the MCP server that captures a reference to collected_values - let mcp_server = make_mcp_server::(&values); + let mcp_server = make_mcp_server::(&values); Proxy .builder() diff --git a/src/agent-client-protocol-conductor/tests/standalone_mcp_server.rs b/src/agent-client-protocol-conductor/tests/standalone_mcp_server.rs index 77a7b90..4501c97 100644 --- a/src/agent-client-protocol-conductor/tests/standalone_mcp_server.rs +++ b/src/agent-client-protocol-conductor/tests/standalone_mcp_server.rs @@ -3,7 +3,7 @@ //! These tests verify that `McpServer` can be used directly with MCP clients //! via the `Component` implementation. -use agent_client_protocol_core::{ +use agent_client_protocol::{ ByteStreams, ConnectTo, RunWithConnectionTo, mcp_server::McpServer, role::mcp, util::run_until, }; use rmcp::{ClientHandler, ServiceExt, model::ClientInfo}; @@ -38,7 +38,7 @@ fn create_test_server() -> McpServer McpServer Result<(), agent_client_protocol_core::Error> { +async fn test_standalone_server_list_tools() -> Result<(), agent_client_protocol::Error> { // Create duplex streams for communication let (server_stream, client_stream) = tokio::io::duplex(8192); let (server_read, server_write) = tokio::io::split(server_stream); @@ -83,13 +83,13 @@ async fn test_standalone_server_list_tools() -> Result<(), agent_client_protocol let client = MinimalClientHandler .serve((server_read, server_write)) .await - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; // List tools let tools_result = client .list_tools(None) .await - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; // Verify we got both tools assert_eq!(tools_result.tools.len(), 2); @@ -103,7 +103,7 @@ async fn test_standalone_server_list_tools() -> Result<(), agent_client_protocol client .cancel() .await - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; Ok(()) }, ) @@ -111,7 +111,7 @@ async fn test_standalone_server_list_tools() -> Result<(), agent_client_protocol } #[tokio::test] -async fn test_standalone_server_call_echo_tool() -> Result<(), agent_client_protocol_core::Error> { +async fn test_standalone_server_call_echo_tool() -> Result<(), agent_client_protocol::Error> { let (server_stream, client_stream) = tokio::io::duplex(8192); let (server_read, server_write) = tokio::io::split(server_stream); let (client_read, client_write) = tokio::io::split(client_stream); @@ -125,7 +125,7 @@ async fn test_standalone_server_call_echo_tool() -> Result<(), agent_client_prot let client = MinimalClientHandler .serve((server_read, server_write)) .await - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; // Call the echo tool let result = client @@ -138,7 +138,7 @@ async fn test_standalone_server_call_echo_tool() -> Result<(), agent_client_prot ), ) .await - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; // Verify the result let text = result @@ -153,7 +153,7 @@ async fn test_standalone_server_call_echo_tool() -> Result<(), agent_client_prot client .cancel() .await - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; Ok(()) }, ) @@ -161,7 +161,7 @@ async fn test_standalone_server_call_echo_tool() -> Result<(), agent_client_prot } #[tokio::test] -async fn test_standalone_server_call_add_tool() -> Result<(), agent_client_protocol_core::Error> { +async fn test_standalone_server_call_add_tool() -> Result<(), agent_client_protocol::Error> { let (server_stream, client_stream) = tokio::io::duplex(8192); let (server_read, server_write) = tokio::io::split(server_stream); let (client_read, client_write) = tokio::io::split(client_stream); @@ -175,7 +175,7 @@ async fn test_standalone_server_call_add_tool() -> Result<(), agent_client_proto let client = MinimalClientHandler .serve((server_read, server_write)) .await - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; // Call the add tool let result = client @@ -188,7 +188,7 @@ async fn test_standalone_server_call_add_tool() -> Result<(), agent_client_proto ), ) .await - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; // The add tool returns structured output (AddOutput) // Check that we get the expected result @@ -206,7 +206,7 @@ async fn test_standalone_server_call_add_tool() -> Result<(), agent_client_proto client .cancel() .await - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; Ok(()) }, ) @@ -214,7 +214,7 @@ async fn test_standalone_server_call_add_tool() -> Result<(), agent_client_proto } #[tokio::test] -async fn test_standalone_server_tool_not_found() -> Result<(), agent_client_protocol_core::Error> { +async fn test_standalone_server_tool_not_found() -> Result<(), agent_client_protocol::Error> { let (server_stream, client_stream) = tokio::io::duplex(8192); let (server_read, server_write) = tokio::io::split(server_stream); let (client_read, client_write) = tokio::io::split(client_stream); @@ -228,7 +228,7 @@ async fn test_standalone_server_tool_not_found() -> Result<(), agent_client_prot let client = MinimalClientHandler .serve((server_read, server_write)) .await - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; // Call a non-existent tool let result = client @@ -241,7 +241,7 @@ async fn test_standalone_server_tool_not_found() -> Result<(), agent_client_prot client .cancel() .await - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; Ok(()) }, ) @@ -249,8 +249,7 @@ async fn test_standalone_server_tool_not_found() -> Result<(), agent_client_prot } #[tokio::test] -async fn test_standalone_server_with_disabled_tools() --> Result<(), agent_client_protocol_core::Error> { +async fn test_standalone_server_with_disabled_tools() -> Result<(), agent_client_protocol::Error> { let (server_stream, client_stream) = tokio::io::duplex(8192); let (server_read, server_write) = tokio::io::split(server_stream); let (client_read, client_write) = tokio::io::split(client_stream); @@ -261,7 +260,7 @@ async fn test_standalone_server_with_disabled_tools() "echo", "Echo a message", async |input: EchoInput, _cx| Ok(format!("Echo: {}", input.message)), - agent_client_protocol_core::tool_fn!(), + agent_client_protocol::tool_fn!(), ) .tool_fn( "add", @@ -271,7 +270,7 @@ async fn test_standalone_server_with_disabled_tools() result: input.a + input.b, }) }, - agent_client_protocol_core::tool_fn!(), + agent_client_protocol::tool_fn!(), ) .disable_tool("echo")? .build(); @@ -284,13 +283,13 @@ async fn test_standalone_server_with_disabled_tools() let client = MinimalClientHandler .serve((server_read, server_write)) .await - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; // List tools - should only show "add" let tools_result = client .list_tools(None) .await - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; assert_eq!(tools_result.tools.len(), 1); assert_eq!(tools_result.tools[0].name.as_ref(), "add"); @@ -311,7 +310,7 @@ async fn test_standalone_server_with_disabled_tools() client .cancel() .await - .map_err(agent_client_protocol_core::util::internal_error)?; + .map_err(agent_client_protocol::util::internal_error)?; Ok(()) }, ) diff --git a/src/agent-client-protocol-conductor/tests/test_mcp_tool_output_types.rs b/src/agent-client-protocol-conductor/tests/test_mcp_tool_output_types.rs index 54c3846..5b65118 100644 --- a/src/agent-client-protocol-conductor/tests/test_mcp_tool_output_types.rs +++ b/src/agent-client-protocol-conductor/tests/test_mcp_tool_output_types.rs @@ -3,9 +3,9 @@ //! MCP structured output requires JSON objects. This test verifies behavior //! when tools return non-object types like bare strings or integers. +use agent_client_protocol::mcp_server::McpServer; +use agent_client_protocol::{Conductor, ConnectTo, DynConnectTo, Proxy, RunWithConnectionTo}; use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; -use agent_client_protocol_core::mcp_server::McpServer; -use agent_client_protocol_core::{Conductor, ConnectTo, DynConnectTo, Proxy, RunWithConnectionTo}; use agent_client_protocol_test::testy::{Testy, TestyCommand}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -22,13 +22,13 @@ fn create_test_proxy() -> DynConnectTo { "return_string", "Returns a bare string", async |_input: EmptyInput, _context| Ok("hello world".to_string()), - agent_client_protocol_core::tool_fn_mut!(), + agent_client_protocol::tool_fn_mut!(), ) .tool_fn_mut( "return_integer", "Returns a bare integer", async |_input: EmptyInput, _context| Ok(42i32), - agent_client_protocol_core::tool_fn_mut!(), + agent_client_protocol::tool_fn_mut!(), ) .build(); @@ -45,8 +45,8 @@ impl + 'static + Send> ConnectTo async fn connect_to( self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { - agent_client_protocol_core::Proxy + ) -> Result<(), agent_client_protocol::Error> { + agent_client_protocol::Proxy .builder() .name("test-proxy") .with_mcp_server(self.mcp_server) @@ -56,7 +56,7 @@ impl + 'static + Send> ConnectTo } #[tokio::test] -async fn test_tool_returning_string() -> Result<(), agent_client_protocol_core::Error> { +async fn test_tool_returning_string() -> Result<(), agent_client_protocol::Error> { let result = yopo::prompt( ConductorImpl::new_agent( "test-conductor".to_string(), @@ -82,7 +82,7 @@ async fn test_tool_returning_string() -> Result<(), agent_client_protocol_core:: } #[tokio::test] -async fn test_tool_returning_integer() -> Result<(), agent_client_protocol_core::Error> { +async fn test_tool_returning_integer() -> Result<(), agent_client_protocol::Error> { let result = yopo::prompt( ConductorImpl::new_agent( "test-conductor".to_string(), diff --git a/src/agent-client-protocol-conductor/tests/test_session_id_in_mcp_tools.rs b/src/agent-client-protocol-conductor/tests/test_session_id_in_mcp_tools.rs index dc464fb..27682fa 100644 --- a/src/agent-client-protocol-conductor/tests/test_session_id_in_mcp_tools.rs +++ b/src/agent-client-protocol-conductor/tests/test_session_id_in_mcp_tools.rs @@ -8,10 +8,10 @@ //! 5. The tool returns the session_id in its response //! 6. We verify the session_ids match +use agent_client_protocol::RunWithConnectionTo; +use agent_client_protocol::mcp_server::McpServer; +use agent_client_protocol::{Conductor, ConnectTo, DynConnectTo, Proxy}; use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; -use agent_client_protocol_core::RunWithConnectionTo; -use agent_client_protocol_core::mcp_server::McpServer; -use agent_client_protocol_core::{Conductor, ConnectTo, DynConnectTo, Proxy}; use agent_client_protocol_test::testy::{Testy, TestyCommand}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -39,7 +39,7 @@ fn create_echo_proxy() -> DynConnectTo { acp_url: context.acp_url(), }) }, - agent_client_protocol_core::tool_fn_mut!(), + agent_client_protocol::tool_fn_mut!(), ) .build(); @@ -57,8 +57,8 @@ impl + 'static + Send> ConnectTo async fn connect_to( self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { - agent_client_protocol_core::Proxy + ) -> Result<(), agent_client_protocol::Error> { + agent_client_protocol::Proxy .builder() .name("echo-proxy") .with_mcp_server(self.mcp_server) @@ -68,7 +68,7 @@ impl + 'static + Send> ConnectTo } #[tokio::test] -async fn test_list_tools_from_mcp_server() -> Result<(), agent_client_protocol_core::Error> { +async fn test_list_tools_from_mcp_server() -> Result<(), agent_client_protocol::Error> { use expect_test::expect; let result = yopo::prompt( @@ -94,7 +94,7 @@ async fn test_list_tools_from_mcp_server() -> Result<(), agent_client_protocol_c } #[tokio::test] -async fn test_session_id_delivered_to_mcp_tools() -> Result<(), agent_client_protocol_core::Error> { +async fn test_session_id_delivered_to_mcp_tools() -> Result<(), agent_client_protocol::Error> { let result = yopo::prompt( ConductorImpl::new_agent( "test-conductor".to_string(), diff --git a/src/agent-client-protocol-conductor/tests/test_tool_enable_disable.rs b/src/agent-client-protocol-conductor/tests/test_tool_enable_disable.rs index 60d8ac1..cb1b865 100644 --- a/src/agent-client-protocol-conductor/tests/test_tool_enable_disable.rs +++ b/src/agent-client-protocol-conductor/tests/test_tool_enable_disable.rs @@ -3,9 +3,9 @@ //! These tests verify that `disable_tool`, `enable_tool`, `disable_all_tools`, //! and `enable_all_tools` correctly filter which tools are visible and callable. +use agent_client_protocol::mcp_server::McpServer; +use agent_client_protocol::{Conductor, ConnectTo, DynConnectTo, Proxy, RunWithConnectionTo}; use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; -use agent_client_protocol_core::mcp_server::McpServer; -use agent_client_protocol_core::{Conductor, ConnectTo, DynConnectTo, Proxy, RunWithConnectionTo}; use agent_client_protocol_test::testy::{Testy, TestyCommand}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -27,27 +27,27 @@ struct GreetInput { struct EmptyInput {} /// Create a proxy with multiple tools, some disabled via deny-list -fn create_proxy_with_disabled_tool() --> Result, agent_client_protocol_core::Error> { +fn create_proxy_with_disabled_tool() -> Result, agent_client_protocol::Error> +{ let mcp_server = McpServer::builder("test_server".to_string()) .instructions("Test MCP server with some disabled tools") .tool_fn( "echo", "Echo a message back", async |input: EchoInput, _context| Ok(format!("Echo: {}", input.message)), - agent_client_protocol_core::tool_fn!(), + agent_client_protocol::tool_fn!(), ) .tool_fn( "greet", "Greet someone by name", async |input: GreetInput, _context| Ok(format!("Hello, {}!", input.name)), - agent_client_protocol_core::tool_fn!(), + agent_client_protocol::tool_fn!(), ) .tool_fn( "secret", "A secret tool that should be disabled", async |_input: EmptyInput, _context| Ok("This is secret!".to_string()), - agent_client_protocol_core::tool_fn!(), + agent_client_protocol::tool_fn!(), ) .disable_tool("secret")? .build(); @@ -56,27 +56,26 @@ fn create_proxy_with_disabled_tool() } /// Create a proxy where all tools are disabled except specific ones (allow-list) -fn create_proxy_with_allowlist() --> Result, agent_client_protocol_core::Error> { +fn create_proxy_with_allowlist() -> Result, agent_client_protocol::Error> { let mcp_server = McpServer::builder("allowlist_server".to_string()) .instructions("Test MCP server with allow-list") .tool_fn( "echo", "Echo a message back", async |input: EchoInput, _context| Ok(format!("Echo: {}", input.message)), - agent_client_protocol_core::tool_fn!(), + agent_client_protocol::tool_fn!(), ) .tool_fn( "greet", "Greet someone by name", async |input: GreetInput, _context| Ok(format!("Hello, {}!", input.name)), - agent_client_protocol_core::tool_fn!(), + agent_client_protocol::tool_fn!(), ) .tool_fn( "secret", "A secret tool", async |_input: EmptyInput, _context| Ok("This is secret!".to_string()), - agent_client_protocol_core::tool_fn!(), + agent_client_protocol::tool_fn!(), ) .disable_all_tools() .enable_tool("echo")? @@ -93,8 +92,8 @@ impl + 'static + Send> ConnectTo fo async fn connect_to( self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { - agent_client_protocol_core::Proxy + ) -> Result<(), agent_client_protocol::Error> { + agent_client_protocol::Proxy .builder() .name("test-proxy") .with_mcp_server(self.mcp_server) @@ -108,7 +107,7 @@ impl + 'static + Send> ConnectTo fo // ============================================================================ #[tokio::test] -async fn test_list_tools_excludes_disabled() -> Result<(), agent_client_protocol_core::Error> { +async fn test_list_tools_excludes_disabled() -> Result<(), agent_client_protocol::Error> { let result = yopo::prompt( ConductorImpl::new_agent( "test-conductor".to_string(), @@ -134,7 +133,7 @@ async fn test_list_tools_excludes_disabled() -> Result<(), agent_client_protocol } #[tokio::test] -async fn test_enabled_tool_can_be_called() -> Result<(), agent_client_protocol_core::Error> { +async fn test_enabled_tool_can_be_called() -> Result<(), agent_client_protocol::Error> { let result = yopo::prompt( ConductorImpl::new_agent( "test-conductor".to_string(), @@ -159,7 +158,7 @@ async fn test_enabled_tool_can_be_called() -> Result<(), agent_client_protocol_c } #[tokio::test] -async fn test_disabled_tool_returns_not_found() -> Result<(), agent_client_protocol_core::Error> { +async fn test_disabled_tool_returns_not_found() -> Result<(), agent_client_protocol::Error> { let result = yopo::prompt( ConductorImpl::new_agent( "test-conductor".to_string(), @@ -189,8 +188,7 @@ async fn test_disabled_tool_returns_not_found() -> Result<(), agent_client_proto // ============================================================================ #[tokio::test] -async fn test_allowlist_only_shows_enabled_tools() -> Result<(), agent_client_protocol_core::Error> -{ +async fn test_allowlist_only_shows_enabled_tools() -> Result<(), agent_client_protocol::Error> { let result = yopo::prompt( ConductorImpl::new_agent( "test-conductor".to_string(), @@ -219,7 +217,7 @@ async fn test_allowlist_only_shows_enabled_tools() -> Result<(), agent_client_pr } #[tokio::test] -async fn test_allowlist_enabled_tool_works() -> Result<(), agent_client_protocol_core::Error> { +async fn test_allowlist_enabled_tool_works() -> Result<(), agent_client_protocol::Error> { let result = yopo::prompt( ConductorImpl::new_agent( "test-conductor".to_string(), @@ -245,7 +243,7 @@ async fn test_allowlist_enabled_tool_works() -> Result<(), agent_client_protocol #[tokio::test] async fn test_allowlist_non_enabled_tool_returns_not_found() --> Result<(), agent_client_protocol_core::Error> { +-> Result<(), agent_client_protocol::Error> { let result = yopo::prompt( ConductorImpl::new_agent( "test-conductor".to_string(), diff --git a/src/agent-client-protocol-conductor/tests/test_tool_fn.rs b/src/agent-client-protocol-conductor/tests/test_tool_fn.rs index e74fd7e..b0fbb43 100644 --- a/src/agent-client-protocol-conductor/tests/test_tool_fn.rs +++ b/src/agent-client-protocol-conductor/tests/test_tool_fn.rs @@ -3,9 +3,9 @@ //! This test verifies that `tool_fn` works correctly for stateless tools //! that don't need mutable state. +use agent_client_protocol::mcp_server::McpServer; +use agent_client_protocol::{Conductor, ConnectTo, DynConnectTo, Proxy, RunWithConnectionTo}; use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; -use agent_client_protocol_core::mcp_server::McpServer; -use agent_client_protocol_core::{Conductor, ConnectTo, DynConnectTo, Proxy, RunWithConnectionTo}; use agent_client_protocol_test::testy::{Testy, TestyCommand}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -25,7 +25,7 @@ fn create_greet_proxy() -> DynConnectTo { "greet", "Greet someone by name", async |input: GreetInput, _context| Ok(format!("Hello, {}!", input.name)), - agent_client_protocol_core::tool_fn!(), + agent_client_protocol::tool_fn!(), ) .build(); @@ -43,7 +43,7 @@ impl + 'static + Send> ConnectTo async fn connect_to( self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { Proxy .builder() .name("greet-proxy") @@ -54,7 +54,7 @@ impl + 'static + Send> ConnectTo } #[tokio::test] -async fn test_tool_fn_greet() -> Result<(), agent_client_protocol_core::Error> { +async fn test_tool_fn_greet() -> Result<(), agent_client_protocol::Error> { let result = yopo::prompt( ConductorImpl::new_agent( "test-conductor".to_string(), diff --git a/src/agent-client-protocol-conductor/tests/test_util.rs b/src/agent-client-protocol-conductor/tests/test_util.rs index cde9f65..af519e1 100644 --- a/src/agent-client-protocol-conductor/tests/test_util.rs +++ b/src/agent-client-protocol-conductor/tests/test_util.rs @@ -8,9 +8,11 @@ pub fn init_test_tracing() { drop( fmt() - .with_env_filter(EnvFilter::try_from_default_env().unwrap_or_else(|_| { - EnvFilter::new("trace,agent_client_protocol_core::jsonrpc=trace") - })) + .with_env_filter( + EnvFilter::try_from_default_env().unwrap_or_else(|_| { + EnvFilter::new("trace,agent_client_protocol::jsonrpc=trace") + }), + ) .with_test_writer() .try_init(), ); diff --git a/src/agent-client-protocol-conductor/tests/trace_client_mcp_server.rs b/src/agent-client-protocol-conductor/tests/trace_client_mcp_server.rs index 77527c1..753f91c 100644 --- a/src/agent-client-protocol-conductor/tests/trace_client_mcp_server.rs +++ b/src/agent-client-protocol-conductor/tests/trace_client_mcp_server.rs @@ -9,11 +9,11 @@ //! Unlike trace_mcp_tool_call.rs which tests proxy-hosted MCP servers, this test //! verifies that MCP requests travel all the way back to the client. +use agent_client_protocol::mcp_server::McpServer; +use agent_client_protocol::schema::{InitializeRequest, ProtocolVersion}; +use agent_client_protocol::{Client, Role, RunWithConnectionTo}; use agent_client_protocol_conductor::trace::TraceEvent; use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; -use agent_client_protocol_core::mcp_server::McpServer; -use agent_client_protocol_core::schema::{InitializeRequest, ProtocolVersion}; -use agent_client_protocol_core::{Client, Role, RunWithConnectionTo}; use agent_client_protocol_test::testy::{Testy, TestyCommand}; use expect_test::expect; use futures::StreamExt; @@ -211,13 +211,13 @@ fn make_echo_mcp_server( call_number: *count, }) }, - agent_client_protocol_core::tool_fn_mut!(), + agent_client_protocol::tool_fn_mut!(), ) .build() } #[tokio::test] -async fn test_trace_client_mcp_server() -> Result<(), agent_client_protocol_core::Error> { +async fn test_trace_client_mcp_server() -> Result<(), agent_client_protocol::Error> { // Create channel for collecting trace events let (trace_tx, trace_rx) = mpsc::unbounded(); @@ -233,7 +233,7 @@ async fn test_trace_client_mcp_server() -> Result<(), agent_client_protocol_core McpBridgeMode::default(), ) .trace_to(trace_tx) - .run(agent_client_protocol_core::ByteStreams::new( + .run(agent_client_protocol::ByteStreams::new( conductor_write.compat_write(), conductor_read.compat(), )) @@ -242,11 +242,11 @@ async fn test_trace_client_mcp_server() -> Result<(), agent_client_protocol_core // Run the client with a client-hosted MCP server let test_result = tokio::time::timeout(std::time::Duration::from_secs(30), async move { - agent_client_protocol_core::Client + agent_client_protocol::Client .builder() .name("test-client") .connect_with( - agent_client_protocol_core::ByteStreams::new( + agent_client_protocol::ByteStreams::new( client_write.compat_write(), client_read.compat(), ), diff --git a/src/agent-client-protocol-conductor/tests/trace_generation.rs b/src/agent-client-protocol-conductor/tests/trace_generation.rs index 6b93d22..3c2a284 100644 --- a/src/agent-client-protocol-conductor/tests/trace_generation.rs +++ b/src/agent-client-protocol-conductor/tests/trace_generation.rs @@ -15,7 +15,7 @@ use tokio::io::duplex; use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; #[tokio::test] -async fn test_trace_generation() -> Result<(), agent_client_protocol_core::Error> { +async fn test_trace_generation() -> Result<(), agent_client_protocol::Error> { // Enable tracing if RUST_LOG is set drop( tracing_subscriber::fmt() @@ -47,7 +47,7 @@ async fn test_trace_generation() -> Result<(), agent_client_protocol_core::Error ) .trace_to_path(&trace_path_clone) .expect("Failed to create trace writer") - .run(agent_client_protocol_core::ByteStreams::new( + .run(agent_client_protocol::ByteStreams::new( conductor_write.compat_write(), conductor_read.compat(), )) @@ -57,7 +57,7 @@ async fn test_trace_generation() -> Result<(), agent_client_protocol_core::Error // Run a simple prompt through the conductor let result = tokio::time::timeout(std::time::Duration::from_secs(30), async move { let result = yopo::prompt( - agent_client_protocol_core::ByteStreams::new( + agent_client_protocol::ByteStreams::new( editor_write.compat_write(), editor_read.compat(), ), @@ -65,7 +65,7 @@ async fn test_trace_generation() -> Result<(), agent_client_protocol_core::Error ) .await?; - Ok::(result) + Ok::(result) }) .await .expect("Test timed out") diff --git a/src/agent-client-protocol-conductor/tests/trace_mcp_tool_call.rs b/src/agent-client-protocol-conductor/tests/trace_mcp_tool_call.rs index f2ea4af..f8ffc4c 100644 --- a/src/agent-client-protocol-conductor/tests/trace_mcp_tool_call.rs +++ b/src/agent-client-protocol-conductor/tests/trace_mcp_tool_call.rs @@ -10,12 +10,12 @@ mod mcp_integration; -use agent_client_protocol_conductor::trace::TraceEvent; -use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; -use agent_client_protocol_core::schema::{ +use agent_client_protocol::schema::{ ContentBlock, InitializeRequest, NewSessionRequest, PromptRequest, ProtocolVersion, SessionNotification, TextContent, }; +use agent_client_protocol_conductor::trace::TraceEvent; +use agent_client_protocol_conductor::{ConductorImpl, McpBridgeMode, ProxiesAndAgent}; use agent_client_protocol_test::testy::{Testy, TestyCommand}; use expect_test::expect; use futures::channel::mpsc; @@ -183,20 +183,20 @@ impl EventNormalizer { } /// Test helper to receive a JSON-RPC response -async fn recv( - response: agent_client_protocol_core::SentRequest, -) -> Result { +async fn recv( + response: agent_client_protocol::SentRequest, +) -> Result { let (tx, rx) = tokio::sync::oneshot::channel(); response.on_receiving_result(async move |result| { tx.send(result) - .map_err(|_| agent_client_protocol_core::Error::internal_error()) + .map_err(|_| agent_client_protocol::Error::internal_error()) })?; rx.await - .map_err(|_| agent_client_protocol_core::Error::internal_error())? + .map_err(|_| agent_client_protocol::Error::internal_error())? } #[tokio::test] -async fn test_trace_mcp_tool_call() -> Result<(), agent_client_protocol_core::Error> { +async fn test_trace_mcp_tool_call() -> Result<(), agent_client_protocol::Error> { // Create channel for collecting trace events let (trace_tx, trace_rx) = mpsc::unbounded(); @@ -218,7 +218,7 @@ async fn test_trace_mcp_tool_call() -> Result<(), agent_client_protocol_core::Er McpBridgeMode::default(), ) .trace_to(trace_tx) - .run(agent_client_protocol_core::ByteStreams::new( + .run(agent_client_protocol::ByteStreams::new( conductor_write.compat_write(), conductor_read.compat(), )) @@ -227,7 +227,7 @@ async fn test_trace_mcp_tool_call() -> Result<(), agent_client_protocol_core::Er // Run the client interaction let test_result = tokio::time::timeout(std::time::Duration::from_secs(30), async move { - agent_client_protocol_core::Client + agent_client_protocol::Client .builder() .name("test-client") .on_receive_notification( @@ -237,13 +237,13 @@ async fn test_trace_mcp_tool_call() -> Result<(), agent_client_protocol_core::Er notif_tx .send(notification) .await - .map_err(|_| agent_client_protocol_core::Error::internal_error()) + .map_err(|_| agent_client_protocol::Error::internal_error()) } }, - agent_client_protocol_core::on_receive_notification!(), + agent_client_protocol::on_receive_notification!(), ) .connect_with( - agent_client_protocol_core::ByteStreams::new( + agent_client_protocol::ByteStreams::new( client_write.compat_write(), client_read.compat(), ), diff --git a/src/agent-client-protocol-conductor/tests/trace_snapshot.rs b/src/agent-client-protocol-conductor/tests/trace_snapshot.rs index 5c90706..f59c0f3 100644 --- a/src/agent-client-protocol-conductor/tests/trace_snapshot.rs +++ b/src/agent-client-protocol-conductor/tests/trace_snapshot.rs @@ -128,7 +128,7 @@ impl EventNormalizer { } #[tokio::test] -async fn test_trace_snapshot() -> Result<(), agent_client_protocol_core::Error> { +async fn test_trace_snapshot() -> Result<(), agent_client_protocol::Error> { // Create channel for collecting trace events let (tx, rx) = mpsc::unbounded(); @@ -150,7 +150,7 @@ async fn test_trace_snapshot() -> Result<(), agent_client_protocol_core::Error> McpBridgeMode::default(), ) .trace_to(tx) - .run(agent_client_protocol_core::ByteStreams::new( + .run(agent_client_protocol::ByteStreams::new( conductor_write.compat_write(), conductor_read.compat(), )) @@ -160,7 +160,7 @@ async fn test_trace_snapshot() -> Result<(), agent_client_protocol_core::Error> // Run a simple prompt through the conductor let result = tokio::time::timeout(std::time::Duration::from_secs(30), async move { yopo::prompt( - agent_client_protocol_core::ByteStreams::new( + agent_client_protocol::ByteStreams::new( editor_write.compat_write(), editor_read.compat(), ), diff --git a/src/agent-client-protocol-cookbook/Cargo.toml b/src/agent-client-protocol-cookbook/Cargo.toml index ef2a3aa..2bdfdf4 100644 --- a/src/agent-client-protocol-cookbook/Cargo.toml +++ b/src/agent-client-protocol-cookbook/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "agent-client-protocol-cookbook" -version = "0.1.0" +version = "0.11.0" edition.workspace = true authors.workspace = true license.workspace = true @@ -12,7 +12,7 @@ categories = ["development-tools"] [dependencies] agent-client-protocol-conductor.workspace = true -agent-client-protocol-core.workspace = true +agent-client-protocol.workspace = true agent-client-protocol-rmcp.workspace = true agent-client-protocol-tokio.workspace = true rmcp.workspace = true diff --git a/src/agent-client-protocol-cookbook/src/lib.rs b/src/agent-client-protocol-cookbook/src/lib.rs index fc3be1f..9308d7c 100644 --- a/src/agent-client-protocol-cookbook/src/lib.rs +++ b/src/agent-client-protocol-cookbook/src/lib.rs @@ -6,13 +6,13 @@ //! - **Proxies** - Sit between client and agent to add capabilities (like MCP tools) //! - **Agents** - Respond to prompts with AI-powered responses //! -//! See the [`agent_client_protocol_core::concepts`] module for detailed explanations of +//! See the [`agent_client_protocol::concepts`] module for detailed explanations of //! the concepts behind the API. //! //! # Building Clients //! //! A client connects to an agent, sends requests, and handles responses. Use -//! [`Client.builder()`](agent_client_protocol_core::Client) to build connections. +//! [`Client.builder()`](agent_client_protocol::Client) to build connections. //! //! - [`one_shot_prompt`] - Send a single prompt and get a response (simplest pattern) //! - [`connecting_as_client`] - More details on connection setup and permission handling @@ -20,7 +20,7 @@ //! # Building Proxies //! //! A proxy sits between client and agent, intercepting and optionally modifying -//! messages. The most common use case is adding MCP tools. Use [`Proxy.builder()`](agent_client_protocol_core::Proxy) +//! messages. The most common use case is adding MCP tools. Use [`Proxy.builder()`](agent_client_protocol::Proxy) //! to build proxy connections. //! //! **Important:** Proxies don't run standalone—they need the [`agent-client-protocol-conductor`] to @@ -37,18 +37,18 @@ //! //! # Building Agents //! -//! An agent receives prompts and generates responses. Use [`Agent.builder()`](agent_client_protocol_core::Agent) +//! An agent receives prompts and generates responses. Use [`Agent.builder()`](agent_client_protocol::Agent) //! to build agent connections. //! //! - [`building_an_agent`] - Handle initialization, sessions, and prompts //! - [`reusable_components`] - Package your agent as a [`ConnectTo`] //! - [`custom_message_handlers`] - Fine-grained control over message routing //! -//! [`agent_client_protocol_core::concepts`]: agent_client_protocol_core::concepts -//! [`Client`]: agent_client_protocol_core::Client -//! [`Agent`]: agent_client_protocol_core::Agent -//! [`Proxy`]: agent_client_protocol_core::Proxy -//! [`ConnectTo`]: agent_client_protocol_core::ConnectTo +//! [`agent_client_protocol::concepts`]: agent_client_protocol::concepts +//! [`Client`]: agent_client_protocol::Client +//! [`Agent`]: agent_client_protocol::Agent +//! [`Proxy`]: agent_client_protocol::Proxy +//! [`ConnectTo`]: agent_client_protocol::ConnectTo pub mod one_shot_prompt { //! Pattern: You Only Prompt Once. @@ -60,13 +60,13 @@ pub mod one_shot_prompt { //! # Example //! //! ``` - //! use agent_client_protocol_core::{Client, Agent, ConnectTo}; - //! use agent_client_protocol_core::schema::{InitializeRequest, ProtocolVersion}; + //! use agent_client_protocol::{Client, Agent, ConnectTo}; + //! use agent_client_protocol::schema::{InitializeRequest, ProtocolVersion}; //! //! async fn ask_agent( //! transport: impl ConnectTo + 'static, //! prompt: &str, - //! ) -> Result { + //! ) -> Result { //! Client.builder() //! .name("my-client") //! .connect_with(transport, async |connection| { @@ -105,16 +105,16 @@ pub mod one_shot_prompt { //! commands or writing files. See [`connecting_as_client`] for how to handle //! [`RequestPermissionRequest`] messages. //! - //! [`connect_with`]: agent_client_protocol_core::Builder::connect_with - //! [`send_request`]: agent_client_protocol_core::ConnectionTo::send_request - //! [`block_task`]: agent_client_protocol_core::SentRequest::block_task - //! [`build_session_cwd`]: agent_client_protocol_core::ConnectionTo::build_session_cwd - //! [`start_session`]: agent_client_protocol_core::SessionBuilder::start_session - //! [`ActiveSession`]: agent_client_protocol_core::ActiveSession - //! [`send_prompt`]: agent_client_protocol_core::ActiveSession::send_prompt - //! [`read_to_string`]: agent_client_protocol_core::ActiveSession::read_to_string + //! [`connect_with`]: agent_client_protocol::Builder::connect_with + //! [`send_request`]: agent_client_protocol::ConnectionTo::send_request + //! [`block_task`]: agent_client_protocol::SentRequest::block_task + //! [`build_session_cwd`]: agent_client_protocol::ConnectionTo::build_session_cwd + //! [`start_session`]: agent_client_protocol::SessionBuilder::start_session + //! [`ActiveSession`]: agent_client_protocol::ActiveSession + //! [`send_prompt`]: agent_client_protocol::ActiveSession::send_prompt + //! [`read_to_string`]: agent_client_protocol::ActiveSession::read_to_string //! [`connecting_as_client`]: super::connecting_as_client - //! [`RequestPermissionRequest`]: agent_client_protocol_core::schema::RequestPermissionRequest + //! [`RequestPermissionRequest`]: agent_client_protocol::schema::RequestPermissionRequest } pub mod connecting_as_client { @@ -127,10 +127,10 @@ pub mod connecting_as_client { //! # Basic Example //! //! ``` - //! use agent_client_protocol_core::{Client, Agent, ConnectTo}; - //! use agent_client_protocol_core::schema::{InitializeRequest, ProtocolVersion}; + //! use agent_client_protocol::{Client, Agent, ConnectTo}; + //! use agent_client_protocol::schema::{InitializeRequest, ProtocolVersion}; //! - //! async fn connect_to_agent(transport: impl ConnectTo) -> Result<(), agent_client_protocol_core::Error> { + //! async fn connect_to_agent(transport: impl ConnectTo) -> Result<(), agent_client_protocol::Error> { //! Client.builder() //! .name("my-client") //! .connect_with(transport, async |connection| { @@ -182,7 +182,7 @@ pub mod connecting_as_client { //! }, //! meta: None, //! }) - //! }, agent_client_protocol_core::on_receive_request!()) + //! }, agent_client_protocol::on_receive_request!()) //! .connect_with(transport, async |connection| { /* ... */ }) //! .await //! ``` @@ -193,16 +193,16 @@ pub mod connecting_as_client { //! as a spawned task, not on the event loop. The event loop continues processing //! messages (including the response you're waiting for) while your task blocks. //! - //! [`connect_with`]: agent_client_protocol_core::Builder::connect_with - //! [`block_task`]: agent_client_protocol_core::SentRequest::block_task - //! [`build_session`]: agent_client_protocol_core::ConnectionTo::build_session - //! [`SessionBuilder`]: agent_client_protocol_core::SessionBuilder - //! [`send_prompt`]: agent_client_protocol_core::ActiveSession::send_prompt - //! [`read_update`]: agent_client_protocol_core::ActiveSession::read_update - //! [`read_to_string`]: agent_client_protocol_core::ActiveSession::read_to_string - //! [`with_mcp_server`]: agent_client_protocol_core::SessionBuilder::with_mcp_server - //! [`RequestPermissionRequest`]: agent_client_protocol_core::schema::RequestPermissionRequest - //! [`on_receive_request`]: agent_client_protocol_core::Builder::on_receive_request + //! [`connect_with`]: agent_client_protocol::Builder::connect_with + //! [`block_task`]: agent_client_protocol::SentRequest::block_task + //! [`build_session`]: agent_client_protocol::ConnectionTo::build_session + //! [`SessionBuilder`]: agent_client_protocol::SessionBuilder + //! [`send_prompt`]: agent_client_protocol::ActiveSession::send_prompt + //! [`read_update`]: agent_client_protocol::ActiveSession::read_update + //! [`read_to_string`]: agent_client_protocol::ActiveSession::read_to_string + //! [`with_mcp_server`]: agent_client_protocol::SessionBuilder::with_mcp_server + //! [`RequestPermissionRequest`]: agent_client_protocol::schema::RequestPermissionRequest + //! [`on_receive_request`]: agent_client_protocol::Builder::on_receive_request } pub mod building_an_agent { @@ -214,19 +214,19 @@ pub mod building_an_agent { //! 2. Handle [`NewSessionRequest`] to create sessions //! 3. Handle [`PromptRequest`] to process prompts //! - //! Use [`Agent.builder()`](agent_client_protocol_core::Agent) to build agent connections. + //! Use [`Agent.builder()`](agent_client_protocol::Agent) to build agent connections. //! //! # Minimal Example //! //! ``` - //! use agent_client_protocol_core::{Agent, Client, ConnectTo, Dispatch, ConnectionTo}; - //! use agent_client_protocol_core::schema::{ + //! use agent_client_protocol::{Agent, Client, ConnectTo, Dispatch, ConnectionTo}; + //! use agent_client_protocol::schema::{ //! InitializeRequest, InitializeResponse, AgentCapabilities, //! NewSessionRequest, NewSessionResponse, SessionId, //! PromptRequest, PromptResponse, StopReason, //! }; //! - //! async fn run_agent(transport: impl ConnectTo) -> Result<(), agent_client_protocol_core::Error> { + //! async fn run_agent(transport: impl ConnectTo) -> Result<(), agent_client_protocol::Error> { //! Agent.builder() //! .name("my-agent") //! // Handle initialization @@ -235,11 +235,11 @@ pub mod building_an_agent { //! InitializeResponse::new(req.protocol_version) //! .agent_capabilities(AgentCapabilities::new()) //! ) - //! }, agent_client_protocol_core::on_receive_request!()) + //! }, agent_client_protocol::on_receive_request!()) //! // Handle session creation //! .on_receive_request(async |req: NewSessionRequest, responder, _connection| { //! responder.respond(NewSessionResponse::new(SessionId::new("session-1"))) - //! }, agent_client_protocol_core::on_receive_request!()) + //! }, agent_client_protocol::on_receive_request!()) //! // Handle prompts //! .on_receive_request(async |req: PromptRequest, responder, connection| { //! // Send streaming updates via notifications @@ -247,11 +247,11 @@ pub mod building_an_agent { //! //! // Return final response //! responder.respond(PromptResponse::new(StopReason::EndTurn)) - //! }, agent_client_protocol_core::on_receive_request!()) + //! }, agent_client_protocol::on_receive_request!()) //! // Reject unknown messages //! .on_receive_dispatch(async |message: Dispatch, connection: ConnectionTo| { - //! message.respond_with_error(agent_client_protocol_core::Error::method_not_found(), connection) - //! }, agent_client_protocol_core::on_receive_dispatch!()) + //! message.respond_with_error(agent_client_protocol::Error::method_not_found(), connection) + //! }, agent_client_protocol::on_receive_dispatch!()) //! .connect_to(transport) //! .await //! } @@ -287,7 +287,7 @@ pub mod building_an_agent { //! stop_reason: StopReason::EndTurn, //! meta: None, //! }) - //! }, agent_client_protocol_core::on_receive_request!()) + //! }, agent_client_protocol::on_receive_request!()) //! ``` //! //! # Requesting Permissions @@ -321,13 +321,13 @@ pub mod building_an_agent { //! For agents that will be composed with proxies, implement [`ConnectTo`]. //! See [`reusable_components`] for the pattern. //! - //! [`InitializeRequest`]: agent_client_protocol_core::schema::InitializeRequest - //! [`NewSessionRequest`]: agent_client_protocol_core::schema::NewSessionRequest - //! [`PromptRequest`]: agent_client_protocol_core::schema::PromptRequest - //! [`SessionNotification`]: agent_client_protocol_core::schema::SessionNotification - //! [`RequestPermissionRequest`]: agent_client_protocol_core::schema::RequestPermissionRequest - //! [`Agent`]: agent_client_protocol_core::Agent - //! [`ConnectTo`]: agent_client_protocol_core::ConnectTo + //! [`InitializeRequest`]: agent_client_protocol::schema::InitializeRequest + //! [`NewSessionRequest`]: agent_client_protocol::schema::NewSessionRequest + //! [`PromptRequest`]: agent_client_protocol::schema::PromptRequest + //! [`SessionNotification`]: agent_client_protocol::schema::SessionNotification + //! [`RequestPermissionRequest`]: agent_client_protocol::schema::RequestPermissionRequest + //! [`Agent`]: agent_client_protocol::Agent + //! [`ConnectTo`]: agent_client_protocol::ConnectTo //! [`reusable_components`]: super::reusable_components } @@ -341,8 +341,8 @@ pub mod reusable_components { //! # Example //! //! ``` - //! use agent_client_protocol_core::{ConnectTo, Agent, Client}; - //! use agent_client_protocol_core::schema::{ + //! use agent_client_protocol::{ConnectTo, Agent, Client}; + //! use agent_client_protocol::schema::{ //! InitializeRequest, InitializeResponse, AgentCapabilities, //! }; //! @@ -351,7 +351,7 @@ pub mod reusable_components { //! } //! //! impl ConnectTo for MyAgent { - //! async fn connect_to(self, client: impl ConnectTo) -> Result<(), agent_client_protocol_core::Error> { + //! async fn connect_to(self, client: impl ConnectTo) -> Result<(), agent_client_protocol::Error> { //! Agent.builder() //! .name(&self.name) //! .on_receive_request(async move |req: InitializeRequest, responder, _connection| { @@ -359,7 +359,7 @@ pub mod reusable_components { //! InitializeResponse::new(req.protocol_version) //! .agent_capabilities(AgentCapabilities::new()) //! ) - //! }, agent_client_protocol_core::on_receive_request!()) + //! }, agent_client_protocol::on_receive_request!()) //! .connect_to(client) //! .await //! } @@ -376,9 +376,9 @@ pub mod reusable_components { //! - Use [`ConnectionTo::spawn`] to offload work to a background task //! - Use [`on_receiving_result`] to schedule work when a response arrives //! - //! [`ConnectTo`]: agent_client_protocol_core::ConnectTo - //! [`ConnectionTo::spawn`]: agent_client_protocol_core::ConnectionTo::spawn - //! [`on_receiving_result`]: agent_client_protocol_core::SentRequest::on_receiving_result + //! [`ConnectTo`]: agent_client_protocol::ConnectTo + //! [`ConnectionTo::spawn`]: agent_client_protocol::ConnectionTo::spawn + //! [`on_receiving_result`]: agent_client_protocol::SentRequest::on_receiving_result //! [`agent-client-protocol-conductor`]: https://crates.io/crates/agent-client-protocol-conductor } @@ -396,9 +396,9 @@ pub mod custom_message_handlers { //! # Example //! //! ``` - //! use agent_client_protocol_core::{HandleDispatchFrom, Dispatch, Handled, ConnectionTo, UntypedRole}; - //! use agent_client_protocol_core::schema::{InitializeRequest, InitializeResponse, AgentCapabilities}; - //! use agent_client_protocol_core::util::MatchDispatch; + //! use agent_client_protocol::{HandleDispatchFrom, Dispatch, Handled, ConnectionTo, UntypedRole}; + //! use agent_client_protocol::schema::{InitializeRequest, InitializeResponse, AgentCapabilities}; + //! use agent_client_protocol::util::MatchDispatch; //! //! struct MyHandler; //! @@ -407,7 +407,7 @@ pub mod custom_message_handlers { //! &mut self, //! message: Dispatch, //! _connection: ConnectionTo, - //! ) -> Result, agent_client_protocol_core::Error> { + //! ) -> Result, agent_client_protocol::Error> { //! MatchDispatch::new(message) //! .if_request(async |req: InitializeRequest, responder| { //! responder.respond( @@ -431,9 +431,9 @@ pub mod custom_message_handlers { //! - [`MatchDispatchFrom`] - Use in proxies where messages come from different //! peers (`Client` vs `Agent`) and may need different handling //! - //! [`HandleDispatchFrom`]: agent_client_protocol_core::HandleDispatchFrom - //! [`MatchDispatch`]: agent_client_protocol_core::util::MatchDispatch - //! [`MatchDispatchFrom`]: agent_client_protocol_core::util::MatchDispatchFrom + //! [`HandleDispatchFrom`]: agent_client_protocol::HandleDispatchFrom + //! [`MatchDispatch`]: agent_client_protocol::util::MatchDispatch + //! [`MatchDispatchFrom`]: agent_client_protocol::util::MatchDispatchFrom } pub mod global_mcp_server { @@ -454,8 +454,8 @@ pub mod global_mcp_server { //! The simplest way to create an MCP server is with [`McpServer::builder`]: //! //! ``` - //! use agent_client_protocol_core::mcp_server::McpServer; - //! use agent_client_protocol_core::{ConnectTo, RunWithConnectionTo, Proxy, Conductor}; + //! use agent_client_protocol::mcp_server::McpServer; + //! use agent_client_protocol::{ConnectTo, RunWithConnectionTo, Proxy, Conductor}; //! use schemars::JsonSchema; //! use serde::{Deserialize, Serialize}; //! @@ -471,7 +471,7 @@ pub mod global_mcp_server { //! async |params: EchoParams, _cx| { //! Ok(EchoOutput { echoed: params.message }) //! }, - //! agent_client_protocol_core::tool_fn!()) + //! agent_client_protocol::tool_fn!()) //! .build(); //! //! // The proxy component is generic over the MCP server's responder type @@ -480,7 +480,7 @@ pub mod global_mcp_server { //! } //! //! impl + Send + 'static> ConnectTo for MyProxy { - //! async fn connect_to(self, conductor: impl ConnectTo) -> Result<(), agent_client_protocol_core::Error> { + //! async fn connect_to(self, conductor: impl ConnectTo) -> Result<(), agent_client_protocol::Error> { //! Proxy.builder() //! .with_mcp_server(self.mcp_server) //! .connect_to(conductor) @@ -501,8 +501,8 @@ pub mod global_mcp_server { //! use rmcp::handler::server::router::tool::ToolRouter; //! use rmcp::handler::server::wrapper::Parameters; //! use rmcp::model::*; - //! use agent_client_protocol_core::mcp_server::McpServer; - //! use agent_client_protocol_core::Conductor; + //! use agent_client_protocol::mcp_server::McpServer; + //! use agent_client_protocol::Conductor; //! use agent_client_protocol_rmcp::McpServerExt; //! use serde::{Deserialize, Serialize}; //! @@ -556,9 +556,9 @@ pub mod global_mcp_server { //! 2. Passes the modified request through to the next handler //! 3. Handles incoming MCP protocol messages (tool calls, etc.) for its URL //! - //! [`McpServer::builder`]: agent_client_protocol_core::mcp_server::McpServer::builder + //! [`McpServer::builder`]: agent_client_protocol::mcp_server::McpServer::builder //! [`McpServer::from_rmcp`]: agent_client_protocol_rmcp::McpServerExt::from_rmcp - //! [`with_mcp_server`]: agent_client_protocol_core::Builder::with_mcp_server + //! [`with_mcp_server`]: agent_client_protocol::Builder::with_mcp_server } pub mod per_session_mcp_server { @@ -580,11 +580,11 @@ pub mod per_session_mcp_server { //! run code after the session is established: //! //! ``` - //! use agent_client_protocol_core::mcp_server::McpServer; - //! use agent_client_protocol_core::schema::NewSessionRequest; - //! use agent_client_protocol_core::{Client, Proxy, Conductor, ConnectTo}; + //! use agent_client_protocol::mcp_server::McpServer; + //! use agent_client_protocol::schema::NewSessionRequest; + //! use agent_client_protocol::{Client, Proxy, Conductor, ConnectTo}; //! - //! async fn run_proxy(transport: impl ConnectTo) -> Result<(), agent_client_protocol_core::Error> { + //! async fn run_proxy(transport: impl ConnectTo) -> Result<(), agent_client_protocol::Error> { //! Proxy.builder() //! .on_receive_request_from(Client, async move |request: NewSessionRequest, responder, connection| { //! // Extract session context from the request @@ -596,7 +596,7 @@ pub mod per_session_mcp_server { //! async move |_params: (), _cx| { //! Ok(workspace_path.display().to_string()) //! } - //! }, agent_client_protocol_core::tool_fn!()) + //! }, agent_client_protocol::tool_fn!()) //! .build(); //! //! // Build the session and run code after it starts @@ -613,7 +613,7 @@ pub mod per_session_mcp_server { //! tracing::info!(%session_id, "Session started"); //! Ok(()) //! }) - //! }, agent_client_protocol_core::on_receive_request!()) + //! }, agent_client_protocol::on_receive_request!()) //! .connect_to(transport) //! .await //! } @@ -638,17 +638,17 @@ pub mod per_session_mcp_server { //! blocking is safe), use [`block_task`] + [`start_session_proxy`]: //! //! ``` - //! # use agent_client_protocol_core::mcp_server::McpServer; - //! # use agent_client_protocol_core::schema::NewSessionRequest; - //! # use agent_client_protocol_core::{Client, Proxy, Conductor, ConnectTo}; - //! # async fn run_proxy(transport: impl ConnectTo) -> Result<(), agent_client_protocol_core::Error> { + //! # use agent_client_protocol::mcp_server::McpServer; + //! # use agent_client_protocol::schema::NewSessionRequest; + //! # use agent_client_protocol::{Client, Proxy, Conductor, ConnectTo}; + //! # async fn run_proxy(transport: impl ConnectTo) -> Result<(), agent_client_protocol::Error> { //! Proxy.builder() //! .on_receive_request_from(Client, async |request: NewSessionRequest, responder, connection| { //! let cwd = request.cwd.clone(); //! let mcp_server = McpServer::builder("tools") //! .tool_fn("get_cwd", "Returns working directory", { //! async move |_params: (), _cx| Ok(cwd.display().to_string()) - //! }, agent_client_protocol_core::tool_fn!()) + //! }, agent_client_protocol::tool_fn!()) //! .build(); //! //! let session_id = connection.build_session_from(request) @@ -659,7 +659,7 @@ pub mod per_session_mcp_server { //! //! tracing::info!(%session_id, "Session started"); //! Ok(()) - //! }, agent_client_protocol_core::on_receive_request!()) + //! }, agent_client_protocol::on_receive_request!()) //! .connect_to(transport) //! .await //! # } @@ -668,13 +668,13 @@ pub mod per_session_mcp_server { //! For patterns where you need to interact with the session before proxying, //! use [`start_session`] + [`proxy_remaining_messages`] instead. //! - //! [`start_session`]: agent_client_protocol_core::SessionBuilder::start_session - //! [`proxy_remaining_messages`]: agent_client_protocol_core::ActiveSession::proxy_remaining_messages + //! [`start_session`]: agent_client_protocol::SessionBuilder::start_session + //! [`proxy_remaining_messages`]: agent_client_protocol::ActiveSession::proxy_remaining_messages //! - //! [`NewSessionRequest`]: agent_client_protocol_core::schema::NewSessionRequest - //! [`on_proxy_session_start`]: agent_client_protocol_core::SessionBuilder::on_proxy_session_start - //! [`block_task`]: agent_client_protocol_core::SessionBuilder::block_task - //! [`start_session_proxy`]: agent_client_protocol_core::SessionBuilder::start_session_proxy + //! [`NewSessionRequest`]: agent_client_protocol::schema::NewSessionRequest + //! [`on_proxy_session_start`]: agent_client_protocol::SessionBuilder::on_proxy_session_start + //! [`block_task`]: agent_client_protocol::SessionBuilder::block_task + //! [`start_session_proxy`]: agent_client_protocol::SessionBuilder::start_session_proxy } pub mod filtering_tools { @@ -693,22 +693,22 @@ pub mod filtering_tools { //! hide specific tools: //! //! ``` - //! use agent_client_protocol_core::mcp_server::McpServer; - //! use agent_client_protocol_core::{Conductor, RunWithConnectionTo}; + //! use agent_client_protocol::mcp_server::McpServer; + //! use agent_client_protocol::{Conductor, RunWithConnectionTo}; //! use schemars::JsonSchema; //! use serde::Deserialize; //! //! #[derive(Debug, Deserialize, JsonSchema)] //! struct Params {} //! - //! fn build_server(enable_admin: bool) -> Result>, agent_client_protocol_core::Error> { + //! fn build_server(enable_admin: bool) -> Result>, agent_client_protocol::Error> { //! let mut builder = McpServer::builder("my-server") //! .tool_fn("echo", "Echo a message", //! async |_p: Params, _cx| Ok("echoed"), - //! agent_client_protocol_core::tool_fn!()) + //! agent_client_protocol::tool_fn!()) //! .tool_fn("admin", "Admin-only tool", //! async |_p: Params, _cx| Ok("admin action"), - //! agent_client_protocol_core::tool_fn!()); + //! agent_client_protocol::tool_fn!()); //! //! // Conditionally disable the admin tool //! if !enable_admin { @@ -729,25 +729,25 @@ pub mod filtering_tools { //! allow-list where only explicitly enabled tools are available: //! //! ``` - //! use agent_client_protocol_core::mcp_server::McpServer; - //! use agent_client_protocol_core::{Conductor, RunWithConnectionTo}; + //! use agent_client_protocol::mcp_server::McpServer; + //! use agent_client_protocol::{Conductor, RunWithConnectionTo}; //! use schemars::JsonSchema; //! use serde::Deserialize; //! //! #[derive(Debug, Deserialize, JsonSchema)] //! struct Params {} //! - //! fn build_restricted_server() -> Result>, agent_client_protocol_core::Error> { + //! fn build_restricted_server() -> Result>, agent_client_protocol::Error> { //! McpServer::builder("restricted-server") //! .tool_fn("safe", "Safe operation", //! async |_p: Params, _cx| Ok("safe"), - //! agent_client_protocol_core::tool_fn!()) + //! agent_client_protocol::tool_fn!()) //! .tool_fn("dangerous", "Dangerous operation", //! async |_p: Params, _cx| Ok("danger!"), - //! agent_client_protocol_core::tool_fn!()) + //! agent_client_protocol::tool_fn!()) //! .tool_fn("experimental", "Experimental feature", //! async |_p: Params, _cx| Ok("experimental"), - //! agent_client_protocol_core::tool_fn!()) + //! agent_client_protocol::tool_fn!()) //! // Start with all tools disabled //! .disable_all_tools() //! // Only enable the safe tool @@ -762,8 +762,8 @@ pub mod filtering_tools { //! if the tool name doesn't match any registered tool. This helps catch typos: //! //! ``` - //! use agent_client_protocol_core::mcp_server::McpServer; - //! use agent_client_protocol_core::Conductor; + //! use agent_client_protocol::mcp_server::McpServer; + //! use agent_client_protocol::Conductor; //! //! // This will error because "ech" is not a registered tool //! let result = McpServer::::builder("server") @@ -775,9 +775,9 @@ pub mod filtering_tools { //! Calling enable/disable on an already enabled/disabled tool is not an error - //! the operations are idempotent. //! - //! [`disable_tool`]: agent_client_protocol_core::mcp_server::McpServerBuilder::disable_tool - //! [`enable_tool`]: agent_client_protocol_core::mcp_server::McpServerBuilder::enable_tool - //! [`disable_all_tools`]: agent_client_protocol_core::mcp_server::McpServerBuilder::disable_all_tools + //! [`disable_tool`]: agent_client_protocol::mcp_server::McpServerBuilder::disable_tool + //! [`enable_tool`]: agent_client_protocol::mcp_server::McpServerBuilder::enable_tool + //! [`disable_all_tools`]: agent_client_protocol::mcp_server::McpServerBuilder::disable_all_tools } pub mod running_proxies_with_conductor { @@ -850,6 +850,6 @@ pub mod running_proxies_with_conductor { //! running with the conductor. //! //! [`agent-client-protocol-conductor`]: https://crates.io/crates/agent-client-protocol-conductor - //! [`SuccessorMessage`]: agent_client_protocol_core::schema::SuccessorMessage + //! [`SuccessorMessage`]: agent_client_protocol::schema::SuccessorMessage //! [`agent-client-protocol-conductor` tests]: https://github.com/anthropics/acp-rust-sdk/tree/main/src/agent-client-protocol-conductor/tests } diff --git a/src/agent-client-protocol-core/CHANGELOG.md b/src/agent-client-protocol-core/CHANGELOG.md deleted file mode 100644 index c19d951..0000000 --- a/src/agent-client-protocol-core/CHANGELOG.md +++ /dev/null @@ -1,2 +0,0 @@ -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). diff --git a/src/agent-client-protocol-core/Cargo.toml b/src/agent-client-protocol-core/Cargo.toml deleted file mode 100644 index 376bb6a..0000000 --- a/src/agent-client-protocol-core/Cargo.toml +++ /dev/null @@ -1,68 +0,0 @@ -[package] -name = "agent-client-protocol-core" -version = "0.1.0" -edition.workspace = true -authors.workspace = true -license.workspace = true -repository.workspace = true -homepage.workspace = true -description = "Core protocol types and traits for the Agent Client Protocol" -keywords = ["acp", "agent", "protocol", "ai"] -categories = ["development-tools"] - -[features] -default = [] - -# Forward unstable features from agent-client-protocol-schema. -# Enable these to get support for the corresponding unstable ACP methods. -unstable = [ - "unstable_auth_methods", - "unstable_boolean_config", - "unstable_logout", - "unstable_message_id", - "unstable_session_additional_directories", - "unstable_session_close", - "unstable_session_fork", - "unstable_session_model", - "unstable_session_resume", - "unstable_session_usage", -] -unstable_auth_methods = ["agent-client-protocol-schema/unstable_auth_methods"] -unstable_boolean_config = ["agent-client-protocol-schema/unstable_boolean_config"] -unstable_logout = ["agent-client-protocol-schema/unstable_logout"] -unstable_message_id = ["agent-client-protocol-schema/unstable_message_id"] -unstable_session_additional_directories = ["agent-client-protocol-schema/unstable_session_additional_directories"] -unstable_session_close = ["agent-client-protocol-schema/unstable_session_close"] -unstable_session_fork = ["agent-client-protocol-schema/unstable_session_fork"] -unstable_session_model = ["agent-client-protocol-schema/unstable_session_model"] -unstable_session_resume = ["agent-client-protocol-schema/unstable_session_resume"] -unstable_session_usage = ["agent-client-protocol-schema/unstable_session_usage"] - -[dependencies] -agent-client-protocol-schema.workspace = true -agent-client-protocol-derive.workspace = true -anyhow.workspace = true -boxfnonce.workspace = true -futures.workspace = true -futures-concurrency.workspace = true -rustc-hash.workspace = true -jsonrpcmsg.workspace = true -rmcp = { workspace = true, features = ["server"] } -schemars.workspace = true -serde.workspace = true -serde_json.workspace = true -thiserror.workspace = true -tokio.workspace = true -tokio-util.workspace = true -tracing.workspace = true -uuid.workspace = true - -[dev-dependencies] -agent-client-protocol-test.workspace = true -clap.workspace = true -expect-test.workspace = true -shell-words.workspace = true -tokio.workspace = true - -[lints] -workspace = true diff --git a/src/agent-client-protocol-core/README.md b/src/agent-client-protocol-core/README.md deleted file mode 100644 index a33a37d..0000000 --- a/src/agent-client-protocol-core/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# agent-client-protocol-core - -Core protocol types and traits for the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/). - -ACP is a protocol for communication between AI agents and their clients (IDEs, CLIs, etc.), -enabling features like tool use, permission requests, and streaming responses. - -## What can you build with this crate? - -- **Clients** that talk to ACP agents (like building your own Claude Code interface) -- **Proxies** that add capabilities to existing agents (like adding custom tools via MCP) -- **Agents** that respond to prompts with AI-powered responses - -## Quick Start: Connecting to an Agent - -The most common use case is connecting to an existing ACP agent as a client: - -```rust -use agent_client_protocol_core::{Client, Agent, ConnectTo}; -use agent_client_protocol_core::schema::{InitializeRequest, ProtocolVersion}; - -Client.builder() - .name("my-client") - .connect_with(transport, async |cx| { - // Initialize the connection - cx.send_request(InitializeRequest::new(ProtocolVersion::V1)) - .block_task() - .await?; - - Ok(()) - }) - .await?; -``` - -## Learning More - -See the [crate documentation](https://docs.rs/agent-client-protocol-core) for: - -- **[Cookbook](https://docs.rs/agent-client-protocol-core/latest/agent_client_protocol_core/cookbook/)** — Patterns for building clients, proxies, and agents -- **[Examples](https://github.com/agentclientprotocol/rust-sdk/tree/main/src/agent-client-protocol-core/examples)** — Working code you can run - -## Related Crates - -- **[agent-client-protocol-tokio](../agent-client-protocol-tokio/)** — Tokio utilities for spawning agent processes -- **[agent-client-protocol-derive](../agent-client-protocol-derive/)** — Derive macros for JSON-RPC traits -- **[agent-client-protocol-trace-viewer](../agent-client-protocol-trace-viewer/)** — Interactive trace visualization - -## License - -Apache-2.0 diff --git a/src/agent-client-protocol-core/src/lib.rs b/src/agent-client-protocol-core/src/lib.rs deleted file mode 100644 index 9175751..0000000 --- a/src/agent-client-protocol-core/src/lib.rs +++ /dev/null @@ -1,210 +0,0 @@ -#![deny(missing_docs)] - -//! # agent-client-protocol-core -- the Symposium Agent Client Protocol (ACP) SDK -//! -//! **agent-client-protocol-core** is a Rust SDK for building [Agent-Client Protocol (ACP)][acp] applications. -//! ACP is a protocol for communication between AI agents and their clients (IDEs, CLIs, etc.), -//! enabling features like tool use, permission requests, and streaming responses. -//! -//! [acp]: https://agentclientprotocol.com/ -//! -//! ## What can you build with agent-client-protocol-core? -//! -//! - **Clients** that talk to ACP agents (like building your own Claude Code interface) -//! - **Proxies** that add capabilities to existing agents (like adding custom tools via MCP) -//! - **Agents** that respond to prompts with AI-powered responses -//! -//! ## Quick Start: Connecting to an Agent -//! -//! The most common use case is connecting to an existing ACP agent as a client. -//! Here's a minimal example that initializes a connection, creates a session, -//! and sends a prompt: -//! -//! ```no_run -//! use agent_client_protocol_core::Client; -//! use agent_client_protocol_core::schema::{InitializeRequest, ProtocolVersion}; -//! -//! # async fn run(transport: impl agent_client_protocol_core::ConnectTo) -> agent_client_protocol_core::Result<()> { -//! Client.builder() -//! .name("my-client") -//! .connect_with(transport, async |cx| { -//! // Step 1: Initialize the connection -//! cx.send_request(InitializeRequest::new(ProtocolVersion::V1)) -//! .block_task().await?; -//! -//! // Step 2: Create a session and send a prompt -//! cx.build_session_cwd()? -//! .block_task() -//! .run_until(async |mut session| { -//! session.send_prompt("What is 2 + 2?")?; -//! let response = session.read_to_string().await?; -//! println!("{}", response); -//! Ok(()) -//! }) -//! .await -//! }) -//! .await -//! # } -//! ``` -//! -//! For a complete working example, see [`yolo_one_shot_client.rs`][yolo]. -//! -//! [yolo]: https://github.com/agentclientprotocol/rust-sdk/blob/main/src/agent-client-protocol-core/examples/yolo_one_shot_client.rs -//! -//! ## Cookbook -//! -//! The [`agent_client_protocol_cookbook`] crate contains practical guides and examples: -//! -//! - Connecting as a client -//! - Global MCP server -//! - Per-session MCP server with workspace context -//! - Building agents and reusable components -//! - Running proxies with the conductor -//! -//! [`agent_client_protocol_cookbook`]: https://docs.rs/agent-client-protocol-cookbook -//! -//! ## Core Concepts -//! -//! The [`concepts`] module provides detailed explanations of how agent-client-protocol-core works, -//! including connections, sessions, callbacks, ordering guarantees, and more. -//! -//! ## Related Crates -//! -//! - [`agent-client-protocol-tokio`] - Tokio utilities for spawning agent processes -//! - [`agent-client-protocol-conductor`] - Binary for running proxy chains -//! -//! [`agent-client-protocol-tokio`]: https://crates.io/crates/agent-client-protocol-tokio -//! [`agent-client-protocol-conductor`]: https://crates.io/crates/agent-client-protocol-conductor - -/// Capability management for the `_meta.symposium` object -mod capabilities; -/// Component abstraction for agents and proxies -pub mod component; -/// Core concepts for understanding and using agent-client-protocol-core -pub mod concepts; -/// Cookbook of common patterns for building ACP components -pub mod cookbook; -/// JSON-RPC handler types for building custom message handlers -pub mod handler; -/// JSON-RPC connection and handler infrastructure -mod jsonrpc; -/// MCP server support for providing MCP tools over ACP -pub mod mcp_server; -/// Role types for ACP connections -pub mod role; -/// ACP protocol schema types - all message types, requests, responses, and supporting types -pub mod schema; -/// Utility functions and types -pub mod util; - -pub use capabilities::*; - -/// JSON-RPC message types. -/// -/// This module re-exports types from the `jsonrpcmsg` crate that are transitively -/// reachable through the public API (e.g., via [`Channel`]). -/// -/// Users of the `agent-client-protocol-core` crate can use these types without adding a direct dependency -/// on `jsonrpcmsg`. -pub mod jsonrpcmsg { - pub use jsonrpcmsg::{Error, Id, Message, Params, Request, Response}; -} - -pub use jsonrpc::{ - Builder, ByteStreams, Channel, ConnectionTo, Dispatch, HandleDispatchFrom, Handled, - IntoHandled, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse, Lines, - NullHandler, Responder, ResponseRouter, SentRequest, UntypedMessage, - run::{ChainRun, NullRun, RunWithConnectionTo}, -}; - -pub use role::{ - Role, RoleId, UntypedRole, - acp::{Agent, Client, Conductor, Proxy}, -}; - -pub use component::{ConnectTo, DynConnectTo}; - -// Re-export BoxFuture for implementing Component traits -pub use futures::future::BoxFuture; - -// Re-export the six primary message enum types at the root -pub use schema::{ - AgentNotification, AgentRequest, AgentResponse, ClientNotification, ClientRequest, - ClientResponse, -}; - -// Re-export commonly used infrastructure types for convenience -pub use schema::{Error, ErrorCode, Result}; - -// Re-export derive macros for custom JSON-RPC types -pub use agent_client_protocol_derive::{JsonRpcNotification, JsonRpcRequest, JsonRpcResponse}; - -mod session; -pub use session::*; - -/// This is a hack that must be given as the final argument of -/// [`McpServerBuilder::tool_fn`](`crate::mcp_server::McpServerBuilder::tool_fn`) when defining tools. -/// Look away, lest ye be blinded by its vileness! -/// -/// Fine, if you MUST know, it's a horrific workaround for not having -/// [return-type notation](https://github.com/rust-lang/rust/issues/109417) -/// and for [this !@$#!%! bug](https://github.com/rust-lang/rust/issues/110338). -/// Trust me, the need for it hurts me more than it hurts you. --nikomatsakis -#[macro_export] -macro_rules! tool_fn_mut { - () => { - |func, params, context| Box::pin(func(params, context)) - }; -} - -/// This is a hack that must be given as the final argument of -/// [`McpServerBuilder::tool_fn`](`crate::mcp_server::McpServerBuilder::tool_fn`) when defining stateless concurrent tools. -/// See [`tool_fn_mut!`] for the gory details. -#[macro_export] -macro_rules! tool_fn { - () => { - |func, params, context| Box::pin(func(params, context)) - }; -} - -/// This macro is used for the value of the `to_future_hack` parameter of -/// [`Builder::on_receive_request`] and [`Builder::on_receive_request_from`]. -/// -/// It expands to `|f, req, responder, cx| Box::pin(f(req, responder, cx))`. -/// -/// This is needed until [return-type notation](https://github.com/rust-lang/rust/issues/109417) -/// is stabilized. -#[macro_export] -macro_rules! on_receive_request { - () => { - |f: &mut _, req, responder, cx| Box::pin(f(req, responder, cx)) - }; -} - -/// This macro is used for the value of the `to_future_hack` parameter of -/// [`Builder::on_receive_notification`] and [`Builder::on_receive_notification_from`]. -/// -/// It expands to `|f, notif, cx| Box::pin(f(notif, cx))`. -/// -/// This is needed until [return-type notation](https://github.com/rust-lang/rust/issues/109417) -/// is stabilized. -#[macro_export] -macro_rules! on_receive_notification { - () => { - |f: &mut _, notif, cx| Box::pin(f(notif, cx)) - }; -} - -/// This macro is used for the value of the `to_future_hack` parameter of -/// [`Builder::on_receive_dispatch`] and [`Builder::on_receive_dispatch_from`]. -/// -/// It expands to `|f, dispatch, cx| Box::pin(f(dispatch, cx))`. -/// -/// This is needed until [return-type notation](https://github.com/rust-lang/rust/issues/109417) -/// is stabilized. -#[macro_export] -macro_rules! on_receive_dispatch { - () => { - |f: &mut _, dispatch, cx| Box::pin(f(dispatch, cx)) - }; -} diff --git a/src/agent-client-protocol-derive/Cargo.toml b/src/agent-client-protocol-derive/Cargo.toml index 597e553..976d3fe 100644 --- a/src/agent-client-protocol-derive/Cargo.toml +++ b/src/agent-client-protocol-derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "agent-client-protocol-derive" -version = "0.1.0" +version = "0.11.0" edition.workspace = true authors.workspace = true license.workspace = true diff --git a/src/agent-client-protocol-derive/src/lib.rs b/src/agent-client-protocol-derive/src/lib.rs index 9275858..325ed57 100644 --- a/src/agent-client-protocol-derive/src/lib.rs +++ b/src/agent-client-protocol-derive/src/lib.rs @@ -46,7 +46,7 @@ use syn::{DeriveInput, Expr, Lit, Path, Type, parse_macro_input}; /// # Attributes /// /// - `#[request(method = "method_name", response = ResponseType)]` -/// - `#[request(method = "method_name", response = ResponseType, crate = crate)]` - for use within the `agent_client_protocol_core` crate +/// - `#[request(method = "method_name", response = ResponseType, crate = crate)]` - for use within the `agent_client_protocol` crate /// /// # Example /// @@ -106,7 +106,7 @@ pub fn derive_json_rpc_request(input: TokenStream) -> TokenStream { /// # Attributes /// /// - `#[notification(method = "method_name")]` -/// - `#[notification(method = "method_name", crate = crate)]` - for use within the `agent_client_protocol_core` crate +/// - `#[notification(method = "method_name", crate = crate)]` - for use within the `agent_client_protocol` crate /// /// # Example /// @@ -163,7 +163,7 @@ pub fn derive_json_rpc_notification(input: TokenStream) -> TokenStream { /// /// # Attributes /// -/// - `#[response(crate = crate)]` - for use within the `agent_client_protocol_core` crate +/// - `#[response(crate = crate)]` - for use within the `agent_client_protocol` crate /// /// # Example /// @@ -199,7 +199,7 @@ pub fn derive_json_rpc_response_payload(input: TokenStream) -> TokenStream { } fn default_crate_path() -> Path { - syn::parse_quote!(agent_client_protocol_core) + syn::parse_quote!(agent_client_protocol) } fn parse_request_attrs(input: &DeriveInput) -> syn::Result<(String, Type, Path)> { diff --git a/src/agent-client-protocol-rmcp/Cargo.toml b/src/agent-client-protocol-rmcp/Cargo.toml index 48c9efe..1550958 100644 --- a/src/agent-client-protocol-rmcp/Cargo.toml +++ b/src/agent-client-protocol-rmcp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "agent-client-protocol-rmcp" -version = "0.1.0" +version = "0.11.0" edition.workspace = true authors.workspace = true license.workspace = true @@ -11,7 +11,7 @@ keywords = ["acp", "agent", "proxy", "mcp", "rmcp"] categories = ["development-tools"] [dependencies] -agent-client-protocol-core.workspace = true +agent-client-protocol.workspace = true futures.workspace = true futures-concurrency.workspace = true rmcp.workspace = true diff --git a/src/agent-client-protocol-rmcp/README.md b/src/agent-client-protocol-rmcp/README.md index c4fb9c5..7c2738a 100644 --- a/src/agent-client-protocol-rmcp/README.md +++ b/src/agent-client-protocol-rmcp/README.md @@ -4,14 +4,14 @@ ## Overview -This crate bridges [rmcp](https://docs.rs/rmcp)-based MCP server implementations with the ACP MCP server framework from `agent-client-protocol-core`. It lets you use any rmcp service as an MCP server in an ACP proxy. +This crate bridges [rmcp](https://docs.rs/rmcp)-based MCP server implementations with the ACP MCP server framework from `agent-client-protocol`. It lets you use any rmcp service as an MCP server in an ACP proxy. ## Usage Use the `McpServerExt` trait to create an MCP server from an rmcp service: ```rust -use agent_client_protocol_core::mcp_server::McpServer; +use agent_client_protocol::mcp_server::McpServer; use agent_client_protocol_rmcp::McpServerExt; let server = McpServer::from_rmcp("my-server", MyRmcpService::new); @@ -25,15 +25,15 @@ Proxy.builder() ## Why a Separate Crate? -This crate is separate from `agent-client-protocol-core` to avoid coupling the core protocol crate to the `rmcp` dependency. This allows: +This crate is separate from `agent-client-protocol` to avoid coupling the core protocol crate to the `rmcp` dependency. This allows: -- `agent-client-protocol-core` to remain focused on the ACP protocol +- `agent-client-protocol` to remain focused on the ACP protocol - `agent-client-protocol-rmcp` to track `rmcp` updates independently - Breaking changes in `rmcp` only require updating this crate ## Related Crates -- **[agent-client-protocol-core](../agent-client-protocol-core/)** — Core ACP protocol types and traits +- **[agent-client-protocol](../agent-client-protocol/)** — Core ACP protocol types and traits - **[agent-client-protocol-tokio](../agent-client-protocol-tokio/)** — Tokio utilities for spawning agent processes ## License diff --git a/src/agent-client-protocol-rmcp/examples/with_mcp_server.rs b/src/agent-client-protocol-rmcp/examples/with_mcp_server.rs index 7b8139c..68856da 100644 --- a/src/agent-client-protocol-rmcp/examples/with_mcp_server.rs +++ b/src/agent-client-protocol-rmcp/examples/with_mcp_server.rs @@ -8,7 +8,7 @@ //! cargo run --example with_mcp_server //! ``` -use agent_client_protocol_core::{Proxy, mcp_server::McpServer}; +use agent_client_protocol::{Proxy, mcp_server::McpServer}; use agent_client_protocol_rmcp::McpServerExt; use rmcp::{ ErrorData as McpError, ServerHandler, @@ -93,7 +93,7 @@ async fn main() -> Result<(), Box> { // Register the MCP server as a handler .with_mcp_server(mcp_server) // Start serving - .connect_to(agent_client_protocol_core::ByteStreams::new( + .connect_to(agent_client_protocol::ByteStreams::new( tokio::io::stdout().compat_write(), tokio::io::stdin().compat(), )) diff --git a/src/agent-client-protocol-rmcp/src/lib.rs b/src/agent-client-protocol-rmcp/src/lib.rs index 4b436c9..7faf143 100644 --- a/src/agent-client-protocol-rmcp/src/lib.rs +++ b/src/agent-client-protocol-rmcp/src/lib.rs @@ -8,7 +8,7 @@ //! Create an MCP server from an rmcp service using the extension trait: //! //! ```ignore -//! use agent_client_protocol_core::mcp_server::McpServer; +//! use agent_client_protocol::mcp_server::McpServer; //! use agent_client_protocol_rmcp::McpServerExt; //! //! let server = McpServer::from_rmcp("my-server", MyRmcpService::new); @@ -20,9 +20,9 @@ //! .await?; //! ``` -use agent_client_protocol_core::mcp_server::{McpConnectionTo, McpServer, McpServerConnect}; -use agent_client_protocol_core::role::{self, HasPeer}; -use agent_client_protocol_core::{Agent, ByteStreams, ConnectTo, DynConnectTo, NullRun, Role}; +use agent_client_protocol::mcp_server::{McpConnectionTo, McpServer, McpServerConnect}; +use agent_client_protocol::role::{self, HasPeer}; +use agent_client_protocol::{Agent, ByteStreams, ConnectTo, DynConnectTo, NullRun, Role}; use futures_concurrency::future::TryJoin as _; use rmcp::ServiceExt; use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; @@ -94,7 +94,7 @@ where async fn connect_to( self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { // Create tokio byte streams that rmcp expects let (mcp_server_stream, mcp_client_stream) = tokio::io::duplex(8192); let (mcp_server_read, mcp_server_write) = tokio::io::split(mcp_server_stream); @@ -117,14 +117,14 @@ where .service .serve((mcp_server_read, mcp_server_write)) .await - .map_err(agent_client_protocol_core::Error::into_internal_error)?; + .map_err(agent_client_protocol::Error::into_internal_error)?; // Wait for the server to finish running_server .waiting() .await .map(|_quit_reason| ()) - .map_err(agent_client_protocol_core::Error::into_internal_error) + .map_err(agent_client_protocol::Error::into_internal_error) }; (bytes_to_acp, bytes_to_rmcp).try_join().await?; diff --git a/src/agent-client-protocol-test/Cargo.toml b/src/agent-client-protocol-test/Cargo.toml index e404df6..2ea2fde 100644 --- a/src/agent-client-protocol-test/Cargo.toml +++ b/src/agent-client-protocol-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "agent-client-protocol-test" -version = "0.1.0" +version = "0.11.0" edition.workspace = true authors.workspace = true license.workspace = true @@ -18,7 +18,7 @@ name = "testy" path = "src/bin/testy.rs" [dependencies] -agent-client-protocol-core.workspace = true +agent-client-protocol.workspace = true agent-client-protocol-tokio.workspace = true yopo.workspace = true anyhow.workspace = true diff --git a/src/agent-client-protocol-test/examples/arrow_proxy.rs b/src/agent-client-protocol-test/examples/arrow_proxy.rs index 3b7b2bb..bd425f8 100644 --- a/src/agent-client-protocol-test/examples/arrow_proxy.rs +++ b/src/agent-client-protocol-test/examples/arrow_proxy.rs @@ -20,7 +20,7 @@ async fn main() -> Result<(), Box> { let stdout = tokio::io::stdout().compat_write(); // Run the arrow proxy - run_arrow_proxy(agent_client_protocol_core::ByteStreams::new(stdout, stdin)).await?; + run_arrow_proxy(agent_client_protocol::ByteStreams::new(stdout, stdin)).await?; Ok(()) } diff --git a/src/agent-client-protocol-test/src/arrow_proxy.rs b/src/agent-client-protocol-test/src/arrow_proxy.rs index 5a95767..6a006b9 100644 --- a/src/agent-client-protocol-test/src/arrow_proxy.rs +++ b/src/agent-client-protocol-test/src/arrow_proxy.rs @@ -3,10 +3,10 @@ //! This proxy demonstrates basic proxy functionality by intercepting //! `session/update` notifications and prepending `>` to the content. -use agent_client_protocol_core::schema::{ +use agent_client_protocol::schema::{ ContentBlock, ContentChunk, SessionNotification, SessionUpdate, }; -use agent_client_protocol_core::{Agent, Client, ConnectTo, Proxy}; +use agent_client_protocol::{Agent, Client, ConnectTo, Proxy}; /// Run the arrow proxy that adds `>` to each session update. /// @@ -15,7 +15,7 @@ use agent_client_protocol_core::{Agent, Client, ConnectTo, Proxy}; /// * `transport` - Component to the predecessor (conductor or another proxy) pub async fn run_arrow_proxy( transport: impl ConnectTo + 'static, -) -> Result<(), agent_client_protocol_core::Error> { +) -> Result<(), agent_client_protocol::Error> { Proxy .builder() .name("arrow-proxy") @@ -40,7 +40,7 @@ pub async fn run_arrow_proxy( cx.send_notification_to(Client, notification)?; Ok(()) }, - agent_client_protocol_core::on_receive_notification!(), + agent_client_protocol::on_receive_notification!(), ) .connect_to(transport) .await diff --git a/src/agent-client-protocol-test/src/bin/testy.rs b/src/agent-client-protocol-test/src/bin/testy.rs index 72834f9..76b67dd 100644 --- a/src/agent-client-protocol-test/src/bin/testy.rs +++ b/src/agent-client-protocol-test/src/bin/testy.rs @@ -1,4 +1,4 @@ -use agent_client_protocol_core::ConnectTo; +use agent_client_protocol::ConnectTo; use agent_client_protocol_test::testy::Testy; #[tokio::main] diff --git a/src/agent-client-protocol-test/src/lib.rs b/src/agent-client-protocol-test/src/lib.rs index 8833d68..166c797 100644 --- a/src/agent-client-protocol-test/src/lib.rs +++ b/src/agent-client-protocol-test/src/lib.rs @@ -1,4 +1,4 @@ -use agent_client_protocol_core::*; +use agent_client_protocol::*; use serde::{Deserialize, Serialize}; pub mod arrow_proxy; @@ -129,7 +129,7 @@ macro_rules! impl_jr_message { if !Self::matches_method(method) { return Err(crate::Error::method_not_found()); } - agent_client_protocol_core::util::json_cast_params(params) + agent_client_protocol::util::json_cast_params(params) } } }; diff --git a/src/agent-client-protocol-test/src/testy.rs b/src/agent-client-protocol-test/src/testy.rs index 3e3d5ea..d882fdf 100644 --- a/src/agent-client-protocol-test/src/testy.rs +++ b/src/agent-client-protocol-test/src/testy.rs @@ -2,12 +2,12 @@ //! //! The agent accepts JSON-serialized [`TestyCommand`] values as prompt text. -use agent_client_protocol_core::schema::{ +use agent_client_protocol::schema::{ AgentCapabilities, ContentBlock, ContentChunk, InitializeRequest, InitializeResponse, McpServer, NewSessionRequest, NewSessionResponse, PromptRequest, PromptResponse, SessionId, SessionNotification, SessionUpdate, StopReason, TextContent, }; -use agent_client_protocol_core::{Agent, Client, ConnectTo, ConnectionTo, Responder}; +use agent_client_protocol::{Agent, Client, ConnectTo, ConnectionTo, Responder}; use anyhow::Result; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -88,7 +88,7 @@ impl Testy { request: PromptRequest, responder: Responder, connection: ConnectionTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { let session_id = request.session_id.clone(); let input_text = extract_text_from_prompt(&request.prompt); @@ -258,7 +258,7 @@ impl ConnectTo for Testy { async fn connect_to( self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { Agent .builder() .name("test-agent") @@ -269,7 +269,7 @@ impl ConnectTo for Testy { .agent_capabilities(AgentCapabilities::new()), ) }, - agent_client_protocol_core::on_receive_request!(), + agent_client_protocol::on_receive_request!(), ) .on_receive_request( { @@ -280,7 +280,7 @@ impl ConnectTo for Testy { responder.respond(NewSessionResponse::new(session_id)) } }, - agent_client_protocol_core::on_receive_request!(), + agent_client_protocol::on_receive_request!(), ) .on_receive_request( { @@ -293,7 +293,7 @@ impl ConnectTo for Testy { }) } }, - agent_client_protocol_core::on_receive_request!(), + agent_client_protocol::on_receive_request!(), ) .connect_to(client) .await diff --git a/src/agent-client-protocol-tokio/Cargo.toml b/src/agent-client-protocol-tokio/Cargo.toml index be67f97..92b6c89 100644 --- a/src/agent-client-protocol-tokio/Cargo.toml +++ b/src/agent-client-protocol-tokio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "agent-client-protocol-tokio" -version = "0.1.0" +version = "0.11.0" edition.workspace = true authors.workspace = true license.workspace = true @@ -11,7 +11,7 @@ keywords = ["acp", "agent", "protocol", "ai", "tokio"] categories = ["development-tools"] [dependencies] -agent-client-protocol-core.workspace = true +agent-client-protocol.workspace = true futures.workspace = true serde.workspace = true serde_json.workspace = true diff --git a/src/agent-client-protocol-tokio/README.md b/src/agent-client-protocol-tokio/README.md index 146f230..850a9e6 100644 --- a/src/agent-client-protocol-tokio/README.md +++ b/src/agent-client-protocol-tokio/README.md @@ -14,7 +14,7 @@ This crate provides helpers for spawning and connecting to ACP agents using the The main use case is spawning an agent process and connecting to it: ```rust -use agent_client_protocol_core::{Client, ConnectTo}; +use agent_client_protocol::{Client, ConnectTo}; use agent_client_protocol_tokio::AcpAgent; use std::str::FromStr; @@ -47,11 +47,11 @@ Use `agent-client-protocol-tokio` when you need to: - Build tools that orchestrate multiple agents If you're implementing an agent that listens on stdin/stdout, you only need the core -[`agent-client-protocol-core`](../agent-client-protocol-core/) crate. +[`agent-client-protocol`](../agent-client-protocol/) crate. ## Related Crates -- **[agent-client-protocol-core](../agent-client-protocol-core/)** — Core ACP protocol types and traits +- **[agent-client-protocol](../agent-client-protocol/)** — Core ACP protocol types and traits - **[agent-client-protocol-derive](../agent-client-protocol-derive/)** — Derive macros for JSON-RPC traits - **[agent-client-protocol-trace-viewer](../agent-client-protocol-trace-viewer/)** — Interactive trace visualization diff --git a/src/agent-client-protocol-tokio/src/acp_agent.rs b/src/agent-client-protocol-tokio/src/acp_agent.rs index 1139ae2..acdfea4 100644 --- a/src/agent-client-protocol-tokio/src/acp_agent.rs +++ b/src/agent-client-protocol-tokio/src/acp_agent.rs @@ -1,13 +1,13 @@ //! Utilities for connecting to ACP agents and proxies. //! -//! This module provides [`AcpAgent`], a convenient wrapper around [`agent_client_protocol_core::schema::McpServer`] +//! This module provides [`AcpAgent`], a convenient wrapper around [`agent_client_protocol::schema::McpServer`] //! that can be parsed from either a command string or JSON configuration. use std::path::PathBuf; use std::str::FromStr; use std::sync::Arc; -use agent_client_protocol_core::{Client, Conductor, Role}; +use agent_client_protocol::{Client, Conductor, Role}; use tokio::process::Child; use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; @@ -24,12 +24,12 @@ pub enum LineDirection { /// A component representing an external ACP agent running in a separate process. /// -/// `AcpAgent` implements the [`agent_client_protocol_core::ConnectTo`] trait for spawning and communicating with +/// `AcpAgent` implements the [`agent_client_protocol::ConnectTo`] trait for spawning and communicating with /// external agents or proxies via stdio. It handles process spawning, stream setup, and /// byte stream serialization automatically. This is the primary way to connect to agents /// that run as separate executables. /// -/// This is a wrapper around [`agent_client_protocol_core::schema::McpServer`] that provides convenient parsing +/// This is a wrapper around [`agent_client_protocol::schema::McpServer`] that provides convenient parsing /// from command-line strings or JSON configurations. /// /// # Use Cases @@ -57,7 +57,7 @@ pub enum LineDirection { /// /// Use as a component to connect to an external agent: /// ```ignore -/// use agent_client_protocol_core::{Client, Builder}; +/// use agent_client_protocol::{Client, Builder}; /// use agent_client_protocol_tokio::AcpAgent; /// use std::str::FromStr; /// @@ -79,7 +79,7 @@ pub enum LineDirection { /// /// [`agent_client_protocol_conductor::Conductor`]: https://docs.rs/agent-client-protocol-conductor/latest/agent_client_protocol_conductor/struct.Conductor.html pub struct AcpAgent { - server: agent_client_protocol_core::schema::McpServer, + server: agent_client_protocol::schema::McpServer, debug_callback: Option>, } @@ -96,9 +96,9 @@ impl std::fmt::Debug for AcpAgent { } impl AcpAgent { - /// Create a new `AcpAgent` from an [`agent_client_protocol_core::schema::McpServer`] configuration. + /// Create a new `AcpAgent` from an [`agent_client_protocol::schema::McpServer`] configuration. #[must_use] - pub fn new(server: agent_client_protocol_core::schema::McpServer) -> Self { + pub fn new(server: agent_client_protocol::schema::McpServer) -> Self { Self { server, debug_callback: None, @@ -127,15 +127,15 @@ impl AcpAgent { .expect("valid bash command") } - /// Get the underlying [`agent_client_protocol_core::schema::McpServer`] configuration. + /// Get the underlying [`agent_client_protocol::schema::McpServer`] configuration. #[must_use] - pub fn server(&self) -> &agent_client_protocol_core::schema::McpServer { + pub fn server(&self) -> &agent_client_protocol::schema::McpServer { &self.server } - /// Convert into the underlying [`agent_client_protocol_core::schema::McpServer`] configuration. + /// Convert into the underlying [`agent_client_protocol::schema::McpServer`] configuration. #[must_use] - pub fn into_server(self) -> agent_client_protocol_core::schema::McpServer { + pub fn into_server(self) -> agent_client_protocol::schema::McpServer { self.server } @@ -175,10 +175,10 @@ impl AcpAgent { tokio::process::ChildStderr, Child, ), - agent_client_protocol_core::Error, + agent_client_protocol::Error, > { match &self.server { - agent_client_protocol_core::schema::McpServer::Stdio(stdio) => { + agent_client_protocol::schema::McpServer::Stdio(stdio) => { let mut cmd = tokio::process::Command::new(&stdio.command); cmd.args(&stdio.args); for env_var in &stdio.env { @@ -190,31 +190,31 @@ impl AcpAgent { let mut child = cmd .spawn() - .map_err(agent_client_protocol_core::Error::into_internal_error)?; + .map_err(agent_client_protocol::Error::into_internal_error)?; let child_stdin = child.stdin.take().ok_or_else(|| { - agent_client_protocol_core::util::internal_error("Failed to open stdin") + agent_client_protocol::util::internal_error("Failed to open stdin") })?; let child_stdout = child.stdout.take().ok_or_else(|| { - agent_client_protocol_core::util::internal_error("Failed to open stdout") + agent_client_protocol::util::internal_error("Failed to open stdout") })?; let child_stderr = child.stderr.take().ok_or_else(|| { - agent_client_protocol_core::util::internal_error("Failed to open stderr") + agent_client_protocol::util::internal_error("Failed to open stderr") })?; Ok((child_stdin, child_stdout, child_stderr, child)) } - agent_client_protocol_core::schema::McpServer::Http(_) => { - Err(agent_client_protocol_core::util::internal_error( + agent_client_protocol::schema::McpServer::Http(_) => { + Err(agent_client_protocol::util::internal_error( "HTTP transport not yet supported by AcpAgent", )) } - agent_client_protocol_core::schema::McpServer::Sse(_) => { - Err(agent_client_protocol_core::util::internal_error( + agent_client_protocol::schema::McpServer::Sse(_) => { + Err(agent_client_protocol::util::internal_error( "SSE transport not yet supported by AcpAgent", )) } - _ => Err(agent_client_protocol_core::util::internal_error( + _ => Err(agent_client_protocol::util::internal_error( "Unknown MCP server transport type", )), } @@ -243,12 +243,12 @@ impl Drop for ChildGuard { async fn monitor_child( child: Child, stderr_rx: tokio::sync::oneshot::Receiver, -) -> Result<(), agent_client_protocol_core::Error> { +) -> Result<(), agent_client_protocol::Error> { let mut guard = ChildGuard(child); // Wait for the child to exit let status = guard.wait().await.map_err(|e| { - agent_client_protocol_core::util::internal_error(format!("Failed to wait for process: {e}")) + agent_client_protocol::util::internal_error(format!("Failed to wait for process: {e}")) })?; if status.success() { @@ -263,7 +263,7 @@ async fn monitor_child( format!("Process exited with {status}: {stderr}") }; - Err(agent_client_protocol_core::util::internal_error(message)) + Err(agent_client_protocol::util::internal_error(message)) } } @@ -274,13 +274,13 @@ impl AcpAgentCounterpartRole for Client {} impl AcpAgentCounterpartRole for Conductor {} -impl agent_client_protocol_core::ConnectTo +impl agent_client_protocol::ConnectTo for AcpAgent { async fn connect_to( self, - client: impl agent_client_protocol_core::ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + client: impl agent_client_protocol::ConnectTo, + ) -> Result<(), agent_client_protocol::Error> { use futures::AsyncBufReadExt; use futures::AsyncWriteExt; use futures::StreamExt; @@ -359,8 +359,8 @@ impl agent_client_protocol_core::ConnectTo // Race the protocol against child process exit // If the child exits early (e.g., with an error), we return that error - let protocol_future = agent_client_protocol_core::ConnectTo::::connect_to( - agent_client_protocol_core::Lines::new(outgoing_sink, incoming_lines), + let protocol_future = agent_client_protocol::ConnectTo::::connect_to( + agent_client_protocol::Lines::new(outgoing_sink, incoming_lines), client, ); @@ -389,7 +389,7 @@ impl AcpAgent { /// "my-crate", /// ]).unwrap(); /// ``` - pub fn from_args(args: I) -> Result + pub fn from_args(args: I) -> Result where I: IntoIterator, T: ToString, @@ -397,7 +397,7 @@ impl AcpAgent { let args: Vec = args.into_iter().map(|s| s.to_string()).collect(); if args.is_empty() { - return Err(agent_client_protocol_core::util::internal_error( + return Err(agent_client_protocol::util::internal_error( "Arguments cannot be empty", )); } @@ -408,9 +408,7 @@ impl AcpAgent { // Parse leading FOO=bar arguments as environment variables for (i, arg) in args.iter().enumerate() { if let Some((name, value)) = parse_env_var(arg) { - env.push(agent_client_protocol_core::schema::EnvVariable::new( - name, value, - )); + env.push(agent_client_protocol::schema::EnvVariable::new(name, value)); command_idx = i + 1; } else { break; @@ -418,7 +416,7 @@ impl AcpAgent { } if command_idx >= args.len() { - return Err(agent_client_protocol_core::util::internal_error( + return Err(agent_client_protocol::util::internal_error( "No command found (only environment variables provided)", )); } @@ -434,8 +432,8 @@ impl AcpAgent { .to_string(); Ok(AcpAgent { - server: agent_client_protocol_core::schema::McpServer::Stdio( - agent_client_protocol_core::schema::McpServerStdio::new(name, command) + server: agent_client_protocol::schema::McpServer::Stdio( + agent_client_protocol::schema::McpServerStdio::new(name, command) .args(cmd_args) .env(env), ), @@ -471,16 +469,16 @@ fn parse_env_var(s: &str) -> Option<(String, String)> { } impl FromStr for AcpAgent { - type Err = agent_client_protocol_core::Error; + type Err = agent_client_protocol::Error; fn from_str(s: &str) -> Result { let trimmed = s.trim(); // If it starts with '{', try to parse as JSON if trimmed.starts_with('{') { - let server: agent_client_protocol_core::schema::McpServer = - serde_json::from_str(trimmed).map_err(|e| { - agent_client_protocol_core::util::internal_error(format!( + let server: agent_client_protocol::schema::McpServer = serde_json::from_str(trimmed) + .map_err(|e| { + agent_client_protocol::util::internal_error(format!( "Failed to parse JSON: {e}" )) })?; @@ -492,9 +490,7 @@ impl FromStr for AcpAgent { // Otherwise, parse as a command string let parts = shell_words::split(trimmed).map_err(|e| { - agent_client_protocol_core::util::internal_error(format!( - "Failed to parse command: {e}" - )) + agent_client_protocol::util::internal_error(format!("Failed to parse command: {e}")) })?; Self::from_args(parts) @@ -509,7 +505,7 @@ mod tests { fn test_parse_simple_command() { let agent = AcpAgent::from_str("python agent.py").unwrap(); match agent.server { - agent_client_protocol_core::schema::McpServer::Stdio(stdio) => { + agent_client_protocol::schema::McpServer::Stdio(stdio) => { assert_eq!(stdio.name, "python"); assert_eq!(stdio.command, PathBuf::from("python")); assert_eq!(stdio.args, vec!["agent.py"]); @@ -523,7 +519,7 @@ mod tests { fn test_parse_command_with_args() { let agent = AcpAgent::from_str("node server.js --port 8080 --verbose").unwrap(); match agent.server { - agent_client_protocol_core::schema::McpServer::Stdio(stdio) => { + agent_client_protocol::schema::McpServer::Stdio(stdio) => { assert_eq!(stdio.name, "node"); assert_eq!(stdio.command, PathBuf::from("node")); assert_eq!(stdio.args, vec!["server.js", "--port", "8080", "--verbose"]); @@ -537,7 +533,7 @@ mod tests { fn test_parse_command_with_quotes() { let agent = AcpAgent::from_str(r#"python "my agent.py" --name "Test Agent""#).unwrap(); match agent.server { - agent_client_protocol_core::schema::McpServer::Stdio(stdio) => { + agent_client_protocol::schema::McpServer::Stdio(stdio) => { assert_eq!(stdio.name, "python"); assert_eq!(stdio.command, PathBuf::from("python")); assert_eq!(stdio.args, vec!["my agent.py", "--name", "Test Agent"]); @@ -558,7 +554,7 @@ mod tests { }"#; let agent = AcpAgent::from_str(json).unwrap(); match agent.server { - agent_client_protocol_core::schema::McpServer::Stdio(stdio) => { + agent_client_protocol::schema::McpServer::Stdio(stdio) => { assert_eq!(stdio.name, "my-agent"); assert_eq!(stdio.command, PathBuf::from("/usr/bin/python")); assert_eq!(stdio.args, vec!["agent.py", "--verbose"]); @@ -578,7 +574,7 @@ mod tests { }"#; let agent = AcpAgent::from_str(json).unwrap(); match agent.server { - agent_client_protocol_core::schema::McpServer::Http(http) => { + agent_client_protocol::schema::McpServer::Http(http) => { assert_eq!(http.name, "remote-agent"); assert_eq!(http.url, "https://example.com/agent"); assert!(http.headers.is_empty()); diff --git a/src/agent-client-protocol-tokio/src/lib.rs b/src/agent-client-protocol-tokio/src/lib.rs index 5936e0c..0f2075c 100644 --- a/src/agent-client-protocol-tokio/src/lib.rs +++ b/src/agent-client-protocol-tokio/src/lib.rs @@ -7,7 +7,7 @@ mod acp_agent; pub use acp_agent::{AcpAgent, LineDirection}; -use agent_client_protocol_core::{ByteStreams, ConnectTo, Role}; +use agent_client_protocol::{ByteStreams, ConnectTo, Role}; use std::sync::Arc; use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; @@ -49,7 +49,7 @@ impl ConnectTo for Stdio { async fn connect_to( self, client: impl ConnectTo, - ) -> Result<(), agent_client_protocol_core::Error> { + ) -> Result<(), agent_client_protocol::Error> { if let Some(callback) = self.debug_callback { use futures::AsyncBufReadExt; use futures::AsyncWriteExt; @@ -85,7 +85,7 @@ impl ConnectTo for Stdio { as std::pin::Pin + Send>>; ConnectTo::::connect_to( - agent_client_protocol_core::Lines::new(outgoing_sink, incoming_lines), + agent_client_protocol::Lines::new(outgoing_sink, incoming_lines), client, ) .await diff --git a/src/agent-client-protocol-tokio/tests/debug_logging.rs b/src/agent-client-protocol-tokio/tests/debug_logging.rs index 277d212..893255c 100644 --- a/src/agent-client-protocol-tokio/tests/debug_logging.rs +++ b/src/agent-client-protocol-tokio/tests/debug_logging.rs @@ -1,22 +1,22 @@ //! Integration test for AcpAgent debug logging -use agent_client_protocol_core::schema::InitializeRequest; -use agent_client_protocol_core::{Client, ConnectTo}; +use agent_client_protocol::schema::InitializeRequest; +use agent_client_protocol::{Client, ConnectTo}; use agent_client_protocol_test::test_binaries::testy; use agent_client_protocol_tokio::LineDirection; use std::sync::{Arc, Mutex}; /// Test helper to receive a JSON-RPC response -async fn recv( - response: agent_client_protocol_core::SentRequest, -) -> Result { +async fn recv( + response: agent_client_protocol::SentRequest, +) -> Result { let (tx, rx) = tokio::sync::oneshot::channel(); response.on_receiving_result(async move |result| { tx.send(result) - .map_err(|_| agent_client_protocol_core::Error::internal_error()) + .map_err(|_| agent_client_protocol::Error::internal_error()) })?; rx.await - .map_err(|_| agent_client_protocol_core::Error::internal_error())? + .map_err(|_| agent_client_protocol::Error::internal_error())? } #[tokio::test] @@ -58,7 +58,7 @@ async fn test_acp_agent_debug_callback() -> Result<(), Box Result<(), Box::connect_to( agent, - agent_client_protocol_core::ByteStreams::new( + agent_client_protocol::ByteStreams::new( agent_out.compat_write(), agent_in.compat(), ), @@ -76,7 +76,7 @@ async fn test_acp_agent_debug_callback() -> Result<(), Box"] version = "0.10.4" -edition = "2024" -license = "Apache-2.0" -description = "A protocol for standardizing communication between code editors and AI coding agents" -repository = "https://github.com/agentclientprotocol/rust-sdk" -homepage = "https://github.com/agentclientprotocol/rust-sdk" -documentation = "https://docs.rs/agent-client-protocol" -readme = "README.md" -keywords = ["agent", "client", "protocol", "ai", "editor"] -categories = ["development-tools", "api-bindings"] +edition.workspace = true +authors.workspace = true +license.workspace = true +repository.workspace = true +homepage.workspace = true +description = "Core protocol types and traits for the Agent Client Protocol" +keywords = ["acp", "agent", "protocol", "ai"] +categories = ["development-tools"] [features] +default = [] + +# Forward unstable features from agent-client-protocol-schema. +# Enable these to get support for the corresponding unstable ACP methods. unstable = [ "unstable_auth_methods", - "unstable_cancel_request", - "unstable_elicitation", + "unstable_boolean_config", "unstable_logout", - "unstable_nes", + "unstable_message_id", "unstable_session_additional_directories", - "unstable_session_fork", "unstable_session_close", + "unstable_session_fork", "unstable_session_model", "unstable_session_resume", "unstable_session_usage", - "unstable_message_id", - "unstable_boolean_config", ] unstable_auth_methods = ["agent-client-protocol-schema/unstable_auth_methods"] -unstable_cancel_request = ["agent-client-protocol-schema/unstable_cancel_request"] -unstable_elicitation = ["agent-client-protocol-schema/unstable_elicitation"] +unstable_boolean_config = ["agent-client-protocol-schema/unstable_boolean_config"] unstable_logout = ["agent-client-protocol-schema/unstable_logout"] -unstable_nes = ["agent-client-protocol-schema/unstable_nes"] +unstable_message_id = ["agent-client-protocol-schema/unstable_message_id"] unstable_session_additional_directories = ["agent-client-protocol-schema/unstable_session_additional_directories"] +unstable_session_close = ["agent-client-protocol-schema/unstable_session_close"] unstable_session_fork = ["agent-client-protocol-schema/unstable_session_fork"] unstable_session_model = ["agent-client-protocol-schema/unstable_session_model"] unstable_session_resume = ["agent-client-protocol-schema/unstable_session_resume"] unstable_session_usage = ["agent-client-protocol-schema/unstable_session_usage"] -unstable_session_close = ["agent-client-protocol-schema/unstable_session_close"] -unstable_message_id = ["agent-client-protocol-schema/unstable_message_id"] -unstable_boolean_config = ["agent-client-protocol-schema/unstable_boolean_config"] - [dependencies] agent-client-protocol-schema.workspace = true +agent-client-protocol-derive.workspace = true anyhow.workspace = true -async-broadcast.workspace = true -async-trait.workspace = true -derive_more.workspace = true +boxfnonce.workspace = true futures.workspace = true -log.workspace = true +futures-concurrency.workspace = true +rustc-hash.workspace = true +jsonrpcmsg.workspace = true +rmcp = { workspace = true, features = ["server"] } +schemars.workspace = true serde.workspace = true serde_json.workspace = true +thiserror.workspace = true +tokio.workspace = true +tokio-util.workspace = true +tracing.workspace = true +uuid.workspace = true [dev-dependencies] -env_logger.workspace = true -futures-util.workspace = true -piper.workspace = true -pretty_assertions.workspace = true -rustyline.workspace = true +agent-client-protocol-test.workspace = true +clap.workspace = true +expect-test.workspace = true +shell-words.workspace = true tokio.workspace = true -tokio-util.workspace = true [lints] workspace = true diff --git a/src/agent-client-protocol/README.md b/src/agent-client-protocol/README.md index ef510fd..1f6b12a 100644 --- a/src/agent-client-protocol/README.md +++ b/src/agent-client-protocol/README.md @@ -2,27 +2,52 @@ Agent Client Protocol -# Agent Client Protocol +# agent-client-protocol -The Agent Client Protocol (ACP) standardizes communication between _code editors_ (interactive programs for viewing and editing source code) and _coding agents_ (programs that use generative AI to autonomously modify code). +Core protocol types and traits for the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/). -Learn more at [agentclientprotocol.com](https://agentclientprotocol.com/). +ACP is a protocol for communication between AI agents and their clients (IDEs, CLIs, etc.), +enabling features like tool use, permission requests, and streaming responses. -## Integrations +## What can you build with this crate? -- [Schema](./schema/schema.json) -- [Agents](https://agentclientprotocol.com/overview/agents) -- [Clients](https://agentclientprotocol.com/overview/clients) -- Official Libraries - - **Kotlin**: [`acp-kotlin`](https://github.com/agentclientprotocol/kotlin-sdk) - Supports JVM, other targets are in progress, see [samples](https://github.com/agentclientprotocol/kotlin-sdk/tree/master/samples/kotlin-acp-client-sample/src/main/kotlin/com/agentclientprotocol/samples) - - **Python**: [`python-sdk`](https://github.com/agentclientprotocol/python-sdk) - See [examples](https://github.com/agentclientprotocol/python-sdk/tree/main/examples) - - **Rust**: [`agent-client-protocol`](https://crates.io/crates/agent-client-protocol) - See [examples/agent.rs](https://github.com/agentclientprotocol/rust-sdk/blob/main/examples/agent.rs) and [examples/client.rs](https://github.com/agentclientprotocol/rust-sdk/blob/main/examples/client.rs) - - **TypeScript**: [`@agentclientprotocol/sdk`](https://www.npmjs.com/package/@agentclientprotocol/sdk) - See [examples/](https://github.com/agentclientprotocol/typescript-sdk/tree/main/src/examples) -- [Community Libraries](https://agentclientprotocol.com/libraries/community) +- **Clients** that talk to ACP agents (like building your own Claude Code interface) +- **Proxies** that add capabilities to existing agents (like adding custom tools via MCP) +- **Agents** that respond to prompts with AI-powered responses -## Contributing +## Quick Start: Connecting to an Agent -ACP is a protocol intended for broad adoption across the ecosystem; we follow a structured process to ensure changes are well-considered. Read the [Contributing Guide](./CONTRIBUTING.md) for more information. +The most common use case is connecting to an existing ACP agent as a client: + +```rust +use agent_client_protocol::{Client, Agent, ConnectTo}; +use agent_client_protocol::schema::{InitializeRequest, ProtocolVersion}; + +Client.builder() + .name("my-client") + .connect_with(transport, async |cx| { + // Initialize the connection + cx.send_request(InitializeRequest::new(ProtocolVersion::V1)) + .block_task() + .await?; + + Ok(()) + }) + .await?; +``` + +## Learning More + +See the [crate documentation](https://docs.rs/agent-client-protocol) for: + +- **[Cookbook](https://docs.rs/agent-client-protocol/latest/agent_client_protocol/cookbook/)** — Patterns for building clients, proxies, and agents +- **[Examples](https://github.com/agentclientprotocol/rust-sdk/tree/main/src/agent-client-protocol/examples)** — Working code you can run + +## Related Crates + +- **[agent-client-protocol-tokio](../agent-client-protocol-tokio/)** — Tokio utilities for spawning agent processes +- **[agent-client-protocol-derive](../agent-client-protocol-derive/)** — Derive macros for JSON-RPC traits +- **[agent-client-protocol-trace-viewer](../agent-client-protocol-trace-viewer/)** — Interactive trace visualization ## Contribution Policy diff --git a/src/agent-client-protocol/examples/agent.rs b/src/agent-client-protocol/examples/agent.rs deleted file mode 100644 index 7eb32ba..0000000 --- a/src/agent-client-protocol/examples/agent.rs +++ /dev/null @@ -1,198 +0,0 @@ -//! A simple ACP agent server for educational purposes. -//! -//! The agent communicates with clients over stdio. To run it with logging: -//! -//! ```bash -//! RUST_LOG=info cargo run --example agent -//! ``` -//! -//! To connect it to the example client from this crate: -//! -//! ```bash -//! cargo build --example agent && cargo run --example client -- target/debug/examples/agent -//! ``` - -use std::cell::Cell; - -use agent_client_protocol::{self as acp, Client as _}; -use serde_json::json; -use tokio::sync::{mpsc, oneshot}; -use tokio_util::compat::{TokioAsyncReadCompatExt as _, TokioAsyncWriteCompatExt as _}; - -struct ExampleAgent { - session_update_tx: mpsc::UnboundedSender<(acp::SessionNotification, oneshot::Sender<()>)>, - next_session_id: Cell, -} - -impl ExampleAgent { - fn new( - session_update_tx: mpsc::UnboundedSender<(acp::SessionNotification, oneshot::Sender<()>)>, - ) -> Self { - Self { - session_update_tx, - next_session_id: Cell::new(0), - } - } -} - -#[async_trait::async_trait(?Send)] -impl acp::Agent for ExampleAgent { - async fn initialize( - &self, - arguments: acp::InitializeRequest, - ) -> Result { - log::info!("Received initialize request {arguments:?}"); - Ok(acp::InitializeResponse::new(acp::ProtocolVersion::V1) - .agent_info(acp::Implementation::new("example-agent", "0.1.0").title("Example Agent"))) - } - - async fn authenticate( - &self, - arguments: acp::AuthenticateRequest, - ) -> Result { - log::info!("Received authenticate request {arguments:?}"); - Ok(acp::AuthenticateResponse::default()) - } - - async fn new_session( - &self, - arguments: acp::NewSessionRequest, - ) -> Result { - log::info!("Received new session request {arguments:?}"); - let session_id = self.next_session_id.get(); - self.next_session_id.set(session_id + 1); - Ok(acp::NewSessionResponse::new(session_id.to_string())) - } - - async fn load_session( - &self, - arguments: acp::LoadSessionRequest, - ) -> Result { - log::info!("Received load session request {arguments:?}"); - Ok(acp::LoadSessionResponse::new()) - } - - async fn prompt( - &self, - arguments: acp::PromptRequest, - ) -> Result { - log::info!("Received prompt request {arguments:?}"); - for content in ["Client sent: ".into()].into_iter().chain(arguments.prompt) { - let (tx, rx) = oneshot::channel(); - self.session_update_tx - .send(( - acp::SessionNotification::new( - arguments.session_id.clone(), - acp::SessionUpdate::AgentMessageChunk(acp::ContentChunk::new(content)), - ), - tx, - )) - .map_err(|_| acp::Error::internal_error())?; - rx.await.map_err(|_| acp::Error::internal_error())?; - } - Ok(acp::PromptResponse::new(acp::StopReason::EndTurn)) - } - - async fn cancel(&self, args: acp::CancelNotification) -> Result<(), acp::Error> { - log::info!("Received cancel request {args:?}"); - Ok(()) - } - - async fn set_session_mode( - &self, - args: acp::SetSessionModeRequest, - ) -> Result { - log::info!("Received set session mode request {args:?}"); - Ok(acp::SetSessionModeResponse::default()) - } - - #[cfg(feature = "unstable_session_model")] - async fn set_session_model( - &self, - args: acp::SetSessionModelRequest, - ) -> Result { - log::info!("Received select model request {args:?}"); - Ok(acp::SetSessionModelResponse::default()) - } - - async fn set_session_config_option( - &self, - args: acp::SetSessionConfigOptionRequest, - ) -> Result { - log::info!("Received set session config option request {args:?}"); - #[cfg(feature = "unstable_boolean_config")] - let value = args - .value - .as_value_id() - .ok_or(acp::Error::invalid_params())? - .clone(); - #[cfg(not(feature = "unstable_boolean_config"))] - let value: acp::SessionConfigValueId = args.value.into(); - let option = acp::SessionConfigOption::select( - args.config_id, - "Example Option", - value, - vec![ - acp::SessionConfigSelectOption::new("option1", "Option 1"), - acp::SessionConfigSelectOption::new("option2", "Option 2"), - ], - ); - Ok(acp::SetSessionConfigOptionResponse::new(vec![option])) - } - - async fn ext_method(&self, args: acp::ExtRequest) -> Result { - log::info!( - "Received extension method call: method={}, params={:?}", - args.method, - args.params - ); - Ok(acp::ExtResponse::new( - serde_json::value::to_raw_value(&json!({"example": "response"}))?.into(), - )) - } - - async fn ext_notification(&self, args: acp::ExtNotification) -> Result<(), acp::Error> { - log::info!( - "Received extension notification: method={}, params={:?}", - args.method, - args.params - ); - Ok(()) - } -} - -#[tokio::main(flavor = "current_thread")] -async fn main() -> acp::Result<()> { - env_logger::init(); - - let outgoing = tokio::io::stdout().compat_write(); - let incoming = tokio::io::stdin().compat(); - - // The AgentSideConnection will spawn futures onto our Tokio runtime. - // LocalSet and spawn_local are used because the futures from the - // agent-client-protocol crate are not Send. - let local_set = tokio::task::LocalSet::new(); - local_set - .run_until(async move { - let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel(); - // Start up the ExampleAgent connected to stdio. - let (conn, handle_io) = - acp::AgentSideConnection::new(ExampleAgent::new(tx), outgoing, incoming, |fut| { - tokio::task::spawn_local(fut); - }); - // Kick off a background task to send the ExampleAgent's session notifications to the client. - tokio::task::spawn_local(async move { - while let Some((session_notification, tx)) = rx.recv().await { - let result = conn.session_notification(session_notification).await; - if let Err(e) = result { - log::error!("{e}"); - break; - } - tx.send(()).ok(); - } - }); - // Run until stdin/stdout are closed. - handle_io.await - }) - .await -} diff --git a/src/agent-client-protocol/examples/client.rs b/src/agent-client-protocol/examples/client.rs deleted file mode 100644 index 34736ae..0000000 --- a/src/agent-client-protocol/examples/client.rs +++ /dev/null @@ -1,173 +0,0 @@ -//! A simple ACP client for educational purposes. -//! -//! The client starts an agent as a subprocess and communicates with it over stdio. Run the client like this: -//! -//! ```bash -//! cargo run --example client -- path/to/agent --agent-arg -//! ``` -//! -//! To connect it to the example agent from this crate: -//! -//! ```bash -//! cargo build --example agent && cargo run --example client -- target/debug/examples/agent -//! ``` - -use agent_client_protocol::{self as acp, Agent as _}; -use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; - -struct ExampleClient {} - -#[async_trait::async_trait(?Send)] -impl acp::Client for ExampleClient { - async fn request_permission( - &self, - _args: acp::RequestPermissionRequest, - ) -> acp::Result { - Err(acp::Error::method_not_found()) - } - - async fn write_text_file( - &self, - _args: acp::WriteTextFileRequest, - ) -> acp::Result { - Err(acp::Error::method_not_found()) - } - - async fn read_text_file( - &self, - _args: acp::ReadTextFileRequest, - ) -> acp::Result { - Err(acp::Error::method_not_found()) - } - - async fn create_terminal( - &self, - _args: acp::CreateTerminalRequest, - ) -> Result { - Err(acp::Error::method_not_found()) - } - - async fn terminal_output( - &self, - _args: acp::TerminalOutputRequest, - ) -> acp::Result { - Err(acp::Error::method_not_found()) - } - - async fn release_terminal( - &self, - _args: acp::ReleaseTerminalRequest, - ) -> acp::Result { - Err(acp::Error::method_not_found()) - } - - async fn wait_for_terminal_exit( - &self, - _args: acp::WaitForTerminalExitRequest, - ) -> acp::Result { - Err(acp::Error::method_not_found()) - } - - async fn kill_terminal( - &self, - _args: acp::KillTerminalRequest, - ) -> acp::Result { - Err(acp::Error::method_not_found()) - } - - async fn session_notification( - &self, - args: acp::SessionNotification, - ) -> acp::Result<(), acp::Error> { - if let acp::SessionUpdate::AgentMessageChunk(acp::ContentChunk { content, .. }) = - args.update - { - let text = match content { - acp::ContentBlock::Text(text_content) => text_content.text, - acp::ContentBlock::Image(_) => "".into(), - acp::ContentBlock::Audio(_) => "