[codex] Add comp_hash to model metadata (#27532)

## Summary
- add optional `comp_hash` metadata to `ModelInfo`
- update `ModelInfo` fixtures for the shared schema change
- keep older model responses compatible by defaulting the field to
`None`

## Why
The models endpoint needs an opaque identifier for compaction-compatible
model configurations. This PR only exposes that value in model metadata;
it does not add it to turn context or change runtime behavior.

Follow-up #27520 carries the value through turn context and rollouts,
then uses it to trigger compaction.

## Stack
- based directly on `main`
- replaces #27519, which was accidentally merged into the wrong base
branch
- functionality follow-up: #27520

## Testing
- `just test -p codex-protocol
model_info_defaults_availability_nux_to_none_when_omitted`
- `just fix -p codex-core -p codex-protocol -p codex-analytics -p
codex-models-manager`
This commit is contained in:
Ahmed Ibrahim
2026-06-10 20:42:55 -07:00
committed by GitHub
Unverified
parent 06afd63f4a
commit e614fad02e
13 changed files with 21 additions and 0 deletions
@@ -47,6 +47,7 @@ fn preset_to_info(preset: &ModelPreset, priority: i32) -> ModelInfo {
context_window: Some(272_000),
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: Vec::new(),
input_modalities: default_input_modalities(),
@@ -93,6 +93,7 @@ async fn models_client_hits_models_endpoint() {
context_window: Some(272_000),
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: Vec::new(),
input_modalities: default_input_modalities(),
+1
View File
@@ -256,6 +256,7 @@ fn remote_model_with_auto_review_override(slug: &str, review_model: &str) -> Mod
context_window: Some(272_000),
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: Vec::new(),
}
@@ -136,6 +136,7 @@ fn test_model_info(
context_window: Some(272_000),
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: Vec::new(),
}
@@ -957,6 +958,7 @@ async fn model_switch_to_smaller_model_updates_token_context_window() -> Result<
context_window: Some(large_context_window),
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent,
experimental_supported_tools: Vec::new(),
};
@@ -365,6 +365,7 @@ fn test_remote_model(slug: &str, priority: i32) -> ModelInfo {
context_window: Some(272_000),
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: Vec::new(),
input_modalities: default_input_modalities(),
+2
View File
@@ -587,6 +587,7 @@ async fn remote_model_friendly_personality_instructions_with_feature() -> anyhow
context_window: Some(128_000),
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: Vec::new(),
input_modalities: default_input_modalities(),
@@ -701,6 +702,7 @@ async fn user_turn_personality_remote_model_template_includes_update_message() -
context_window: Some(128_000),
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: Vec::new(),
input_modalities: default_input_modalities(),
@@ -499,6 +499,7 @@ async fn remote_models_remote_model_uses_unified_exec() -> Result<()> {
context_window: Some(272_000),
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: Vec::new(),
};
@@ -751,6 +752,7 @@ async fn remote_models_apply_remote_base_instructions() -> Result<()> {
context_window: Some(272_000),
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: Vec::new(),
};
@@ -1237,6 +1239,7 @@ fn test_remote_model_with_policy(
context_window: Some(272_000),
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: Vec::new(),
}
+1
View File
@@ -1499,6 +1499,7 @@ async fn stdio_image_responses_are_sanitized_for_text_only_model() -> anyhow::Re
context_window: Some(272_000),
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: Vec::new(),
input_modalities: vec![InputModality::Text],
@@ -84,6 +84,7 @@ fn test_model_info(
context_window: Some(272_000),
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: Vec::new(),
}
+1
View File
@@ -1470,6 +1470,7 @@ async fn view_image_tool_returns_unsupported_message_for_text_only_model() -> an
context_window: Some(272_000),
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: Vec::new(),
};
@@ -94,6 +94,7 @@ pub fn model_info_from_slug(slug: &str) -> ModelInfo {
context_window: Some(272_000),
max_context_window: Some(272_000),
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: Vec::new(),
input_modalities: default_input_modalities(),
+5
View File
@@ -389,6 +389,9 @@ pub struct ModelInfo {
/// context window when available.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub auto_compact_token_limit: Option<i64>,
/// Opaque identifier for compaction-compatible model configurations.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub comp_hash: Option<String>,
/// Percentage of the context window considered usable for inputs, after
/// reserving headroom for system prompts, tool overhead, and model output.
#[serde(default = "default_effective_context_window_percent")]
@@ -671,6 +674,7 @@ mod tests {
context_window: None,
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: vec![],
input_modalities: default_input_modalities(),
@@ -940,6 +944,7 @@ mod tests {
assert_eq!(model.web_search_tool_type, WebSearchToolType::Text);
assert!(!model.supports_search_tool);
assert!(!model.use_responses_lite);
assert_eq!(model.comp_hash, None);
assert_eq!(model.auto_review_model_override, None);
assert_eq!(model.tool_mode, None);
}
+1
View File
@@ -39,6 +39,7 @@ fn model_with_shell_type(shell_type: ConfigShellToolType) -> ModelInfo {
context_window: None,
max_context_window: None,
auto_compact_token_limit: None,
comp_hash: None,
effective_context_window_percent: 95,
experimental_supported_tools: Vec::new(),
input_modalities: codex_protocol::openai_models::default_input_modalities(),