mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
extension-api: add approval review contributor flow (#22344)
## Why `codex-extension-api` needs an approval hook that lets an installed extension own a rendered approval-review prompt and produce the final `ReviewDecision`. The prior interceptor stub only exposed a yes/no claim and did not model the review result itself, which left the host with the missing half of the control flow. ## What changed - Replaces `ApprovalInterceptorContributor` with [`ApprovalReviewContributor`](https://github.com/openai/codex/blob/c49d17531e15057a373a9b17f410cafb6299d0c1/codex-rs/ext/extension-api/src/contributors.rs#L43-L55), which may claim a rendered prompt and return an async `ReviewDecision`. - Re-exports the new contributor and future types from `extension-api`. - Adds registry support through `approval_review_contributor(...)` plus [`ExtensionRegistry::approval_review(...)`](https://github.com/openai/codex/blob/c49d17531e15057a373a9b17f410cafb6299d0c1/codex-rs/ext/extension-api/src/registry.rs#L90-L101), which returns the first installed contributor that claims the prompt.
This commit is contained in:
committed by
GitHub
Unverified
parent
7e97da7c13
commit
155c04ad40
@@ -2,6 +2,7 @@ use std::future::Future;
|
||||
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::items::TurnItem;
|
||||
use codex_protocol::protocol::ReviewDecision;
|
||||
use codex_tool_api::ToolBundle;
|
||||
|
||||
use crate::ExtensionData;
|
||||
@@ -39,6 +40,20 @@ pub trait ToolContributor: Send + Sync {
|
||||
-> Vec<ToolBundle>;
|
||||
}
|
||||
|
||||
/// Future returned by one claimed approval-review contribution.
|
||||
pub type ApprovalReviewFuture<'a> =
|
||||
std::pin::Pin<Box<dyn Future<Output = ReviewDecision> + Send + 'a>>;
|
||||
|
||||
/// Extension contribution that can claim rendered approval-review prompts.
|
||||
pub trait ApprovalReviewContributor: Send + Sync {
|
||||
fn contribute<'a>(
|
||||
&'a self,
|
||||
session_store: &'a ExtensionData,
|
||||
thread_store: &'a ExtensionData,
|
||||
prompt: &'a str,
|
||||
) -> Option<ApprovalReviewFuture<'a>>;
|
||||
}
|
||||
|
||||
/// Future returned by one ordered turn-item contribution.
|
||||
pub type TurnItemContributionFuture<'a> =
|
||||
std::pin::Pin<Box<dyn Future<Output = Result<(), String>> + Send + 'a>>;
|
||||
@@ -56,15 +71,3 @@ pub trait TurnItemContributor: Send + Sync {
|
||||
item: &'a mut TurnItem,
|
||||
) -> TurnItemContributionFuture<'a>;
|
||||
}
|
||||
|
||||
// TODO: WIP (do not consider)
|
||||
/// Extension contribution that can claim approval requests for a runtime context.
|
||||
/// (ideally we can replace it by a session lifecycle thing or a request contributor?)
|
||||
pub trait ApprovalInterceptorContributor: Send + Sync {
|
||||
/// Returns whether this contributor should intercept approvals in `context`.
|
||||
fn intercepts_approvals(
|
||||
&self,
|
||||
thread_store: &ExtensionData,
|
||||
turn_store: &ExtensionData,
|
||||
) -> bool;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ pub use codex_tool_api::ToolCall;
|
||||
pub use codex_tool_api::ToolError;
|
||||
pub use codex_tool_api::ToolExecutor;
|
||||
pub use codex_tool_api::ToolFuture;
|
||||
pub use contributors::ApprovalInterceptorContributor;
|
||||
pub use contributors::ApprovalReviewContributor;
|
||||
pub use contributors::ApprovalReviewFuture;
|
||||
pub use contributors::ContextContributor;
|
||||
pub use contributors::PromptFragment;
|
||||
pub use contributors::PromptSlot;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::ApprovalInterceptorContributor;
|
||||
use crate::ApprovalReviewContributor;
|
||||
use crate::ApprovalReviewFuture;
|
||||
use crate::ContextContributor;
|
||||
use crate::ExtensionData;
|
||||
use crate::ThreadStartContributor;
|
||||
use crate::ToolContributor;
|
||||
use crate::TurnItemContributor;
|
||||
@@ -12,14 +14,14 @@ pub struct ExtensionRegistryBuilder<C> {
|
||||
context_contributors: Vec<Arc<dyn ContextContributor>>,
|
||||
tool_contributors: Vec<Arc<dyn ToolContributor>>,
|
||||
turn_item_contributors: Vec<Arc<dyn TurnItemContributor>>,
|
||||
approval_interceptor_contributors: Vec<Arc<dyn ApprovalInterceptorContributor>>,
|
||||
approval_review_contributors: Vec<Arc<dyn ApprovalReviewContributor>>,
|
||||
}
|
||||
|
||||
impl<C> Default for ExtensionRegistryBuilder<C> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
thread_start_contributors: Vec::new(),
|
||||
approval_interceptor_contributors: Vec::new(),
|
||||
approval_review_contributors: Vec::new(),
|
||||
context_contributors: Vec::new(),
|
||||
tool_contributors: Vec::new(),
|
||||
turn_item_contributors: Vec::new(),
|
||||
@@ -33,12 +35,9 @@ impl<C> ExtensionRegistryBuilder<C> {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Registers one approval interceptor contributor.
|
||||
pub fn approval_interceptor_contributor(
|
||||
&mut self,
|
||||
contributor: Arc<dyn ApprovalInterceptorContributor>,
|
||||
) {
|
||||
self.approval_interceptor_contributors.push(contributor);
|
||||
/// Registers one approval-review contributor.
|
||||
pub fn approval_review_contributor(&mut self, contributor: Arc<dyn ApprovalReviewContributor>) {
|
||||
self.approval_review_contributors.push(contributor);
|
||||
}
|
||||
|
||||
/// Registers one thread-start contributor.
|
||||
@@ -65,7 +64,7 @@ impl<C> ExtensionRegistryBuilder<C> {
|
||||
pub fn build(self) -> ExtensionRegistry<C> {
|
||||
ExtensionRegistry {
|
||||
thread_start_contributors: self.thread_start_contributors,
|
||||
approval_interceptor_contributors: self.approval_interceptor_contributors,
|
||||
approval_review_contributors: self.approval_review_contributors,
|
||||
context_contributors: self.context_contributors,
|
||||
tool_contributors: self.tool_contributors,
|
||||
turn_item_contributors: self.turn_item_contributors,
|
||||
@@ -79,7 +78,7 @@ pub struct ExtensionRegistry<C> {
|
||||
context_contributors: Vec<Arc<dyn ContextContributor>>,
|
||||
tool_contributors: Vec<Arc<dyn ToolContributor>>,
|
||||
turn_item_contributors: Vec<Arc<dyn TurnItemContributor>>,
|
||||
approval_interceptor_contributors: Vec<Arc<dyn ApprovalInterceptorContributor>>,
|
||||
approval_review_contributors: Vec<Arc<dyn ApprovalReviewContributor>>,
|
||||
}
|
||||
|
||||
impl<C> ExtensionRegistry<C> {
|
||||
@@ -88,9 +87,17 @@ impl<C> ExtensionRegistry<C> {
|
||||
&self.thread_start_contributors
|
||||
}
|
||||
|
||||
/// Returns the registered approval interceptor contributors.
|
||||
pub fn approval_interceptor_contributors(&self) -> &[Arc<dyn ApprovalInterceptorContributor>] {
|
||||
&self.approval_interceptor_contributors
|
||||
/// Claims the first rendered approval-review prompt accepted by an
|
||||
/// installed contributor.
|
||||
pub fn approval_review<'a>(
|
||||
&'a self,
|
||||
session_store: &'a ExtensionData,
|
||||
thread_store: &'a ExtensionData,
|
||||
prompt: &'a str,
|
||||
) -> Option<ApprovalReviewFuture<'a>> {
|
||||
self.approval_review_contributors
|
||||
.iter()
|
||||
.find_map(|contributor| contributor.contribute(session_store, thread_store, prompt))
|
||||
}
|
||||
|
||||
/// Returns the registered prompt contributors.
|
||||
|
||||
Reference in New Issue
Block a user