mirror of
https://github.com/openai/codex.git
synced 2026-11-02 16:20:35 +00:00
[codex] remove responses command (#19640)
This removes the hidden `codex responses` CLI subcommand after confirming no downstream callers rely on it, deleting the raw Responses passthrough implementation, unregistering the subcommand, and dropping the now-unused CLI dependencies on `codex-api` and `codex-model-provider`.
This commit is contained in:
1 parent
355c40ad7e
commit
87bc72408c
4 files changed
+7
-289
No files matched your search
Generated
-2
@@ -2099,7 +2099,6 @@ dependencies = [
|
|||||||
"assert_matches",
|
"assert_matches",
|
||||||
"clap",
|
"clap",
|
||||||
"clap_complete",
|
"clap_complete",
|
||||||
"codex-api",
|
|
||||||
"codex-app-server",
|
"codex-app-server",
|
||||||
"codex-app-server-protocol",
|
"codex-app-server-protocol",
|
||||||
"codex-app-server-test-client",
|
"codex-app-server-test-client",
|
||||||
@@ -2116,7 +2115,6 @@ dependencies = [
|
|||||||
"codex-login",
|
"codex-login",
|
||||||
"codex-mcp",
|
"codex-mcp",
|
||||||
"codex-mcp-server",
|
"codex-mcp-server",
|
||||||
"codex-model-provider",
|
|
||||||
"codex-models-manager",
|
"codex-models-manager",
|
||||||
"codex-protocol",
|
"codex-protocol",
|
||||||
"codex-responses-api-proxy",
|
"codex-responses-api-proxy",
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ codex-app-server = { workspace = true }
|
|||||||
codex-app-server-protocol = { workspace = true }
|
codex-app-server-protocol = { workspace = true }
|
||||||
codex-app-server-test-client = { workspace = true }
|
codex-app-server-test-client = { workspace = true }
|
||||||
codex-arg0 = { workspace = true }
|
codex-arg0 = { workspace = true }
|
||||||
codex-api = { workspace = true }
|
|
||||||
codex-chatgpt = { workspace = true }
|
codex-chatgpt = { workspace = true }
|
||||||
codex-cloud-tasks = { path = "../cloud-tasks" }
|
codex-cloud-tasks = { path = "../cloud-tasks" }
|
||||||
codex-utils-cli = { workspace = true }
|
codex-utils-cli = { workspace = true }
|
||||||
@@ -39,7 +38,6 @@ codex-login = { workspace = true }
|
|||||||
codex-mcp = { workspace = true }
|
codex-mcp = { workspace = true }
|
||||||
codex-mcp-server = { workspace = true }
|
codex-mcp-server = { workspace = true }
|
||||||
codex-models-manager = { workspace = true }
|
codex-models-manager = { workspace = true }
|
||||||
codex-model-provider = { workspace = true }
|
|
||||||
codex-protocol = { workspace = true }
|
codex-protocol = { workspace = true }
|
||||||
codex-responses-api-proxy = { workspace = true }
|
codex-responses-api-proxy = { workspace = true }
|
||||||
codex-rmcp-client = { workspace = true }
|
codex-rmcp-client = { workspace = true }
|
||||||
|
|||||||
@@ -43,14 +43,11 @@ mod app_cmd;
|
|||||||
mod desktop_app;
|
mod desktop_app;
|
||||||
mod marketplace_cmd;
|
mod marketplace_cmd;
|
||||||
mod mcp_cmd;
|
mod mcp_cmd;
|
||||||
mod responses_cmd;
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
mod wsl_paths;
|
mod wsl_paths;
|
||||||
|
|
||||||
use crate::marketplace_cmd::MarketplaceCli;
|
use crate::marketplace_cmd::MarketplaceCli;
|
||||||
use crate::mcp_cmd::McpCli;
|
use crate::mcp_cmd::McpCli;
|
||||||
use crate::responses_cmd::ResponsesCommand;
|
|
||||||
use crate::responses_cmd::run_responses_command;
|
|
||||||
|
|
||||||
use codex_core::build_models_manager;
|
use codex_core::build_models_manager;
|
||||||
use codex_core::clear_memory_roots_contents;
|
use codex_core::clear_memory_roots_contents;
|
||||||
@@ -163,10 +160,6 @@ enum Subcommand {
|
|||||||
#[clap(hide = true)]
|
#[clap(hide = true)]
|
||||||
ResponsesApiProxy(ResponsesApiProxyArgs),
|
ResponsesApiProxy(ResponsesApiProxyArgs),
|
||||||
|
|
||||||
/// Internal: send one raw Responses API payload through Codex auth.
|
|
||||||
#[clap(hide = true)]
|
|
||||||
Responses(ResponsesCommand),
|
|
||||||
|
|
||||||
/// Internal: relay stdio to a Unix domain socket.
|
/// Internal: relay stdio to a Unix domain socket.
|
||||||
#[clap(hide = true, name = "stdio-to-uds")]
|
#[clap(hide = true, name = "stdio-to-uds")]
|
||||||
StdioToUds(StdioToUdsCommand),
|
StdioToUds(StdioToUdsCommand),
|
||||||
@@ -1130,14 +1123,6 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {
|
|||||||
tokio::task::spawn_blocking(move || codex_responses_api_proxy::run_main(args))
|
tokio::task::spawn_blocking(move || codex_responses_api_proxy::run_main(args))
|
||||||
.await??;
|
.await??;
|
||||||
}
|
}
|
||||||
Some(Subcommand::Responses(ResponsesCommand {})) => {
|
|
||||||
reject_remote_mode_for_subcommand(
|
|
||||||
root_remote.as_deref(),
|
|
||||||
root_remote_auth_token_env.as_deref(),
|
|
||||||
"responses",
|
|
||||||
)?;
|
|
||||||
run_responses_command(root_config_overrides).await?;
|
|
||||||
}
|
|
||||||
Some(Subcommand::StdioToUds(cmd)) => {
|
Some(Subcommand::StdioToUds(cmd)) => {
|
||||||
reject_remote_mode_for_subcommand(
|
reject_remote_mode_for_subcommand(
|
||||||
root_remote.as_deref(),
|
root_remote.as_deref(),
|
||||||
@@ -1837,12 +1822,13 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn responses_subcommand_is_hidden_from_help_but_parses() {
|
fn responses_subcommand_is_not_registered() {
|
||||||
let help = MultitoolCli::command().render_help().to_string();
|
let command = MultitoolCli::command();
|
||||||
assert!(!help.contains("responses"));
|
assert!(
|
||||||
|
command
|
||||||
let cli = MultitoolCli::try_parse_from(["codex", "responses"]).expect("parse");
|
.get_subcommands()
|
||||||
assert!(matches!(cli.subcommand, Some(Subcommand::Responses(_))));
|
.all(|subcommand| subcommand.get_name() != "responses")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn help_from_args(args: &[&str]) -> String {
|
fn help_from_args(args: &[&str]) -> String {
|
||||||
|
|||||||
@@ -1,264 +0,0 @@
|
|||||||
use clap::Parser;
|
|
||||||
use codex_core::config::Config;
|
|
||||||
use codex_model_provider::create_model_provider;
|
|
||||||
use codex_utils_cli::CliConfigOverrides;
|
|
||||||
use serde_json::json;
|
|
||||||
use tokio::io::AsyncReadExt;
|
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
|
||||||
pub(crate) struct ResponsesCommand {}
|
|
||||||
|
|
||||||
pub(crate) async fn run_responses_command(
|
|
||||||
root_config_overrides: CliConfigOverrides,
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
let mut payload_text = String::new();
|
|
||||||
tokio::io::stdin().read_to_string(&mut payload_text).await?;
|
|
||||||
if payload_text.trim().is_empty() {
|
|
||||||
anyhow::bail!("expected Responses API JSON payload on stdin");
|
|
||||||
}
|
|
||||||
|
|
||||||
let payload: serde_json::Value = serde_json::from_str(&payload_text)
|
|
||||||
.map_err(|err| anyhow::anyhow!("failed to parse Responses API JSON payload: {err}"))?;
|
|
||||||
if payload.get("stream").and_then(serde_json::Value::as_bool) != Some(true) {
|
|
||||||
anyhow::bail!("codex responses expects a streaming payload with `\"stream\": true`");
|
|
||||||
}
|
|
||||||
|
|
||||||
let cli_overrides = root_config_overrides
|
|
||||||
.parse_overrides()
|
|
||||||
.map_err(anyhow::Error::msg)?;
|
|
||||||
let config = Config::load_with_cli_overrides(cli_overrides).await?;
|
|
||||||
let base_auth_manager = codex_login::AuthManager::shared_from_config(
|
|
||||||
&config, /*enable_codex_api_key_env*/ true,
|
|
||||||
);
|
|
||||||
let model_provider = create_model_provider(config.model_provider, Some(base_auth_manager));
|
|
||||||
let api_provider = model_provider.api_provider().await?;
|
|
||||||
let api_auth = model_provider.api_auth().await?;
|
|
||||||
let client = codex_api::ResponsesClient::new(
|
|
||||||
codex_api::ReqwestTransport::new(codex_login::default_client::build_reqwest_client()),
|
|
||||||
api_provider,
|
|
||||||
api_auth,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut stream = client
|
|
||||||
.stream(
|
|
||||||
payload,
|
|
||||||
Default::default(),
|
|
||||||
codex_api::Compression::None,
|
|
||||||
/*turn_state*/ None,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
while let Some(event) = stream.rx_event.recv().await {
|
|
||||||
let event = event?;
|
|
||||||
println!("{}", serde_json::to_string(&response_event_to_json(event))?);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn response_event_to_json(event: codex_api::ResponseEvent) -> serde_json::Value {
|
|
||||||
match event {
|
|
||||||
codex_api::ResponseEvent::Created => {
|
|
||||||
json!({ "type": "response.created", "response": {} })
|
|
||||||
}
|
|
||||||
codex_api::ResponseEvent::OutputItemDone(item) => {
|
|
||||||
json!({ "type": "response.output_item.done", "item": item })
|
|
||||||
}
|
|
||||||
codex_api::ResponseEvent::OutputItemAdded(item) => {
|
|
||||||
json!({ "type": "response.output_item.added", "item": item })
|
|
||||||
}
|
|
||||||
codex_api::ResponseEvent::ServerModel(model) => {
|
|
||||||
json!({ "type": "response.server_model", "model": model })
|
|
||||||
}
|
|
||||||
codex_api::ResponseEvent::ModelVerifications(verifications) => {
|
|
||||||
json!({ "type": "response.model_verifications", "verifications": verifications })
|
|
||||||
}
|
|
||||||
codex_api::ResponseEvent::ServerReasoningIncluded(included) => {
|
|
||||||
json!({ "type": "response.server_reasoning_included", "included": included })
|
|
||||||
}
|
|
||||||
codex_api::ResponseEvent::Completed {
|
|
||||||
response_id,
|
|
||||||
token_usage,
|
|
||||||
end_turn,
|
|
||||||
} => {
|
|
||||||
let mut response = match token_usage {
|
|
||||||
Some(token_usage) => json!({
|
|
||||||
"id": response_id,
|
|
||||||
"usage": {
|
|
||||||
"input_tokens": token_usage.input_tokens,
|
|
||||||
"input_tokens_details": {
|
|
||||||
"cached_tokens": token_usage.cached_input_tokens,
|
|
||||||
},
|
|
||||||
"output_tokens": token_usage.output_tokens,
|
|
||||||
"output_tokens_details": {
|
|
||||||
"reasoning_tokens": token_usage.reasoning_output_tokens,
|
|
||||||
},
|
|
||||||
"total_tokens": token_usage.total_tokens,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
None => json!({ "id": response_id }),
|
|
||||||
};
|
|
||||||
if let Some(end_turn) = end_turn {
|
|
||||||
response["end_turn"] = json!(end_turn);
|
|
||||||
}
|
|
||||||
json!({ "type": "response.completed", "response": response })
|
|
||||||
}
|
|
||||||
codex_api::ResponseEvent::OutputTextDelta(delta) => {
|
|
||||||
json!({ "type": "response.output_text.delta", "delta": delta })
|
|
||||||
}
|
|
||||||
codex_api::ResponseEvent::ToolCallInputDelta {
|
|
||||||
item_id,
|
|
||||||
call_id,
|
|
||||||
delta,
|
|
||||||
} => {
|
|
||||||
json!({
|
|
||||||
"type": "response.tool_call_input.delta",
|
|
||||||
"item_id": item_id,
|
|
||||||
"call_id": call_id,
|
|
||||||
"delta": delta,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
codex_api::ResponseEvent::ReasoningSummaryDelta {
|
|
||||||
delta,
|
|
||||||
summary_index,
|
|
||||||
} => json!({
|
|
||||||
"type": "response.reasoning_summary_text.delta",
|
|
||||||
"delta": delta,
|
|
||||||
"summary_index": summary_index,
|
|
||||||
}),
|
|
||||||
codex_api::ResponseEvent::ReasoningContentDelta {
|
|
||||||
delta,
|
|
||||||
content_index,
|
|
||||||
} => json!({
|
|
||||||
"type": "response.reasoning_text.delta",
|
|
||||||
"delta": delta,
|
|
||||||
"content_index": content_index,
|
|
||||||
}),
|
|
||||||
codex_api::ResponseEvent::ReasoningSummaryPartAdded { summary_index } => {
|
|
||||||
json!({
|
|
||||||
"type": "response.reasoning_summary_part.added",
|
|
||||||
"summary_index": summary_index,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
codex_api::ResponseEvent::RateLimits(rate_limits) => {
|
|
||||||
json!({ "type": "response.rate_limits", "rate_limits": rate_limits })
|
|
||||||
}
|
|
||||||
codex_api::ResponseEvent::ModelsEtag(etag) => {
|
|
||||||
json!({ "type": "response.models_etag", "etag": etag })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::response_event_to_json;
|
|
||||||
use codex_protocol::protocol::TokenUsage;
|
|
||||||
use pretty_assertions::assert_eq;
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn response_events_keep_replayable_response_envelopes() {
|
|
||||||
let created = response_event_to_json(codex_api::ResponseEvent::Created);
|
|
||||||
assert_eq!(created, json!({"type": "response.created", "response": {}}));
|
|
||||||
|
|
||||||
let completed = response_event_to_json(codex_api::ResponseEvent::Completed {
|
|
||||||
response_id: "resp-1".to_string(),
|
|
||||||
token_usage: Some(TokenUsage {
|
|
||||||
input_tokens: 10,
|
|
||||||
cached_input_tokens: 4,
|
|
||||||
output_tokens: 7,
|
|
||||||
reasoning_output_tokens: 3,
|
|
||||||
total_tokens: 17,
|
|
||||||
}),
|
|
||||||
end_turn: Some(true),
|
|
||||||
});
|
|
||||||
assert_eq!(
|
|
||||||
completed,
|
|
||||||
json!({
|
|
||||||
"type": "response.completed",
|
|
||||||
"response": {
|
|
||||||
"id": "resp-1",
|
|
||||||
"usage": {
|
|
||||||
"input_tokens": 10,
|
|
||||||
"input_tokens_details": {
|
|
||||||
"cached_tokens": 4,
|
|
||||||
},
|
|
||||||
"output_tokens": 7,
|
|
||||||
"output_tokens_details": {
|
|
||||||
"reasoning_tokens": 3,
|
|
||||||
},
|
|
||||||
"total_tokens": 17,
|
|
||||||
},
|
|
||||||
"end_turn": true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let completed_without_usage = response_event_to_json(codex_api::ResponseEvent::Completed {
|
|
||||||
response_id: "resp-2".to_string(),
|
|
||||||
token_usage: None,
|
|
||||||
end_turn: Some(false),
|
|
||||||
});
|
|
||||||
assert_eq!(
|
|
||||||
completed_without_usage,
|
|
||||||
json!({"type": "response.completed", "response": {"id": "resp-2", "end_turn": false}})
|
|
||||||
);
|
|
||||||
|
|
||||||
let completed_without_usage_or_end_turn =
|
|
||||||
response_event_to_json(codex_api::ResponseEvent::Completed {
|
|
||||||
response_id: "resp-3".to_string(),
|
|
||||||
token_usage: None,
|
|
||||||
end_turn: None,
|
|
||||||
});
|
|
||||||
assert_eq!(
|
|
||||||
completed_without_usage_or_end_turn,
|
|
||||||
json!({"type": "response.completed", "response": {"id": "resp-3"}})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn reasoning_deltas_use_responses_event_names() {
|
|
||||||
let summary = response_event_to_json(codex_api::ResponseEvent::ReasoningSummaryDelta {
|
|
||||||
delta: "plan".to_string(),
|
|
||||||
summary_index: 1,
|
|
||||||
});
|
|
||||||
assert_eq!(
|
|
||||||
summary,
|
|
||||||
json!({
|
|
||||||
"type": "response.reasoning_summary_text.delta",
|
|
||||||
"delta": "plan",
|
|
||||||
"summary_index": 1,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let content = response_event_to_json(codex_api::ResponseEvent::ReasoningContentDelta {
|
|
||||||
delta: "detail".to_string(),
|
|
||||||
content_index: 2,
|
|
||||||
});
|
|
||||||
assert_eq!(
|
|
||||||
content,
|
|
||||||
json!({
|
|
||||||
"type": "response.reasoning_text.delta",
|
|
||||||
"delta": "detail",
|
|
||||||
"content_index": 2,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn tool_call_input_delta_uses_responses_event_name() {
|
|
||||||
let delta = response_event_to_json(codex_api::ResponseEvent::ToolCallInputDelta {
|
|
||||||
item_id: "item-1".to_string(),
|
|
||||||
call_id: Some("call-1".to_string()),
|
|
||||||
delta: "patch".to_string(),
|
|
||||||
});
|
|
||||||
assert_eq!(
|
|
||||||
delta,
|
|
||||||
json!({
|
|
||||||
"type": "response.tool_call_input.delta",
|
|
||||||
"item_id": "item-1",
|
|
||||||
"call_id": "call-1",
|
|
||||||
"delta": "patch",
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user