mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-11 03:39:49 +08:00
fix(ai-formats): omit request tool call ids in OpenAI Responses input
This commit is contained in:
@@ -9,7 +9,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
protocol::canonical::{
|
protocol::canonical::{
|
||||||
canonical_response_format_to_openai_responses, canonical_tool_is_openai_custom,
|
canonical_response_format_to_openai_responses, canonical_tool_is_openai_custom,
|
||||||
canonical_tool_use_to_openai_responses_item, is_claude_messages_request,
|
canonical_tool_use_to_openai_responses_input_item, is_claude_messages_request,
|
||||||
is_claude_system_instruction, is_claude_thinking_block, is_claude_tool_result,
|
is_claude_system_instruction, is_claude_thinking_block, is_claude_tool_result,
|
||||||
is_openai_responses_input_message, is_openai_thinking_block, media_data_or_url,
|
is_openai_responses_input_message, is_openai_thinking_block, media_data_or_url,
|
||||||
namespace_extension_object, openai_content_text, openai_extensions,
|
namespace_extension_object, openai_content_text, openai_extensions,
|
||||||
@@ -331,7 +331,7 @@ fn canonical_messages_to_responses_input(canonical: &CanonicalRequest) -> Option
|
|||||||
let call_id = responses_tool_call_id(id, &mut next_generated_tool_call_index);
|
let call_id = responses_tool_call_id(id, &mut next_generated_tool_call_index);
|
||||||
let tool_name = responses_tool_name(name);
|
let tool_name = responses_tool_name(name);
|
||||||
pending_tool_call_ids.push_back(call_id.clone());
|
pending_tool_call_ids.push_back(call_id.clone());
|
||||||
input.push(canonical_tool_use_to_openai_responses_item(
|
input.push(canonical_tool_use_to_openai_responses_input_item(
|
||||||
&call_id, &tool_name, arguments, extensions,
|
&call_id, &tool_name, arguments, extensions,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -1430,7 +1430,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(body["input"].as_array().expect("input").len(), 2);
|
assert_eq!(body["input"].as_array().expect("input").len(), 2);
|
||||||
assert_eq!(body["input"][0]["type"], "function_call");
|
assert_eq!(body["input"][0]["type"], "function_call");
|
||||||
assert_eq!(body["input"][0]["id"], "call_auto_0");
|
assert!(body["input"][0].get("id").is_none());
|
||||||
assert_eq!(body["input"][0]["call_id"], "call_auto_0");
|
assert_eq!(body["input"][0]["call_id"], "call_auto_0");
|
||||||
assert_eq!(body["input"][0]["name"], "unknown");
|
assert_eq!(body["input"][0]["name"], "unknown");
|
||||||
assert_eq!(body["input"][0]["arguments"], "{\"q\":\"rust\"}");
|
assert_eq!(body["input"][0]["arguments"], "{\"q\":\"rust\"}");
|
||||||
|
|||||||
@@ -2609,7 +2609,7 @@ mod tests {
|
|||||||
.value;
|
.value;
|
||||||
|
|
||||||
assert_eq!(converted["input"][0]["type"], "function_call");
|
assert_eq!(converted["input"][0]["type"], "function_call");
|
||||||
assert_eq!(converted["input"][0]["id"], "call_lookup_1");
|
assert!(converted["input"][0].get("id").is_none());
|
||||||
assert_eq!(converted["input"][0]["call_id"], "call_lookup_1");
|
assert_eq!(converted["input"][0]["call_id"], "call_lookup_1");
|
||||||
assert_eq!(converted["input"][1]["type"], "function_call_output");
|
assert_eq!(converted["input"][1]["type"], "function_call_output");
|
||||||
assert_eq!(converted["input"][1]["call_id"], "call_lookup_1");
|
assert_eq!(converted["input"][1]["call_id"], "call_lookup_1");
|
||||||
|
|||||||
@@ -808,6 +808,66 @@ pub(crate) fn canonical_tool_use_to_openai_responses_item(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn canonical_tool_use_to_openai_responses_input_item(
|
||||||
|
id: &str,
|
||||||
|
name: &str,
|
||||||
|
input: &Value,
|
||||||
|
extensions: &BTreeMap<String, Value>,
|
||||||
|
) -> Value {
|
||||||
|
if let Some(item_type) = openai_responses_hosted_tool_call_item_type(extensions) {
|
||||||
|
let mut item = Map::new();
|
||||||
|
item.insert("type".to_string(), Value::String(item_type.to_string()));
|
||||||
|
item.insert("id".to_string(), Value::String(id.to_string()));
|
||||||
|
item.insert("call_id".to_string(), Value::String(id.to_string()));
|
||||||
|
item.insert("status".to_string(), Value::String("completed".to_string()));
|
||||||
|
if let Some(input_object) = input.as_object() {
|
||||||
|
for field in openai_responses_hosted_tool_input_fields(item_type) {
|
||||||
|
if let Some(value) = input_object.get(*field) {
|
||||||
|
item.insert((*field).to_string(), value.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if item_type == "apply_patch_call" {
|
||||||
|
item.insert("operation".to_string(), input.clone());
|
||||||
|
} else if !name.trim().is_empty() {
|
||||||
|
item.insert("name".to_string(), Value::String(name.to_string()));
|
||||||
|
}
|
||||||
|
return Value::Object(item);
|
||||||
|
}
|
||||||
|
if is_openai_custom_tool_call(extensions) {
|
||||||
|
let mut item = Map::new();
|
||||||
|
item.insert(
|
||||||
|
"type".to_string(),
|
||||||
|
Value::String("custom_tool_call".to_string()),
|
||||||
|
);
|
||||||
|
if let Some(item_id) = openai_responses_request_tool_call_item_id(extensions, "ctc") {
|
||||||
|
item.insert("id".to_string(), Value::String(item_id));
|
||||||
|
}
|
||||||
|
item.insert("call_id".to_string(), Value::String(id.to_string()));
|
||||||
|
item.insert("status".to_string(), Value::String("completed".to_string()));
|
||||||
|
item.insert("name".to_string(), Value::String(name.to_string()));
|
||||||
|
item.insert(
|
||||||
|
"input".to_string(),
|
||||||
|
Value::String(openai_custom_tool_input_text(input)),
|
||||||
|
);
|
||||||
|
return Value::Object(item);
|
||||||
|
}
|
||||||
|
let mut item = Map::new();
|
||||||
|
item.insert(
|
||||||
|
"type".to_string(),
|
||||||
|
Value::String("function_call".to_string()),
|
||||||
|
);
|
||||||
|
if let Some(item_id) = openai_responses_request_tool_call_item_id(extensions, "fc") {
|
||||||
|
item.insert("id".to_string(), Value::String(item_id));
|
||||||
|
}
|
||||||
|
item.insert("call_id".to_string(), Value::String(id.to_string()));
|
||||||
|
item.insert("name".to_string(), Value::String(name.to_string()));
|
||||||
|
item.insert(
|
||||||
|
"arguments".to_string(),
|
||||||
|
Value::String(canonicalize_tool_arguments(input)),
|
||||||
|
);
|
||||||
|
Value::Object(item)
|
||||||
|
}
|
||||||
|
|
||||||
fn openai_responses_tool_call_item_id(
|
fn openai_responses_tool_call_item_id(
|
||||||
call_id: &str,
|
call_id: &str,
|
||||||
extensions: &BTreeMap<String, Value>,
|
extensions: &BTreeMap<String, Value>,
|
||||||
@@ -828,6 +888,18 @@ fn openai_responses_tool_call_item_id(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn openai_responses_request_tool_call_item_id(
|
||||||
|
extensions: &BTreeMap<String, Value>,
|
||||||
|
prefix: &str,
|
||||||
|
) -> Option<String> {
|
||||||
|
openai_responses_extension(extensions)
|
||||||
|
.and_then(|value| value.get("item_id").or_else(|| value.get("id")))
|
||||||
|
.and_then(Value::as_str)
|
||||||
|
.map(str::trim)
|
||||||
|
.filter(|value| value.starts_with(prefix))
|
||||||
|
.map(ToString::to_string)
|
||||||
|
}
|
||||||
|
|
||||||
fn openai_responses_hosted_tool_call_item_type(
|
fn openai_responses_hosted_tool_call_item_type(
|
||||||
extensions: &BTreeMap<String, Value>,
|
extensions: &BTreeMap<String, Value>,
|
||||||
) -> Option<&str> {
|
) -> Option<&str> {
|
||||||
|
|||||||
Reference in New Issue
Block a user