mirror of
https://github.com/openai/codex.git
synced 2026-09-05 15:18:41 +00:00
## Why - Currently, there is no analytics event for `/goal` behavior - Existing events cannot identify goal execution or its resulting outcome - The original update in [#26182](https://github.com/openai/codex/pull/26182) was implemented before `/goal` moved into `codex-goal-extension`. ## What Changed - Adds `codex_goal_event` serialization and enrichment to `codex-analytics` - Emits goal events from the canonical `codex-goal-extension` mutation and accounting paths: - `created` when a new logical goal is persisted - `usage_accounted` when cumulative goal usage is persisted - `status_changed` when the stored goal status changes - `cleared` when the goal is deleted - Preserves causal `turn_id` for turn driven events and uses null attribution for external or idle lifecycle events - Changes goal deletion to return the deleted row so `cleared` retains the stable goal ID ## Event Details Includes standard analytics metadata along with goal specific fields: - `goal_id`: Stable ID stored in the local SQLite goal row and shared across the goal's events - `event_kind`: Observed operation (see the 4 lifecycle events cited in the above bullet) - `goal_status`: Resulting or last stored status: `active`, `paused`, `blocked`, `usage_limited`, etc. - `has_token_budget`: Indicates whether a token budget is configured - `turn_id`: Causal turn ID, or null when no causal turn exists - `cumulative_tokens_accounted`: Cumulative tokens on `usage_accounted` events; null otherwise - `cumulative_time_accounted_seconds`: Cumulative active time on `usage_accounted` events; null otherwise ## Validation - `just test -p codex-analytics -p codex-state -p codex-goal-extension` - `just test -p codex-core -E 'test(/goal/)'` - `just test -p codex-app-server` - `cargo build -p codex-analytics -p codex-core -p codex-state -p codex-app-server`
87 lines
2.5 KiB
Rust
87 lines
2.5 KiB
Rust
mod accepted_lines;
|
|
mod client;
|
|
mod events;
|
|
mod facts;
|
|
mod reducer;
|
|
|
|
use std::time::SystemTime;
|
|
use std::time::UNIX_EPOCH;
|
|
|
|
pub use accepted_lines::accepted_line_fingerprints_from_unified_diff;
|
|
pub use accepted_lines::fingerprint_hash;
|
|
pub use client::AnalyticsEventsClient;
|
|
pub use events::AppServerRpcTransport;
|
|
pub use events::GuardianApprovalRequestSource;
|
|
pub use events::GuardianReviewAnalyticsResult;
|
|
pub use events::GuardianReviewDecision;
|
|
pub use events::GuardianReviewEventParams;
|
|
pub use events::GuardianReviewFailureReason;
|
|
pub use events::GuardianReviewSessionKind;
|
|
pub use events::GuardianReviewTerminalStatus;
|
|
pub use events::GuardianReviewTrackContext;
|
|
pub use events::GuardianReviewedAction;
|
|
pub use facts::AcceptedLineFingerprint;
|
|
pub use facts::AnalyticsJsonRpcError;
|
|
pub use facts::AppInvocation;
|
|
pub use facts::CodexCompactionEvent;
|
|
pub use facts::CodexGoalEvent;
|
|
pub use facts::CodexTurnSteerEvent;
|
|
pub use facts::CompactionImplementation;
|
|
pub use facts::CompactionPhase;
|
|
pub use facts::CompactionReason;
|
|
pub use facts::CompactionStatus;
|
|
pub use facts::CompactionStrategy;
|
|
pub use facts::CompactionTrigger;
|
|
pub use facts::GoalEventKind;
|
|
pub use facts::HookRunFact;
|
|
pub use facts::InputError;
|
|
pub use facts::InvocationType;
|
|
pub use facts::SkillInvocation;
|
|
pub use facts::SubAgentThreadStartedInput;
|
|
pub use facts::ThreadInitializationMode;
|
|
pub use facts::TrackEventsContext;
|
|
pub use facts::TurnCodexErrorFact;
|
|
pub use facts::TurnProfile;
|
|
pub use facts::TurnProfileFact;
|
|
pub use facts::TurnResolvedConfigFact;
|
|
pub use facts::TurnStatus;
|
|
pub use facts::TurnSteerRejectionReason;
|
|
pub use facts::TurnSteerRequestError;
|
|
pub use facts::TurnSteerResult;
|
|
pub use facts::TurnTokenUsageFact;
|
|
pub use facts::build_track_events_context;
|
|
|
|
#[cfg(test)]
|
|
mod analytics_client_tests;
|
|
|
|
pub fn now_unix_seconds() -> u64 {
|
|
SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.unwrap_or_default()
|
|
.as_secs()
|
|
}
|
|
|
|
pub fn now_unix_millis() -> u64 {
|
|
u64::try_from(
|
|
SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.unwrap_or_default()
|
|
.as_millis(),
|
|
)
|
|
.unwrap_or(u64::MAX)
|
|
}
|
|
|
|
pub(crate) fn serialize_enum_as_string<T: serde::Serialize>(value: &T) -> Option<String> {
|
|
serde_json::to_value(value)
|
|
.ok()
|
|
.and_then(|value| value.as_str().map(str::to_string))
|
|
}
|
|
|
|
pub(crate) fn usize_to_u64(value: usize) -> u64 {
|
|
u64::try_from(value).unwrap_or(u64::MAX)
|
|
}
|
|
|
|
pub(crate) fn option_i64_to_u64(value: Option<i64>) -> Option<u64> {
|
|
value.and_then(|value| u64::try_from(value).ok())
|
|
}
|