From c991b670ee2cd6b1a2f61d9f6643351dfc6d5f26 Mon Sep 17 00:00:00 2001 From: Anton Panasenko Date: Wed, 25 Mar 2026 16:04:07 -0700 Subject: [PATCH] update --- .../remote_control/client_manager_tests.rs | 4 +- .../connection_manager_tests.rs | 14 +++---- .../src/remote_control/enrollment_tests.rs | 22 ++++++++++- codex-rs/app-server/src/remote_control/mod.rs | 39 ++++++++++++++----- 4 files changed, 59 insertions(+), 20 deletions(-) diff --git a/codex-rs/app-server/src/remote_control/client_manager_tests.rs b/codex-rs/app-server/src/remote_control/client_manager_tests.rs index 38a0671509..17f95a9dc9 100644 --- a/codex-rs/app-server/src/remote_control/client_manager_tests.rs +++ b/codex-rs/app-server/src/remote_control/client_manager_tests.rs @@ -92,7 +92,7 @@ async fn remote_control_transport_manages_virtual_clients_and_routes_messages() .await .expect("listener should bind"); let remote_control_url = format!( - "http://{}/backend-api/wham", + "http://{}/api/codex", listener .local_addr() .expect("listener should have a local addr") @@ -114,7 +114,7 @@ async fn remote_control_transport_manages_virtual_clients_and_routes_messages() let enroll_request = accept_http_request(&listener).await; assert_eq!( enroll_request.request_line, - "POST /backend-api/wham/remote/control/server/enroll HTTP/1.1" + "POST /api/codex/remote/control/server/enroll HTTP/1.1" ); respond_with_json( enroll_request.stream, diff --git a/codex-rs/app-server/src/remote_control/connection_manager_tests.rs b/codex-rs/app-server/src/remote_control/connection_manager_tests.rs index 37d1b908a0..110108b56c 100644 --- a/codex-rs/app-server/src/remote_control/connection_manager_tests.rs +++ b/codex-rs/app-server/src/remote_control/connection_manager_tests.rs @@ -36,7 +36,7 @@ async fn connect_remote_control_websocket_captures_handshake_request_id() { .await .expect("listener should bind"); let remote_control_url = format!( - "http://{}/backend-api/wham", + "http://{}/api/codex", listener .local_addr() .expect("listener should have a local addr") @@ -47,7 +47,7 @@ async fn connect_remote_control_websocket_captures_handshake_request_id() { let enroll_request = accept_http_request(&listener).await; assert_eq!( enroll_request.request_line, - "POST /backend-api/wham/remote/control/server/enroll HTTP/1.1" + "POST /api/codex/remote/control/server/enroll HTTP/1.1" ); assert_eq!( enroll_request.headers.get("authorization"), @@ -97,7 +97,7 @@ async fn connect_remote_control_websocket_includes_http_error_details() { .await .expect("listener should bind"); let remote_control_url = format!( - "http://{}/backend-api/wham", + "http://{}/api/codex", listener .local_addr() .expect("listener should have a local addr") @@ -112,7 +112,7 @@ async fn connect_remote_control_websocket_includes_http_error_details() { let enroll_request = accept_http_request(&listener).await; assert_eq!( enroll_request.request_line, - "POST /backend-api/wham/remote/control/server/enroll HTTP/1.1" + "POST /api/codex/remote/control/server/enroll HTTP/1.1" ); assert_eq!( enroll_request.headers.get("authorization"), @@ -136,7 +136,7 @@ async fn connect_remote_control_websocket_includes_http_error_details() { let request = accept_http_request(&listener).await; assert_eq!( request.request_line, - "GET /backend-api/wham/remote/control/server HTTP/1.1" + "GET /api/codex/remote/control/server HTTP/1.1" ); respond_with_status_and_headers( request.stream, @@ -177,7 +177,7 @@ async fn remote_control_transport_reconnects_and_keeps_virtual_client_writer_ali .await .expect("listener should bind"); let remote_control_url = format!( - "http://{}/backend-api/wham", + "http://{}/api/codex", listener .local_addr() .expect("listener should have a local addr") @@ -200,7 +200,7 @@ async fn remote_control_transport_reconnects_and_keeps_virtual_client_writer_ali let enroll_request = accept_http_request(&listener).await; assert_eq!( enroll_request.request_line, - "POST /backend-api/wham/remote/control/server/enroll HTTP/1.1" + "POST /api/codex/remote/control/server/enroll HTTP/1.1" ); respond_with_json(enroll_request.stream, json!({ "server_id": "srv_e_test" })).await; diff --git a/codex-rs/app-server/src/remote_control/enrollment_tests.rs b/codex-rs/app-server/src/remote_control/enrollment_tests.rs index 1f78956e5f..93782b5a7d 100644 --- a/codex-rs/app-server/src/remote_control/enrollment_tests.rs +++ b/codex-rs/app-server/src/remote_control/enrollment_tests.rs @@ -57,7 +57,7 @@ fn normalize_remote_control_url_handles_supported_and_unsupported_inputs() { ); assert_eq!( normalize_remote_control_url("https://chatgpt.com/backend-api") - .expect("chatgpt backend-api base should gain wham"), + .expect("chatgpt backend-api base should target the public wham path"), RemoteControlTarget { websocket_url: "wss://chatgpt.com/backend-api/wham/remote/control/server".to_string(), enroll_url: "https://chatgpt.com/backend-api/wham/remote/control/server/enroll" @@ -74,6 +74,24 @@ fn normalize_remote_control_url_handles_supported_and_unsupported_inputs() { .to_string(), } ); + assert_eq!( + normalize_remote_control_url("https://chatgpt.com/api/codex/remote/control/server") + .expect("internal chatgpt remote-control path should rewrite to the public wham path"), + RemoteControlTarget { + websocket_url: "wss://chatgpt.com/backend-api/wham/remote/control/server".to_string(), + enroll_url: "https://chatgpt.com/backend-api/wham/remote/control/server/enroll" + .to_string(), + } + ); + assert_eq!( + normalize_remote_control_url("https://chatgpt.com/api/codex") + .expect("explicit chatgpt api/codex base should rewrite to the public wham path"), + RemoteControlTarget { + websocket_url: "wss://chatgpt.com/backend-api/wham/remote/control/server".to_string(), + enroll_url: "https://chatgpt.com/backend-api/wham/remote/control/server/enroll" + .to_string(), + } + ); let err = normalize_remote_control_url("ftp://example.com/control") .expect_err("unsupported scheme should fail"); assert_eq!( @@ -256,7 +274,7 @@ async fn enroll_remote_control_server_parse_failure_includes_response_body() { .await .expect("listener should bind"); let remote_control_url = format!( - "http://{}/backend-api/wham", + "http://{}/api/codex", listener .local_addr() .expect("listener should have a local addr") diff --git a/codex-rs/app-server/src/remote_control/mod.rs b/codex-rs/app-server/src/remote_control/mod.rs index 04bef2a947..5a62e55eb7 100644 --- a/codex-rs/app-server/src/remote_control/mod.rs +++ b/codex-rs/app-server/src/remote_control/mod.rs @@ -185,19 +185,40 @@ fn normalize_http_remote_control_url( } fn normalize_chatgpt_remote_control_base(rest: &str) -> String { - if !(rest.starts_with("chatgpt.com") || rest.starts_with("chat.openai.com")) { - return rest.to_string(); + let trimmed = rest.trim_end_matches('/'); + let (host, path) = match trimmed.split_once('/') { + Some((host, path)) => (host, Some(path)), + None => (trimmed, None), + }; + if host != "chatgpt.com" && host != "chat.openai.com" { + return trimmed.to_string(); } - if rest.contains("/backend-api/wham/") || rest.ends_with("/backend-api/wham") { - return rest.to_string(); + + let Some(path) = path else { + return format!("{host}/backend-api/wham"); + }; + + if path == "backend-api/wham" || path.starts_with("backend-api/wham/") { + return trimmed.to_string(); } - if let Some((prefix, suffix)) = rest.split_once("/backend-api/") { - return format!("{prefix}/backend-api/wham/{suffix}"); + + for internal_prefix in ["api/codex", "backend-api"] { + if path == internal_prefix { + return format!("{host}/backend-api/wham"); + } + if let Some(suffix) = path.strip_prefix(&format!("{internal_prefix}/")) { + if suffix == "remote/control/server" || suffix == "remote/control/server/enroll" { + return format!("{host}/backend-api/wham/{suffix}"); + } + return format!("{host}/backend-api/wham"); + } } - if let Some(prefix) = rest.strip_suffix("/backend-api") { - return format!("{prefix}/backend-api/wham"); + + if path == "remote/control/server" || path == "remote/control/server/enroll" { + return format!("{host}/backend-api/wham/{path}"); } - format!("{}/backend-api/wham", rest.trim_end_matches('/')) + + trimmed.to_string() } async fn load_remote_control_auth(