Skip to content

Conversation

@aibrahim-oai
Copy link
Collaborator

@aibrahim-oai aibrahim-oai commented Dec 19, 2025

  • store etag on client
  • make TurnContext
  • refactor refresh_available_models to always refresh without checking cache. Only used in try_refresh_available_models and refreshing mid session
  • send etag to responses api
  • remove etag from ModelResponses because we send it as a header

@aibrahim-oai aibrahim-oai changed the title tag Refresh models on 412 (etag mismatch) Dec 19, 2025
@aibrahim-oai
Copy link
Collaborator Author

@codex review this

Copy link
Contributor

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

let model_supports_parallel = turn_context
.client
.get_model_family()
.supports_parallel_tool_calls;
let prompt = Prompt {
input,
tools: router.specs(),
parallel_tool_calls: model_supports_parallel && sess.enabled(Feature::ParallelToolCalls),
base_instructions_override: turn_context.base_instructions.clone(),

P2 Badge Recompute prompt after model refresh

When an outdated models error occurs, run_turn refreshes the models list and calls turn_context.client.update_model_family(...), but the Prompt is built once before the retry loop with parallel_tool_calls derived from the old model family. Subsequent retries reuse the stale prompt, so if the refreshed model family changes supports_parallel_tool_calls (or other prompt-derived capabilities), the retried request can still send the wrong parallel_tool_calls value. This can cause the retry to fail again (e.g., if the model now disallows parallel tool calls) or miss newly supported behavior. Consider rebuilding the prompt (or at least recomputing parallel_tool_calls) after updating the model family.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@aibrahim-oai
Copy link
Collaborator Author

@codex review this

Copy link
Contributor

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 2487 to 2488
turn_context.client.update_model_family(model_family);
turn_context.client.update_models_etag(models_etag);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Rebuild tools config after model_family refresh

When a 412 triggers OutdatedModels, you update the ModelClient’s model_family/etag and then retry, but the turn’s ToolsConfig/ToolRouter were built once before the loop from the old model_family. If the refreshed models list changes capabilities (e.g., shell_type, apply_patch_tool_type, or experimental_supported_tools), the retry still advertises stale tool definitions, which can keep failing or omit newly required tools. Consider rebuilding the tools config/router (or storing them in a lock like model_family) when the model family is refreshed.

Useful? React with 👍 / 👎.

@aibrahim-oai
Copy link
Collaborator Author

@codex review this

Copy link
Contributor

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 2478 to 2480
*turn_context = sess
.new_default_turn_with_sub_id(turn_context.sub_id.clone())
.await;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve per-turn output schema on 412 retry

When a 412 triggers the OutdatedModels retry, the code rebuilds the turn context via new_default_turn_with_sub_id, which reuses the session configuration but drops per-turn overrides like final_output_json_schema (only applied in new_turn_from_configuration when Op::UserTurn supplies it). If a caller requested a structured JSON response, the retry will run without the schema and can return unstructured output, breaking clients that depend on the schema. This only occurs for turns that set final_output_json_schema and then hit the 412 path.

Useful? React with 👍 / 👎.

@aibrahim-oai
Copy link
Collaborator Author

@codex review this

Copy link
Contributor

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 463 to 464
if let Some(final_output_json_schema) = updates.final_output_json_schema.clone() {
next_configuration.final_output_json_schema = final_output_json_schema;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid persisting per-turn output schema

Persisting final_output_json_schema in SessionConfiguration makes the schema stick across future turns instead of being scoped to a single UserTurn. Since Op::UserInput and subsequent UserTurns don’t clear it unless the caller explicitly sends a new value, later turns can be unintentionally constrained by an old schema, causing unexpected validation failures or malformed outputs. This is a regression from the previous per-turn override behavior where the schema was applied only for the specific turn.

Useful? React with 👍 / 👎.

@aibrahim-oai
Copy link
Collaborator Author

@codex review this

Copy link
Contributor

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 2390 to 2394
let session_configuration = sess.state.lock().await.session_configuration.clone();
*turn_context = sess
.new_turn_from_configuration(
turn_context.sub_id.clone(),
session_configuration,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve per-turn settings when rebuilding context

When a 412 triggers refresh_models_and_reset_turn_context, the code rebuilds the turn context from session_configuration instead of the existing TurnContext. This drops per-turn overrides (e.g., review threads set base_instructions to REVIEW_PROMPT and disable WebSearch/ViewImage in spawn_review_thread), so the retried request can run with the wrong instructions/tools after an outdated-models error. That changes behavior mid-turn and can invalidate review outputs or re-enable tools that were intentionally disabled for the turn.

Useful? React with 👍 / 👎.

@aibrahim-oai
Copy link
Collaborator Author

@codex review

Copy link
Contributor

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +2398 to +2400
let models_etag = sess.services.models_manager.get_models_etag().await;
turn_context.client.update_model_family(model_family).await;
turn_context.client.update_models_etag(models_etag).await;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Rebuild tool config after models refresh

After refreshing models on a 412, you only update the client’s model family and ETag, but TurnContext.tools_config is still the one built before the refresh. ToolsConfig::new depends on the model family (e.g., shell_type, apply_patch_tool_type, experimental_supported_tools), so if the catalog change altered tool capabilities, the retry will keep advertising the old tool set and can continue to fail or send unsupported tools. Consider rebuilding tools_config (or a new turn context) alongside the refreshed model family/etag so retries reflect the updated model metadata.

Useful? React with 👍 / 👎.

@aibrahim-oai
Copy link
Collaborator Author

@codex review this

Copy link
Contributor

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@aibrahim-oai
Copy link
Collaborator Author

@codex review this

@chatgpt-codex-connector
Copy link
Contributor

Codex Review: Didn't find any major issues. Another round soon, please!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

status,
request_id: extract_request_id(headers.as_ref()),
})
} else if status == http::StatusCode::PRECONDITION_FAILED
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use a status code, don't match on strings

Comment on lines +61 to +62
model_family: RwLock<ModelFamily>,
models_etag: RwLock<Option<String>>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two values are connected and should be only used/updated together. Let's not spread them across two fields.

self.model_family.read().await.clone()
}

pub async fn get_models_etag(&self) -> Option<String> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't make the client event larger model storage God-object.

}

impl Prompt {
pub(crate) async fn new(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this extracted?
This is one way to create the prompt but not the only one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants