mirror of
https://github.com/openai/codex.git
synced 2026-05-15 16:53:05 +00:00
## Why For reproducibility. A hand-written `config.toml` is not enough to recreate what a Codex session actually ran with because layered config, CLI overrides, defaults, feature aliases, resolved feature config, prompt setup, and model-catalog/session values can all affect the final runtime behavior. This PR adds an effective config lockfile path: one run can export the resolved session config, and a later run can replay that lockfile and fail early if the regenerated effective config drifts. ## What Changed - Add a dedicated `ConfigLockfileToml` wrapper with top-level lockfile metadata plus the replayable config: ```toml version = 1 codex_version = "..." [config] # effective ConfigToml fields ``` - Keep lockfile metadata out of regular `ConfigToml`; replay loads `ConfigLockfileToml` and then uses its nested `config` as the authoritative config layer. - Add `debug.config_lockfile.export_dir` to write `<thread_id>.config.lock.toml` when a root session starts. - Add `debug.config_lockfile.load_path` to replay a saved lockfile and validate the regenerated session lockfile against it. - Add `debug.config_lockfile.allow_codex_version_mismatch` to optionally tolerate Codex binary version drift while still comparing the rest of the lockfile. - Add `debug.config_lockfile.save_fields_resolved_from_model_catalog` so lock creation can either save model-catalog/session-resolved fields or intentionally leave those fields dynamic. - Build lockfiles from the effective config plus resolved runtime values such as model selection, reasoning settings, prompts, service tier, web search mode, feature states/config, memories config, skill instructions, and agent limits. - Materialize feature aliases and custom feature config into the lockfile so replay compares canonical resolved behavior instead of user-authored alias shape. - Strip profile/debug/file-include/environment-specific inputs from generated lockfiles so they contain replayable values rather than the inputs that produced those values. - Surface JSON-RPC server error code/data in app-server client and TUI bootstrap errors so config-lock replay failures include the actual TOML diff. - Regenerate the config schema for the new debug config keys. ## Review Notes The main flow is split across these files: - `config/src/config_toml.rs`: lockfile/debug TOML shapes. - `core/src/config/mod.rs`: loading `debug.config_lockfile.*`, replaying a lockfile as a config layer, and preserving the expected lockfile for validation. - `core/src/session/config_lock.rs`: exporting the current session lockfile and materializing resolved session/config values. - `core/src/config_lock.rs`: lockfile parsing, metadata/version checks, replay comparison, and diff formatting. ## Usage Export a lockfile from a normal session: ```sh codex -c 'debug.config_lockfile.export_dir="/tmp/codex-locks"' ``` Export a lockfile without saving model-catalog/session-resolved fields: ```sh codex -c 'debug.config_lockfile.export_dir="/tmp/codex-locks"' \ -c 'debug.config_lockfile.save_fields_resolved_from_model_catalog=false' ``` Replay a saved lockfile in a later session: ```sh codex -c 'debug.config_lockfile.load_path="/tmp/codex-locks/<thread_id>.config.lock.toml"' ``` If replay resolves to a different effective config, startup fails with a TOML diff. To tolerate Codex binary version drift during replay: ```sh codex -c 'debug.config_lockfile.load_path="/tmp/codex-locks/<thread_id>.config.lock.toml"' \ -c 'debug.config_lockfile.allow_codex_version_mismatch=true' ``` ## Limitations This does not support custom rules/network policies. ## Verification - `cargo test -p codex-core config_lock` - `cargo test -p codex-config` - `cargo test -p codex-thread-manager-sample`
204 lines
6.7 KiB
Rust
204 lines
6.7 KiB
Rust
//! Root of the `codex-core` library.
|
|
|
|
// Prevent accidental direct writes to stdout/stderr in library code. All
|
|
// user-visible output must go through the appropriate abstraction (e.g.,
|
|
// the TUI or the tracing stack).
|
|
#![deny(clippy::print_stdout, clippy::print_stderr)]
|
|
|
|
mod apply_patch;
|
|
mod apps;
|
|
mod arc_monitor;
|
|
mod client;
|
|
mod client_common;
|
|
mod realtime_context;
|
|
mod realtime_conversation;
|
|
mod realtime_prompt;
|
|
pub(crate) mod session;
|
|
pub use session::SteerInputError;
|
|
mod codex_thread;
|
|
mod compact_remote;
|
|
mod config_lock;
|
|
pub use codex_thread::CodexThread;
|
|
pub use codex_thread::CodexThreadTurnContextOverrides;
|
|
pub use codex_thread::ThreadConfigSnapshot;
|
|
mod agent;
|
|
mod codex_delegate;
|
|
mod command_canonicalization;
|
|
mod commit_attribution;
|
|
pub mod config;
|
|
pub mod connectors;
|
|
pub mod context;
|
|
mod context_manager;
|
|
mod environment_selection;
|
|
pub mod exec;
|
|
pub mod exec_env;
|
|
mod exec_policy;
|
|
pub mod file_watcher;
|
|
mod flags;
|
|
#[cfg(test)]
|
|
mod git_info_tests;
|
|
mod goals;
|
|
mod guardian;
|
|
mod hook_runtime;
|
|
mod installation_id;
|
|
pub(crate) mod landlock;
|
|
pub use landlock::spawn_command_under_linux_sandbox;
|
|
pub(crate) mod mcp;
|
|
mod mcp_skill_dependencies;
|
|
mod mcp_tool_approval_templates;
|
|
mod mcp_tool_exposure;
|
|
mod network_policy_decision;
|
|
pub(crate) mod network_proxy_loader;
|
|
pub use mcp::McpManager;
|
|
pub use network_proxy_loader::MtimeConfigReloader;
|
|
pub use network_proxy_loader::build_network_proxy_state;
|
|
pub use network_proxy_loader::build_network_proxy_state_and_reloader;
|
|
mod original_image_detail;
|
|
pub use codex_mcp::SandboxState;
|
|
mod mcp_openai_file;
|
|
mod mcp_tool_call;
|
|
pub(crate) mod mention_syntax;
|
|
pub(crate) mod message_history;
|
|
pub(crate) mod utils;
|
|
pub use mention_syntax::PLUGIN_TEXT_MENTION_SIGIL;
|
|
pub use mention_syntax::TOOL_MENTION_SIGIL;
|
|
pub use message_history::HistoryEntry as MessageHistoryEntry;
|
|
pub use message_history::append_entry as append_message_history_entry;
|
|
pub use message_history::history_metadata as message_history_metadata;
|
|
pub use message_history::lookup as lookup_message_history_entry;
|
|
pub use utils::path_utils;
|
|
pub mod personality_migration;
|
|
pub(crate) mod plugins;
|
|
#[doc(hidden)]
|
|
pub(crate) mod prompt_debug;
|
|
#[doc(hidden)]
|
|
pub use prompt_debug::build_prompt_input;
|
|
pub(crate) mod mentions {
|
|
pub(crate) use crate::plugins::build_connector_slug_counts;
|
|
pub(crate) use crate::plugins::build_skill_name_counts;
|
|
pub(crate) use crate::plugins::collect_explicit_app_ids;
|
|
pub(crate) use crate::plugins::collect_explicit_plugin_mentions;
|
|
pub(crate) use crate::plugins::collect_tool_mentions_from_messages;
|
|
}
|
|
mod sandbox_tags;
|
|
pub mod sandboxing;
|
|
mod session_prefix;
|
|
mod session_startup_prewarm;
|
|
mod shell_detect;
|
|
pub mod skills;
|
|
pub(crate) use skills::SkillError;
|
|
pub(crate) use skills::SkillInjections;
|
|
pub(crate) use skills::SkillLoadOutcome;
|
|
pub(crate) use skills::SkillMetadata;
|
|
pub(crate) use skills::SkillsLoadInput;
|
|
pub(crate) use skills::SkillsManager;
|
|
pub(crate) use skills::build_available_skills;
|
|
pub(crate) use skills::build_skill_injections;
|
|
pub(crate) use skills::build_skill_name_counts;
|
|
pub(crate) use skills::collect_env_var_dependencies;
|
|
pub(crate) use skills::collect_explicit_skill_mentions;
|
|
pub(crate) use skills::default_skill_metadata_budget;
|
|
pub(crate) use skills::injection;
|
|
pub(crate) use skills::manager;
|
|
pub(crate) use skills::maybe_emit_implicit_skill_invocation;
|
|
pub(crate) use skills::resolve_skill_dependencies_for_turn;
|
|
pub(crate) use skills::skills_load_input_from_config;
|
|
mod skills_watcher;
|
|
mod stream_events_utils;
|
|
pub mod test_support;
|
|
mod unified_exec;
|
|
pub mod windows_sandbox;
|
|
pub use client::X_RESPONSESAPI_INCLUDE_TIMING_METRICS_HEADER;
|
|
pub use codex_protocol::config_types::ModelProviderAuthInfo;
|
|
mod event_mapping;
|
|
pub mod review_format;
|
|
pub mod review_prompts;
|
|
mod thread_manager;
|
|
pub(crate) mod web_search;
|
|
pub(crate) mod windows_sandbox_read_grants;
|
|
pub use thread_manager::ForkSnapshot;
|
|
pub use thread_manager::NewThread;
|
|
pub use thread_manager::StartThreadOptions;
|
|
pub use thread_manager::ThreadManager;
|
|
pub use thread_manager::ThreadShutdownReport;
|
|
pub use thread_manager::build_models_manager;
|
|
pub use thread_manager::thread_store_from_config;
|
|
pub use web_search::web_search_action_detail;
|
|
pub use web_search::web_search_detail;
|
|
pub use windows_sandbox_read_grants::grant_read_root_non_elevated;
|
|
#[deprecated(note = "use ThreadManager")]
|
|
pub type ConversationManager = ThreadManager;
|
|
#[deprecated(note = "use NewThread")]
|
|
pub type NewConversation = NewThread;
|
|
#[deprecated(note = "use CodexThread")]
|
|
pub type CodexConversation = CodexThread;
|
|
pub(crate) mod agents_md;
|
|
pub use agents_md::AgentsMdManager;
|
|
pub use agents_md::DEFAULT_AGENTS_MD_FILENAME;
|
|
pub use agents_md::LOCAL_AGENTS_MD_FILENAME;
|
|
mod rollout;
|
|
pub(crate) mod safety;
|
|
mod session_rollout_init_error;
|
|
pub mod shell;
|
|
pub(crate) mod shell_snapshot;
|
|
pub mod spawn;
|
|
pub(crate) mod state_db_bridge;
|
|
pub use state_db_bridge::StateDbHandle;
|
|
pub use state_db_bridge::get_state_db;
|
|
mod thread_rollout_truncation;
|
|
mod tools;
|
|
pub(crate) mod turn_diff_tracker;
|
|
mod turn_metadata;
|
|
mod turn_timing;
|
|
mod unavailable_tool;
|
|
pub use rollout::ARCHIVED_SESSIONS_SUBDIR;
|
|
pub use rollout::Cursor;
|
|
pub use rollout::EventPersistenceMode;
|
|
pub use rollout::INTERACTIVE_SESSION_SOURCES;
|
|
pub use rollout::RolloutRecorder;
|
|
pub use rollout::RolloutRecorderParams;
|
|
pub use rollout::SESSIONS_SUBDIR;
|
|
pub use rollout::SessionMeta;
|
|
pub use rollout::SortDirection;
|
|
pub use rollout::ThreadItem;
|
|
pub use rollout::ThreadSortKey;
|
|
pub use rollout::ThreadsPage;
|
|
pub use rollout::append_thread_name;
|
|
pub use rollout::find_archived_thread_path_by_id_str;
|
|
#[deprecated(note = "use find_thread_path_by_id_str")]
|
|
pub use rollout::find_conversation_path_by_id_str;
|
|
pub use rollout::find_thread_meta_by_name_str;
|
|
pub use rollout::find_thread_name_by_id;
|
|
pub use rollout::find_thread_names_by_ids;
|
|
pub use rollout::find_thread_path_by_id_str;
|
|
pub use rollout::parse_cursor;
|
|
pub use rollout::read_head_for_summary;
|
|
pub use rollout::read_session_meta_line;
|
|
pub use rollout::rollout_date_parts;
|
|
mod function_tool;
|
|
mod state;
|
|
mod tasks;
|
|
mod user_shell_command;
|
|
pub mod util;
|
|
|
|
pub use client::ModelClient;
|
|
pub use client::ModelClientSession;
|
|
pub use client::X_CODEX_INSTALLATION_ID_HEADER;
|
|
pub use client::X_CODEX_TURN_METADATA_HEADER;
|
|
pub use client_common::Prompt;
|
|
pub use client_common::REVIEW_PROMPT;
|
|
pub use client_common::ResponseEvent;
|
|
pub use client_common::ResponseStream;
|
|
pub use compact::content_items_to_text;
|
|
pub use event_mapping::parse_turn_item;
|
|
pub use exec_policy::ExecPolicyError;
|
|
pub use exec_policy::check_execpolicy_for_warnings;
|
|
pub use exec_policy::format_exec_policy_error_with_source;
|
|
pub use exec_policy::load_exec_policy;
|
|
pub use file_watcher::FileWatcherEvent;
|
|
pub use installation_id::resolve_installation_id;
|
|
pub use turn_metadata::build_turn_metadata_header;
|
|
pub mod compact;
|
|
mod memory_usage;
|
|
pub mod otel_init;
|