Skip to main content

codex_mobile_bridge/app_server/
mod.rs

1mod handshake;
2mod manager;
3mod running;
4mod streams;
5
6#[cfg(test)]
7mod tests;
8
9use std::collections::HashMap;
10use std::path::PathBuf;
11use std::sync::{
12    Arc,
13    atomic::{AtomicBool, AtomicU64},
14};
15
16use anyhow::Result;
17use serde::{Deserialize, Serialize};
18use serde_json::Value;
19use tokio::io::BufWriter;
20use tokio::process::{Child, ChildStdin};
21use tokio::sync::{Mutex, mpsc, oneshot};
22
23const APP_SERVER_EXPERIMENTAL_API_ENABLED: bool = true;
24const APP_SERVER_OPT_OUT_NOTIFICATION_METHODS: &[&str] = &[
25    "account/login/completed",
26    "account/rateLimits/updated",
27    "account/updated",
28    "app/list/updated",
29    "fs/changed",
30    "fuzzyFileSearch/sessionCompleted",
31    "fuzzyFileSearch/sessionUpdated",
32    "hook/completed",
33    "hook/started",
34    "item/autoApprovalReview/completed",
35    "item/autoApprovalReview/started",
36    "item/commandExecution/terminalInteraction",
37    "mcpServer/oauthLogin/completed",
38    "mcpServer/startupStatus/updated",
39    "skills/changed",
40    "thread/compacted",
41    "thread/realtime/closed",
42    "thread/realtime/error",
43    "thread/realtime/itemAdded",
44    "thread/realtime/outputAudio/delta",
45    "thread/realtime/sdp",
46    "thread/realtime/started",
47    "thread/realtime/transcriptUpdated",
48    "windows/worldWritableWarning",
49    "windowsSandbox/setupCompleted",
50];
51
52#[derive(Debug, Clone)]
53pub struct AppServerLaunchConfig {
54    pub runtime_id: String,
55    pub codex_binary: String,
56    pub codex_home: Option<PathBuf>,
57}
58
59#[derive(Debug, Clone)]
60pub struct InitializeInfo {
61    pub user_agent: String,
62    pub codex_home: String,
63    pub platform_family: String,
64    pub platform_os: String,
65}
66
67#[derive(Debug, Clone)]
68pub enum AppServerInbound {
69    Starting {
70        runtime_id: String,
71    },
72    ProcessChanged {
73        runtime_id: String,
74        pid: Option<u32>,
75        running: bool,
76    },
77    Initializing {
78        runtime_id: String,
79        experimental_api_enabled: bool,
80        opt_out_notification_methods: Vec<String>,
81    },
82    Initialized {
83        runtime_id: String,
84        info: InitializeInfo,
85        experimental_api_enabled: bool,
86        opt_out_notification_methods: Vec<String>,
87    },
88    HandshakeFailed {
89        runtime_id: String,
90        message: String,
91        experimental_api_enabled: bool,
92        opt_out_notification_methods: Vec<String>,
93    },
94    Notification {
95        runtime_id: String,
96        method: String,
97        params: Value,
98    },
99    ServerRequest {
100        runtime_id: String,
101        id: Value,
102        method: String,
103        params: Value,
104    },
105    Exited {
106        runtime_id: String,
107        message: String,
108        expected: bool,
109    },
110    LogChunk {
111        runtime_id: String,
112        stream: String,
113        level: String,
114        source: String,
115        message: String,
116        detail: Option<Value>,
117        occurred_at_ms: i64,
118    },
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct RpcErrorPayload {
123    pub code: i64,
124    pub message: String,
125    #[serde(default)]
126    pub data: Option<Value>,
127}
128
129impl std::fmt::Display for RpcErrorPayload {
130    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131        write!(f, "[{}] {}", self.code, self.message)
132    }
133}
134
135pub struct AppServerManager {
136    launch_config: AppServerLaunchConfig,
137    inbound_tx: mpsc::UnboundedSender<AppServerInbound>,
138    inner: Mutex<Option<Arc<RunningAppServer>>>,
139}
140
141struct RunningAppServer {
142    runtime_id: String,
143    stdin: Arc<Mutex<BufWriter<ChildStdin>>>,
144    child: Arc<Mutex<Option<Child>>>,
145    pending: Arc<Mutex<HashMap<String, oneshot::Sender<Result<Value, RpcErrorPayload>>>>>,
146    next_id: AtomicU64,
147    alive: Arc<AtomicBool>,
148    stopping: Arc<AtomicBool>,
149}