mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
enable/disable remote control at runtime, not via features (#22578)
## Why reapplies https://github.com/openai/codex/pull/22386 which was previously reverted Also, introduce `remoteControl/enable` and `remoteControl/disable` app-server APIs to toggle on/off remote control at runtime for a given running app-server instance. ## What Changed - Adds experimental v2 RPCs: - `remoteControl/enable` - `remoteControl/disable` - Adds `RemoteControlRequestProcessor` and routes the new RPCs through it instead of `ConfigRequestProcessor`. - Adds named `RemoteControlHandle::enable`, `disable`, and `status` methods. - Makes `remoteControl/enable` return an error when sqlite state DB is unavailable, while keeping enrollment/websocket failures as async status updates. - Adds `AppServerRuntimeOptions.remote_control_enabled` and hidden `--remote-control` flags for `codex app-server` and `codex-app-server`. - Updates managed daemon startup to use `codex app-server --remote-control --listen unix://`. - Marks `Feature::RemoteControl` as removed and ignores `[features].remote_control`. - Updates app-server README entries for the new remote-control methods.
This commit is contained in:
@@ -570,6 +570,18 @@ impl McpProcess {
|
||||
.await
|
||||
}
|
||||
|
||||
/// Send a `remoteControl/enable` JSON-RPC request.
|
||||
pub async fn send_remote_control_enable_request(&mut self) -> anyhow::Result<i64> {
|
||||
self.send_request("remoteControl/enable", /*params*/ None)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Send a `remoteControl/disable` JSON-RPC request.
|
||||
pub async fn send_remote_control_disable_request(&mut self) -> anyhow::Result<i64> {
|
||||
self.send_request("remoteControl/disable", /*params*/ None)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Send an `app/list` JSON-RPC request.
|
||||
pub async fn send_apps_list_request(&mut self, params: AppsListParams) -> anyhow::Result<i64> {
|
||||
let params = Some(serde_json::to_value(params)?);
|
||||
|
||||
@@ -38,6 +38,7 @@ mod plugin_uninstall;
|
||||
mod process_exec;
|
||||
mod rate_limits;
|
||||
mod realtime_conversation;
|
||||
mod remote_control;
|
||||
#[cfg(debug_assertions)]
|
||||
mod remote_thread_store;
|
||||
mod request_permissions;
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_app_server_protocol::RemoteControlConnectionStatus;
|
||||
use codex_app_server_protocol::RemoteControlDisableResponse;
|
||||
use codex_app_server_protocol::RemoteControlEnableResponse;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use tempfile::TempDir;
|
||||
use tokio::time::timeout;
|
||||
|
||||
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
#[tokio::test]
|
||||
async fn remote_control_disable_returns_disabled_status() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp.send_remote_control_disable_request().await?;
|
||||
let response: JSONRPCResponse = timeout(
|
||||
DEFAULT_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(request_id)),
|
||||
)
|
||||
.await??;
|
||||
let received: RemoteControlDisableResponse = to_response(response)?;
|
||||
|
||||
assert_eq!(received.status, RemoteControlConnectionStatus::Disabled);
|
||||
assert_eq!(received.environment_id, None);
|
||||
assert!(!received.installation_id.is_empty());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn remote_control_enable_returns_connecting_status() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp.send_remote_control_enable_request().await?;
|
||||
let response: JSONRPCResponse = timeout(
|
||||
DEFAULT_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(request_id)),
|
||||
)
|
||||
.await??;
|
||||
let received: RemoteControlEnableResponse = to_response(response)?;
|
||||
|
||||
assert_eq!(received.status, RemoteControlConnectionStatus::Connecting);
|
||||
assert_eq!(received.environment_id, None);
|
||||
assert!(!received.installation_id.is_empty());
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user