mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
[codex-analytics] add tool review event schema (#18747)
## Why We want to emit terminal review analytics for tool-related approval flows, but the event contract needs to exist before the reducer can publish anything. This PR is the schema-only slice for the Codex review event family. ## What changed - add the `ReviewEvent` analytics envelope in `codex-rs/analytics/src/events.rs` - define the review subject kind, reviewer, trigger, terminal status, and post-review resolution enums - define the review event payload with thread, turn, item, lineage, tool, and timing fields that the emitter stack will populate ## Verification - stacked verification in dependent PRs: `cargo test -p codex-analytics analytics_client_tests --manifest-path codex-rs/Cargo.toml` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/18747). * #18748 * #21434 * __->__ #18747 * #17090 * #17089 * #20514
This commit is contained in:
1 parent
9b6c6f7a01
commit
3444b0d60a
3 files changed
+82
-3
No files matched your search
@@ -1012,7 +1012,7 @@ fn command_execution_event_serializes_expected_shape() {
|
|||||||
runtime_os_version: "15.3.1".to_string(),
|
runtime_os_version: "15.3.1".to_string(),
|
||||||
runtime_arch: "aarch64".to_string(),
|
runtime_arch: "aarch64".to_string(),
|
||||||
},
|
},
|
||||||
thread_source: Some("user"),
|
thread_source: Some(ThreadSource::User),
|
||||||
subagent_source: None,
|
subagent_source: None,
|
||||||
parent_thread_id: None,
|
parent_thread_id: None,
|
||||||
tool_name: "shell".to_string(),
|
tool_name: "shell".to_string(),
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ pub(crate) enum TrackEventRequest {
|
|||||||
CollabAgentToolCall(CodexCollabAgentToolCallEventRequest),
|
CollabAgentToolCall(CodexCollabAgentToolCallEventRequest),
|
||||||
WebSearch(CodexWebSearchEventRequest),
|
WebSearch(CodexWebSearchEventRequest),
|
||||||
ImageGeneration(CodexImageGenerationEventRequest),
|
ImageGeneration(CodexImageGenerationEventRequest),
|
||||||
|
#[allow(dead_code)]
|
||||||
|
ReviewEvent(CodexReviewEventRequest),
|
||||||
PluginUsed(CodexPluginUsedEventRequest),
|
PluginUsed(CodexPluginUsedEventRequest),
|
||||||
PluginInstalled(CodexPluginEventRequest),
|
PluginInstalled(CodexPluginEventRequest),
|
||||||
PluginUninstalled(CodexPluginEventRequest),
|
PluginUninstalled(CodexPluginEventRequest),
|
||||||
@@ -442,7 +444,7 @@ pub(crate) struct CodexToolItemEventBase {
|
|||||||
pub(crate) item_id: String,
|
pub(crate) item_id: String,
|
||||||
pub(crate) app_server_client: CodexAppServerClientMetadata,
|
pub(crate) app_server_client: CodexAppServerClientMetadata,
|
||||||
pub(crate) runtime: CodexRuntimeMetadata,
|
pub(crate) runtime: CodexRuntimeMetadata,
|
||||||
pub(crate) thread_source: Option<&'static str>,
|
pub(crate) thread_source: Option<ThreadSource>,
|
||||||
pub(crate) subagent_source: Option<String>,
|
pub(crate) subagent_source: Option<String>,
|
||||||
pub(crate) parent_thread_id: Option<String>,
|
pub(crate) parent_thread_id: Option<String>,
|
||||||
pub(crate) tool_name: String,
|
pub(crate) tool_name: String,
|
||||||
@@ -462,6 +464,83 @@ pub(crate) struct CodexToolItemEventBase {
|
|||||||
pub(crate) requested_network_access: bool,
|
pub(crate) requested_network_access: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub(crate) enum ReviewSubjectKind {
|
||||||
|
CommandExecution,
|
||||||
|
FileChange,
|
||||||
|
McpToolCall,
|
||||||
|
Permissions,
|
||||||
|
NetworkAccess,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub(crate) enum Reviewer {
|
||||||
|
Guardian,
|
||||||
|
User,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub(crate) enum ReviewTrigger {
|
||||||
|
Initial,
|
||||||
|
SandboxDenial,
|
||||||
|
NetworkPolicyDenial,
|
||||||
|
ExecveIntercept,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub(crate) enum ReviewStatus {
|
||||||
|
Approved,
|
||||||
|
Denied,
|
||||||
|
Aborted,
|
||||||
|
TimedOut,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub(crate) enum ReviewResolution {
|
||||||
|
None,
|
||||||
|
SessionApproval,
|
||||||
|
ExecPolicyAmendment,
|
||||||
|
NetworkPolicyAmendment,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct CodexReviewEventParams {
|
||||||
|
pub(crate) thread_id: String,
|
||||||
|
pub(crate) turn_id: String,
|
||||||
|
pub(crate) item_id: Option<String>,
|
||||||
|
pub(crate) review_id: String,
|
||||||
|
pub(crate) app_server_client: CodexAppServerClientMetadata,
|
||||||
|
pub(crate) runtime: CodexRuntimeMetadata,
|
||||||
|
pub(crate) thread_source: Option<ThreadSource>,
|
||||||
|
pub(crate) subagent_source: Option<String>,
|
||||||
|
pub(crate) parent_thread_id: Option<String>,
|
||||||
|
pub(crate) tool_kind: ReviewSubjectKind,
|
||||||
|
pub(crate) tool_name: String,
|
||||||
|
pub(crate) reviewer: Reviewer,
|
||||||
|
pub(crate) trigger: ReviewTrigger,
|
||||||
|
pub(crate) status: ReviewStatus,
|
||||||
|
pub(crate) resolution: ReviewResolution,
|
||||||
|
pub(crate) started_at_ms: u64,
|
||||||
|
pub(crate) completed_at_ms: u64,
|
||||||
|
pub(crate) duration_ms: Option<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct CodexReviewEventRequest {
|
||||||
|
pub(crate) event_type: &'static str,
|
||||||
|
pub(crate) event_params: CodexReviewEventParams,
|
||||||
|
}
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Clone, Copy, Debug, Serialize)]
|
#[derive(Clone, Copy, Debug, Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub(crate) enum WebSearchActionKind {
|
pub(crate) enum WebSearchActionKind {
|
||||||
|
|||||||
@@ -1447,7 +1447,7 @@ fn tool_item_base(
|
|||||||
item_id,
|
item_id,
|
||||||
app_server_client: context.connection_state.app_server_client.clone(),
|
app_server_client: context.connection_state.app_server_client.clone(),
|
||||||
runtime: context.connection_state.runtime.clone(),
|
runtime: context.connection_state.runtime.clone(),
|
||||||
thread_source: thread_metadata.thread_source.map(ThreadSource::as_str),
|
thread_source: thread_metadata.thread_source,
|
||||||
subagent_source: thread_metadata.subagent_source.clone(),
|
subagent_source: thread_metadata.subagent_source.clone(),
|
||||||
parent_thread_id: thread_metadata.parent_thread_id.clone(),
|
parent_thread_id: thread_metadata.parent_thread_id.clone(),
|
||||||
tool_name,
|
tool_name,
|
||||||
|
|||||||
Reference in new issue
Block a user