From 09e26c95bb17f4c2c683d6f952024e2962acb9ec Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Tue, 10 Feb 2026 01:04:51 -0800 Subject: [PATCH] feat: include network_proxy in /debug-config --- .../schema/json/EventMsg.json | 43 ++++++++++++++++++- .../schema/json/ServerNotification.json | 32 +++++++++++++- .../codex_app_server_protocol.schemas.json | 32 +++++++++++++- .../json/v1/ForkConversationResponse.json | 32 +++++++++++++- .../json/v1/ResumeConversationResponse.json | 32 +++++++++++++- .../v1/SessionConfiguredNotification.json | 32 +++++++++++++- .../typescript/SessionConfiguredEvent.ts | 5 +++ .../typescript/SessionNetworkProxyRuntime.ts | 5 +++ .../schema/typescript/index.ts | 1 + codex-rs/core/src/codex.rs | 10 +++++ .../tests/event_processor_with_json_output.rs | 1 + codex-rs/mcp-server/src/outgoing_message.rs | 3 ++ codex-rs/network-proxy/src/proxy.rs | 12 ++++++ codex-rs/protocol/src/protocol.rs | 13 ++++++ codex-rs/tui/src/app.rs | 4 ++ codex-rs/tui/src/chatwidget.rs | 11 ++++- codex-rs/tui/src/chatwidget/tests.rs | 6 +++ codex-rs/tui/src/debug_config.rs | 24 ++++++++++- 18 files changed, 289 insertions(+), 9 deletions(-) create mode 100644 codex-rs/app-server-protocol/schema/typescript/SessionNetworkProxyRuntime.ts diff --git a/codex-rs/app-server-protocol/schema/json/EventMsg.json b/codex-rs/app-server-protocol/schema/json/EventMsg.json index 59976887d3..5991401b84 100644 --- a/codex-rs/app-server-protocol/schema/json/EventMsg.json +++ b/codex-rs/app-server-protocol/schema/json/EventMsg.json @@ -887,6 +887,17 @@ "model_provider_id": { "type": "string" }, + "network_proxy": { + "anyOf": [ + { + "$ref": "#/definitions/SessionNetworkProxyRuntime" + }, + { + "type": "null" + } + ], + "description": "Runtime proxy bind addresses, when the managed proxy was started for this session." + }, "reasoning_effort": { "anyOf": [ { @@ -4427,6 +4438,25 @@ } ] }, + "SessionNetworkProxyRuntime": { + "properties": { + "admin_addr": { + "type": "string" + }, + "http_addr": { + "type": "string" + }, + "socks_addr": { + "type": "string" + } + }, + "required": [ + "admin_addr", + "http_addr", + "socks_addr" + ], + "type": "object" + }, "SkillDependencies": { "properties": { "tools": { @@ -5600,6 +5630,17 @@ "model_provider_id": { "type": "string" }, + "network_proxy": { + "anyOf": [ + { + "$ref": "#/definitions/SessionNetworkProxyRuntime" + }, + { + "type": "null" + } + ], + "description": "Runtime proxy bind addresses, when the managed proxy was started for this session." + }, "reasoning_effort": { "anyOf": [ { @@ -7580,4 +7621,4 @@ } ], "title": "EventMsg" -} +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/ServerNotification.json b/codex-rs/app-server-protocol/schema/json/ServerNotification.json index edaceb5a12..69c6c2cb9b 100644 --- a/codex-rs/app-server-protocol/schema/json/ServerNotification.json +++ b/codex-rs/app-server-protocol/schema/json/ServerNotification.json @@ -1531,6 +1531,17 @@ "model_provider_id": { "type": "string" }, + "network_proxy": { + "anyOf": [ + { + "$ref": "#/definitions/SessionNetworkProxyRuntime" + }, + { + "type": "null" + } + ], + "description": "Runtime proxy bind addresses, when the managed proxy was started for this session." + }, "reasoning_effort": { "anyOf": [ { @@ -5583,6 +5594,25 @@ ], "type": "object" }, + "SessionNetworkProxyRuntime": { + "properties": { + "admin_addr": { + "type": "string" + }, + "http_addr": { + "type": "string" + }, + "socks_addr": { + "type": "string" + } + }, + "required": [ + "admin_addr", + "http_addr", + "socks_addr" + ], + "type": "object" + }, "SessionSource": { "oneOf": [ { @@ -8197,4 +8227,4 @@ } ], "title": "ServerNotification" -} +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json index f6b072e7d1..b7e922dd17 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json @@ -2900,6 +2900,17 @@ "model_provider_id": { "type": "string" }, + "network_proxy": { + "anyOf": [ + { + "$ref": "#/definitions/SessionNetworkProxyRuntime" + }, + { + "type": "null" + } + ], + "description": "Runtime proxy bind addresses, when the managed proxy was started for this session." + }, "reasoning_effort": { "anyOf": [ { @@ -8678,6 +8689,25 @@ "title": "SessionConfiguredNotification", "type": "object" }, + "SessionNetworkProxyRuntime": { + "properties": { + "admin_addr": { + "type": "string" + }, + "http_addr": { + "type": "string" + }, + "socks_addr": { + "type": "string" + } + }, + "required": [ + "admin_addr", + "http_addr", + "socks_addr" + ], + "type": "object" + }, "SessionSource": { "oneOf": [ { @@ -16361,4 +16391,4 @@ }, "title": "CodexAppServerProtocol", "type": "object" -} +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/v1/ForkConversationResponse.json b/codex-rs/app-server-protocol/schema/json/v1/ForkConversationResponse.json index 8204afaaed..90949d56f2 100644 --- a/codex-rs/app-server-protocol/schema/json/v1/ForkConversationResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v1/ForkConversationResponse.json @@ -887,6 +887,17 @@ "model_provider_id": { "type": "string" }, + "network_proxy": { + "anyOf": [ + { + "$ref": "#/definitions/SessionNetworkProxyRuntime" + }, + { + "type": "null" + } + ], + "description": "Runtime proxy bind addresses, when the managed proxy was started for this session." + }, "reasoning_effort": { "anyOf": [ { @@ -4427,6 +4438,25 @@ } ] }, + "SessionNetworkProxyRuntime": { + "properties": { + "admin_addr": { + "type": "string" + }, + "http_addr": { + "type": "string" + }, + "socks_addr": { + "type": "string" + } + }, + "required": [ + "admin_addr", + "http_addr", + "socks_addr" + ], + "type": "object" + }, "SkillDependencies": { "properties": { "tools": { @@ -5186,4 +5216,4 @@ ], "title": "ForkConversationResponse", "type": "object" -} +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/v1/ResumeConversationResponse.json b/codex-rs/app-server-protocol/schema/json/v1/ResumeConversationResponse.json index e45cb6d351..b25d2dbed3 100644 --- a/codex-rs/app-server-protocol/schema/json/v1/ResumeConversationResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v1/ResumeConversationResponse.json @@ -887,6 +887,17 @@ "model_provider_id": { "type": "string" }, + "network_proxy": { + "anyOf": [ + { + "$ref": "#/definitions/SessionNetworkProxyRuntime" + }, + { + "type": "null" + } + ], + "description": "Runtime proxy bind addresses, when the managed proxy was started for this session." + }, "reasoning_effort": { "anyOf": [ { @@ -4427,6 +4438,25 @@ } ] }, + "SessionNetworkProxyRuntime": { + "properties": { + "admin_addr": { + "type": "string" + }, + "http_addr": { + "type": "string" + }, + "socks_addr": { + "type": "string" + } + }, + "required": [ + "admin_addr", + "http_addr", + "socks_addr" + ], + "type": "object" + }, "SkillDependencies": { "properties": { "tools": { @@ -5186,4 +5216,4 @@ ], "title": "ResumeConversationResponse", "type": "object" -} +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/v1/SessionConfiguredNotification.json b/codex-rs/app-server-protocol/schema/json/v1/SessionConfiguredNotification.json index 7d782f438b..fa9e144c48 100644 --- a/codex-rs/app-server-protocol/schema/json/v1/SessionConfiguredNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v1/SessionConfiguredNotification.json @@ -887,6 +887,17 @@ "model_provider_id": { "type": "string" }, + "network_proxy": { + "anyOf": [ + { + "$ref": "#/definitions/SessionNetworkProxyRuntime" + }, + { + "type": "null" + } + ], + "description": "Runtime proxy bind addresses, when the managed proxy was started for this session." + }, "reasoning_effort": { "anyOf": [ { @@ -4427,6 +4438,25 @@ } ] }, + "SessionNetworkProxyRuntime": { + "properties": { + "admin_addr": { + "type": "string" + }, + "http_addr": { + "type": "string" + }, + "socks_addr": { + "type": "string" + } + }, + "required": [ + "admin_addr", + "http_addr", + "socks_addr" + ], + "type": "object" + }, "SkillDependencies": { "properties": { "tools": { @@ -5208,4 +5238,4 @@ ], "title": "SessionConfiguredNotification", "type": "object" -} +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/typescript/SessionConfiguredEvent.ts b/codex-rs/app-server-protocol/schema/typescript/SessionConfiguredEvent.ts index 2e1896a396..d964f44451 100644 --- a/codex-rs/app-server-protocol/schema/typescript/SessionConfiguredEvent.ts +++ b/codex-rs/app-server-protocol/schema/typescript/SessionConfiguredEvent.ts @@ -5,6 +5,7 @@ import type { AskForApproval } from "./AskForApproval"; import type { EventMsg } from "./EventMsg"; import type { ReasoningEffort } from "./ReasoningEffort"; import type { SandboxPolicy } from "./SandboxPolicy"; +import type { SessionNetworkProxyRuntime } from "./SessionNetworkProxyRuntime"; import type { ThreadId } from "./ThreadId"; export type SessionConfiguredEvent = { session_id: ThreadId, forked_from_id: ThreadId | null, @@ -46,6 +47,10 @@ history_entry_count: number, * When present, UIs can use these to seed the history. */ initial_messages: Array | null, +/** + * Runtime proxy bind addresses, when the managed proxy was started for this session. + */ +network_proxy?: SessionNetworkProxyRuntime, /** * Path in which the rollout is stored. Can be `None` for ephemeral threads */ diff --git a/codex-rs/app-server-protocol/schema/typescript/SessionNetworkProxyRuntime.ts b/codex-rs/app-server-protocol/schema/typescript/SessionNetworkProxyRuntime.ts new file mode 100644 index 0000000000..3f0c6d857e --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/SessionNetworkProxyRuntime.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SessionNetworkProxyRuntime = { http_addr: string, socks_addr: string, admin_addr: string, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/index.ts b/codex-rs/app-server-protocol/schema/typescript/index.ts index c0c00a0c81..895936de2b 100644 --- a/codex-rs/app-server-protocol/schema/typescript/index.ts +++ b/codex-rs/app-server-protocol/schema/typescript/index.ts @@ -175,6 +175,7 @@ export type { ServerNotification } from "./ServerNotification"; export type { ServerRequest } from "./ServerRequest"; export type { SessionConfiguredEvent } from "./SessionConfiguredEvent"; export type { SessionConfiguredNotification } from "./SessionConfiguredNotification"; +export type { SessionNetworkProxyRuntime } from "./SessionNetworkProxyRuntime"; export type { SessionSource } from "./SessionSource"; export type { SetDefaultModelParams } from "./SetDefaultModelParams"; export type { SetDefaultModelResponse } from "./SetDefaultModelResponse"; diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index 81512490eb..9c24476215 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -174,6 +174,7 @@ use crate::protocol::RequestUserInputEvent; use crate::protocol::ReviewDecision; use crate::protocol::SandboxPolicy; use crate::protocol::SessionConfiguredEvent; +use crate::protocol::SessionNetworkProxyRuntime; use crate::protocol::SkillDependencies as ProtocolSkillDependencies; use crate::protocol::SkillErrorInfo; use crate::protocol::SkillInterface as ProtocolSkillInterface; @@ -1076,6 +1077,14 @@ impl Session { })?), None => None, }; + let session_network_proxy = network_proxy.as_ref().map(|started| { + let proxy = started.proxy(); + SessionNetworkProxyRuntime { + http_addr: proxy.http_addr().to_string(), + socks_addr: proxy.socks_addr().to_string(), + admin_addr: proxy.admin_addr().to_string(), + } + }); let services = SessionServices { mcp_connection_manager: Arc::new(RwLock::new(McpConnectionManager::default())), @@ -1157,6 +1166,7 @@ impl Session { history_log_id, history_entry_count, initial_messages, + network_proxy: session_network_proxy, rollout_path, }), }) diff --git a/codex-rs/exec/tests/event_processor_with_json_output.rs b/codex-rs/exec/tests/event_processor_with_json_output.rs index 8c1c73e579..f349e4835f 100644 --- a/codex-rs/exec/tests/event_processor_with_json_output.rs +++ b/codex-rs/exec/tests/event_processor_with_json_output.rs @@ -98,6 +98,7 @@ fn session_configured_produces_thread_started_event() { history_log_id: 0, history_entry_count: 0, initial_messages: None, + network_proxy: None, rollout_path: Some(rollout_path), }), ); diff --git a/codex-rs/mcp-server/src/outgoing_message.rs b/codex-rs/mcp-server/src/outgoing_message.rs index e512eedbd7..1bf98534b0 100644 --- a/codex-rs/mcp-server/src/outgoing_message.rs +++ b/codex-rs/mcp-server/src/outgoing_message.rs @@ -307,6 +307,7 @@ mod tests { history_log_id: 1, history_entry_count: 1000, initial_messages: None, + network_proxy: None, rollout_path: Some(rollout_file.path().to_path_buf()), }), }; @@ -348,6 +349,7 @@ mod tests { history_log_id: 1, history_entry_count: 1000, initial_messages: None, + network_proxy: None, rollout_path: Some(rollout_file.path().to_path_buf()), }; let event = Event { @@ -413,6 +415,7 @@ mod tests { history_log_id: 1, history_entry_count: 1000, initial_messages: None, + network_proxy: None, rollout_path: Some(rollout_file.path().to_path_buf()), }; let event = Event { diff --git a/codex-rs/network-proxy/src/proxy.rs b/codex-rs/network-proxy/src/proxy.rs index c4f3d97dc5..0a95e44608 100644 --- a/codex-rs/network-proxy/src/proxy.rs +++ b/codex-rs/network-proxy/src/proxy.rs @@ -363,6 +363,18 @@ impl NetworkProxy { NetworkProxyBuilder::default() } + pub fn http_addr(&self) -> SocketAddr { + self.http_addr + } + + pub fn socks_addr(&self) -> SocketAddr { + self.socks_addr + } + + pub fn admin_addr(&self) -> SocketAddr { + self.admin_addr + } + pub fn apply_to_env(&self, env: &mut HashMap) { // Enforce proxying for child processes. We intentionally override existing values so // command-level environment cannot bypass the managed proxy endpoint. diff --git a/codex-rs/protocol/src/protocol.rs b/codex-rs/protocol/src/protocol.rs index 462730f982..8f6e998792 100644 --- a/codex-rs/protocol/src/protocol.rs +++ b/codex-rs/protocol/src/protocol.rs @@ -2265,6 +2265,13 @@ pub struct SkillsListEntry { pub errors: Vec, } +#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS, PartialEq, Eq)] +pub struct SessionNetworkProxyRuntime { + pub http_addr: String, + pub socks_addr: String, + pub admin_addr: String, +} + #[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS)] pub struct SessionConfiguredEvent { pub session_id: ThreadId, @@ -2306,6 +2313,11 @@ pub struct SessionConfiguredEvent { #[serde(skip_serializing_if = "Option::is_none")] pub initial_messages: Option>, + /// Runtime proxy bind addresses, when the managed proxy was started for this session. + #[serde(default, skip_serializing_if = "Option::is_none")] + #[ts(optional)] + pub network_proxy: Option, + /// Path in which the rollout is stored. Can be `None` for ephemeral threads #[serde(skip_serializing_if = "Option::is_none")] pub rollout_path: Option, @@ -2696,6 +2708,7 @@ mod tests { history_log_id: 0, history_entry_count: 0, initial_messages: None, + network_proxy: None, rollout_path: Some(rollout_file.path().to_path_buf()), }), }; diff --git a/codex-rs/tui/src/app.rs b/codex-rs/tui/src/app.rs index 6294df8347..d18ec23544 100644 --- a/codex-rs/tui/src/app.rs +++ b/codex-rs/tui/src/app.rs @@ -2353,6 +2353,7 @@ impl App { history_log_id: 0, history_entry_count: 0, initial_messages: None, + network_proxy: None, rollout_path: thread.rollout_path(), }), }; @@ -3042,6 +3043,7 @@ mod tests { history_log_id: 0, history_entry_count: 0, initial_messages: None, + network_proxy: None, rollout_path: Some(PathBuf::new()), }; Arc::new(new_session_info( @@ -3096,6 +3098,7 @@ mod tests { history_log_id: 0, history_entry_count: 0, initial_messages: None, + network_proxy: None, rollout_path: Some(PathBuf::new()), }), }); @@ -3142,6 +3145,7 @@ mod tests { history_log_id: 0, history_entry_count: 0, initial_messages: None, + network_proxy: None, rollout_path: Some(PathBuf::new()), }; diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index 30f3d17b20..c381686c9f 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -613,6 +613,8 @@ pub(crate) struct ChatWidget { current_rollout_path: Option, // Current working directory (if known) current_cwd: Option, + // Runtime network proxy bind addresses from SessionConfigured. + session_network_proxy: Option, // Shared latch so we only warn once about invalid status-line item IDs. status_line_invalid_items_warned: Arc, // Cached git branch name for the status line (None if unknown). @@ -1015,6 +1017,7 @@ impl ChatWidget { self.bottom_pane .set_history_metadata(event.history_log_id, event.history_entry_count); self.set_skills(None); + self.session_network_proxy = event.network_proxy.clone(); self.thread_id = Some(event.session_id); self.thread_name = event.thread_name.clone(); self.forked_from = event.forked_from_id; @@ -2658,6 +2661,7 @@ impl ChatWidget { feedback_audience, current_rollout_path: None, current_cwd, + session_network_proxy: None, status_line_invalid_items_warned, status_line_branch: None, status_line_branch_cwd: None, @@ -2822,6 +2826,7 @@ impl ChatWidget { feedback_audience, current_rollout_path: None, current_cwd, + session_network_proxy: None, status_line_invalid_items_warned, status_line_branch: None, status_line_branch_cwd: None, @@ -2975,6 +2980,7 @@ impl ChatWidget { feedback_audience, current_rollout_path: None, current_cwd, + session_network_proxy: None, status_line_invalid_items_warned, status_line_branch: None, status_line_branch_cwd: None, @@ -4239,7 +4245,10 @@ impl ChatWidget { } pub(crate) fn add_debug_config_output(&mut self) { - self.add_to_history(crate::debug_config::new_debug_config_output(&self.config)); + self.add_to_history(crate::debug_config::new_debug_config_output( + &self.config, + self.session_network_proxy.as_ref(), + )); } fn open_status_line_setup(&mut self) { diff --git a/codex-rs/tui/src/chatwidget/tests.rs b/codex-rs/tui/src/chatwidget/tests.rs index ad4c4fc62d..78f9dd3081 100644 --- a/codex-rs/tui/src/chatwidget/tests.rs +++ b/codex-rs/tui/src/chatwidget/tests.rs @@ -164,6 +164,7 @@ async fn resumed_initial_messages_render_history() { message: "assistant reply".to_string(), }), ]), + network_proxy: None, rollout_path: Some(rollout_file.path().to_path_buf()), }; @@ -226,6 +227,7 @@ async fn replayed_user_message_preserves_text_elements_and_local_images() { text_elements: text_elements.clone(), local_images: local_images.clone(), })]), + network_proxy: None, rollout_path: Some(rollout_file.path().to_path_buf()), }; @@ -338,6 +340,7 @@ async fn submission_preserves_text_elements_and_local_images() { history_log_id: 0, history_entry_count: 0, initial_messages: None, + network_proxy: None, rollout_path: Some(rollout_file.path().to_path_buf()), }; chat.handle_codex_event(Event { @@ -417,6 +420,7 @@ async fn submission_prefers_selected_duplicate_skill_path() { history_log_id: 0, history_entry_count: 0, initial_messages: None, + network_proxy: None, rollout_path: Some(rollout_file.path().to_path_buf()), }; chat.handle_codex_event(Event { @@ -1108,6 +1112,7 @@ async fn make_chatwidget_manual( feedback_audience: FeedbackAudience::External, current_rollout_path: None, current_cwd: None, + session_network_proxy: None, status_line_invalid_items_warned: Arc::new(AtomicBool::new(false)), status_line_branch: None, status_line_branch_cwd: None, @@ -2973,6 +2978,7 @@ async fn plan_slash_command_with_args_submits_prompt_in_plan_mode() { history_log_id: 0, history_entry_count: 0, initial_messages: None, + network_proxy: None, rollout_path: None, }; chat.handle_codex_event(Event { diff --git a/codex-rs/tui/src/debug_config.rs b/codex-rs/tui/src/debug_config.rs index 908ee1d24a..b5edeeb232 100644 --- a/codex-rs/tui/src/debug_config.rs +++ b/codex-rs/tui/src/debug_config.rs @@ -8,11 +8,31 @@ use codex_core::config_loader::RequirementSource; use codex_core::config_loader::ResidencyRequirement; use codex_core::config_loader::SandboxModeRequirement; use codex_core::config_loader::WebSearchModeRequirement; +use codex_core::protocol::SessionNetworkProxyRuntime; use ratatui::style::Stylize; use ratatui::text::Line; -pub(crate) fn new_debug_config_output(config: &Config) -> PlainHistoryCell { - PlainHistoryCell::new(render_debug_config_lines(&config.config_layer_stack)) +pub(crate) fn new_debug_config_output( + config: &Config, + session_network_proxy: Option<&SessionNetworkProxyRuntime>, +) -> PlainHistoryCell { + let mut lines = render_debug_config_lines(&config.config_layer_stack); + + if let Some(proxy) = session_network_proxy { + lines.push("".into()); + lines.push("Session runtime:".bold().into()); + lines.push(" - network_proxy".into()); + let SessionNetworkProxyRuntime { + http_addr, + socks_addr, + admin_addr, + } = proxy; + lines.push(format!(" - HTTP_PROXY = http://{http_addr}").into()); + lines.push(format!(" - ALL_PROXY = socks5h://{socks_addr}").into()); + lines.push(format!(" - ADMIN_PROXY = http://{admin_addr}").into()); + } + + PlainHistoryCell::new(lines) } fn render_debug_config_lines(stack: &ConfigLayerStack) -> Vec> {