From 8739b6166a31121a24061d9d0f8a1105fe8aab50 Mon Sep 17 00:00:00 2001 From: Travis Gockel Date: Mon, 13 Jul 2026 18:22:09 -0600 Subject: [PATCH] chore: bring dependencies up to the latest versions Bump rmcp 1.8 -> 2.2 and rig-core 0.39 -> 0.40 (the two upgrades with breaking API changes) plus routine patch/minor bumps (anyhow, ignore, jiff, rand, toml/toml_edit) and a full Cargo.lock refresh. rmcp 2.x realigned its content model to the 2025-11-25 MCP spec: the Annotated wrapper collapsed into a flat, #[non_exhaustive] ContentBlock enum. The proxy, client, and self-server match on ContentBlock directly, with wildcard arms for the non-exhaustive enums. rig-core 0.40 replaced the two-method PromptHook with a unified AgentHook::on_event(StepEvent), dropped ToolDyn::definition for sync description()/parameters(), and renamed the prompt-builder setters. The tool-call tracer is ported onto on_event and narrows observes() to stay off the per-token streaming delta path. max_turns now counts total model calls rather than tool-call rounds, so the rig-side backstop is passed tool_call_max + 2 to preserve the prior allowance; outrig's per-turn hook remains the limiter that fires first, so the observable tool-call ceiling is unchanged. candle-core, hf-hub, and regex are held on purpose: mistralrs-core 0.8.1 (already the latest) requires candle-core ^0.10.2 and hf-hub ^0.4.3, and its serde-saphyr dep caps regex below 1.13. --- Cargo.lock | 356 +++++++++--------- Cargo.toml | 12 +- crates/outrig-cli/CHANGELOG.md | 7 + crates/outrig-cli/src/llm.rs | 93 +++-- crates/outrig-cli/src/mcp_self/server.rs | 22 +- crates/outrig-cli/src/rig_tool.rs | 15 +- crates/outrig-cli/tests/mcp_self.rs | 6 +- crates/outrig-cli/tests/mcp_sidecar_smoke.rs | 4 +- .../outrig-cli/tests/mcp_subcommand_smoke.rs | 4 +- crates/outrig/CHANGELOG.md | 6 + crates/outrig/src/mcp.rs | 16 +- crates/outrig/src/mcp_proxy.rs | 12 +- crates/outrig/tests/mcp_proxy_dispatch.rs | 4 +- 13 files changed, 283 insertions(+), 274 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 979ea4f..5a1597f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -127,7 +127,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -138,7 +138,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -193,9 +193,9 @@ checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02882884d3e1bc524fb12c79f107f6ad0e1cfd498c536ffb494301740995dfe" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" [[package]] name = "as-any" @@ -302,9 +302,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" +checksum = "4342d8937fc7e5dd9b1c60292261c0670c882a2cd1719cfc11b1af41731e32ad" dependencies = [ "aws-lc-sys", "zeroize", @@ -312,14 +312,15 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.41.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" +checksum = "6d9ceb1da931507a12f4fccea479dccd00da1943e1b4ae72d8e502d707361444" dependencies = [ "cc", "cmake", "dunce", "fs_extra", + "pkg-config", ] [[package]] @@ -523,18 +524,18 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytemuck" -version = "1.25.0" +version = "1.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +checksum = "d6aedf8ae72766347502cf3cb4f41cf5e9cc37d28bee90f1fdaaae15f9cf9424" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.10.2" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +checksum = "f65693059b6b9c588b9f62fed1cedbf0a8b805631457ea162d68f0de186f3de5" dependencies = [ "proc-macro2", "quote", @@ -555,9 +556,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "cached" @@ -612,7 +613,7 @@ dependencies = [ "num_cpus", "objc2-foundation", "objc2-metal", - "rand 0.9.4", + "rand 0.9.5", "rand_distr 0.5.1", "rayon", "safetensors 0.7.0", @@ -686,9 +687,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.65" +version = "1.2.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" +checksum = "e17dd265a7d0f31ef544e1b20e03add05d3b45b491b633b10d67145d2acc1a38" dependencies = [ "find-msvc-tools", "jobserver", @@ -849,9 +850,9 @@ dependencies = [ [[package]] name = "console" -version = "0.16.3" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" +checksum = "4fe5f465a4f6fee88fad41b85d990f84c835335e85b5d9e6e63e0d06d28cba7c" dependencies = [ "encode_unicode", "libc", @@ -931,9 +932,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -941,18 +942,18 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "crossterm" @@ -1206,9 +1207,9 @@ checksum = "aafbece59594ed57696a1a69e8bb3ca1683fbc9cdb41d5c02726070b2cd8f19d" [[package]] name = "defmt" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6e524506490a1953d237cb87b1cfc1e46f88c18f10a22dfe0f507dc6bfc7f7f" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" dependencies = [ "bitflags 1.3.2", "defmt-macros", @@ -1216,12 +1217,11 @@ dependencies = [ [[package]] name = "defmt-macros" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a27770e9c8f719a79d8b638281f4d828f77d8fd61e0bd94451b9b85e576a0b" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" dependencies = [ "defmt-parser", - "proc-macro-error2", "proc-macro2", "quote", "syn 2.0.118", @@ -1334,7 +1334,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25f104b501bf2364e78d0d3974cbc774f738f5865306ed128e1e0d7499c0ad96" dependencies = [ - "console 0.16.3", + "console 0.16.4", "fuzzy-matcher", "shell-words", "tempfile", @@ -1378,7 +1378,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1548,7 +1548,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -1570,14 +1570,16 @@ dependencies = [ [[package]] name = "exr" -version = "1.74.0" +version = "1.74.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" +checksum = "711fe42c9964295e01ee3fba3f9fe0e1d24b98886950d68efe81b1c76e21adf3" dependencies = [ "bit_field", "half", "lebe", "miniz_oxide", + "num-complex", + "pulp 0.22.3", "rayon-core", "smallvec 1.15.2", "zune-inflate", @@ -1656,7 +1658,7 @@ checksum = "c2d1f04709a8ac06e8e8042875a3c466cc4832d3c1a18dbcb9dba3c6e83046bc" dependencies = [ "half", "num-traits", - "rand 0.9.4", + "rand 0.9.5", "rand_distr 0.5.1", ] @@ -2157,9 +2159,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi 6.0.0", "rand_core 0.10.1", + "wasm-bindgen", ] [[package]] @@ -2232,7 +2236,7 @@ dependencies = [ "cfg-if", "crunchy", "num-traits", - "rand 0.9.4", + "rand 0.9.5", "rand_distr 0.5.1", "zerocopy", ] @@ -2304,7 +2308,7 @@ dependencies = [ "libc", "log", "num_cpus", - "rand 0.9.4", + "rand 0.9.5", "reqwest 0.12.28", "serde", "serde_json", @@ -2327,7 +2331,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12d23156ea4dbe6b37ad48fab2da56ff27b0f6192fb5db210c44eb07bfe6e787" dependencies = [ "html5ever 0.38.0", - "tendril 0.5.0", + "tendril 0.5.1", "thiserror 2.0.18", "unicode-width", ] @@ -2364,9 +2368,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" dependencies = [ "bytes", "http", @@ -2374,9 +2378,9 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2" dependencies = [ "bytes", "futures-core", @@ -2595,9 +2599,9 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe112b004901c62c2faa11f4f75e9864e0cc5af8da71c9115d184a3aa888749f" +checksum = "2adf14691c72bcfc1058740436a35bdd3ae9c07d1a941ef00b749e9ea16aefa7" dependencies = [ "crossbeam-deque", "globset", @@ -2687,11 +2691,11 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.18.4" +version = "0.18.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" +checksum = "9433806cd6b4ec1aba79c021c7e4c58fb4c3b9977c085062e611ac929998fb0c" dependencies = [ - "console 0.16.3", + "console 0.16.4", "portable-atomic", "rayon", "unicode-width", @@ -2752,9 +2756,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccfe6121cbe750cf81efa362d85c0bde7ea298ec43092d3a193baca59cdbd634" +checksum = "961d16382652bfdd8c6f68b223b26a8c93e0d475c672f414411db31c6c5c900e" dependencies = [ "defmt", "jiff-static", @@ -2768,9 +2772,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e165e897f662d428f3cd3828a919dbe067c2d42bb1031eede74ef9d27ecdedd2" +checksum = "d0879bd39df99c4c5e2c6615ccc026391a423dde10532c573e6086eb94a802cc" dependencies = [ "proc-macro2", "quote", @@ -2779,9 +2783,9 @@ dependencies = [ [[package]] name = "jiff-tzdb" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c900ef84826f1338a557697dc8fc601df9ca9af4ac137c7fb61d4c6f2dfd3076" +checksum = "142bd39932ad231f10513df9ab62661fead8719872150b7ad02a2df79f4e141e" [[package]] name = "jiff-tzdb-platform" @@ -2843,11 +2847,11 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.3", "libc", ] @@ -2918,9 +2922,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" dependencies = [ "libc", ] @@ -3044,7 +3048,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8983d30f2915feeaaab2d6babdd6bc7e9ed1a00b66b5e6d74df19aa9c0e91862" dependencies = [ "log", - "tendril 0.5.0", + "tendril 0.5.1", "web_atoms", ] @@ -3085,9 +3089,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "memmap2" @@ -3187,9 +3191,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" +checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" dependencies = [ "libc", "wasi", @@ -3247,7 +3251,7 @@ dependencies = [ "http", "image", "indexmap 2.14.0", - "indicatif 0.18.4", + "indicatif 0.18.6", "interprocess", "itertools", "libc", @@ -3267,7 +3271,7 @@ dependencies = [ "ordered-float", "parking_lot", "radix_trie", - "rand 0.9.4", + "rand 0.9.5", "rand_distr 0.5.1", "rand_isaac", "rayon", @@ -3276,7 +3280,7 @@ dependencies = [ "reqwest 0.13.4", "rubato", "rust-mcp-schema", - "rustc-hash 2.1.2", + "rustc-hash 2.1.3", "rustfft", "safetensors 0.7.0", "schemars 1.2.1", @@ -3302,7 +3306,7 @@ dependencies = [ "tracing", "tracing-subscriber", "urlencoding", - "uuid 1.23.4", + "uuid 1.23.5", "variantly", "vob", ] @@ -3325,7 +3329,7 @@ dependencies = [ "tokio-tungstenite", "tracing", "utoipa", - "uuid 1.23.4", + "uuid 1.23.5", ] [[package]] @@ -3431,21 +3435,12 @@ dependencies = [ "num-complex", "num-rational", "num-traits", - "rand 0.8.6", + "rand 0.8.7", "rand_distr 0.4.3", "simba", "typenum", ] -[[package]] -name = "nanoid" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" -dependencies = [ - "rand 0.8.6", -] - [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -3528,7 +3523,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3547,9 +3542,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" dependencies = [ "num-integer", "num-traits", @@ -3593,11 +3588,10 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b" dependencies = [ - "autocfg", "num-integer", "num-traits", ] @@ -4066,28 +4060,6 @@ dependencies = [ "num-integer", ] -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn 2.0.118", -] - [[package]] name = "proc-macro2" version = "1.0.106" @@ -4169,9 +4141,9 @@ checksum = "1d8f70e07b9c3962945a74e59ca1c511bba65b6419468acc217c457d93f3c740" [[package]] name = "pxfm" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" +checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" [[package]] name = "qoi" @@ -4199,7 +4171,7 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.1.2", + "rustc-hash 2.1.3", "rustls", "socket2", "thiserror 2.0.18", @@ -4210,17 +4182,18 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.15" +version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fcb935c5bec503c2f0e306bdd3e58bb9029dcb14fa8d9ac76e3a5256ac0763e" +checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" dependencies = [ "aws-lc-rs", "bytes", - "getrandom 0.3.4", + "getrandom 0.4.3", "lru-slab", - "rand 0.9.4", + "rand 0.10.2", + "rand_pcg", "ring", - "rustc-hash 2.1.2", + "rustc-hash 2.1.3", "rustls", "rustls-pki-types", "slab", @@ -4232,16 +4205,16 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" dependencies = [ "cfg_aliases", "libc", "once_cell", "socket2", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -4277,9 +4250,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -4288,9 +4261,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -4358,7 +4331,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand 0.8.6", + "rand 0.8.7", ] [[package]] @@ -4368,7 +4341,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463" dependencies = [ "num-traits", - "rand 0.9.4", + "rand 0.9.5", ] [[package]] @@ -4380,6 +4353,15 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand_pcg" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" +dependencies = [ + "rand_core 0.10.1", +] + [[package]] name = "rav1e" version = "0.8.1" @@ -4407,7 +4389,7 @@ dependencies = [ "num-traits", "paste", "profiling", - "rand 0.9.4", + "rand 0.9.5", "rand_chacha 0.9.0", "simd_helpers", "thiserror 2.0.18", @@ -4551,9 +4533,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +checksum = "1f388202e4b80542a0921078cc23b6333bcf1409c1e3f86404cae4766a6131db" dependencies = [ "aho-corasick", "memchr", @@ -4665,9 +4647,9 @@ checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" [[package]] name = "rig-core" -version = "0.39.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80a4bc7a93b329c4e1a66d5fd211d79990e7331e3c701f057c29f135f548686d" +checksum = "d8731dd5532b3a12ce1613af73073fb2051ef750f50c504778c21d55ae933cac" dependencies = [ "as-any", "async-stream", @@ -4682,7 +4664,6 @@ dependencies = [ "indexmap 2.14.0", "mime", "mime_guess", - "nanoid", "ordered-float", "pin-project-lite", "reqwest 0.13.4", @@ -4713,9 +4694,9 @@ dependencies = [ [[package]] name = "rmcp" -version = "1.8.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1f571c72940a19d9532fe52dbea8bc9912bf1d766c2970bb824056b86f3f59" +checksum = "14db48ee17a9ba61810ab1a9c1beb7d06d8136ae39ac25a1137f10d357af01af" dependencies = [ "async-trait", "base64 0.22.1", @@ -4740,14 +4721,14 @@ dependencies = [ "tokio-util", "tower-service", "tracing", - "uuid 1.23.4", + "uuid 1.23.5", ] [[package]] name = "rmcp-macros" -version = "1.8.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aad0035b69380782d78ea95b508327e6deaa2235909053e596eea8f27b5e1d5" +checksum = "783d787bf21813b285f13019adc49e11af501c658890c1e519f31f937c68b7e3" dependencies = [ "darling 0.23.0", "proc-macro2", @@ -4796,9 +4777,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustc_version" @@ -4833,14 +4814,14 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.41" +version = "0.23.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" +checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138" dependencies = [ "aws-lc-rs", "log", @@ -4866,9 +4847,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" dependencies = [ "web-time", "zeroize", @@ -4892,7 +4873,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -4915,9 +4896,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "ryu" @@ -5080,7 +5061,7 @@ dependencies = [ "phf", "phf_codegen", "precomputed-hash", - "rustc-hash 2.1.2", + "rustc-hash 2.1.3", "servo_arc", "smallvec 1.15.2", ] @@ -5260,9 +5241,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8" dependencies = [ "cfg-if", "cpufeatures 0.2.17", @@ -5353,9 +5334,9 @@ checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "simd_cesu8" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" dependencies = [ "rustc_version", "simdutf8", @@ -5402,12 +5383,12 @@ checksum = "ef784004ca8777809dcdad6ac37629f0a97caee4c685fcea805278d81dd8b857" [[package]] name = "socket2" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -5446,9 +5427,9 @@ dependencies = [ [[package]] name = "sse-stream" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3962b63f038885f15bce2c6e02c0e7925c072f1ac86bb60fd44c5c6b762fb72" +checksum = "39f24a9b78c40b90817bbcd1821c74ddfd74916aadd29403d001532a9195532d" dependencies = [ "bytes", "futures-util", @@ -5478,7 +5459,7 @@ dependencies = [ "approx", "nalgebra", "num-traits", - "rand 0.8.6", + "rand 0.8.7", ] [[package]] @@ -5813,10 +5794,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -5832,12 +5813,11 @@ dependencies = [ [[package]] name = "tendril" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4790fc369d5a530f4b544b094e31388b9b3a37c0f4652ade4505945f5660d24" +checksum = "5fed54709c5b3a53d09bb1c113ea4f5ceafd1e772ddcb0030a82e1d56c087b08" dependencies = [ "new_debug_unreachable", - "utf-8", ] [[package]] @@ -5847,7 +5827,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5892,9 +5872,9 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" dependencies = [ "cfg-if", ] @@ -5915,9 +5895,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.51" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c17d80feb7334b40c484e45ed1a5273dfd8bfda537c3be2e74a06a6686f327" +checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" dependencies = [ "deranged", "num-conv", @@ -5935,9 +5915,9 @@ checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.30" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcef1a61bdb119096e153208ec5cbec23944ce8bca13be5c7f60c634f7403935" +checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f" dependencies = [ "num-conv", "time-core", @@ -5955,9 +5935,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" dependencies = [ "tinyvec_macros", ] @@ -5987,7 +5967,7 @@ dependencies = [ "macro_rules_attribute", "monostate", "paste", - "rand 0.9.4", + "rand 0.9.5", "rayon", "rayon-cond", "regex", @@ -6020,7 +6000,7 @@ dependencies = [ "monostate", "onig", "paste", - "rand 0.9.4", + "rand 0.9.5", "rayon", "rayon-cond", "regex", @@ -6042,7 +6022,7 @@ checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", - "mio 1.2.1", + "mio 1.2.2", "parking_lot", "pin-project-lite", "signal-hook-registry", @@ -6176,7 +6156,7 @@ dependencies = [ "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "toml_writer", - "winnow 1.0.3", + "winnow 1.0.4", ] [[package]] @@ -6207,7 +6187,7 @@ dependencies = [ "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "toml_writer", - "winnow 1.0.3", + "winnow 1.0.4", ] [[package]] @@ -6216,7 +6196,7 @@ version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.3", + "winnow 1.0.4", ] [[package]] @@ -6381,7 +6361,7 @@ dependencies = [ "http", "httparse", "log", - "rand 0.9.4", + "rand 0.9.5", "rustls", "rustls-pki-types", "sha1", @@ -6595,9 +6575,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.23.4" +version = "1.23.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53" +checksum = "ea5fab0d6c3c01ae70085a09cb03d4c7a1d6314e2b3e075392783396d724ca0a" dependencies = [ "getrandom 0.4.3", "js-sys", @@ -6881,7 +6861,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -7339,9 +7319,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" [[package]] name = "winnow" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" dependencies = [ "memchr", ] @@ -7419,18 +7399,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.52" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" +checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.52" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" +checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" dependencies = [ "proc-macro2", "quote", @@ -7511,9 +7491,9 @@ dependencies = [ [[package]] name = "zmij" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" [[package]] name = "zune-core" diff --git a/Cargo.toml b/Cargo.toml index 215b242..37e40fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ keywords = ["llm", "agent", "mcp", "podman", "sandbox"] categories = ["command-line-utilities", "development-tools"] [workspace.dependencies] -anyhow = { version = "1.0.102", default-features = false } +anyhow = { version = "1.0.103", default-features = false } async-stream = { version = "0.3.6", default-features = false } axum = { version = "0.8.9", default-features = false } blake3 = { version = "1.8.5", default-features = false } @@ -26,16 +26,16 @@ directories = { version = "6.0.0", default-features = false } futures-util = { version = "0.3.32", default-features = false } heck = { version = "0.5.0", default-features = false } hf-hub = { version = "=0.4.3", default-features = false } -ignore = { version = "0.4.26", default-features = false } +ignore = { version = "0.4.28", default-features = false } indexmap = { version = "2.14.0", default-features = false } -jiff = { version = "0.2.29", default-features = false } +jiff = { version = "0.2.32", default-features = false } mistralrs-core = { version = "=0.8.1", default-features = false } nix = { version = "0.31.3", default-features = false } -rand = { version = "0.10.1", default-features = false } +rand = { version = "0.10.2", default-features = false } regex = { version = "1.12.4", default-features = false } reqwest = { version = "0.13.4", default-features = false } -rig = { version = "0.39.0", default-features = false, package = "rig-core" } -rmcp = { version = "1.8.0", default-features = false } +rig = { version = "0.40.0", default-features = false, package = "rig-core" } +rmcp = { version = "2.2.0", default-features = false } schemars = { version = "1.2.1", default-features = false } serde = { version = "1.0.228", default-features = false } serde_json = { version = "1.0.150", default-features = false } diff --git a/crates/outrig-cli/CHANGELOG.md b/crates/outrig-cli/CHANGELOG.md index d30147e..7ea9cd5 100644 --- a/crates/outrig-cli/CHANGELOG.md +++ b/crates/outrig-cli/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- Upgraded the LLM/agent stack: `rig-core` 0.39 -> 0.40 and the `rmcp` MCP SDK + 1.x -> 2.x, plus routine dependency bumps (anyhow, ignore, jiff, rand, toml). + rig 0.40's `max_turns` now counts total model calls rather than tool-call + rounds; outrig compensates so the per-turn tool-call limit behaves as before. + ## [0.1.0](https://github.com/tgockel/outrig/releases/tag/outrig-cli-v0.1.0) - 2026-06-26 ### Added diff --git a/crates/outrig-cli/src/llm.rs b/crates/outrig-cli/src/llm.rs index 759e297..f31c106 100644 --- a/crates/outrig-cli/src/llm.rs +++ b/crates/outrig-cli/src/llm.rs @@ -8,12 +8,12 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; #[cfg(feature = "local-llm")] use futures_util::StreamExt; -use rig::agent::{HookAction, PromptHook, ToolCallHookAction}; +use rig::agent::{AgentHook, Flow, HookContext, StepEvent, StepEventKind}; #[cfg(feature = "local-llm")] use rig::agent::{MultiTurnStreamItem, StreamingError}; use rig::completion::{CompletionModel, Message, Prompt}; #[cfg(feature = "local-llm")] -use rig::streaming::{StreamedAssistantContent, StreamingPrompt}; +use rig::streaming::{StreamedAssistantContent, StreamingChat}; use thiserror::Error; #[cfg(feature = "local-llm")] use tokio::io::{AsyncWrite, AsyncWriteExt}; @@ -22,9 +22,13 @@ use crate::error::Result; use crate::rig_tool::McpToolAdapter; use outrig::config::{Config, DEFAULT_TOOL_CALL_MAX, LlmProvider, MistralrsDeviceSpec}; -/// Hard max on tool calls per turn. The hook below trips this; rig's own -/// `max_turns` is set to the same value as a defense in depth, so whichever -/// fires first surfaces a controllable message. +/// Hard max on tool calls per turn. The per-turn [`OutrigPromptHook`] trips +/// this and surfaces a controllable message. rig's own `max_turns` is a +/// backstop set a little higher: as of rig 0.40 it counts *total* model calls +/// (initial completion + one continuation per tool call) rather than the looser +/// 0.39 budget, so callers pass `tool_call_max + 2` to preserve the previous +/// effective allowance and keep the hook -- not rig -- the limiter that fires +/// first. pub const MAX_TOOL_CALLS: usize = DEFAULT_TOOL_CALL_MAX as usize; /// Default byte ceiling applied to each individual MCP tool result before it @@ -603,9 +607,9 @@ async fn run_turn_inner( let hook = OutrigPromptHook::new(tool_call_max); let result = agent .prompt(prompt.to_string()) - .with_history(history.clone()) - .max_turns(tool_call_max) - .with_hook(hook) + .history(history.clone()) + .max_turns(tool_call_max + 2) + .add_hook(hook) .extended_details() .await; @@ -646,10 +650,9 @@ where { let hook = OutrigPromptHook::new(tool_call_max); let mut stream = agent - .stream_prompt(prompt.to_string()) - .with_history(history.clone()) - .multi_turn(tool_call_max) - .with_hook(hook) + .stream_chat(prompt.to_string(), history.clone()) + .max_turns(tool_call_max + 2) + .add_hook(hook) .await; let mut streamed_reply = String::new(); @@ -668,7 +671,7 @@ where stdout.flush().await?; } Ok(MultiTurnStreamItem::FinalResponse(response)) => { - final_history = response.history().map(|messages| messages.to_vec()); + final_history = response.messages().map(|messages| messages.to_vec()); } Ok(_) => {} Err(err) => { @@ -762,36 +765,46 @@ impl OutrigPromptHook { } } -impl PromptHook for OutrigPromptHook { - async fn on_completion_call(&self, _prompt: &Message, _history: &[Message]) -> HookAction { - if self.cap_reached.load(Ordering::SeqCst) { - return HookAction::terminate(format!( - "tool-call iteration max ({}) reached; ending turn", - self.max - )); - } - HookAction::cont() +impl AgentHook for OutrigPromptHook { + // The hook only acts on `CompletionCall` and `ToolCall`; narrowing + // `observes` keeps it off the per-token `TextDelta`/`ToolCallDelta` stream + // in the streaming path, where `on_event` below would just no-op anyway. + fn observes(&self, kind: StepEventKind) -> bool { + matches!( + kind, + StepEventKind::CompletionCall | StepEventKind::ToolCall + ) } - async fn on_tool_call( - &self, - tool_name: &str, - _tool_call_id: Option, - _internal_call_id: &str, - args: &str, - ) -> ToolCallHookAction { - let n = self.counter.fetch_add(1, Ordering::SeqCst) + 1; - if n > self.max { - self.cap_reached.store(true, Ordering::SeqCst); - return ToolCallHookAction::skip(format!( - "[outrig] tool call not executed: per-turn tool-call max ({}) \ - was reached before this call could run. The user may continue \ - with a fresh max; repeat the tool call if still needed.", - self.max - )); + async fn on_event(&self, _ctx: &HookContext, event: StepEvent<'_, M>) -> Flow { + match event { + StepEvent::CompletionCall { .. } => { + if self.cap_reached.load(Ordering::SeqCst) { + return Flow::terminate(format!( + "tool-call iteration max ({}) reached; ending turn", + self.max + )); + } + Flow::cont() + } + StepEvent::ToolCall { + tool_name, args, .. + } => { + let n = self.counter.fetch_add(1, Ordering::SeqCst) + 1; + if n > self.max { + self.cap_reached.store(true, Ordering::SeqCst); + return Flow::skip(format!( + "[outrig] tool call not executed: per-turn tool-call max ({}) \ + was reached before this call could run. The user may continue \ + with a fresh max; repeat the tool call if still needed.", + self.max + )); + } + eprintln!("[outrig] tool call: {tool_name}({args})"); + Flow::cont() + } + _ => Flow::cont(), } - eprintln!("[outrig] tool call: {tool_name}({args})"); - ToolCallHookAction::cont() } } diff --git a/crates/outrig-cli/src/mcp_self/server.rs b/crates/outrig-cli/src/mcp_self/server.rs index 2f2bd01..580c181 100644 --- a/crates/outrig-cli/src/mcp_self/server.rs +++ b/crates/outrig-cli/src/mcp_self/server.rs @@ -3,8 +3,8 @@ use std::sync::Arc; use rmcp::ErrorData as McpError; use rmcp::ServerHandler; use rmcp::model::{ - CallToolRequestParams, CallToolResult, Content, Implementation, JsonObject, ListToolsResult, - PaginatedRequestParams, ServerCapabilities, ServerInfo, Tool, ToolAnnotations, + CallToolRequestParams, CallToolResult, ContentBlock, Implementation, JsonObject, + ListToolsResult, PaginatedRequestParams, ServerCapabilities, ServerInfo, Tool, ToolAnnotations, }; use rmcp::service::{RequestContext, RoleServer}; use schemars::JsonSchema; @@ -117,7 +117,7 @@ impl SelfServer { }; match docs::get_doc(&args.page) { Some(doc) => json_result(doc), - None => Ok(CallToolResult::error(vec![Content::text(format!( + None => Ok(CallToolResult::error(vec![ContentBlock::text(format!( "unknown doc page: {}", args.page ))])), @@ -147,7 +147,7 @@ impl SelfServer { }; json_result(validate::validate_image_toml(&args.toml)) } - other => Ok(CallToolResult::error(vec![Content::text(format!( + other => Ok(CallToolResult::error(vec![ContentBlock::text(format!( "unknown tool: {other}" ))])), } @@ -226,18 +226,22 @@ fn parse_args( arguments: Option, ) -> std::result::Result { serde_json::from_value(serde_json::Value::Object(arguments.unwrap_or_default())).map_err( - |err| CallToolResult::error(vec![Content::text(format!("invalid arguments: {err}"))]), + |err| { + CallToolResult::error(vec![ContentBlock::text(format!( + "invalid arguments: {err}" + ))]) + }, ) } fn json_result(value: T) -> std::result::Result { - Ok(CallToolResult::success(vec![Content::json(value)?])) + Ok(CallToolResult::success(vec![ContentBlock::json(value)?])) } #[cfg(test)] mod tests { use super::*; - use rmcp::model::RawContent; + use rmcp::model::ContentBlock; use serde_json::json; fn call(name: &str, args: serde_json::Value) -> CallToolResult { @@ -254,8 +258,8 @@ mod tests { } fn text(result: &CallToolResult) -> &str { - match &result.content[0].raw { - RawContent::Text(t) => &t.text, + match &result.content[0] { + ContentBlock::Text(t) => &t.text, other => panic!("expected text content, got {other:?}"), } } diff --git a/crates/outrig-cli/src/rig_tool.rs b/crates/outrig-cli/src/rig_tool.rs index 16be2d7..5b7f9df 100644 --- a/crates/outrig-cli/src/rig_tool.rs +++ b/crates/outrig-cli/src/rig_tool.rs @@ -9,7 +9,6 @@ use std::sync::Arc; -use rig::completion::ToolDefinition; use rig::tool::{ToolDyn, ToolError}; use rig::wasm_compat::WasmBoxedFuture; use serde_json::Value; @@ -142,14 +141,12 @@ impl ToolDyn for McpToolAdapter { self.openai_name.clone() } - fn definition(&self, _prompt: String) -> WasmBoxedFuture<'_, ToolDefinition> { - Box::pin(async move { - ToolDefinition { - name: self.openai_name.clone(), - description: self.description.clone(), - parameters: self.input_schema.clone(), - } - }) + fn description(&self) -> String { + self.description.clone() + } + + fn parameters(&self) -> Value { + self.input_schema.clone() } fn call(&self, args: String) -> WasmBoxedFuture<'_, std::result::Result> { diff --git a/crates/outrig-cli/tests/mcp_self.rs b/crates/outrig-cli/tests/mcp_self.rs index 05c0462..e6d7229 100644 --- a/crates/outrig-cli/tests/mcp_self.rs +++ b/crates/outrig-cli/tests/mcp_self.rs @@ -8,7 +8,7 @@ use std::process::Stdio; use std::sync::{Arc, Mutex}; use std::time::Duration; -use rmcp::model::{CallToolRequestParams, RawContent}; +use rmcp::model::{CallToolRequestParams, ContentBlock}; use rmcp::service::serve_client; use serde::de::DeserializeOwned; use serde_json::Value; @@ -240,8 +240,8 @@ where let body = result .content .iter() - .filter_map(|content| match &content.raw { - RawContent::Text(t) => Some(t.text.as_str()), + .filter_map(|content| match content { + ContentBlock::Text(t) => Some(t.text.as_str()), _ => None, }) .collect::>() diff --git a/crates/outrig-cli/tests/mcp_sidecar_smoke.rs b/crates/outrig-cli/tests/mcp_sidecar_smoke.rs index 485571e..a193461 100644 --- a/crates/outrig-cli/tests/mcp_sidecar_smoke.rs +++ b/crates/outrig-cli/tests/mcp_sidecar_smoke.rs @@ -262,8 +262,8 @@ async fn sidecar_hosts_servers_with_labels_record_and_clean_reap() { let body = call .content .iter() - .filter_map(|c| match &c.raw { - rmcp::model::RawContent::Text(t) => Some(t.text.as_str()), + .filter_map(|c| match c { + rmcp::model::ContentBlock::Text(t) => Some(t.text.as_str()), _ => None, }) .collect::>() diff --git a/crates/outrig-cli/tests/mcp_subcommand_smoke.rs b/crates/outrig-cli/tests/mcp_subcommand_smoke.rs index eaeba7d..e8a185e 100644 --- a/crates/outrig-cli/tests/mcp_subcommand_smoke.rs +++ b/crates/outrig-cli/tests/mcp_subcommand_smoke.rs @@ -427,8 +427,8 @@ async fn mcp_subcommand_serves_namespaced_tools_and_exits_clean() { let body = call .content .iter() - .filter_map(|c| match &c.raw { - rmcp::model::RawContent::Text(t) => Some(t.text.as_str()), + .filter_map(|c| match c { + rmcp::model::ContentBlock::Text(t) => Some(t.text.as_str()), _ => None, }) .collect::>() diff --git a/crates/outrig/CHANGELOG.md b/crates/outrig/CHANGELOG.md index 89d0973..fc69480 100644 --- a/crates/outrig/CHANGELOG.md +++ b/crates/outrig/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- Upgraded the `rmcp` MCP SDK from 1.x to 2.x. The proxy and client now build on + rmcp 2.2's flat `ContentBlock` content model (replacing `RawContent`), so + consumers of this library link against rmcp 2.x. + ## [0.1.0](https://github.com/tgockel/outrig/releases/tag/outrig-v0.1.0) - 2026-06-26 ### Added diff --git a/crates/outrig/src/mcp.rs b/crates/outrig/src/mcp.rs index b53cd75..33f1e7f 100644 --- a/crates/outrig/src/mcp.rs +++ b/crates/outrig/src/mcp.rs @@ -17,7 +17,7 @@ use std::path::Path; use std::process::Stdio; use std::time::Duration; -use rmcp::model::{CallToolRequestParams, RawContent, ResourceContents}; +use rmcp::model::{CallToolRequestParams, ContentBlock, ResourceContents}; use rmcp::service::{RoleClient, RunningService, serve_client}; use serde_json::Value; use tokio::process::Child; @@ -270,9 +270,9 @@ impl McpClient { if i > 0 { content_text.push('\n'); } - match &content.raw { - RawContent::Text(t) => content_text.push_str(&t.text), - RawContent::Image(img) => { + match content { + ContentBlock::Text(t) => content_text.push_str(&t.text), + ContentBlock::Image(img) => { let _ = write!( content_text, "[image: {}, {} base64 bytes]", @@ -280,7 +280,7 @@ impl McpClient { img.data.len() ); } - RawContent::Resource(r) => match &r.resource { + ContentBlock::Resource(r) => match &r.resource { ResourceContents::TextResourceContents { text, .. } => { content_text.push_str(text) } @@ -290,8 +290,9 @@ impl McpClient { let mime = mime_type.as_deref().unwrap_or("application/octet-stream"); let _ = write!(content_text, "[blob: {mime}, {} base64 bytes]", blob.len()); } + _ => content_text.push_str("[unsupported resource contents]"), }, - RawContent::Audio(audio) => { + ContentBlock::Audio(audio) => { let _ = write!( content_text, "[audio: {}, {} base64 bytes]", @@ -299,9 +300,10 @@ impl McpClient { audio.data.len() ); } - RawContent::ResourceLink(link) => { + ContentBlock::ResourceLink(link) => { let _ = write!(content_text, "[resource link: {}]", link.uri); } + _ => content_text.push_str("[unsupported content block]"), } } diff --git a/crates/outrig/src/mcp_proxy.rs b/crates/outrig/src/mcp_proxy.rs index 29e1da9..512184b 100644 --- a/crates/outrig/src/mcp_proxy.rs +++ b/crates/outrig/src/mcp_proxy.rs @@ -19,8 +19,8 @@ use std::sync::Arc; use rmcp::ErrorData as McpError; use rmcp::ServerHandler; use rmcp::model::{ - CallToolRequestParams, CallToolResult, Content, Implementation, JsonObject, ListToolsResult, - PaginatedRequestParams, ServerCapabilities, ServerInfo, Tool, + CallToolRequestParams, CallToolResult, ContentBlock, Implementation, JsonObject, + ListToolsResult, PaginatedRequestParams, ServerCapabilities, ServerInfo, Tool, }; use rmcp::service::{RequestContext, RoleServer}; use serde_json::Value; @@ -270,7 +270,7 @@ impl ProxyServer { pub async fn dispatch_call(&self, request: CallToolRequestParams) -> CallToolResult { let public_name = request.name.as_ref(); let Some(&idx) = self.inner.by_public_name.get(public_name) else { - return CallToolResult::error(vec![Content::text(format!( + return CallToolResult::error(vec![ContentBlock::text(format!( "unknown tool: {public_name}" ))]); }; @@ -280,9 +280,9 @@ impl ProxyServer { let client = &self.inner.clients[entry.client_idx]; match client.call_tool(&entry.backend_tool, args).await { Ok(result) if result.is_error => { - CallToolResult::error(vec![Content::text(result.content_text)]) + CallToolResult::error(vec![ContentBlock::text(result.content_text)]) } - Ok(result) => CallToolResult::success(vec![Content::text(result.content_text)]), + Ok(result) => CallToolResult::success(vec![ContentBlock::text(result.content_text)]), Err(e) => { let server = client.name(); tracing::warn!( @@ -290,7 +290,7 @@ impl ProxyServer { "backing server {server:?} call to {tool:?} failed: {e}", tool = entry.backend_tool, ); - CallToolResult::error(vec![Content::text(format!( + CallToolResult::error(vec![ContentBlock::text(format!( "outrig: backing server `{server}` call failed: {e}" ))]) } diff --git a/crates/outrig/tests/mcp_proxy_dispatch.rs b/crates/outrig/tests/mcp_proxy_dispatch.rs index a086436..ac4f6c8 100644 --- a/crates/outrig/tests/mcp_proxy_dispatch.rs +++ b/crates/outrig/tests/mcp_proxy_dispatch.rs @@ -8,7 +8,7 @@ use std::sync::{Arc, Mutex}; use outrig::error::OutrigError; use outrig::mcp_proxy::{BackingClient, ProxyServer}; use outrig::{McpTool, McpToolResult}; -use rmcp::model::{CallToolRequestParams, RawContent}; +use rmcp::model::{CallToolRequestParams, ContentBlock}; use serde_json::{Value, json}; /// Per-tool canned response. `Ok` becomes a successful `CallToolResult`; @@ -88,7 +88,7 @@ impl BackingClient for FakeClient { fn text_body(result: &rmcp::model::CallToolResult) -> String { let mut out = String::new(); for content in &result.content { - if let RawContent::Text(t) = &content.raw { + if let ContentBlock::Text(t) = content { if !out.is_empty() { out.push('\n'); }