Files
codex/codex-rs/ext/extension-api/src/user_instructions.rs
T
vinh-gpt e24ac448b3 Allow thread instruction providers to share updates with subagents (#46577)
## Why

Subagents inherit applied instruction snapshots, so later provider updates do not reach running descendants. Hosts need an explicit way to share current thread instructions across an agent tree.

## What changed

- Add `ThreadInstructionsProvider::share_with_subagents()`, defaulting to `false`. Opted-in descendants refresh instructions at their next model-request boundary.
- Retain shared providers across root unloads and descendant reloads. Let a resumed root replace the provider for surviving descendants, or preserve their last shared instructions when it supplies a non-sharing provider.
- Keep providers scoped to their root tree and preserve snapshot-only instructions for root forks and isolated sessions, including Guardian reviews.

## Testing

Add coverage for child and grandchild instruction updates and clearing, provider replacement after root restart, lazy descendant reloads, default snapshot inheritance, and isolation between roots and Guardian sessions.

GitOrigin-RevId: 44c9fb7fe9ae1f96156bdf3c47ab6c4a81bd65e9
2026-09-19 02:15:20 +00:00

71 lines
3.4 KiB
Rust

use std::future::Future;
use std::pin::Pin;
use codex_utils_absolute_path::AbsolutePathBuf;
/// Instructions supplied by the host.
///
/// Filesystem-backed instructions retain their absolute source path for the
/// app-server `instructionSources` API. Other host-provided instructions do
/// not report a filesystem source.
// TODO(anp): Replace the absolute path with a more general instruction-source
// abstraction when non-filesystem providers need first-class attribution.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Instructions {
/// Model-visible instruction text.
pub text: String,
/// Absolute filesystem path reported through `instructionSources`, if any.
pub source: Option<AbsolutePathBuf>,
}
/// Result of loading host-provided user instructions.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct LoadedUserInstructions {
/// Loaded instructions, or `None` when the provider has no applicable text.
pub instructions: Option<Instructions>,
/// Recoverable loading problems that should be surfaced to the host.
/// Providers own suppression of recurring warnings; Core forwards each returned warning.
pub warnings: Vec<String>,
}
/// Future returned by an instruction provider.
pub type LoadInstructionsFuture<'a> =
Pin<Box<dyn Future<Output = LoadedUserInstructions> + Send + 'a>>;
/// Loads host-provided instructions that apply to one root thread.
///
/// These instructions follow the global [`UserInstructionsProvider`] snapshot
/// and precede repository instructions. A result with no instructions or
/// blank instructions clears only the thread-scoped contribution. Core retains
/// the provider and reads it at startup and when capturing model-request context.
/// Implementations own fetching and caching; repeated reads should be cheap and
/// return a coherent snapshot. On a recoverable fetch failure, return the last
/// usable snapshot with warnings rather than an empty result that clears it.
pub trait ThreadInstructionsProvider: Send + Sync {
/// Loads the current snapshot for the provider's root thread.
fn load_thread_instructions(&self) -> LoadInstructionsFuture<'_>;
/// Whether descendants should retain this provider instead of only its applied text.
/// Defaults to snapshot inheritance. Opt in only when the same instruction scope and
/// credentials apply to descendants. Descendants share the installed provider; a root
/// resume can replace it for surviving descendants. Providers must coalesce/cache
/// concurrent reads and retain a usable snapshot during outages.
/// If a resumed root supplies a non-sharing provider, existing descendants keep their
/// last shared instructions without receiving any new private updates.
/// Updates are loaded at each descendant's next model-request boundary, not mid-request.
fn share_with_subagents(&self) -> bool {
false
}
}
/// Loads global user instructions shared across root threads.
///
/// Core reads this provider at startup and when capturing model-request context.
/// Implementations own fetching and caching, so repeated reads should be cheap.
/// Implementations should return any recoverable loading problems as warnings
/// while still returning usable fallback instructions when available.
pub trait UserInstructionsProvider: Send + Sync {
/// Loads the current global snapshot for a root runtime.
fn load_user_instructions(&self) -> LoadInstructionsFuture<'_>;
}