Skip to content

Commit b27f4e0

Browse files
committed
v0.0.17: Sanitize tool names for Kimi API compatibility
Kimi's API requires tool names matching [a-zA-Z0-9_-] but AO MCP tools use dots (ao.task.create). Added automatic sanitization: dots→underscores when sending to Kimi, underscores→dots when processing tool call responses. Also fixes pool_size overwrite bug and reasoning_content for multi-turn.
1 parent 1304858 commit b27f4e0

3 files changed

Lines changed: 29 additions & 11 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/oai-runner/src/runner/agent_loop.rs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,18 @@ pub async fn run_agent_loop(
135135
tool_call_id: None,
136136
});
137137

138+
let needs_tool_name_sanitization = model.contains("kimi");
139+
let sanitized_tools: Vec<ToolDefinition> = if needs_tool_name_sanitization {
140+
tools.iter().map(|t| {
141+
let mut t = t.clone();
142+
t.function.name = t.function.name.replace('.', "_");
143+
t
144+
}).collect()
145+
} else {
146+
tools.to_vec()
147+
};
148+
let api_tools = if needs_tool_name_sanitization { &sanitized_tools } else { tools };
149+
138150
for turn in 0..max_turns {
139151
if cancel_token.is_cancelled() {
140152
eprintln!("[oai-runner] Cancelled by signal");
@@ -161,7 +173,7 @@ pub async fn run_agent_loop(
161173
model: model.to_string(),
162174
messages: messages.clone(),
163175
stream: true,
164-
tools: Some(tools.to_vec()),
176+
tools: Some(api_tools.to_vec()),
165177
max_tokens: Some(max_tokens as u32),
166178
response_format: format,
167179
stream_options: Some(StreamOptions { include_usage: true }),
@@ -237,32 +249,38 @@ pub async fn run_agent_loop(
237249
break;
238250
}
239251

252+
let tool_name = if needs_tool_name_sanitization {
253+
tc.function.name.replace('_', ".")
254+
} else {
255+
tc.function.name.clone()
256+
};
257+
240258
let args: serde_json::Value =
241259
serde_json::from_str(&tc.function.arguments).unwrap_or(serde_json::Value::Null);
242260

243-
output.tool_call(&tc.function.name, &args);
261+
output.tool_call(&tool_name, &args);
244262

245-
let result = if let Some(mcp) = mcp_client::find_client_for_tool(mcp_clients, &tc.function.name) {
246-
match mcp_client::call_tool(mcp, &tc.function.name, &tc.function.arguments).await {
263+
let result = if let Some(mcp) = mcp_client::find_client_for_tool(mcp_clients, &tool_name) {
264+
match mcp_client::call_tool(mcp, &tool_name, &tc.function.arguments).await {
247265
Ok(r) => {
248-
output.tool_result(&tc.function.name, &r);
266+
output.tool_result(&tool_name, &r);
249267
r
250268
}
251269
Err(e) => {
252270
let err_msg = e.to_string();
253-
output.tool_error(&tc.function.name, &err_msg);
271+
output.tool_error(&tool_name, &err_msg);
254272
format!("Error: {}", err_msg)
255273
}
256274
}
257275
} else {
258-
match executor::execute_tool(&tc.function.name, &tc.function.arguments, working_dir).await {
276+
match executor::execute_tool(&tool_name, &tc.function.arguments, working_dir).await {
259277
Ok(r) => {
260-
output.tool_result(&tc.function.name, &r);
278+
output.tool_result(&tool_name, &r);
261279
r
262280
}
263281
Err(e) => {
264282
let err_msg = e.to_string();
265-
output.tool_error(&tc.function.name, &err_msg);
283+
output.tool_error(&tool_name, &err_msg);
266284
format!("Error: {}", err_msg)
267285
}
268286
}

crates/orchestrator-cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "orchestrator-cli"
3-
version = "0.0.16"
3+
version = "0.0.17"
44
edition = "2021"
55

66
[[bin]]

0 commit comments

Comments
 (0)