Expose the Codex version to commands and turn metadata (#42395)

## What changed

- Set `CODEX_VERSION` to the running package version in user shell and unified
  exec environments, overriding stale shell-policy or snapshot values.
- Add the reserved `codex_version` field to MCP turn metadata.

## Testing

- Cover version propagation through shell policies, shell snapshots, unified
  exec, and MCP metadata.

GitOrigin-RevId: 7846c70d668176530b1f467293b749dc9ddd79a0
This commit is contained in:
jif
2026-09-03 00:17:19 +00:00
committed by copyberry
parent 91608236ea
commit 9bb1ea035f
11 changed files with 74 additions and 17 deletions
@@ -17,10 +17,11 @@ use super::oneshot::Completion;
use crate::codex_thread::BackgroundTerminalInfo;
use crate::exec_env::CODEX_PERMISSION_PROFILE_ENV_VAR;
use crate::exec_env::CODEX_THREAD_ID_ENV_VAR;
use crate::exec_env::CODEX_VERSION_ENV_VAR;
use crate::exec_env::create_env;
use crate::exec_env::inject_apply_patch_env;
use crate::exec_env::inject_permission_profile_env;
use crate::exec_env::inject_session_id_env;
use crate::exec_env::inject_session_env;
use crate::exec_policy::ExecApprovalRequest;
use crate::guardian::GuardianReviewContext;
use crate::plugins::metrics::finish_and_track_measurements;
@@ -138,6 +139,7 @@ pub(super) fn exec_env_policy_from_shell_policy(
.collect::<Vec<_>>();
exclude.extend([
CODEX_PERMISSION_PROFILE_ENV_VAR.to_string(),
CODEX_VERSION_ENV_VAR.to_string(),
codex_apply_patch::CODEX_APPLY_PATCH_PRESERVE_LINE_ENDINGS_ENV_VAR.to_string(),
PLUGIN_METRICS_OUTPUT_ENV_VAR.to_string(),
]);
@@ -145,6 +147,7 @@ pub(super) fn exec_env_policy_from_shell_policy(
r#set.retain(|key, _| {
![
CODEX_PERMISSION_PROFILE_ENV_VAR,
CODEX_VERSION_ENV_VAR,
codex_apply_patch::CODEX_APPLY_PATCH_PRESERVE_LINE_ENDINGS_ENV_VAR,
PLUGIN_METRICS_OUTPUT_ENV_VAR,
]
@@ -176,6 +179,7 @@ fn env_overlay_for_exec_server(
&& (matches!(
key.as_str(),
CODEX_PERMISSION_PROFILE_ENV_VAR
| CODEX_VERSION_ENV_VAR
| codex_apply_patch::CODEX_APPLY_PATCH_PRESERVE_LINE_ENDINGS_ENV_VAR
) || local_policy_env.get(*key) != Some(*value))
})
@@ -1362,7 +1366,7 @@ impl UnifiedExecProcessManager {
CODEX_THREAD_ID_ENV_VAR.to_string(),
context.session.thread_id.to_string(),
);
inject_session_id_env(&mut env, context.session.session_id());
inject_session_env(&mut env, context.session.session_id());
inject_apply_patch_env(&mut env, &turn.config.features);
let active_permission_profile = request.turn_environment.active_permission_profile();
inject_permission_profile_env(&mut env, active_permission_profile.as_ref());
@@ -53,6 +53,10 @@ fn env_overlay_for_exec_server_keeps_runtime_changes_only() {
("HOME".to_string(), "/client-home".to_string()),
("PATH".to_string(), "/client-path".to_string()),
("SHELL_SET".to_string(), "policy".to_string()),
(
CODEX_VERSION_ENV_VAR.to_string(),
"client-version".to_string(),
),
(
CODEX_PERMISSION_PROFILE_ENV_VAR.to_string(),
"current-profile".to_string(),
@@ -68,6 +72,10 @@ fn env_overlay_for_exec_server_keeps_runtime_changes_only() {
("OpenAI_Federation_Rule_Id".to_string(), "rule".to_string()),
("SHELL_SET".to_string(), "policy".to_string()),
("CODEX_THREAD_ID".to_string(), "thread-1".to_string()),
(
CODEX_VERSION_ENV_VAR.to_string(),
"client-version".to_string(),
),
(
CODEX_PERMISSION_PROFILE_ENV_VAR.to_string(),
"current-profile".to_string(),
@@ -87,6 +95,10 @@ fn env_overlay_for_exec_server_keeps_runtime_changes_only() {
HashMap::from([
("PATH".to_string(), "/sandbox-path".to_string()),
("CODEX_THREAD_ID".to_string(), "thread-1".to_string()),
(
CODEX_VERSION_ENV_VAR.to_string(),
"client-version".to_string()
),
(
CODEX_PERMISSION_PROFILE_ENV_VAR.to_string(),
"current-profile".to_string(),
@@ -107,6 +119,7 @@ fn env_overlay_for_exec_server_keeps_runtime_changes_only() {
fn exec_env_policy_excludes_non_inheritable_and_runtime_variables() {
let policy = ShellEnvironmentPolicy {
r#set: HashMap::from([
("codex_version".to_string(), "stale-version".to_string()),
(
"codex_permission_profile".to_string(),
"stale-profile".to_string(),
@@ -135,6 +148,7 @@ fn exec_env_policy_excludes_non_inheritable_and_runtime_variables() {
ignore_default_excludes: policy.ignore_default_excludes,
exclude: vec![
CODEX_PERMISSION_PROFILE_ENV_VAR.to_string(),
CODEX_VERSION_ENV_VAR.to_string(),
codex_apply_patch::CODEX_APPLY_PATCH_PRESERVE_LINE_ENDINGS_ENV_VAR.to_string(),
PLUGIN_METRICS_OUTPUT_ENV_VAR.to_string(),
],
@@ -23,7 +23,7 @@ use crate::config::NetworkProxySpec;
use crate::exec_env::CODEX_THREAD_ID_ENV_VAR;
use crate::exec_env::inject_apply_patch_env;
use crate::exec_env::inject_permission_profile_env;
use crate::exec_env::inject_session_id_env;
use crate::exec_env::inject_session_env;
use crate::session::session::Session;
use crate::session::step_context::StepContext;
use crate::shell::ShellType;
@@ -114,7 +114,7 @@ impl Session {
CODEX_THREAD_ID_ENV_VAR.to_string(),
session.thread_id().to_string(),
);
inject_session_id_env(&mut env, session.session_id());
inject_session_env(&mut env, session.session_id());
inject_apply_patch_env(&mut env, &config.features);
inject_permission_profile_env(
&mut env,