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`
This commit is contained in:
pakrym-oai
2026-05-08 18:19:23 -07:00
committed by GitHub
Unverified
parent 408e6218ab
commit c579da41b1
12 changed files with 56 additions and 17 deletions
+12 -1
View File
@@ -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"
+2
View File
@@ -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" }
+1
View File
@@ -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 }
+6 -6
View File
@@ -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;
+6 -6
View File
@@ -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;
+1 -1
View File
@@ -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;
-1
View File
@@ -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 }
-2
View File
@@ -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;
+6
View File
@@ -0,0 +1,6 @@
load("//:defs.bzl", "codex_rust_crate")
codex_rust_crate(
name = "file-watcher",
crate_name = "codex_file_watcher",
)
+22
View File
@@ -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 }