Retire the unused Guardian extension prototype API (#45679)

## What changed

- Mark `guardian_ext` as a removed compatibility flag.
- Remove `InternalSessionSpawner`, `InternalSessionSpawnFuture`, `ApprovalReviewInput`, and `ApprovalReviewError` from the extension API, along with the spawner test.
- Remove `NodeReplReviewEvidence::review_inputs` and make the core re-exports of `NodeReplReviewEvidenceMode` crate-private.

GitOrigin-RevId: 1c532bc57264644cf521ef8077285a9b8ed67391
This commit is contained in:
felixxia-oai
2026-09-15 11:39:20 +00:00
committed by copyberry
parent 0265dd7b45
commit 1fd392f6b2
9 changed files with 4 additions and 140 deletions
+1 -1
View File
@@ -98,7 +98,7 @@ pub(crate) use multi_agent_role_instructions::MultiAgentRoleInstructions;
pub(crate) use multi_agent_usage_hint::MultiAgentUsageHint;
pub(crate) use network_rule_saved::NetworkRuleSaved;
pub use node_repl_review_evidence::NodeReplReviewEvidence;
pub use node_repl_review_evidence::NodeReplReviewEvidenceMode;
pub(crate) use node_repl_review_evidence::NodeReplReviewEvidenceMode;
pub(crate) use node_repl_review_evidence::node_repl_review_evidence_mode;
pub use permissions_instructions::ApprovalPromptContext;
pub use permissions_instructions::PermissionsInstructions;
@@ -10,7 +10,7 @@ use std::sync::PoisonError;
use codex_features::Feature;
use codex_guardian_context::NodeReplContext;
use codex_guardian_context::NodeReplResponse;
pub use codex_guardian_context::NodeReplReviewEvidenceMode;
pub(crate) use codex_guardian_context::NodeReplReviewEvidenceMode;
use codex_protocol::models::ContentItem;
use codex_protocol::models::ImageReference;
use codex_protocol::user_input::UserInput;
@@ -129,16 +129,6 @@ impl NodeReplReviewEvidence {
.collect()
}
/// Returns bounded REPL evidence using the existing Guardian text and image layout.
pub fn review_inputs(&self, mode: NodeReplReviewEvidenceMode) -> Vec<UserInput> {
if mode == NodeReplReviewEvidenceMode::Disabled {
return Vec::new();
}
self.snapshot_since(/*reviewed_sequence*/ 0)
.map(|snapshot| snapshot.context(mode).render_inputs())
.unwrap_or_default()
}
pub(crate) fn record(
&self,
tool_name: &str,
@@ -1,40 +0,0 @@
use std::future::Future;
use std::pin::Pin;
use codex_protocol::ThreadId;
/// Future returned by one host-owned internal-session spawning request.
pub type InternalSessionSpawnFuture<'a, T, E> =
Pin<Box<dyn Future<Output = Result<T, E>> + Send + 'a>>;
/// Constructor-injected host helper for extensions that need private internal sessions.
///
/// The extension owns the request shape and resulting handle types. The host
/// provides the implementation when it constructs the extension.
pub trait InternalSessionSpawner<R>: Send + Sync {
type Spawned;
type Error;
/// Starts a fresh host-owned internal session associated with its parent.
fn spawn_internal_session<'a>(
&'a self,
parent_thread_id: ThreadId,
request: R,
) -> InternalSessionSpawnFuture<'a, Self::Spawned, Self::Error>;
}
impl<R, S, E, F> InternalSessionSpawner<R> for F
where
F: Fn(ThreadId, R) -> InternalSessionSpawnFuture<'static, S, E> + Send + Sync,
{
type Spawned = S;
type Error = E;
fn spawn_internal_session<'a>(
&'a self,
parent_thread_id: ThreadId,
request: R,
) -> InternalSessionSpawnFuture<'a, Self::Spawned, Self::Error> {
self(parent_thread_id, request)
}
}
@@ -1,6 +1,5 @@
mod conversation_history;
mod events;
mod internal_session;
mod metrics;
mod response_items;
@@ -8,8 +7,6 @@ pub use conversation_history::ConversationHistorySnapshot;
pub use events::ExtensionEventSink;
pub use events::ExtensionWarning;
pub use events::NoopExtensionEventSink;
pub use internal_session::InternalSessionSpawnFuture;
pub use internal_session::InternalSessionSpawner;
pub use metrics::ExtensionMetrics;
pub use response_items::NoopResponseItemInjector;
pub use response_items::ResponseItemInjectionFuture;
@@ -24,8 +24,6 @@ mod world_state;
pub use approval_review::ApprovalDecision;
pub use approval_review::ApprovalDecisionInput;
pub use approval_review::ApprovalReviewError;
pub use approval_review::ApprovalReviewInput;
pub use approval_review::GuardianV2Enabled;
pub use approval_review::SynchronousApprovalReviewer;
pub use context::TurnContextContributionInput;
@@ -1,58 +1,14 @@
//! Request-scoped approval decisions. A review only satisfies the review gate; the host enforces permissions.
use std::fmt;
use std::sync::Arc;
use codex_protocol::ThreadId;
use serde_json::Value;
use crate::ConversationHistorySnapshot;
use crate::ExtensionData;
/// Thread-local state installed only after Guardian V2's async classifier initializes.
pub struct GuardianV2Enabled;
/// Operational failure returned by an approval reviewer.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ApprovalReviewError {
/// The reviewer could not produce a valid assessment.
Failed(String),
/// The request exceeded its synchronous review deadline.
TimedOut,
/// The request was cancelled by its parent approval.
Cancelled,
}
impl fmt::Display for ApprovalReviewError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Failed(message) => write!(formatter, "approval review failed: {message}"),
Self::TimedOut => formatter.write_str("approval review timed out"),
Self::Cancelled => formatter.write_str("approval review was cancelled"),
}
}
}
impl std::error::Error for ApprovalReviewError {}
/// Immutable context for reviewing an existing host-owned approval action.
pub struct ApprovalReviewInput<'a> {
/// Structured action evidence rendered by the host's existing approval path.
pub action: &'a Value,
/// Canonical immutable conversation snapshot captured before review.
pub conversation_history: Arc<dyn ConversationHistorySnapshot>,
/// Stable host-owned thread identifier.
pub thread_id: ThreadId,
/// Store scoped to this thread runtime.
pub thread_store: &'a ExtensionData,
/// Stable host-owned turn identifier.
pub turn_id: &'a str,
/// Policy reason that caused the host to request approval.
pub approval_reason: Option<&'a str>,
/// Reason an earlier request is being retried, when applicable.
pub retry_reason: Option<&'a str>,
}
/// Guardian's choice for one approval. Synchronous results pass through unchanged.
#[derive(Clone, Debug, PartialEq)]
pub enum ApprovalDecision {
-4
View File
@@ -12,8 +12,6 @@ pub use capabilities::ConversationHistorySnapshot;
pub use capabilities::ExtensionEventSink;
pub use capabilities::ExtensionMetrics;
pub use capabilities::ExtensionWarning;
pub use capabilities::InternalSessionSpawnFuture;
pub use capabilities::InternalSessionSpawner;
pub use capabilities::NoopExtensionEventSink;
pub use capabilities::NoopResponseItemInjector;
pub use capabilities::ResponseItemInjectionFuture;
@@ -46,8 +44,6 @@ pub use codex_tools::parse_tool_input_schema_without_compaction;
pub use contributors::ApprovalDecision;
pub use contributors::ApprovalDecisionInput;
pub use contributors::ApprovalReviewContributor;
pub use contributors::ApprovalReviewError;
pub use contributors::ApprovalReviewInput;
pub use contributors::ConfigContributor;
pub use contributors::ContextContributor;
pub use contributors::ExtensionFuture;
@@ -1,11 +1,5 @@
use std::sync::Arc;
use std::sync::Mutex;
use codex_extension_api::InternalSessionSpawnFuture;
use codex_extension_api::InternalSessionSpawner;
use codex_extension_api::NoopResponseItemInjector;
use codex_extension_api::ResponseItemInjector;
use codex_protocol::ThreadId;
use codex_protocol::models::ContentItem;
use codex_protocol::models::ResponseInputItem;
use pretty_assertions::assert_eq;
@@ -27,30 +21,3 @@ async fn noop_response_item_injector_returns_original_items() {
assert_eq!(returned_items, items);
}
#[tokio::test]
async fn closure_internal_session_spawner_forwards_arguments_and_result() {
let calls = Arc::new(Mutex::new(Vec::new()));
let recorded_calls = Arc::clone(&calls);
let spawner = move |thread_id: ThreadId,
request: String|
-> InternalSessionSpawnFuture<'static, usize, &'static str> {
recorded_calls
.lock()
.expect("agent spawn calls lock")
.push((thread_id, request.clone()));
Box::pin(async move { Ok(request.len()) })
};
let thread_id =
ThreadId::from_string("11111111-1111-4111-8111-111111111111").expect("valid thread id");
let spawned = spawner
.spawn_internal_session(thread_id, "delegate this".to_string())
.await;
assert_eq!(spawned, Ok(13));
assert_eq!(
calls.lock().expect("agent spawn calls lock").as_slice(),
[(thread_id, "delegate this".to_string())]
);
}
+2 -2
View File
@@ -322,7 +322,7 @@ pub enum Feature {
GuardianNodeReplTranscriptImages,
/// Enable Guardian V2 automatic approval reviews.
GuardianV2,
/// Enable the extension-owned synchronous Guardian reviewer.
/// Removed compatibility flag for the unused Guardian extension prototype.
GuardianExt,
/// Enable persisted thread goals and automatic goal continuation.
Goals,
@@ -1610,7 +1610,7 @@ pub const FEATURES: &[FeatureSpec] = &[
FeatureSpec {
id: Feature::GuardianExt,
key: "guardian_ext",
stage: Stage::UnderDevelopment,
stage: Stage::Removed,
default_enabled: false,
},
FeatureSpec {