From c579da41b16dc88b62d9cb2611f70ccdb7ac2735 Mon Sep 17 00:00:00 2001 From: pakrym-oai Date: Fri, 8 May 2026 18:19:23 -0700 Subject: [PATCH] Move file watcher out of core (#21290) ## Why The app-server watcher relocation leaves the generic filesystem watcher as the last watcher-specific implementation still living inside `codex-core`. Moving that code to a small crate keeps `codex-core` focused on thread execution and lets app-server depend on the watcher without reaching back into core for filesystem watching primitives. This PR is stacked on #21287. ## What changed - Added a new `codex-file-watcher` crate containing the existing watcher implementation and its unit tests. - Updated app-server `fs_watch`, `skills_watcher`, and listener state to import watcher types from `codex-file-watcher`. - Removed the `file_watcher` module and `notify` dependency from `codex-core`. - Updated Cargo workspace metadata and `Cargo.lock` for the new internal crate. ## Validation - `cargo check -p codex-file-watcher -p codex-core -p codex-app-server` - `cargo test -p codex-file-watcher` - `cargo test -p codex-app-server skills_changed_notification_is_emitted_after_skill_change` - `just bazel-lock-update` - `just bazel-lock-check` - `just fix -p codex-file-watcher` - `just fix -p codex-core` - `just fix -p codex-app-server` --- codex-rs/Cargo.lock | 13 ++++++++++- codex-rs/Cargo.toml | 2 ++ codex-rs/app-server/Cargo.toml | 1 + codex-rs/app-server/src/fs_watch.rs | 12 +++++----- codex-rs/app-server/src/skills_watcher.rs | 12 +++++----- codex-rs/app-server/src/thread_state.rs | 2 +- codex-rs/core/Cargo.toml | 1 - codex-rs/core/src/lib.rs | 2 -- codex-rs/file-watcher/BUILD.bazel | 6 +++++ codex-rs/file-watcher/Cargo.toml | 22 +++++++++++++++++++ .../src/file_watcher_tests.rs | 0 .../src/lib.rs} | 0 12 files changed, 56 insertions(+), 17 deletions(-) create mode 100644 codex-rs/file-watcher/BUILD.bazel create mode 100644 codex-rs/file-watcher/Cargo.toml rename codex-rs/{core => file-watcher}/src/file_watcher_tests.rs (100%) rename codex-rs/{core/src/file_watcher.rs => file-watcher/src/lib.rs} (100%) diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index 8ea52e9304..ec654051e4 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -1900,6 +1900,7 @@ dependencies = [ "codex-features", "codex-feedback", "codex-file-search", + "codex-file-watcher", "codex-git-utils", "codex-hooks", "codex-login", @@ -2551,7 +2552,6 @@ dependencies = [ "insta", "libc", "maplit", - "notify", "once_cell", "openssl-sys", "opentelemetry", @@ -2894,6 +2894,17 @@ dependencies = [ "serde", ] +[[package]] +name = "codex-file-watcher" +version = "0.0.0" +dependencies = [ + "notify", + "pretty_assertions", + "tempfile", + "tokio", + "tracing", +] + [[package]] name = "codex-git-utils" version = "0.0.0" diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index 9e203e9f8a..dd0cd7e491 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -49,6 +49,7 @@ members = [ "external-agent-sessions", "keyring-store", "file-search", + "file-watcher", "linux-sandbox", "lmstudio", "login", @@ -166,6 +167,7 @@ codex-features = { path = "features" } codex-feedback = { path = "feedback" } codex-install-context = { path = "install-context" } codex-file-search = { path = "file-search" } +codex-file-watcher = { path = "file-watcher" } codex-git-utils = { path = "git-utils" } codex-hooks = { path = "hooks" } codex-keyring-store = { path = "keyring-store" } diff --git a/codex-rs/app-server/Cargo.toml b/codex-rs/app-server/Cargo.toml index b4a5e64a89..5675640ff0 100644 --- a/codex-rs/app-server/Cargo.toml +++ b/codex-rs/app-server/Cargo.toml @@ -41,6 +41,7 @@ codex-external-agent-migration = { workspace = true } codex-external-agent-sessions = { workspace = true } codex-features = { workspace = true } codex-git-utils = { workspace = true } +codex-file-watcher = { workspace = true } codex-hooks = { workspace = true } codex-otel = { workspace = true } codex-plugin = { workspace = true } diff --git a/codex-rs/app-server/src/fs_watch.rs b/codex-rs/app-server/src/fs_watch.rs index 47248451a2..09c6dc5533 100644 --- a/codex-rs/app-server/src/fs_watch.rs +++ b/codex-rs/app-server/src/fs_watch.rs @@ -8,12 +8,12 @@ use codex_app_server_protocol::FsWatchParams; use codex_app_server_protocol::FsWatchResponse; use codex_app_server_protocol::JSONRPCErrorError; use codex_app_server_protocol::ServerNotification; -use codex_core::file_watcher::FileWatcher; -use codex_core::file_watcher::FileWatcherEvent; -use codex_core::file_watcher::FileWatcherSubscriber; -use codex_core::file_watcher::Receiver; -use codex_core::file_watcher::WatchPath; -use codex_core::file_watcher::WatchRegistration; +use codex_file_watcher::FileWatcher; +use codex_file_watcher::FileWatcherEvent; +use codex_file_watcher::FileWatcherSubscriber; +use codex_file_watcher::Receiver; +use codex_file_watcher::WatchPath; +use codex_file_watcher::WatchRegistration; use std::collections::HashMap; use std::collections::HashSet; use std::collections::hash_map::Entry; diff --git a/codex-rs/app-server/src/skills_watcher.rs b/codex-rs/app-server/src/skills_watcher.rs index 33acf65335..d20628d386 100644 --- a/codex-rs/app-server/src/skills_watcher.rs +++ b/codex-rs/app-server/src/skills_watcher.rs @@ -6,14 +6,14 @@ use codex_app_server_protocol::ServerNotification; use codex_app_server_protocol::SkillsChangedNotification; use codex_core::ThreadManager; use codex_core::config::Config; -use codex_core::file_watcher::FileWatcher; -use codex_core::file_watcher::FileWatcherSubscriber; -use codex_core::file_watcher::Receiver; -use codex_core::file_watcher::ThrottledWatchReceiver; -use codex_core::file_watcher::WatchPath; -use codex_core::file_watcher::WatchRegistration; use codex_core::skills::SkillsLoadInput; use codex_core::skills::SkillsManager; +use codex_file_watcher::FileWatcher; +use codex_file_watcher::FileWatcherSubscriber; +use codex_file_watcher::Receiver; +use codex_file_watcher::ThrottledWatchReceiver; +use codex_file_watcher::WatchPath; +use codex_file_watcher::WatchRegistration; use codex_protocol::protocol::TurnEnvironmentSelection; use tracing::warn; diff --git a/codex-rs/app-server/src/thread_state.rs b/codex-rs/app-server/src/thread_state.rs index f31257e8cf..f0dbb0e326 100644 --- a/codex-rs/app-server/src/thread_state.rs +++ b/codex-rs/app-server/src/thread_state.rs @@ -7,7 +7,7 @@ use codex_app_server_protocol::Turn; use codex_app_server_protocol::TurnError; use codex_core::CodexThread; use codex_core::ThreadConfigSnapshot; -use codex_core::file_watcher::WatchRegistration; +use codex_file_watcher::WatchRegistration; use codex_protocol::ThreadId; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::RolloutItem; diff --git a/codex-rs/core/Cargo.toml b/codex-rs/core/Cargo.toml index 5e799b259f..3e1d650a98 100644 --- a/codex-rs/core/Cargo.toml +++ b/codex-rs/core/Cargo.toml @@ -84,7 +84,6 @@ iana-time-zone = { workspace = true } image = { workspace = true, features = ["jpeg", "png", "webp"] } indexmap = { workspace = true } libc = { workspace = true } -notify = { workspace = true } once_cell = { workspace = true } rand = { workspace = true } regex-lite = { workspace = true } diff --git a/codex-rs/core/src/lib.rs b/codex-rs/core/src/lib.rs index 41205c14db..7b3de524c5 100644 --- a/codex-rs/core/src/lib.rs +++ b/codex-rs/core/src/lib.rs @@ -35,7 +35,6 @@ mod environment_selection; pub mod exec; pub mod exec_env; mod exec_policy; -pub mod file_watcher; mod flags; #[cfg(test)] mod git_info_tests; @@ -194,7 +193,6 @@ pub use exec_policy::ExecPolicyError; pub use exec_policy::check_execpolicy_for_warnings; pub use exec_policy::format_exec_policy_error_with_source; pub use exec_policy::load_exec_policy; -pub use file_watcher::FileWatcherEvent; pub use installation_id::resolve_installation_id; pub use turn_metadata::build_turn_metadata_header; pub mod compact; diff --git a/codex-rs/file-watcher/BUILD.bazel b/codex-rs/file-watcher/BUILD.bazel new file mode 100644 index 0000000000..59cf10350c --- /dev/null +++ b/codex-rs/file-watcher/BUILD.bazel @@ -0,0 +1,6 @@ +load("//:defs.bzl", "codex_rust_crate") + +codex_rust_crate( + name = "file-watcher", + crate_name = "codex_file_watcher", +) diff --git a/codex-rs/file-watcher/Cargo.toml b/codex-rs/file-watcher/Cargo.toml new file mode 100644 index 0000000000..7816987947 --- /dev/null +++ b/codex-rs/file-watcher/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "codex-file-watcher" +version.workspace = true +edition.workspace = true +license.workspace = true + +[lib] +name = "codex_file_watcher" +path = "src/lib.rs" +doctest = false + +[lints] +workspace = true + +[dependencies] +notify = { workspace = true } +tokio = { workspace = true, features = ["macros", "rt", "sync", "time"] } +tracing = { workspace = true, features = ["log"] } + +[dev-dependencies] +pretty_assertions = { workspace = true } +tempfile = { workspace = true } diff --git a/codex-rs/core/src/file_watcher_tests.rs b/codex-rs/file-watcher/src/file_watcher_tests.rs similarity index 100% rename from codex-rs/core/src/file_watcher_tests.rs rename to codex-rs/file-watcher/src/file_watcher_tests.rs diff --git a/codex-rs/core/src/file_watcher.rs b/codex-rs/file-watcher/src/lib.rs similarity index 100% rename from codex-rs/core/src/file_watcher.rs rename to codex-rs/file-watcher/src/lib.rs