Files
codex/codex-rs/app-server/src/transport/remote_control/mod.rs
T
jif-oai 76ea694db5 fix: auth preflight (#18117)
Fix app-server startup when `remote_control = true` is enabled without
ChatGPT auth.

Remote control now starts in a degraded/retrying state instead of
failing app-server initialization, so Desktop is not stranded before the
initial initialize handshake.
2026-04-16 16:17:11 +01:00

87 lines
2.2 KiB
Rust

mod client_tracker;
mod enroll;
mod protocol;
mod websocket;
use crate::transport::remote_control::websocket::RemoteControlWebsocket;
pub use self::protocol::ClientId;
use self::protocol::ServerEvent;
use self::protocol::StreamId;
use self::protocol::normalize_remote_control_url;
use super::CHANNEL_CAPACITY;
use super::TransportEvent;
use super::next_connection_id;
use codex_login::AuthManager;
use codex_state::StateRuntime;
use std::io;
use std::sync::Arc;
use tokio::sync::mpsc;
use tokio::sync::oneshot;
use tokio::sync::watch;
use tokio::task::JoinHandle;
use tokio_util::sync::CancellationToken;
pub(super) struct QueuedServerEnvelope {
pub(super) event: ServerEvent,
pub(super) client_id: ClientId,
pub(super) stream_id: StreamId,
pub(super) write_complete_tx: Option<oneshot::Sender<()>>,
}
#[derive(Clone)]
pub(crate) struct RemoteControlHandle {
enabled_tx: Arc<watch::Sender<bool>>,
}
impl RemoteControlHandle {
pub(crate) fn set_enabled(&self, enabled: bool) {
self.enabled_tx.send_if_modified(|state| {
let changed = *state != enabled;
*state = enabled;
changed
});
}
}
pub(crate) async fn start_remote_control(
remote_control_url: String,
state_db: Option<Arc<StateRuntime>>,
auth_manager: Arc<AuthManager>,
transport_event_tx: mpsc::Sender<TransportEvent>,
shutdown_token: CancellationToken,
app_server_client_name_rx: Option<oneshot::Receiver<String>>,
initial_enabled: bool,
) -> io::Result<(JoinHandle<()>, RemoteControlHandle)> {
let remote_control_target = if initial_enabled {
Some(normalize_remote_control_url(&remote_control_url)?)
} else {
None
};
let (enabled_tx, enabled_rx) = watch::channel(initial_enabled);
let join_handle = tokio::spawn(async move {
RemoteControlWebsocket::new(
remote_control_url,
remote_control_target,
state_db,
auth_manager,
transport_event_tx,
shutdown_token,
enabled_rx,
)
.run(app_server_client_name_rx)
.await;
});
Ok((
join_handle,
RemoteControlHandle {
enabled_tx: Arc::new(enabled_tx),
},
))
}
#[cfg(test)]
mod tests;