clawdex-mobile 5.1.3-internal.7 → 5.1.3-internal.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -102,7 +102,7 @@ npm run codespaces:bootstrap -- --no-start
102
102
 
103
103
  - The bridge can transcribe with `OPENAI_API_KEY`, `BRIDGE_CHATGPT_ACCESS_TOKEN`, a legacy bridge token cache, or the Codex-managed ChatGPT token in `$CODEX_HOME/auth.json`.
104
104
  - In GitHub Codespaces, finish the Codex login step from the app first. Codex writes the login to `$HOME/.codex/auth.json`, and `.env.secure` sets `CODEX_HOME` to that persistent location.
105
- - If you still see the error after logging in, restart the bridge once so app-server reloads the Codex auth home:
105
+ - Current app builds automatically restart the Codespace Codex app-server after the Codex login step so it reloads the Codex auth home. On older builds, restart the bridge once after logging in:
106
106
 
107
107
  ```bash
108
108
  npm run secure:bridge
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawdex-mobile",
3
- "version": "5.1.3-internal.7",
3
+ "version": "5.1.3-internal.8",
4
4
  "description": "Private-network mobile bridge and CLI for Codex and OpenCode",
5
5
  "keywords": [
6
6
  "codex",
@@ -149,7 +149,7 @@ dependencies = [
149
149
 
150
150
  [[package]]
151
151
  name = "codex-rust-bridge"
152
- version = "5.1.3-internal.7"
152
+ version = "5.1.3-internal.8"
153
153
  dependencies = [
154
154
  "axum",
155
155
  "base64",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "codex-rust-bridge"
3
- version = "5.1.3-internal.7"
3
+ version = "5.1.3-internal.8"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -1266,7 +1266,7 @@ impl BrowserPreviewService {
1266
1266
  #[derive(Clone)]
1267
1267
  struct RuntimeBackend {
1268
1268
  preferred_engine: BridgeRuntimeEngine,
1269
- codex: Option<Arc<AppServerBridge>>,
1269
+ codex: Arc<StdRwLock<Option<Arc<AppServerBridge>>>>,
1270
1270
  opencode: Option<Arc<OpencodeBackend>>,
1271
1271
  cursor: Arc<StdRwLock<Option<Arc<AppServerBridge>>>>,
1272
1272
  }
@@ -1281,7 +1281,7 @@ impl RuntimeBackend {
1281
1281
  let cursor_enabled = config
1282
1282
  .enabled_engines
1283
1283
  .contains(&BridgeRuntimeEngine::Cursor);
1284
- let mut codex = None;
1284
+ let codex = Arc::new(StdRwLock::new(None));
1285
1285
  let mut opencode = None;
1286
1286
  let cursor = Arc::new(StdRwLock::new(None));
1287
1287
 
@@ -1291,7 +1291,7 @@ impl RuntimeBackend {
1291
1291
  let app_server =
1292
1292
  AppServerBridge::start_codex(&config.cli_bin, hub.clone()).await?;
1293
1293
  spawn_rollout_live_sync(hub.clone());
1294
- codex = Some(app_server);
1294
+ Self::store_codex_backend(&codex, app_server);
1295
1295
  }
1296
1296
 
1297
1297
  if opencode_enabled {
@@ -1327,7 +1327,7 @@ impl RuntimeBackend {
1327
1327
  {
1328
1328
  Ok(app_server) => {
1329
1329
  spawn_rollout_live_sync(hub.clone());
1330
- codex = Some(app_server);
1330
+ Self::store_codex_backend(&codex, app_server);
1331
1331
  }
1332
1332
  Err(error) => eprintln!(
1333
1333
  "codex backend unavailable; continuing with selected harnesses only: {error}"
@@ -1358,7 +1358,7 @@ impl RuntimeBackend {
1358
1358
  match AppServerBridge::start_codex(&config.cli_bin, hub.clone()).await {
1359
1359
  Ok(app_server) => {
1360
1360
  spawn_rollout_live_sync(hub.clone());
1361
- codex = Some(app_server);
1361
+ Self::store_codex_backend(&codex, app_server);
1362
1362
  }
1363
1363
  Err(error) => eprintln!(
1364
1364
  "codex backend unavailable; continuing with selected harnesses only: {error}"
@@ -1389,6 +1389,19 @@ impl RuntimeBackend {
1389
1389
  self.cursor.read().ok().and_then(|guard| guard.clone())
1390
1390
  }
1391
1391
 
1392
+ fn codex_backend(&self) -> Option<Arc<AppServerBridge>> {
1393
+ self.codex.read().ok().and_then(|guard| guard.clone())
1394
+ }
1395
+
1396
+ fn store_codex_backend(
1397
+ codex_slot: &Arc<StdRwLock<Option<Arc<AppServerBridge>>>>,
1398
+ bridge: Arc<AppServerBridge>,
1399
+ ) {
1400
+ if let Ok(mut guard) = codex_slot.write() {
1401
+ *guard = Some(bridge);
1402
+ }
1403
+ }
1404
+
1392
1405
  fn store_cursor_backend(
1393
1406
  cursor_slot: &Arc<StdRwLock<Option<Arc<AppServerBridge>>>>,
1394
1407
  bridge: Arc<AppServerBridge>,
@@ -1398,8 +1411,31 @@ impl RuntimeBackend {
1398
1411
  }
1399
1412
  }
1400
1413
 
1414
+ async fn restart_codex_app_server(
1415
+ &self,
1416
+ config: &Arc<BridgeConfig>,
1417
+ hub: Arc<ClientHub>,
1418
+ ) -> Result<(), String> {
1419
+ if !config.enabled_engines.contains(&BridgeRuntimeEngine::Codex) {
1420
+ return Err("codex backend is not enabled".to_string());
1421
+ }
1422
+
1423
+ let next_backend = AppServerBridge::start_codex(&config.cli_bin, hub).await?;
1424
+ let previous_backend = self
1425
+ .codex
1426
+ .write()
1427
+ .map(|mut guard| guard.replace(next_backend))
1428
+ .map_err(|_| "codex backend lock is unavailable".to_string())?;
1429
+
1430
+ if let Some(previous_backend) = previous_backend {
1431
+ previous_backend.request_shutdown().await;
1432
+ }
1433
+
1434
+ Ok(())
1435
+ }
1436
+
1401
1437
  async fn shutdown(&self) {
1402
- if let Some(codex) = &self.codex {
1438
+ if let Some(codex) = self.codex_backend() {
1403
1439
  codex.request_shutdown().await;
1404
1440
  }
1405
1441
  if let Some(opencode) = &self.opencode {
@@ -1416,7 +1452,7 @@ impl RuntimeBackend {
1416
1452
 
1417
1453
  fn available_engines(&self) -> Vec<BridgeRuntimeEngine> {
1418
1454
  let mut engines = Vec::new();
1419
- if self.codex.is_some() {
1455
+ if self.codex_backend().is_some() {
1420
1456
  engines.push(BridgeRuntimeEngine::Codex);
1421
1457
  }
1422
1458
  if self.opencode.is_some() {
@@ -1469,8 +1505,7 @@ impl RuntimeBackend {
1469
1505
  ) -> Result<RuntimeBackendRef<'_>, String> {
1470
1506
  match engine {
1471
1507
  BridgeRuntimeEngine::Codex => self
1472
- .codex
1473
- .as_ref()
1508
+ .codex_backend()
1474
1509
  .map(RuntimeBackendRef::Codex)
1475
1510
  .ok_or_else(|| "codex backend is unavailable".to_string()),
1476
1511
  BridgeRuntimeEngine::Opencode => self
@@ -1576,7 +1611,7 @@ impl RuntimeBackend {
1576
1611
  let bridge_cursor = extract_thread_list_cursor(params.as_ref())
1577
1612
  .and_then(|cursor| decode_bridge_thread_list_cursor(&cursor));
1578
1613
 
1579
- if let Some(codex) = &self.codex {
1614
+ if let Some(codex) = self.codex_backend() {
1580
1615
  if let Some(cursor_map) = bridge_cursor.as_ref() {
1581
1616
  if let Some(cursor) = cursor_map.get(&BridgeRuntimeEngine::Codex) {
1582
1617
  results.push((
@@ -1660,7 +1695,7 @@ impl RuntimeBackend {
1660
1695
  async fn aggregate_loaded_thread_ids(&self) -> Result<Value, String> {
1661
1696
  let mut results = Vec::new();
1662
1697
 
1663
- if let Some(codex) = &self.codex {
1698
+ if let Some(codex) = self.codex_backend() {
1664
1699
  results.push((
1665
1700
  BridgeRuntimeEngine::Codex,
1666
1701
  codex.request_internal("thread/loaded/list", None).await?,
@@ -1688,7 +1723,7 @@ impl RuntimeBackend {
1688
1723
 
1689
1724
  async fn list_pending_approvals(&self) -> Vec<PendingApproval> {
1690
1725
  let mut approvals = Vec::new();
1691
- if let Some(codex) = &self.codex {
1726
+ if let Some(codex) = self.codex_backend() {
1692
1727
  approvals.extend(codex.list_pending_approvals().await);
1693
1728
  }
1694
1729
  if let Some(opencode) = &self.opencode {
@@ -1703,7 +1738,7 @@ impl RuntimeBackend {
1703
1738
 
1704
1739
  async fn list_pending_user_inputs(&self) -> Vec<PendingUserInputRequest> {
1705
1740
  let mut requests = Vec::new();
1706
- if let Some(codex) = &self.codex {
1741
+ if let Some(codex) = self.codex_backend() {
1707
1742
  requests.extend(codex.list_pending_user_inputs().await);
1708
1743
  }
1709
1744
  if let Some(opencode) = &self.opencode {
@@ -1721,7 +1756,7 @@ impl RuntimeBackend {
1721
1756
  approval_id: &str,
1722
1757
  decision: &Value,
1723
1758
  ) -> Result<Option<PendingApproval>, String> {
1724
- if let Some(codex) = &self.codex {
1759
+ if let Some(codex) = self.codex_backend() {
1725
1760
  if let Some(approval) = codex.resolve_approval(approval_id, decision).await? {
1726
1761
  return Ok(Some(approval));
1727
1762
  }
@@ -1747,7 +1782,7 @@ impl RuntimeBackend {
1747
1782
  request_id: &str,
1748
1783
  answers: &HashMap<String, UserInputAnswerPayload>,
1749
1784
  ) -> Result<Option<PendingUserInputRequest>, String> {
1750
- if let Some(codex) = &self.codex {
1785
+ if let Some(codex) = self.codex_backend() {
1751
1786
  if let Some(request) = codex.resolve_user_input(request_id, answers).await? {
1752
1787
  return Ok(Some(request));
1753
1788
  }
@@ -1792,7 +1827,7 @@ impl RuntimeBackend {
1792
1827
  }
1793
1828
  }),
1794
1829
  };
1795
- if let Some(codex) = &self.codex {
1830
+ if let Some(codex) = self.codex_backend() {
1796
1831
  codex.hub.send_json(client_id, payload).await;
1797
1832
  } else if let Some(opencode) = &self.opencode {
1798
1833
  opencode.hub.send_json(client_id, payload).await;
@@ -1892,7 +1927,7 @@ async fn terminate_process_tree_windows(pid: u32, label: &str) {
1892
1927
  }
1893
1928
 
1894
1929
  enum RuntimeBackendRef<'a> {
1895
- Codex(&'a Arc<AppServerBridge>),
1930
+ Codex(Arc<AppServerBridge>),
1896
1931
  Opencode(&'a Arc<OpencodeBackend>),
1897
1932
  Cursor(Arc<AppServerBridge>),
1898
1933
  }
@@ -7468,6 +7503,17 @@ async fn handle_bridge_method(
7468
7503
  .map_err(|error| BridgeError::invalid_params(&error.to_string()))?;
7469
7504
  forward_codex_auth_callback(state, &request.callback_url).await
7470
7505
  }
7506
+ "bridge/codex/app-server/restart" => {
7507
+ state
7508
+ .backend
7509
+ .restart_codex_app_server(&state.config, state.hub.clone())
7510
+ .await
7511
+ .map_err(|error| BridgeError::server(&error))?;
7512
+ Ok(json!({
7513
+ "ok": true,
7514
+ "message": "Codex app-server restarted."
7515
+ }))
7516
+ }
7471
7517
  "bridge/update/start" => {
7472
7518
  let request: BridgeUpdateStartRequest =
7473
7519
  serde_json::from_value(params.unwrap_or_else(|| json!({})))
@@ -13586,16 +13632,15 @@ mod tests {
13586
13632
  let _ = child.wait().await;
13587
13633
  }
13588
13634
 
13589
- fn test_codex_backend(backend: &Arc<RuntimeBackend>) -> &Arc<AppServerBridge> {
13635
+ fn test_codex_backend(backend: &Arc<RuntimeBackend>) -> Arc<AppServerBridge> {
13590
13636
  backend
13591
- .codex
13592
- .as_ref()
13637
+ .codex_backend()
13593
13638
  .expect("expected codex backend in test")
13594
13639
  }
13595
13640
 
13596
13641
  async fn shutdown_test_backend(backend: &Arc<RuntimeBackend>) {
13597
- if let Some(codex) = &backend.codex {
13598
- shutdown_test_bridge(codex).await;
13642
+ if let Some(codex) = backend.codex_backend() {
13643
+ shutdown_test_bridge(&codex).await;
13599
13644
  }
13600
13645
  if let Some(opencode) = &backend.opencode {
13601
13646
  shutdown_test_opencode_backend(opencode).await;
@@ -13610,7 +13655,7 @@ mod tests {
13610
13655
  preferred_engine: BridgeRuntimeEngine,
13611
13656
  include_opencode: bool,
13612
13657
  ) -> Arc<RuntimeBackend> {
13613
- let codex = Some(build_test_bridge(hub.clone()).await);
13658
+ let codex = Arc::new(StdRwLock::new(Some(build_test_bridge(hub.clone()).await)));
13614
13659
  let opencode = if include_opencode {
13615
13660
  Some(build_test_opencode_backend(hub).await)
13616
13661
  } else {