mirror of
https://github.com/openai/codex.git
synced 2026-10-31 19:28:49 +00:00
Attribute command and plugin analytics to the invoking model (#45445)
## Why Command execution and plugin measurement events lack model and reasoning-effort labels. Attribution needs to reflect the step that invoked the command, even when model settings change before a background process finishes. ## What changed - Add `model_slug` and `reasoning_effort` to command execution and plugin measurement analytics. - Capture model context from resolved step settings and carry it through execution, approval, Guardian review, and plugin metrics collection. - Preserve the first command-start model context when subsequent start notifications arrive. - Keep the carried context out of serialized protocol items and generated schemas. ## Testing Extend analytics tests to cover model switches before invocation and during background execution, default reasoning effort, Guardian-denied commands, and repeated start notifications retaining the original model context. GitOrigin-RevId: af90e1c0d39bab625f2e89786085b61a9b96c0ce
This commit is contained in:
@@ -208,6 +208,10 @@ pub struct GuardianAssessmentEvent {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub review_reason: Option<GuardianReviewReason>,
|
||||
#[serde(skip)]
|
||||
#[schemars(skip)]
|
||||
#[ts(skip)]
|
||||
pub model_context: Option<crate::items::ModelInvocationContext>,
|
||||
/// Stable identifier for this guardian review lifecycle.
|
||||
pub id: String,
|
||||
/// Thread item being reviewed, when the review maps to a concrete item.
|
||||
@@ -264,6 +268,10 @@ pub enum ExecApprovalKind {
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS)]
|
||||
pub struct ExecApprovalRequestEvent {
|
||||
#[serde(skip)]
|
||||
#[schemars(skip)]
|
||||
#[ts(skip)]
|
||||
pub model_context: Option<crate::items::ModelInvocationContext>,
|
||||
/// Missing on older events, which retain command approval semantics.
|
||||
#[serde(default)]
|
||||
pub kind: ExecApprovalKind,
|
||||
|
||||
@@ -232,8 +232,19 @@ pub fn is_safe_plugin_relative_path(path: &str) -> bool {
|
||||
})
|
||||
}
|
||||
|
||||
/// Immutable model labels carried within command lifecycle events for analytics.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ModelInvocationContext {
|
||||
pub model_slug: String,
|
||||
pub reasoning_effort: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
|
||||
pub struct CommandExecutionItem {
|
||||
#[serde(skip)]
|
||||
#[schemars(skip)]
|
||||
#[ts(skip)]
|
||||
pub model_context: Option<ModelInvocationContext>,
|
||||
pub id: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
|
||||
@@ -5516,6 +5516,7 @@ mod tests {
|
||||
turn_id: "turn-1".into(),
|
||||
started_at_ms: 10,
|
||||
item: TurnItem::CommandExecution(CommandExecutionItem {
|
||||
model_context: None,
|
||||
id: "exec-1".into(),
|
||||
plugin_id: Some("sample@openai-curated".into()),
|
||||
script_path: Some("scripts/run.py".into()),
|
||||
@@ -5542,6 +5543,7 @@ mod tests {
|
||||
started_at_ms: Some(10),
|
||||
completed_at_ms: 20,
|
||||
item: TurnItem::CommandExecution(CommandExecutionItem {
|
||||
model_context: None,
|
||||
id: "exec-1".into(),
|
||||
plugin_id: Some("sample@openai-curated".into()),
|
||||
script_path: Some("scripts/run.py".into()),
|
||||
|
||||
Reference in New Issue
Block a user