mirror of
https://github.com/openai/codex.git
synced 2026-04-29 17:06:51 +00:00
chore: nuke chat/completions API (#10157)
This commit is contained in:
@@ -329,200 +329,6 @@ async fn stdio_image_responses_round_trip() -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||
#[serial(mcp_test_value)]
|
||||
async fn stdio_image_completions_round_trip() -> anyhow::Result<()> {
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let server = responses::start_mock_server().await;
|
||||
|
||||
let call_id = "img-cc-1";
|
||||
let server_name = "rmcp";
|
||||
let tool_name = format!("mcp__{server_name}__image");
|
||||
|
||||
let tool_call = json!({
|
||||
"choices": [
|
||||
{
|
||||
"delta": {
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": call_id,
|
||||
"type": "function",
|
||||
"function": {"name": tool_name, "arguments": "{}"}
|
||||
}
|
||||
]
|
||||
},
|
||||
"finish_reason": "tool_calls"
|
||||
}
|
||||
]
|
||||
});
|
||||
let sse_tool_call = format!(
|
||||
"data: {}\n\ndata: [DONE]\n\n",
|
||||
serde_json::to_string(&tool_call)?
|
||||
);
|
||||
|
||||
let final_assistant = json!({
|
||||
"choices": [
|
||||
{
|
||||
"delta": {"content": "rmcp image tool completed successfully."},
|
||||
"finish_reason": "stop"
|
||||
}
|
||||
]
|
||||
});
|
||||
let sse_final = format!(
|
||||
"data: {}\n\ndata: [DONE]\n\n",
|
||||
serde_json::to_string(&final_assistant)?
|
||||
);
|
||||
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
struct ChatSeqResponder {
|
||||
num_calls: AtomicUsize,
|
||||
bodies: Vec<String>,
|
||||
}
|
||||
impl wiremock::Respond for ChatSeqResponder {
|
||||
fn respond(&self, _: &wiremock::Request) -> wiremock::ResponseTemplate {
|
||||
let idx = self.num_calls.fetch_add(1, Ordering::SeqCst);
|
||||
match self.bodies.get(idx) {
|
||||
Some(body) => wiremock::ResponseTemplate::new(200)
|
||||
.insert_header("content-type", "text/event-stream")
|
||||
.set_body_string(body.clone()),
|
||||
None => panic!("no chat completion response for index {idx}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let chat_seq = ChatSeqResponder {
|
||||
num_calls: AtomicUsize::new(0),
|
||||
bodies: vec![sse_tool_call, sse_final],
|
||||
};
|
||||
wiremock::Mock::given(wiremock::matchers::method("POST"))
|
||||
.and(wiremock::matchers::path("/v1/chat/completions"))
|
||||
.respond_with(chat_seq)
|
||||
.expect(2)
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let rmcp_test_server_bin = stdio_server_bin()?;
|
||||
|
||||
let fixture = test_codex()
|
||||
.with_config(move |config| {
|
||||
config.model_provider.wire_api = codex_core::WireApi::Chat;
|
||||
let mut servers = config.mcp_servers.get().clone();
|
||||
servers.insert(
|
||||
server_name.to_string(),
|
||||
McpServerConfig {
|
||||
transport: McpServerTransportConfig::Stdio {
|
||||
command: rmcp_test_server_bin,
|
||||
args: Vec::new(),
|
||||
env: Some(HashMap::from([(
|
||||
"MCP_TEST_IMAGE_DATA_URL".to_string(),
|
||||
OPENAI_PNG.to_string(),
|
||||
)])),
|
||||
env_vars: Vec::new(),
|
||||
cwd: None,
|
||||
},
|
||||
enabled: true,
|
||||
disabled_reason: None,
|
||||
startup_timeout_sec: Some(Duration::from_secs(10)),
|
||||
tool_timeout_sec: None,
|
||||
enabled_tools: None,
|
||||
disabled_tools: None,
|
||||
scopes: None,
|
||||
},
|
||||
);
|
||||
config
|
||||
.mcp_servers
|
||||
.set(servers)
|
||||
.expect("test mcp servers should accept any configuration");
|
||||
})
|
||||
.build(&server)
|
||||
.await?;
|
||||
let session_model = fixture.session_configured.model.clone();
|
||||
|
||||
fixture
|
||||
.codex
|
||||
.submit(Op::UserTurn {
|
||||
items: vec![UserInput::Text {
|
||||
text: "call the rmcp image tool".into(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
final_output_json_schema: None,
|
||||
cwd: fixture.cwd.path().to_path_buf(),
|
||||
approval_policy: AskForApproval::Never,
|
||||
sandbox_policy: SandboxPolicy::ReadOnly,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: ReasoningSummary::Auto,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
let begin_event = wait_for_event(&fixture.codex, |ev| {
|
||||
matches!(ev, EventMsg::McpToolCallBegin(_))
|
||||
})
|
||||
.await;
|
||||
let EventMsg::McpToolCallBegin(begin) = begin_event else {
|
||||
unreachable!("begin");
|
||||
};
|
||||
assert_eq!(
|
||||
begin,
|
||||
McpToolCallBeginEvent {
|
||||
call_id: call_id.to_string(),
|
||||
invocation: McpInvocation {
|
||||
server: server_name.to_string(),
|
||||
tool: "image".to_string(),
|
||||
arguments: Some(json!({})),
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
let end_event = wait_for_event(&fixture.codex, |ev| {
|
||||
matches!(ev, EventMsg::McpToolCallEnd(_))
|
||||
})
|
||||
.await;
|
||||
let EventMsg::McpToolCallEnd(end) = end_event else {
|
||||
unreachable!("end");
|
||||
};
|
||||
assert!(end.result.as_ref().is_ok(), "tool call should succeed");
|
||||
|
||||
wait_for_event(&fixture.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
|
||||
// Chat Completions assertion: the second POST should include a tool role message
|
||||
// with an array `content` containing an item with the expected data URL.
|
||||
let all_requests = server.received_requests().await.expect("requests captured");
|
||||
let requests: Vec<_> = all_requests
|
||||
.iter()
|
||||
.filter(|req| req.method == "POST" && req.url.path().ends_with("/chat/completions"))
|
||||
.collect();
|
||||
assert!(requests.len() >= 2, "expected two chat completion calls");
|
||||
let second = requests[1];
|
||||
let body: Value = serde_json::from_slice(&second.body)?;
|
||||
let messages = body
|
||||
.get("messages")
|
||||
.and_then(Value::as_array)
|
||||
.cloned()
|
||||
.expect("messages array");
|
||||
let tool_msg = messages
|
||||
.iter()
|
||||
.find(|m| {
|
||||
m.get("role") == Some(&json!("tool")) && m.get("tool_call_id") == Some(&json!(call_id))
|
||||
})
|
||||
.cloned()
|
||||
.expect("tool message present");
|
||||
assert_eq!(
|
||||
tool_msg,
|
||||
json!({
|
||||
"role": "tool",
|
||||
"tool_call_id": call_id,
|
||||
"content": [{"type": "image_url", "image_url": {"url": OPENAI_PNG}}]
|
||||
})
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||
#[serial(mcp_test_value)]
|
||||
async fn stdio_server_propagates_whitelisted_env_vars() -> anyhow::Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user