mirror of
https://github.com/openai/codex.git
synced 2026-10-25 18:28:38 +00:00
## Why With deferred executors, a turn can begin before a remote environment attaches. AGENTS.md discovery previously ran only during session setup, so instructions from a later environment never reached the model or the session instruction sources. WorldState persistence has now landed, so this uses the durable model-visible baseline directly instead of carrying a temporary resume/fork compatibility path. ## What - Add an `AgentsMdManager` in `SessionServices` to own host instructions, loaded state, and refresh caching. - When `DeferredExecutor` is enabled, refresh AGENTS.md when attached environment selections change and freeze the result in the corresponding `StepContext`. - Represent AGENTS.md as a persisted WorldState section for every session, with bounded initial, replacement, and removal updates. - Remove duplicate AGENTS.md state and rendering from `SessionConfiguration` and `TurnContext`. - Build initial context, per-request updates, and compaction context from the same step-scoped value. - On resume and fork, compare current instructions with the restored WorldState baseline and inject a replacement exactly once when they differ. Builds on #29833, #29835, and #29837. ## Tests - Covers a remote environment becoming ready mid-turn, with AGENTS.md appearing on the next request exactly once and updating canonical instruction sources. - Covers full, unchanged, replaced, and removed AGENTS.md WorldState rendering. - Covers changed instructions across cold resume and fork without duplicate reinjection. - Covers remote-v2 compaction retaining creation-time instructions in the live session and cold resume appending one replacement when the source changed. - Ran focused `codex-core` AGENTS.md, WorldState, and context-update test suites.
54 lines
1.7 KiB
Rust
54 lines
1.7 KiB
Rust
use crate::agents_md::LoadedAgentsMd;
|
|
use crate::agents_md::load_project_instructions;
|
|
use crate::config::Config;
|
|
use crate::environment_selection::TurnEnvironmentSnapshot;
|
|
use codex_extension_api::UserInstructions;
|
|
use codex_protocol::protocol::TurnEnvironmentSelection;
|
|
use std::sync::Arc;
|
|
use tokio::sync::Mutex;
|
|
|
|
/// Owns the inputs and cached result of AGENTS.md discovery for a session.
|
|
pub(crate) struct AgentsMdManager {
|
|
user_instructions: Option<UserInstructions>,
|
|
cache: Mutex<AgentsMdCache>,
|
|
}
|
|
|
|
#[derive(Default)]
|
|
struct AgentsMdCache {
|
|
selections: Option<Vec<TurnEnvironmentSelection>>,
|
|
loaded: Option<Arc<LoadedAgentsMd>>,
|
|
}
|
|
|
|
impl AgentsMdManager {
|
|
pub(crate) fn new(user_instructions: Option<UserInstructions>) -> Self {
|
|
Self {
|
|
user_instructions: user_instructions
|
|
.filter(|instructions| !instructions.text.trim().is_empty()),
|
|
cache: Mutex::new(AgentsMdCache::default()),
|
|
}
|
|
}
|
|
|
|
pub(crate) async fn refresh(&self, config: &Config, environments: &TurnEnvironmentSnapshot) {
|
|
let selections = environments.to_selections();
|
|
if self.cache.lock().await.selections.as_ref() == Some(&selections) {
|
|
return;
|
|
}
|
|
|
|
let loaded =
|
|
load_project_instructions(config, self.user_instructions.clone(), environments)
|
|
.await
|
|
.map(Arc::new);
|
|
let mut cache = self.cache.lock().await;
|
|
cache.selections = Some(selections);
|
|
cache.loaded = loaded;
|
|
}
|
|
|
|
pub(crate) async fn get_loaded(&self) -> Option<Arc<LoadedAgentsMd>> {
|
|
self.cache.lock().await.loaded.clone()
|
|
}
|
|
|
|
pub(crate) fn user_instructions(&self) -> Option<UserInstructions> {
|
|
self.user_instructions.clone()
|
|
}
|
|
}
|