Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8fe083b
Added support for live updates to skills and AGENTS
etraut-openai Jan 27, 2026
f780842
Changed from strong to weak reference to prevent shutdown.
etraut-openai Jan 27, 2026
7d97287
Improved comments
etraut-openai Jan 27, 2026
0dc71b2
Fixed broken test
etraut-openai Jan 27, 2026
60991e7
Fixed test
etraut-openai Jan 27, 2026
cc5c6d1
Test fix
etraut-openai Jan 27, 2026
45d258f
Fix test
etraut-openai Jan 27, 2026
a95f4e7
Merge origin/main
etraut-openai Jan 28, 2026
dad3af9
Added separate experimental feature flags for live update of skills a…
etraut-openai Jan 28, 2026
57f9c9f
Added integration test
etraut-openai Jan 29, 2026
c8b6f27
Merge remote-tracking branch 'origin/main' into etraut/live_skill_update
etraut-openai Jan 29, 2026
40a223e
Aesthetic improvements
etraut-openai Jan 29, 2026
f3100c7
Add support for fallback filenames
etraut-openai Jan 29, 2026
41e1d66
Added throttling for file watcher events
etraut-openai Jan 29, 2026
d79761f
Merge origin/main into etraut/live_skill_update
etraut-openai Jan 30, 2026
1c62e54
Merge remote-tracking branch 'origin/main' into etraut/live_skill_update
etraut-openai Jan 30, 2026
1925449
Fixed merge issue
etraut-openai Jan 30, 2026
74323b6
Merge remote-tracking branch 'origin/main' into etraut/live_skill_update
etraut-openai Feb 2, 2026
fca6982
Code review feedback
etraut-openai Feb 2, 2026
d0ce01d
Fix lint
etraut-openai Feb 2, 2026
e91f6ff
Merge remote-tracking branch 'origin/main' into etraut/live_skill_update
etraut-openai Feb 2, 2026
c070d14
Merge remote-tracking branch 'origin/main' into etraut/live_skill_update
etraut-openai Feb 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ In the codex-rs folder where the rust code lives:
- Use method references over closures when possible per https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_for_method_calls
- When possible, make `match` statements exhaustive and avoid wildcard arms.
- When writing tests, prefer comparing the equality of entire objects over fields one by one.
- When making a change that adds or changes an API, ensure that the documentation in the `docs/` folder is up to date if applicable.
- If you change `ConfigToml` or nested config types, run `just write-config-schema` to update `codex-rs/core/config.schema.json`.

Run `just fmt` (in `codex-rs` directory) automatically after you have finished making Rust code changes; do not ask for approval to run it. Additionally, run the tests:
Expand Down
1 change: 1 addition & 0 deletions codex-rs/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions codex-rs/app-server-protocol/src/protocol/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@ server_notification_definitions! {
ContextCompacted => "thread/compacted" (v2::ContextCompactedNotification),
DeprecationNotice => "deprecationNotice" (v2::DeprecationNoticeNotification),
ConfigWarning => "configWarning" (v2::ConfigWarningNotification),
SkillsListUpdated => "skills/list/updated" (v2::SkillsListUpdatedNotification),

/// Notifies the user of world-writable directories on Windows, which cannot be protected by the sandbox.
WindowsWorldWritableWarning => "windows/worldWritableWarning" (v2::WindowsWorldWritableWarningNotification),
Expand Down
5 changes: 5 additions & 0 deletions codex-rs/app-server-protocol/src/protocol/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2635,6 +2635,11 @@ pub struct ContextCompactedNotification {
pub turn_id: String,
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct SkillsListUpdatedNotification {}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
Expand Down
30 changes: 30 additions & 0 deletions codex-rs/app-server/src/message_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ use codex_app_server_protocol::JSONRPCResponse;
use codex_app_server_protocol::RequestId;
use codex_app_server_protocol::ServerNotification;
use codex_app_server_protocol::ServerRequestPayload;
use codex_app_server_protocol::SkillsListUpdatedNotification;
use codex_app_server_protocol::experimental_required_message;
use codex_core::AuthManager;
use codex_core::FileWatcherEvent;
use codex_core::ThreadManager;
use codex_core::auth::ExternalAuthRefreshContext;
use codex_core::auth::ExternalAuthRefreshReason;
Expand Down Expand Up @@ -111,6 +113,7 @@ pub(crate) struct MessageProcessor {
config_api: ConfigApi,
config: Arc<Config>,
initialized: bool,
initialized_flag: Arc<AtomicBool>,
experimental_api_enabled: Arc<AtomicBool>,
config_warnings: Vec<ConfigWarningNotification>,
}
Expand Down Expand Up @@ -156,6 +159,31 @@ impl MessageProcessor {
auth_manager.clone(),
SessionSource::VSCode,
));
// Watch for on-disk skill changes and reinject the updated skills into
// subsequent requests.
let initialized_flag = Arc::new(AtomicBool::new(false));
let mut skills_updates_rx = thread_manager.subscribe_file_watcher();
let outgoing_for_skills = Arc::clone(&outgoing);
let initialized_for_skills = Arc::clone(&initialized_flag);
tokio::spawn(async move {
loop {
match skills_updates_rx.recv().await {
Ok(FileWatcherEvent::SkillsChanged { .. }) => {
if !initialized_for_skills.load(Ordering::SeqCst) {
continue;
}
outgoing_for_skills
.send_server_notification(ServerNotification::SkillsListUpdated(
SkillsListUpdatedNotification {},
))
.await;
}
Ok(FileWatcherEvent::AgentsChanged { .. }) => {}
Err(broadcast::error::RecvError::Closed) => break,
Err(broadcast::error::RecvError::Lagged(_)) => continue,
}
}
});
let codex_message_processor = CodexMessageProcessor::new(CodexMessageProcessorArgs {
auth_manager,
thread_manager,
Expand All @@ -179,6 +207,7 @@ impl MessageProcessor {
config_api,
config,
initialized: false,
initialized_flag,
experimental_api_enabled,
config_warnings,
}
Expand Down Expand Up @@ -268,6 +297,7 @@ impl MessageProcessor {
self.outgoing.send_response(request_id, response).await;

self.initialized = true;
self.initialized_flag.store(true, Ordering::SeqCst);
if !self.config_warnings.is_empty() {
for notification in self.config_warnings.drain(..) {
self.outgoing
Expand Down
1 change: 1 addition & 0 deletions codex-rs/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ indexmap = { workspace = true }
indoc = { workspace = true }
keyring = { workspace = true, features = ["crypto-rust"] }
libc = { workspace = true }
notify = { workspace = true }
multimap = { workspace = true }
once_cell = { workspace = true }
os_info = { workspace = true }
Expand Down
14 changes: 13 additions & 1 deletion codex-rs/core/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,12 @@
"include_apply_patch_tool": {
"type": "boolean"
},
"live_agents_reload": {
"type": "boolean"
},
"live_skills_reload": {
"type": "boolean"
},
"personality": {
"type": "boolean"
},
Expand Down Expand Up @@ -1218,6 +1224,12 @@
"include_apply_patch_tool": {
"type": "boolean"
},
"live_agents_reload": {
"type": "boolean"
},
"live_skills_reload": {
"type": "boolean"
},
"personality": {
"type": "boolean"
},
Expand Down Expand Up @@ -1569,4 +1581,4 @@
},
"title": "ConfigToml",
"type": "object"
}
}
Loading
Loading