Update to rmcp 1.1.0 (#7619)

Co-authored-by: Alex Hancock <alexhancock@block.xyz>
This commit is contained in:
Jack Amadeo
2026-03-05 21:40:52 -05:00
committed by GitHub
parent abadb87892
commit 325bf396af
61 changed files with 729 additions and 1757 deletions
+4 -6
View File
@@ -877,12 +877,10 @@ mod tests {
if let Some(img_data) = s.strip_prefix("*img:") {
MessageContent::image(format!("http://example.com/{}", img_data), "image/png")
} else if let Some(tool_name) = s.strip_prefix("*tool:") {
let tool_call = Ok(rmcp::model::CallToolRequestParams {
meta: None,
task: None,
name: tool_name.to_string().into(),
arguments: Some(serde_json::Map::new()),
});
let tool_call = Ok(
rmcp::model::CallToolRequestParams::new(tool_name.to_string())
.with_arguments(serde_json::Map::new()),
);
MessageContent::tool_request(format!("tool_{}", tool_name), tool_call)
} else {
MessageContent::text(s)
+3 -15
View File
@@ -972,11 +972,7 @@ mod tests {
Message::user().with_text("user text"),
Message::assistant().with_text("assistant prelude").with_tool_request(
"call-1",
Ok(CallToolRequestParams {
meta: None, task: None,
name: "tool_name".into(),
arguments: Some(object!({"param": "value"})),
}),
Ok(CallToolRequestParams::new("tool_name").with_arguments(object!({"param": "value"}))),
),
Message::user().with_tool_response(
"call-1",
@@ -998,11 +994,7 @@ mod tests {
Message::user().with_text("user text"),
Message::assistant().with_tool_request(
"call-1",
Ok(CallToolRequestParams {
meta: None, task: None,
name: "tool_name".into(),
arguments: Some(object!({"param": "value"})),
}),
Ok(CallToolRequestParams::new("tool_name").with_arguments(object!({"param": "value"}))),
),
Message::user().with_tool_response(
"call-1",
@@ -1023,11 +1015,7 @@ mod tests {
Message::user().with_text("user text"),
Message::assistant().with_tool_request(
"call-1",
Ok(CallToolRequestParams {
meta: None, task: None,
name: "tool_name".into(),
arguments: Some(object!({"param": "value"})),
}),
Ok(CallToolRequestParams::new("tool_name").with_arguments(object!({"param": "value"}))),
),
Message::user().with_tool_response(
"call-1",
+2 -9
View File
@@ -1019,21 +1019,14 @@ mod tests {
)]
#[test_case(
vec![Message::new(Role::Assistant, 0, vec![
MessageContent::tool_request("call_123", Ok(rmcp::model::CallToolRequestParams {
name: "developer__shell".into(),
arguments: Some(serde_json::from_value(json!({"cmd": "ls"})).unwrap()),
meta: None, task: None,
}))
MessageContent::tool_request("call_123", Ok(rmcp::model::CallToolRequestParams::new("developer__shell").with_arguments(serde_json::from_value(json!({"cmd": "ls"})).unwrap())))
])],
&[json!({"type":"text","text":"Assistant: [tool_use: developer__shell id=call_123]"})]
; "tool_request_no_user_fallback"
)]
#[test_case(
vec![Message::new(Role::User, 0, vec![
MessageContent::tool_response("call_123", Ok(rmcp::model::CallToolResult {
content: vec![rmcp::model::Content::text("file1.txt\nfile2.txt")],
is_error: None, structured_content: None, meta: None,
}))
MessageContent::tool_response("call_123", Ok(rmcp::model::CallToolResult::success(vec![rmcp::model::Content::text("file1.txt\nfile2.txt")])))
])],
&[json!({"type":"text","text":"Human: [tool_result id=call_123] file1.txt\nfile2.txt"})]
; "tool_response"
+3 -12
View File
@@ -876,12 +876,8 @@ mod tests {
fn test_prepare_input_tool_request() {
use rmcp::model::CallToolRequestParams;
let dir = tempfile::tempdir().unwrap();
let tool_call = Ok(CallToolRequestParams {
name: "developer__shell".into(),
arguments: Some(serde_json::from_value(json!({"cmd": "ls"})).unwrap()),
meta: None,
task: None,
});
let tool_call = Ok(CallToolRequestParams::new("developer__shell")
.with_arguments(serde_json::from_value(json!({"cmd": "ls"})).unwrap()));
let messages = vec![Message::new(
Role::Assistant,
0,
@@ -896,12 +892,7 @@ mod tests {
fn test_prepare_input_tool_response() {
use rmcp::model::{CallToolResult, Content};
let dir = tempfile::tempdir().unwrap();
let result = CallToolResult {
content: vec![Content::text("file1.txt\nfile2.txt")],
is_error: None,
structured_content: None,
meta: None,
};
let result = CallToolResult::success(vec![Content::text("file1.txt\nfile2.txt")]);
let messages = vec![Message::new(
Role::User,
0,
@@ -325,12 +325,8 @@ pub fn response_to_message(response: &Value) -> Result<Message> {
.get(INPUT_FIELD)
.ok_or_else(|| anyhow!("Missing tool_use input"))?;
let tool_call = CallToolRequestParams {
meta: None,
task: None,
name: name.into(),
arguments: Some(object(input.clone())),
};
let tool_call =
CallToolRequestParams::new(name).with_arguments(object(input.clone()));
message = message.with_tool_request(id, Ok(tool_call));
}
Some(THINKING_TYPE) => {
@@ -692,11 +688,7 @@ where
}
};
let tool_call = CallToolRequestParams{
meta: None, task: None,
name: name.into(),
arguments: Some(object(parsed_args))
};
let tool_call = CallToolRequestParams::new(name).with_arguments(object(parsed_args));
let mut message = Message::new(
rmcp::model::Role::Assistant,
@@ -1126,12 +1118,8 @@ mod tests {
let messages = vec![
Message::assistant().with_tool_request(
"tool_1",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "calculator".into(),
arguments: Some(object!({"expression": "2 + 2"})),
}),
Ok(CallToolRequestParams::new("calculator")
.with_arguments(object!({"expression": "2 + 2"}))),
),
Message::user().with_tool_response(
"tool_1",
@@ -1168,22 +1156,10 @@ mod tests {
Message::user().with_text("Hello"),
Message::assistant().with_text("").with_tool_request(
"tool_1",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "search".into(),
arguments: Some(object!({"query": "test"})),
}),
),
Message::user().with_tool_response(
"tool_1",
Ok(rmcp::model::CallToolResult {
content: vec![],
structured_content: None,
is_error: Some(false),
meta: None,
}),
Ok(CallToolRequestParams::new("search").with_arguments(object!({"query": "test"}))),
),
Message::user()
.with_tool_response("tool_1", Ok(rmcp::model::CallToolResult::success(vec![]))),
];
let spec = format_messages(&messages);
+12 -36
View File
@@ -312,12 +312,8 @@ pub fn from_bedrock_content_block(block: &bedrock::ContentBlock) -> Result<Messa
bedrock::ContentBlock::Text(text) => MessageContent::text(text),
bedrock::ContentBlock::ToolUse(tool_use) => MessageContent::tool_request(
tool_use.tool_use_id.to_string(),
Ok(CallToolRequestParams {
meta: None,
task: None,
name: tool_use.name.clone().into(),
arguments: Some(object(from_bedrock_json(&tool_use.input.clone())?)),
}),
Ok(CallToolRequestParams::new(tool_use.name.clone())
.with_arguments(object(from_bedrock_json(&tool_use.input.clone())?))),
),
bedrock::ContentBlock::ToolResult(tool_res) => MessageContent::tool_response(
tool_res.tool_use_id.to_string(),
@@ -333,12 +329,7 @@ pub fn from_bedrock_content_block(block: &bedrock::ContentBlock) -> Result<Messa
.iter()
.map(from_bedrock_tool_result_content_block)
.collect::<ToolResult<Vec<_>>>()
.map(|content| rmcp::model::CallToolResult {
content,
structured_content: None,
is_error: Some(false),
meta: None,
})
.map(rmcp::model::CallToolResult::success)
},
),
bedrock::ContentBlock::CachePoint(_) => {
@@ -612,12 +603,8 @@ mod tests {
MessageContent::text("I'll use a tool"),
MessageContent::tool_request(
"tool_1".to_string(),
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "test_tool".into(),
arguments: Some(object(json!({"param": "value"}))),
}),
Ok(CallToolRequestParams::new("test_tool")
.with_arguments(object(json!({"param": "value"})))),
),
],
);
@@ -652,12 +639,9 @@ mod tests {
Utc::now().timestamp(),
vec![MessageContent::tool_response(
"tool_1".to_string(),
Ok(CallToolResult {
content: vec![Content::text("Tool result text".to_string())],
structured_content: None,
is_error: Some(false),
meta: None,
}),
Ok(CallToolResult::success(vec![Content::text(
"Tool result text".to_string(),
)])),
)],
);
@@ -690,21 +674,13 @@ mod tests {
MessageContent::text("Using tools"),
MessageContent::tool_request(
"tool_1".to_string(),
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "tool_a".into(),
arguments: Some(object(json!({"key": "val"}))),
}),
Ok(CallToolRequestParams::new("tool_a")
.with_arguments(object(json!({"key": "val"})))),
),
MessageContent::tool_request(
"tool_2".to_string(),
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "tool_b".into(),
arguments: Some(object(json!({"key": "val"}))),
}),
Ok(CallToolRequestParams::new("tool_b")
.with_arguments(object(json!({"key": "val"})))),
),
],
);
@@ -366,12 +366,8 @@ pub fn response_to_message(response: &Value) -> anyhow::Result<Message> {
Ok(params) => {
content.push(MessageContent::tool_request(
id,
Ok(CallToolRequestParams {
meta: None,
task: None,
name: function_name.into(),
arguments: Some(object(params)),
}),
Ok(CallToolRequestParams::new(function_name)
.with_arguments(object(params))),
));
}
Err(e) => {
@@ -755,12 +751,8 @@ mod tests {
Message::user().with_text("How are you?"),
Message::assistant().with_tool_request(
"tool1",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "example".into(),
arguments: Some(object!({"param1": "value1"})),
}),
Ok(CallToolRequestParams::new("example")
.with_arguments(object!({"param1": "value1"}))),
),
];
@@ -772,12 +764,7 @@ mod tests {
messages.push(Message::user().with_tool_response(
tool_id,
Ok(CallToolResult {
content: vec![Content::text("Result")],
structured_content: None,
is_error: Some(false),
meta: None,
}),
Ok(CallToolResult::success(vec![Content::text("Result")])),
));
let as_value =
@@ -802,12 +789,7 @@ mod tests {
fn test_format_messages_multiple_content() -> anyhow::Result<()> {
let mut messages = vec![Message::assistant().with_tool_request(
"tool1",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "example".into(),
arguments: Some(object!({"param1": "value1"})),
}),
Ok(CallToolRequestParams::new("example").with_arguments(object!({"param1": "value1"}))),
)];
let tool_id = if let MessageContent::ToolRequest(request) = &messages[0].content[0] {
@@ -818,12 +800,7 @@ mod tests {
messages.push(Message::user().with_tool_response(
tool_id,
Ok(CallToolResult {
content: vec![Content::text("Result")],
structured_content: None,
is_error: Some(false),
meta: None,
}),
Ok(CallToolResult::success(vec![Content::text("Result")])),
));
let as_value =
@@ -1182,15 +1159,8 @@ mod tests {
#[test]
fn test_format_messages_tool_request_with_none_arguments() -> anyhow::Result<()> {
// Test that tool calls with None arguments are formatted as "{}" string
let message = Message::assistant().with_tool_request(
"tool1",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "test_tool".into(),
arguments: None, // This is the key case the fix addresses
}),
);
let message = Message::assistant()
.with_tool_request("tool1", Ok(CallToolRequestParams::new("test_tool")));
let spec = format_messages(&[message], &ImageFormat::OpenAi);
let as_value = serde_json::to_value(spec)?;
@@ -1215,12 +1185,8 @@ mod tests {
// Test that tool calls with Some arguments are properly JSON-serialized
let message = Message::assistant().with_tool_request(
"tool1",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "test_tool".into(),
arguments: Some(object!({"param": "value", "number": 42})),
}),
Ok(CallToolRequestParams::new("test_tool")
.with_arguments(object!({"param": "value", "number": 42}))),
);
let spec = format_messages(&[message], &ImageFormat::OpenAi);
@@ -1397,12 +1363,7 @@ mod tests {
let message = Message::assistant().with_tool_request_with_metadata(
"tool1",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "test_tool".into(),
arguments: Some(object!({"param": "value"})),
}),
Ok(CallToolRequestParams::new("test_tool").with_arguments(object!({"param": "value"}))),
Some(&metadata),
None,
);
@@ -1534,12 +1495,7 @@ mod tests {
let message = Message::assistant().with_tool_request_with_metadata(
"tool1",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "test_tool".into(),
arguments: None,
}),
Ok(CallToolRequestParams::new("test_tool")),
Some(&metadata),
None,
);
+10 -29
View File
@@ -292,11 +292,12 @@ fn process_response_part_impl(
Some(MessageContent::tool_request_with_metadata(
id,
Ok(CallToolRequestParams {
meta: None,
task: None,
name: name.to_string().into(),
arguments,
Ok({
let mut params = CallToolRequestParams::new(name.to_string());
if let Some(args) = arguments {
params = params.with_arguments(args);
}
params
}),
metadata.as_ref(),
))
@@ -640,12 +641,7 @@ mod tests {
0,
vec![MessageContent::tool_response(
id.to_string(),
Ok(CallToolResult {
content: tool_response,
structured_content: None,
is_error: Some(false),
meta: None,
}),
Ok(CallToolResult::success(tool_response)),
)],
)
}
@@ -719,21 +715,11 @@ mod tests {
let messages = vec![
set_up_tool_request_message(
"id",
CallToolRequestParams {
meta: None,
task: None,
name: "tool_name".into(),
arguments: Some(object(arguments.clone())),
},
CallToolRequestParams::new("tool_name").with_arguments(object(arguments.clone())),
),
set_up_action_required_message(
"id2",
CallToolRequestParams {
meta: None,
task: None,
name: "tool_name_2".into(),
arguments: Some(object(arguments.clone())),
},
CallToolRequestParams::new("tool_name_2").with_arguments(object(arguments.clone())),
),
];
let payload = format_messages(&messages);
@@ -970,12 +956,7 @@ mod tests {
}
fn tool_result(text: &str) -> CallToolResult {
CallToolResult {
content: vec![Content::text(text)],
structured_content: None,
is_error: Some(false),
meta: None,
}
CallToolResult::success(vec![Content::text(text)])
}
#[test]
+2 -6
View File
@@ -58,12 +58,8 @@ pub fn parse_xml_tool_calls(content: &str) -> (Option<String>, Vec<MessageConten
if is_valid_function_name(&function_name) {
tool_calls.push(MessageContent::tool_request(
id,
Ok(CallToolRequestParams {
meta: None,
task: None,
name: function_name.into(),
arguments: Some(object(serde_json::Value::Object(arguments))),
}),
Ok(CallToolRequestParams::new(function_name)
.with_arguments(object(serde_json::Value::Object(arguments)))),
));
} else {
let error = ErrorData {
+17 -69
View File
@@ -409,12 +409,8 @@ pub fn response_to_message(response: &Value) -> anyhow::Result<Message> {
Ok(params) => {
content.push(MessageContent::tool_request_with_metadata(
id,
Ok(CallToolRequestParams {
meta: None,
task: None,
name: function_name.into(),
arguments: Some(object(params)),
}),
Ok(CallToolRequestParams::new(function_name)
.with_arguments(object(params))),
metadata.as_ref(),
));
}
@@ -670,12 +666,7 @@ where
Ok(params) => {
MessageContent::tool_request_with_metadata(
id.clone(),
Ok(CallToolRequestParams {
meta: None,
task: None,
name: function_name.clone().into(),
arguments: Some(object(params)),
}),
Ok(CallToolRequestParams::new(function_name.clone()).with_arguments(object(params))),
metadata,
)
},
@@ -984,12 +975,8 @@ mod tests {
Message::user().with_text("How are you?"),
Message::assistant().with_tool_request(
"tool1",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "example".into(),
arguments: Some(object!({"param1": "value1"})),
}),
Ok(CallToolRequestParams::new("example")
.with_arguments(object!({"param1": "value1"}))),
),
];
@@ -1002,12 +989,7 @@ mod tests {
messages.push(Message::user().with_tool_response(
tool_id,
Ok(CallToolResult {
content: vec![Content::text("Result")],
structured_content: None,
is_error: Some(false),
meta: None,
}),
Ok(CallToolResult::success(vec![Content::text("Result")])),
));
let spec = format_messages(&messages, &ImageFormat::OpenAi);
@@ -1030,12 +1012,7 @@ mod tests {
fn test_format_messages_multiple_content() -> anyhow::Result<()> {
let mut messages = vec![Message::assistant().with_tool_request(
"tool1",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "example".into(),
arguments: Some(object!({"param1": "value1"})),
}),
Ok(CallToolRequestParams::new("example").with_arguments(object!({"param1": "value1"}))),
)];
// Get the ID from the tool request to use in the response
@@ -1047,12 +1024,7 @@ mod tests {
messages.push(Message::user().with_tool_response(
tool_id,
Ok(CallToolResult {
content: vec![Content::text("Result")],
structured_content: None,
is_error: Some(false),
meta: None,
}),
Ok(CallToolResult::success(vec![Content::text("Result")])),
));
let spec = format_messages(&messages, &ImageFormat::OpenAi);
@@ -1340,15 +1312,8 @@ mod tests {
#[test]
fn test_format_messages_tool_request_with_none_arguments() -> anyhow::Result<()> {
// Test that tool calls with None arguments are formatted as "{}" string
let message = Message::assistant().with_tool_request(
"tool1",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "test_tool".into(),
arguments: None, // This is the key case the fix addresses
}),
);
let message = Message::assistant()
.with_tool_request("tool1", Ok(CallToolRequestParams::new("test_tool")));
let spec = format_messages(&[message], &ImageFormat::OpenAi);
@@ -1371,12 +1336,8 @@ mod tests {
// Test that tool calls with Some arguments are properly JSON-serialized
let message = Message::assistant().with_tool_request(
"tool1",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "test_tool".into(),
arguments: Some(object!({"param": "value", "number": 42})),
}),
Ok(CallToolRequestParams::new("test_tool")
.with_arguments(object!({"param": "value", "number": 42}))),
);
let spec = format_messages(&[message], &ImageFormat::OpenAi);
@@ -1403,12 +1364,7 @@ mod tests {
// Test that FrontendToolRequest with None arguments are formatted as "{}" string
let message = Message::assistant().with_frontend_tool_request(
"frontend_tool1",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "frontend_test_tool".into(),
arguments: None, // This is the key case the fix addresses
}),
Ok(CallToolRequestParams::new("frontend_test_tool")),
);
let spec = format_messages(&[message], &ImageFormat::OpenAi);
@@ -1432,12 +1388,8 @@ mod tests {
// Test that FrontendToolRequest with Some arguments are properly JSON-serialized
let message = Message::assistant().with_frontend_tool_request(
"frontend_tool1",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "frontend_test_tool".into(),
arguments: Some(object!({"action": "click", "element": "button"})),
}),
Ok(CallToolRequestParams::new("frontend_test_tool")
.with_arguments(object!({"action": "click", "element": "button"}))),
);
let spec = format_messages(&[message], &ImageFormat::OpenAi);
@@ -1925,12 +1877,8 @@ data: [DONE]"#;
// Add a tool call to test that reasoning_content works with tool calls
message = message.with_tool_request(
"tool1",
Ok(rmcp::model::CallToolRequestParams {
meta: None,
task: None,
name: "test_tool".into(),
arguments: Some(rmcp::object!({"param": "value"})),
}),
Ok(rmcp::model::CallToolRequestParams::new("test_tool")
.with_arguments(rmcp::object!({"param": "value"}))),
);
let spec = format_messages(&[message], &ImageFormat::OpenAi);
@@ -473,12 +473,8 @@ pub fn responses_api_to_message(response: &ResponsesApiResponse) -> anyhow::Resu
ResponseContentBlock::ToolCall { id, name, input } => {
content.push(MessageContent::tool_request(
id.clone(),
Ok(CallToolRequestParams {
meta: None,
task: None,
name: name.clone().into(),
arguments: Some(object(input.clone())),
}),
Ok(CallToolRequestParams::new(name.clone())
.with_arguments(object(input.clone()))),
));
}
}
@@ -499,12 +495,8 @@ pub fn responses_api_to_message(response: &ResponsesApiResponse) -> anyhow::Resu
content.push(MessageContent::tool_request(
id.clone(),
Ok(CallToolRequestParams {
meta: None,
task: None,
name: name.clone().into(),
arguments: Some(object(parsed_args)),
}),
Ok(CallToolRequestParams::new(name.clone())
.with_arguments(object(parsed_args))),
));
}
}
@@ -559,12 +551,8 @@ fn process_streaming_output_items(
content.push(MessageContent::tool_request(
id,
Ok(CallToolRequestParams {
meta: None,
task: None,
name: name.into(),
arguments: Some(object(parsed_args)),
}),
Ok(CallToolRequestParams::new(name)
.with_arguments(object(parsed_args))),
));
}
}
@@ -584,12 +572,7 @@ fn process_streaming_output_items(
content.push(MessageContent::tool_request(
call_id,
Ok(CallToolRequestParams {
meta: None,
task: None,
name: name.into(),
arguments: Some(object(parsed_args)),
}),
Ok(CallToolRequestParams::new(name).with_arguments(object(parsed_args))),
));
}
}
@@ -835,23 +818,15 @@ mod tests {
.with_text("I'll create that file.")
.with_tool_request(
"call_1",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "shell".into(),
arguments: Some(object!({"command": "echo hello"})),
}),
Ok(CallToolRequestParams::new("shell")
.with_arguments(object!({"command": "echo hello"}))),
),
Message::assistant()
.with_text("Now let me verify.")
.with_tool_request(
"call_2",
Ok(CallToolRequestParams {
meta: None,
task: None,
name: "shell".into(),
arguments: Some(object!({"command": "cat file.txt"})),
}),
Ok(CallToolRequestParams::new("shell")
.with_arguments(object!({"command": "cat file.txt"}))),
),
];
@@ -187,21 +187,11 @@ pub fn parse_streaming_response(sse_data: &str) -> Result<Message> {
if !tool_input.is_empty() {
let input_value = serde_json::from_str::<Value>(&tool_input)
.unwrap_or_else(|_| Value::String(tool_input.clone()));
let tool_call = CallToolRequestParams {
meta: None,
task: None,
name: name.into(),
arguments: Some(object(input_value)),
};
let tool_call = CallToolRequestParams::new(name).with_arguments(object(input_value));
message = message.with_tool_request(&id, Ok(tool_call));
} else {
// Tool with no input - use empty object
let tool_call = CallToolRequestParams {
meta: None,
task: None,
name: name.into(),
arguments: Some(object!({})),
};
let tool_call = CallToolRequestParams::new(name).with_arguments(object!({}));
message = message.with_tool_request(&id, Ok(tool_call));
}
}
@@ -258,12 +248,7 @@ pub fn response_to_message(response: &Value) -> Result<Message> {
.ok_or_else(|| anyhow!("Missing tool input"))?
.clone();
let tool_call = CallToolRequestParams {
meta: None,
task: None,
name: name.into(),
arguments: Some(object(input)),
};
let tool_call = CallToolRequestParams::new(name).with_arguments(object(input));
message = message.with_tool_request(id, Ok(tool_call));
}
Some("thinking") => {
@@ -700,12 +685,8 @@ data: {"id":"a9537c2c-2017-4906-9817-2456168d89fa","model":"claude-sonnet-4-2025
use crate::conversation::message::Message;
// Create a conversation with text, tool requests, and tool responses
let tool_call = CallToolRequestParams {
meta: None,
task: None,
name: "calculator".into(),
arguments: Some(object!({"expression": "2 + 2"})),
};
let tool_call = CallToolRequestParams::new("calculator")
.with_arguments(object!({"expression": "2 + 2"}));
let messages = vec![
Message::user().with_text("Calculate 2 + 2"),
@@ -313,12 +313,8 @@ fn send_emulator_action(
let tool_id = Uuid::new_v4().to_string();
let mut args = serde_json::Map::new();
args.insert("command".to_string(), json!(command));
let tool_call = CallToolRequestParams {
meta: None,
task: None,
name: Cow::Borrowed(SHELL_TOOL),
arguments: Some(args),
};
let tool_call =
CallToolRequestParams::new(Cow::Borrowed(SHELL_TOOL)).with_arguments(args);
let mut message = Message::assistant();
message
.content
@@ -337,12 +333,8 @@ fn send_emulator_action(
};
let mut args = serde_json::Map::new();
args.insert("code".to_string(), json!(wrapped));
let tool_call = CallToolRequestParams {
meta: None,
task: None,
name: Cow::Borrowed(CODE_EXECUTION_TOOL),
arguments: Some(args),
};
let tool_call =
CallToolRequestParams::new(Cow::Borrowed(CODE_EXECUTION_TOOL)).with_arguments(args);
let mut message = Message::assistant();
message
.content
@@ -172,12 +172,8 @@ pub(super) fn extract_tool_call_messages(tool_calls_json: &str, message_id: &str
.map(|s| s.to_string())
.unwrap_or_else(|| Uuid::new_v4().to_string());
let tool_call = CallToolRequestParams {
meta: None,
task: None,
name: Cow::Owned(name),
arguments,
};
let tool_call = CallToolRequestParams::new(Cow::Owned(name))
.with_arguments(arguments.unwrap_or_default());
let mut msg = Message::assistant();
msg.content
@@ -319,11 +315,10 @@ pub(super) fn extract_xml_tool_call_messages(
tool_calls
.into_iter()
.map(|(name, args)| {
let tool_call = CallToolRequestParams {
meta: None,
task: None,
name: Cow::Owned(name),
arguments: if args.is_empty() { None } else { Some(args) },
let tool_call = if args.is_empty() {
CallToolRequestParams::new(Cow::Owned(name))
} else {
CallToolRequestParams::new(Cow::Owned(name)).with_arguments(args)
};
let mut msg = Message::assistant();
msg.content.push(MessageContent::tool_request(
+7 -7
View File
@@ -59,11 +59,11 @@ fn create_sample_weather_tool() -> Tool {
}
}),
)
.annotate(ToolAnnotations {
title: Some("Get weather".to_string()),
read_only_hint: Some(true),
destructive_hint: Some(false),
idempotent_hint: Some(false),
open_world_hint: Some(false),
})
.annotate(
ToolAnnotations::with_title("Get weather".to_string())
.read_only(true)
.destructive(false)
.idempotent(false)
.open_world(false),
)
}
+22 -12
View File
@@ -11,10 +11,10 @@ use std::sync::{Arc, Mutex};
use super::base::stream_from_single_message;
use super::base::{MessageStream, Provider, ProviderDef, ProviderMetadata, ProviderUsage};
use super::errors::ProviderError;
use crate::conversation::message::Message;
use crate::conversation::message::{Message, ToolResponse};
use crate::model::ModelConfig;
use futures::future::BoxFuture;
use rmcp::model::Tool;
use rmcp::model::{CallToolResult, Tool};
#[derive(Debug, Clone, Serialize, Deserialize)]
struct TestInput {
@@ -83,18 +83,28 @@ impl TestProvider {
let stable_messages: Vec<_> = messages
.iter()
.map(|msg| {
let cleaned_content: Vec<_> = msg
.content
.iter()
.map(|c| match c {
MessageContent::ToolRequest(req) => {
let mut req = req.clone();
let mut cleaned_content: Vec<_> = msg.content.to_vec();
for content in &mut cleaned_content {
match content {
MessageContent::ToolRequest(ref mut req) => {
req.tool_meta = None;
MessageContent::ToolRequest(req)
}
other => other.clone(),
})
.collect();
MessageContent::ToolResponse(ToolResponse {
tool_result:
Ok(
ref mut result @ CallToolResult {
is_error: Some(false),
..
},
),
..
}) => {
result.is_error = None;
}
_ => {}
}
}
(msg.role.clone(), cleaned_content)
})
.collect();
+4 -6
View File
@@ -226,12 +226,10 @@ impl OllamaInterpreter {
let arguments = item["arguments"].clone();
// Add the tool call to our result vector
tool_calls.push(CallToolRequestParams {
meta: None,
task: None,
name: name.into(),
arguments: Some(object(arguments)),
});
tool_calls.push(
CallToolRequestParams::new(name)
.with_arguments(object(arguments)),
);
}
}
}
+2 -6
View File
@@ -492,12 +492,8 @@ impl Provider for VeniceProvider {
function["arguments"].clone()
};
let tool_call = CallToolRequestParams {
meta: None,
task: None,
name: name.into(),
arguments: Some(object(arguments)),
};
let tool_call =
CallToolRequestParams::new(name).with_arguments(object(arguments));
// Create a ToolRequest MessageContent
let tool_request = MessageContent::tool_request(id, ToolResult::Ok(tool_call));