mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
59507b8491
## Why The goal extension needs more context when a turn starts than `turn_store` alone provides. In particular, goal accounting needs the stable turn id, the effective collaboration mode, and the cumulative token-usage baseline captured at turn start so it can: - suppress goal accounting for plan-mode turns - compute exact per-turn deltas from cumulative `total_token_usage` snapshots instead of relying on the most recent usage event alone - keep the extension-owned accounting path aligned with the host turn lifecycle ## What - extend `codex_extension_api::TurnStartInput` to expose `turn_id`, `collaboration_mode`, and `token_usage_at_turn_start` - pass the full `TurnContext` plus the captured token-usage baseline through the turn-start lifecycle emission path - initialize goal turn accounting from the turn-start baseline and collaboration mode - switch goal token accounting to compute deltas from cumulative `total_token_usage` snapshots - add coverage for the new turn-start lifecycle fields and for goal-accounting baseline behavior ## Testing - added `turn_start_lifecycle_exposes_turn_metadata_and_token_baseline` in `codex-rs/core/src/session/tests.rs` - added `ext/goal/tests/accounting.rs` coverage for baseline-aware goal accounting and plan-mode suppression
57 lines
2.1 KiB
Rust
57 lines
2.1 KiB
Rust
use codex_extension_api::ExtensionData;
|
|
use codex_protocol::protocol::TokenUsage;
|
|
use codex_protocol::protocol::TurnAbortReason;
|
|
|
|
use crate::session::session::Session;
|
|
use crate::session::turn_context::TurnContext;
|
|
|
|
impl Session {
|
|
pub(super) async fn emit_turn_start_lifecycle(
|
|
&self,
|
|
turn_context: &TurnContext,
|
|
token_usage_at_turn_start: &TokenUsage,
|
|
) {
|
|
for contributor in self.services.extensions.turn_lifecycle_contributors() {
|
|
contributor
|
|
.on_turn_start(codex_extension_api::TurnStartInput {
|
|
turn_id: turn_context.sub_id.as_str(),
|
|
collaboration_mode: &turn_context.collaboration_mode,
|
|
token_usage_at_turn_start,
|
|
session_store: &self.services.session_extension_data,
|
|
thread_store: &self.services.thread_extension_data,
|
|
turn_store: turn_context.extension_data.as_ref(),
|
|
})
|
|
.await;
|
|
}
|
|
}
|
|
|
|
pub(super) async fn emit_turn_stop_lifecycle(&self, turn_store: &ExtensionData) {
|
|
for contributor in self.services.extensions.turn_lifecycle_contributors() {
|
|
contributor
|
|
.on_turn_stop(codex_extension_api::TurnStopInput {
|
|
session_store: &self.services.session_extension_data,
|
|
thread_store: &self.services.thread_extension_data,
|
|
turn_store,
|
|
})
|
|
.await;
|
|
}
|
|
}
|
|
|
|
pub(super) async fn emit_turn_abort_lifecycle(
|
|
&self,
|
|
reason: TurnAbortReason,
|
|
turn_store: &ExtensionData,
|
|
) {
|
|
for contributor in self.services.extensions.turn_lifecycle_contributors() {
|
|
contributor
|
|
.on_turn_abort(codex_extension_api::TurnAbortInput {
|
|
reason: reason.clone(),
|
|
session_store: &self.services.session_extension_data,
|
|
thread_store: &self.services.thread_extension_data,
|
|
turn_store,
|
|
})
|
|
.await;
|
|
}
|
|
}
|
|
}
|