Skip to content

Commit 93334d6

Browse files
committed
feat(remote): add transport providers with Cloudflare WS stub
1 parent c58052b commit 93334d6

35 files changed

Lines changed: 932 additions & 590 deletions

memory/decisions.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,10 @@ Type: decision
204204
Event: Added daemon-side RPC parity coverage for recently extracted workspace/prompts/local-usage adapters and improved open-app failure diagnostics.
205205
Action: Added RPC tests in `src-tauri/src/bin/codex_monitor_daemon.rs` for `add_clone`, `prompts_list`, and `local_usage_snapshot` routing; updated `open_workspace_in_core` in `src-tauri/src/shared/workspaces_core.rs` to include bounded stdout/stderr snippets in non-zero exit errors.
206206
Rule: Keep daemon adapter parity guarded by RPC-level tests for representative workspace/prompts/local-usage methods, and preserve process-output context in open-app failure errors.
207+
208+
## 2026-02-07 17:52
209+
Context: Remote backend transport abstraction for mobile bridge prep
210+
Type: decision
211+
Event: Remote backend was a single TCP-specific module with no transport-level provider split.
212+
Action: Refactored `src-tauri/src/remote_backend.rs` into `remote_backend/{mod,protocol,transport,tcp_transport,cloudflare_ws_transport}.rs`, added `remoteBackendProvider` + Cloudflare settings fields, kept TCP behavior as default, and added a Cloudflare transport stub that returns a clear not-implemented error.
213+
Rule: Keep remote transport wiring behind `RemoteTransport` and use provider selection in settings so new bridge transports can be added without touching command callsites.

memory/todo.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Open
44
- [ ] 2026-02-07: Implement Orbit-only mobile remote foundation: Orbit transport in `remote_backend`, runner Orbit mode, hosted/self-host settings + pairing UX, and iOS keychain-backed auth storage.
5+
- [ ] 2026-02-07: Implement Cloudflare WebSocket transport internals behind `remoteBackendProvider=cloudflare` (handshake/auth/send/subscribe/reconnect/replay) and wire settings UX for worker/session inputs.
56

67
## Done
78
- [x] 2026-02-07: Restored Sentry frontend reporting removed in `83a37da` (`@sentry/react`, `Sentry.init`, captureException callsites, and metrics instrumentation).

src-tauri/src/backend/app_server.rs

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ use tokio::sync::{mpsc, oneshot, Mutex};
1313
use tokio::time::timeout;
1414

1515
use crate::backend::events::{AppServerEvent, EventSink};
16-
use crate::shared::process_core::{kill_child_process_tree, tokio_command};
1716
use crate::codex::args::parse_codex_args;
17+
use crate::shared::process_core::{kill_child_process_tree, tokio_command};
1818
use crate::types::WorkspaceEntry;
1919

2020
#[cfg(target_os = "windows")]
@@ -110,14 +110,18 @@ pub(crate) fn build_codex_path_env(codex_bin: Option<&str>) -> Option<String> {
110110

111111
#[cfg(not(target_os = "windows"))]
112112
{
113-
extras.extend([
114-
"/opt/homebrew/bin",
115-
"/usr/local/bin",
116-
"/usr/bin",
117-
"/bin",
118-
"/usr/sbin",
119-
"/sbin",
120-
].into_iter().map(PathBuf::from));
113+
extras.extend(
114+
[
115+
"/opt/homebrew/bin",
116+
"/usr/local/bin",
117+
"/usr/bin",
118+
"/bin",
119+
"/usr/sbin",
120+
"/sbin",
121+
]
122+
.into_iter()
123+
.map(PathBuf::from),
124+
);
121125

122126
if let Ok(home) = env::var("HOME") {
123127
let home_path = Path::new(&home);
@@ -237,16 +241,14 @@ pub(crate) fn build_codex_command_with_bin(
237241
pub(crate) async fn check_codex_installation(
238242
codex_bin: Option<String>,
239243
) -> Result<Option<String>, String> {
240-
let mut command =
241-
build_codex_command_with_bin(codex_bin, None, vec!["--version".to_string()])?;
244+
let mut command = build_codex_command_with_bin(codex_bin, None, vec!["--version".to_string()])?;
242245
command.stdout(std::process::Stdio::piped());
243246
command.stderr(std::process::Stdio::piped());
244247

245248
let output = match timeout(Duration::from_secs(5), command.output()).await {
246249
Ok(result) => result.map_err(|e| {
247250
if e.kind() == ErrorKind::NotFound {
248-
"Codex CLI not found. Install Codex and ensure `codex` is on your PATH."
249-
.to_string()
251+
"Codex CLI not found. Install Codex and ensure `codex` is on your PATH.".to_string()
250252
} else {
251253
e.to_string()
252254
}
@@ -269,8 +271,7 @@ pub(crate) async fn check_codex_installation(
269271
};
270272
if detail.is_empty() {
271273
return Err(
272-
"Codex CLI failed to start. Try running `codex --version` in Terminal."
273-
.to_string(),
274+
"Codex CLI failed to start. Try running `codex --version` in Terminal.".to_string(),
274275
);
275276
}
276277
return Err(format!(
@@ -279,7 +280,11 @@ pub(crate) async fn check_codex_installation(
279280
}
280281

281282
let version = String::from_utf8_lossy(&output.stdout).trim().to_string();
282-
Ok(if version.is_empty() { None } else { Some(version) })
283+
Ok(if version.is_empty() {
284+
None
285+
} else {
286+
Some(version)
287+
})
283288
}
284289

285290
pub(crate) async fn spawn_workspace_session<E: EventSink>(

src-tauri/src/codex/args.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,20 @@ mod tests {
5454
#[test]
5555
fn parses_empty_args() {
5656
assert!(parse_codex_args(None).expect("parse none").is_empty());
57-
assert!(parse_codex_args(Some(" ")).expect("parse blanks").is_empty());
57+
assert!(parse_codex_args(Some(" "))
58+
.expect("parse blanks")
59+
.is_empty());
5860
}
5961

6062
#[test]
6163
fn parses_simple_args() {
62-
let args =
63-
parse_codex_args(Some("--profile personal --flag")).expect("parse args");
64+
let args = parse_codex_args(Some("--profile personal --flag")).expect("parse args");
6465
assert_eq!(args, vec!["--profile", "personal", "--flag"]);
6566
}
6667

6768
#[test]
6869
fn parses_quoted_args() {
69-
let args =
70-
parse_codex_args(Some("--path \"a b\" --name='c d'")).expect("parse args");
70+
let args = parse_codex_args(Some("--path \"a b\" --name='c d'")).expect("parse args");
7171
assert_eq!(args, vec!["--path", "a b", "--name=c d"]);
7272
}
7373

src-tauri/src/codex/config.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ fn read_feature_flag(key: &str) -> Result<Option<bool>, String> {
9090
return Ok(None);
9191
};
9292
let contents = read_config_contents_from_root(&root)?;
93-
Ok(contents.as_deref().and_then(|value| find_feature_flag(value, key)))
93+
Ok(contents
94+
.as_deref()
95+
.and_then(|value| find_feature_flag(value, key)))
9496
}
9597

9698
fn write_feature_flag(key: &str, enabled: bool) -> Result<(), String> {
@@ -340,9 +342,7 @@ impl<T> RetainWithIndex<T> for Vec<T> {
340342

341343
#[cfg(test)]
342344
mod tests {
343-
use super::{
344-
parse_personality_from_toml, remove_top_level_key, upsert_top_level_string_key,
345-
};
345+
use super::{parse_personality_from_toml, remove_top_level_key, upsert_top_level_string_key};
346346

347347
#[test]
348348
fn parse_personality_reads_supported_values() {
@@ -354,21 +354,30 @@ mod tests {
354354
parse_personality_from_toml("personality = \"pragmatic\"\n"),
355355
Some("pragmatic")
356356
);
357-
assert_eq!(parse_personality_from_toml("personality = \"unknown\"\n"), None);
357+
assert_eq!(
358+
parse_personality_from_toml("personality = \"unknown\"\n"),
359+
None
360+
);
358361
}
359362

360363
#[test]
361364
fn upsert_top_level_personality_before_tables() {
362365
let input = "[features]\nsteer = true\n";
363366
let updated = upsert_top_level_string_key(input, "personality", "friendly");
364-
assert_eq!(updated, "personality = \"friendly\"\n[features]\nsteer = true\n");
367+
assert_eq!(
368+
updated,
369+
"personality = \"friendly\"\n[features]\nsteer = true\n"
370+
);
365371
}
366372

367373
#[test]
368374
fn upsert_replaces_existing_top_level_personality() {
369375
let input = "personality = \"friendly\"\n[features]\nsteer = true\n";
370376
let updated = upsert_top_level_string_key(input, "personality", "pragmatic");
371-
assert_eq!(updated, "personality = \"pragmatic\"\n[features]\nsteer = true\n");
377+
assert_eq!(
378+
updated,
379+
"personality = \"pragmatic\"\n[features]\nsteer = true\n"
380+
);
372381
}
373382

374383
#[test]

src-tauri/src/codex/home.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,10 @@ mod tests {
273273
assert_eq!(appdata, Some(PathBuf::from("/tmp/appdata-root/Codex")));
274274

275275
let appdata_lower = normalize_codex_home("$appdata/Codex");
276-
assert_eq!(appdata_lower, Some(PathBuf::from("/tmp/appdata-root/Codex")));
276+
assert_eq!(
277+
appdata_lower,
278+
Some(PathBuf::from("/tmp/appdata-root/Codex"))
279+
);
277280

278281
match prev_home {
279282
Some(value) => std::env::set_var("HOME", value),

0 commit comments

Comments
 (0)