mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
feat: add token usage contributor hook (#22485)
## Why Extensions need a stable place to observe token accounting after Codex folds model-provider usage into the session's cached `TokenUsageInfo`. Without a contributor hook, extension-owned features that need last-turn or cumulative token usage have to duplicate session plumbing or infer state from client-facing `TokenCount` notifications. ## What changed - Added `TokenUsageContributor` to `codex-extension-api`, passing session/thread `ExtensionData`, `ThreadId`, turn id, and the current `TokenUsageInfo`. - Added registry builder/storage support for token-usage contributors. - Invoked registered contributors from `Session::record_token_usage_info` after the session token cache is updated and before the client `TokenCount` notification is emitted. ## Testing - Added `record_token_usage_info_notifies_extension_contributors`, covering cumulative token usage updates and access to both extension stores.
This commit is contained in:
committed by
GitHub
Unverified
parent
fcc2a92743
commit
083c1962f9
@@ -1,8 +1,10 @@
|
||||
use std::future::Future;
|
||||
use std::sync::Arc;
|
||||
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::items::TurnItem;
|
||||
use codex_protocol::protocol::ReviewDecision;
|
||||
use codex_protocol::protocol::TokenUsageInfo;
|
||||
|
||||
use crate::ExtensionData;
|
||||
|
||||
@@ -66,6 +68,24 @@ pub trait TurnLifecycleContributor: Send + Sync {
|
||||
fn on_turn_abort(&self, _input: TurnAbortInput<'_>) {}
|
||||
}
|
||||
|
||||
/// Contributor for token usage checkpoints reported by the model provider.
|
||||
///
|
||||
/// Implementations should keep this callback cheap. The host calls it after
|
||||
/// updating cached token usage and before emitting the corresponding client
|
||||
/// token-count notification.
|
||||
pub trait TokenUsageContributor: Send + Sync {
|
||||
/// Called each time the host records token usage from a model response.
|
||||
fn on_token_usage(
|
||||
&self,
|
||||
_session_store: &ExtensionData,
|
||||
_thread_store: &ExtensionData,
|
||||
_thread_id: ThreadId,
|
||||
_turn_id: &str,
|
||||
_token_usage: &TokenUsageInfo,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension contribution that exposes native tools owned by a feature.
|
||||
pub trait ToolContributor: Send + Sync {
|
||||
/// Returns the native tools visible for the supplied extension stores.
|
||||
|
||||
@@ -25,6 +25,7 @@ pub use contributors::ThreadLifecycleContributor;
|
||||
pub use contributors::ThreadResumeInput;
|
||||
pub use contributors::ThreadStartInput;
|
||||
pub use contributors::ThreadStopInput;
|
||||
pub use contributors::TokenUsageContributor;
|
||||
pub use contributors::ToolContributor;
|
||||
pub use contributors::TurnAbortInput;
|
||||
pub use contributors::TurnItemContributionFuture;
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::ApprovalReviewFuture;
|
||||
use crate::ContextContributor;
|
||||
use crate::ExtensionData;
|
||||
use crate::ThreadLifecycleContributor;
|
||||
use crate::TokenUsageContributor;
|
||||
use crate::ToolContributor;
|
||||
use crate::TurnItemContributor;
|
||||
use crate::TurnLifecycleContributor;
|
||||
@@ -13,6 +14,7 @@ use crate::TurnLifecycleContributor;
|
||||
pub struct ExtensionRegistryBuilder<C> {
|
||||
thread_lifecycle_contributors: Vec<Arc<dyn ThreadLifecycleContributor<C>>>,
|
||||
turn_lifecycle_contributors: Vec<Arc<dyn TurnLifecycleContributor>>,
|
||||
token_usage_contributors: Vec<Arc<dyn TokenUsageContributor>>,
|
||||
context_contributors: Vec<Arc<dyn ContextContributor>>,
|
||||
tool_contributors: Vec<Arc<dyn ToolContributor>>,
|
||||
turn_item_contributors: Vec<Arc<dyn TurnItemContributor>>,
|
||||
@@ -24,6 +26,7 @@ impl<C> Default for ExtensionRegistryBuilder<C> {
|
||||
Self {
|
||||
thread_lifecycle_contributors: Vec::new(),
|
||||
turn_lifecycle_contributors: Vec::new(),
|
||||
token_usage_contributors: Vec::new(),
|
||||
approval_review_contributors: Vec::new(),
|
||||
context_contributors: Vec::new(),
|
||||
tool_contributors: Vec::new(),
|
||||
@@ -56,6 +59,11 @@ impl<C> ExtensionRegistryBuilder<C> {
|
||||
self.turn_lifecycle_contributors.push(contributor);
|
||||
}
|
||||
|
||||
/// Registers one token-usage contributor.
|
||||
pub fn token_usage_contributor(&mut self, contributor: Arc<dyn TokenUsageContributor>) {
|
||||
self.token_usage_contributors.push(contributor);
|
||||
}
|
||||
|
||||
/// Registers one prompt contributor.
|
||||
pub fn prompt_contributor(&mut self, contributor: Arc<dyn ContextContributor>) {
|
||||
self.context_contributors.push(contributor);
|
||||
@@ -76,6 +84,7 @@ impl<C> ExtensionRegistryBuilder<C> {
|
||||
ExtensionRegistry {
|
||||
thread_lifecycle_contributors: self.thread_lifecycle_contributors,
|
||||
turn_lifecycle_contributors: self.turn_lifecycle_contributors,
|
||||
token_usage_contributors: self.token_usage_contributors,
|
||||
approval_review_contributors: self.approval_review_contributors,
|
||||
context_contributors: self.context_contributors,
|
||||
tool_contributors: self.tool_contributors,
|
||||
@@ -88,6 +97,7 @@ impl<C> ExtensionRegistryBuilder<C> {
|
||||
pub struct ExtensionRegistry<C> {
|
||||
thread_lifecycle_contributors: Vec<Arc<dyn ThreadLifecycleContributor<C>>>,
|
||||
turn_lifecycle_contributors: Vec<Arc<dyn TurnLifecycleContributor>>,
|
||||
token_usage_contributors: Vec<Arc<dyn TokenUsageContributor>>,
|
||||
context_contributors: Vec<Arc<dyn ContextContributor>>,
|
||||
tool_contributors: Vec<Arc<dyn ToolContributor>>,
|
||||
turn_item_contributors: Vec<Arc<dyn TurnItemContributor>>,
|
||||
@@ -105,6 +115,11 @@ impl<C> ExtensionRegistry<C> {
|
||||
&self.turn_lifecycle_contributors
|
||||
}
|
||||
|
||||
/// Returns the registered token-usage contributors.
|
||||
pub fn token_usage_contributors(&self) -> &[Arc<dyn TokenUsageContributor>] {
|
||||
&self.token_usage_contributors
|
||||
}
|
||||
|
||||
/// Claims the first rendered approval-review prompt accepted by an
|
||||
/// installed contributor.
|
||||
pub fn approval_review<'a>(
|
||||
|
||||
Reference in New Issue
Block a user