Skip to content

Conversation

@aibrahim-oai
Copy link
Collaborator

@aibrahim-oai aibrahim-oai commented Jan 5, 2026

  • Merge ModelFamily into ModelInfo
  • Remove logic for adding instructions to apply patch
  • Add compaction limit and visible context window to ModelInfo

@aibrahim-oai aibrahim-oai changed the title Modelfamily into modelinfo Merge Modelfamily into modelinfo Jan 6, 2026
@aibrahim-oai
Copy link
Collaborator Author

@codex review this and note any behavior change

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.

Reviewed commit: b80cd383a5

ℹ️ 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 38 to 41
upgrade: None,
base_instructions: BASE_INSTRUCTIONS.to_string(),
supports_reasoning_summaries: true,
support_verbosity: false,
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 enabling reasoning for unknown models by default

The fallback default_model_info now sets supports_reasoning_summaries: true, which is used whenever a model slug isn’t matched in find_model_info_for_slug and no remote metadata is available. In that case, ModelClient::stream_responses_api will include a reasoning block for custom/third‑party models that may not support it, leading to 400s or rejected requests. Previously unknown models defaulted to not sending reasoning, so this is a behavior change; consider keeping the default false or only enabling when remote metadata explicitly indicates support.

Useful? React with 👍 / 👎.

},
ReasoningEffortPreset {
effort: ReasoningEffort::High,
description: "Maximizes reasoning depth for complex or ambiguous problems".to_string(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be possible to change "Maximizes" to "Greater" like in supported_reasoning_level_low_medium_high_xhigh()?

@aibrahim-oai aibrahim-oai marked this pull request as ready for review January 6, 2026 02:11
@aibrahim-oai aibrahim-oai marked this pull request as draft January 6, 2026 02:11
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.

Reviewed commit: b80cd383a5

ℹ️ 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 176 to 180
pub supported_in_api: bool,
pub priority: i32,
pub upgrade: Option<String>,
pub base_instructions: Option<String>,
pub base_instructions: String,
pub supports_reasoning_summaries: bool,
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 Keep base_instructions backward-compatible in ModelInfo

Because base_instructions is now a required String with no serde default, any cached models written by older clients (or older /models responses that omitted/returned null for this field) will fail to deserialize; ModelsClient::list_models and ModelsCache::load_cache treat this as a hard error, so remote models won’t load and offline users lose their cached list. Consider keeping this optional or adding a serde default to preserve backward compatibility.

Useful? React with 👍 / 👎.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Agree with Codex - are we 100% guaranteed to have base_instructions and context_window present in the models_cache.json file?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah it's required

Comment on lines 183 to 187
pub apply_patch_tool_type: Option<ApplyPatchToolType>,
pub truncation_policy: TruncationPolicyConfig,
pub supports_parallel_tool_calls: bool,
pub context_window: Option<i64>,
pub context_window: i64,
/// Token threshold for automatic compaction. When omitted, core derives it
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 parsing of cached models without context_window

The new required context_window: i64 has the same compatibility problem: older cached entries or backend responses that used null will now fail to parse, causing refresh_available_models_with_cache to drop the cache and remote model discovery to fail when offline. Adding a default or keeping the field optional avoids breaking existing caches.

Useful? React with 👍 / 👎.

@aibrahim-oai aibrahim-oai marked this pull request as ready for review January 6, 2026 06:53
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.

Reviewed commit: b80cd383a5

ℹ️ 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 99 to 101
} else if slug.starts_with("gpt-oss") || slug.starts_with("openai/gpt-oss") {
model.apply_patch_tool_type = Some(ApplyPatchToolType::Function);
model.context_window = 96_000;
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 Disable reasoning summaries for gpt-oss models

In find_model_info_for_slug, the gpt-oss branch no longer overrides supports_reasoning_summaries, so it inherits the new default_model_info value of true. That means ModelClient::stream_responses_api will now include a reasoning block for gpt-oss/openai/gpt-oss requests, whereas previously ModelFamily defaulted this to false. If those models don’t accept reasoning fields, Responses API calls will start failing (400s) whenever reasoning summaries are enabled. Consider explicitly setting supports_reasoning_summaries = false for gpt-oss or restoring the old default.

Useful? React with 👍 / 👎.

let mut model = default_model_info(slug);

if slug.starts_with("o3") || slug.starts_with("o4-mini") {
model.base_instructions = BASE_INSTRUCTIONS_WITH_APPLY_PATCH.to_string();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why isn't this in existing model families?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we reuse the same declarative way of defining models as we had before?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Why isn't this in existing model families?

it's there

Image

Copy link
Collaborator

@dylan-hurd-oai dylan-hurd-oai Jan 6, 2026

Choose a reason for hiding this comment

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

Can we reuse the same declarative way of defining models as we had before?

+1 to this point - purely declarative logic is going to be more maintainable than mutating a struct here. Can we use the same macro w/ defaults pattern?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

okay. I am planning to remove this and just use models.json so won't maintain it for long

Copy link
Collaborator

@dylan-hurd-oai dylan-hurd-oai left a comment

Choose a reason for hiding this comment

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

My only top-level question is whether we can split up this migration into a few smaller pieces, or whether we have sufficient testing on these code paths to be sure we're not missing any config changes.

Self::find_family_for_model(model).with_config_overrides(config)
/// Offline helper that builds a `ModelInfo` without consulting remote state.
pub fn construct_model_info_offline(model: &str, config: &Config) -> ModelInfo {
model_info::with_config_overrides(Self::find_model_info_for_slug(model), config)
Copy link
Collaborator

Choose a reason for hiding this comment

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

(out of scope for this PR) Is this helper function strictly necessary? If tests control the config, couldn't we just call construct_model_info with no remote settings enabled?

If we can remove it, would be great to simplify before or after this migration.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

it's mainly for unit tests not integration tests

Comment on lines 176 to 180
pub supported_in_api: bool,
pub priority: i32,
pub upgrade: Option<String>,
pub base_instructions: Option<String>,
pub base_instructions: String,
pub supports_reasoning_summaries: bool,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Agree with Codex - are we 100% guaranteed to have base_instructions and context_window present in the models_cache.json file?

@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.

Reviewed commit: 7e9f830f72

ℹ️ 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".

Copy link
Collaborator

@dylan-hurd-oai dylan-hurd-oai left a comment

Choose a reason for hiding this comment

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

Thanks for cleaning up model_info - i think we need to address the codex comment, other than that LGTM

@aibrahim-oai
Copy link
Collaborator Author

@codex review this

@aibrahim-oai
Copy link
Collaborator Author

@codex review this

1 similar comment
@aibrahim-oai
Copy link
Collaborator Author

@codex review this

@aibrahim-oai
Copy link
Collaborator Author

@codex list differences in behavior between declarative model info and previous model family

@chatgpt-codex-connector

This comment was marked as outdated.

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.

Reviewed commit: f926231a4c

ℹ️ 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 list differences in behavior between declarative model info and previous model family

@chatgpt-codex-connector

This comment was marked as outdated.

@aibrahim-oai aibrahim-oai force-pushed the modelfamily-into-modelinfo branch from a35c8d6 to f926231 Compare January 7, 2026 07:36
@aibrahim-oai
Copy link
Collaborator Author

@codex list differences in behavior between declarative model info and previous model family

@chatgpt-codex-connector

This comment was marked as outdated.

@aibrahim-oai
Copy link
Collaborator Author

@codex list differences in behavior between declarative model info and previous model family

@chatgpt-codex-connector
Copy link
Contributor

Behavioral differences between declarative ModelInfo and previous ModelFamily

Below are the behavioral differences I can confirm from the current code versus the base ref (3389465).

1) Apply‑patch instructions are no longer conditionally appended

  • Before (ModelFamily): Prompt::get_full_instructions appended APPLY_PATCH_TOOL_INSTRUCTIONS only when there was no base override, the model family required special apply‑patch instructions, and no apply_patch tool was present. This made the apply‑patch text conditional on tool availability.
    (Base ref: codex-rs/core/src/client_common.rs)
  • Now (ModelInfo): Prompt::get_full_instructions always returns the model’s base_instructions (or override) without appending anything. Models that need apply‑patch guidance now pick BASE_INSTRUCTIONS_WITH_APPLY_PATCH inside find_model_info_for_slug, so the extra instructions are always included regardless of tool presence.
    (Current: codex-rs/core/src/client_common.rs, codex-rs/core/src/models_manager/model_info.rs)

Impact: The “only append when no apply_patch tool exists” behavior is gone; instructions are now fully model-defined and always present when the model info selects the apply‑patch base prompt.


2) Remote override semantics changed from “selective field updates” to “replace‑all”

  • Before (ModelFamily): apply_remote_overrides updated a subset of fields and only replaced base_instructions if the remote field was Some(...).
    (Base ref: codex-rs/core/src/models_manager/model_family.rs)
  • Now (ModelInfo): merge_remote_overrides replaces the entire ModelInfo with the remote record, preserving only auto_compact_token_limit if missing.
    (Current: codex-rs/core/src/models_manager/model_info.rs)

Impact: Remote metadata is now authoritative for essentially all fields rather than a partial overlay, so remote values replace local defaults even if they previously would have been left intact.


3) Unknown model context windows moved from None0 sentinel

  • Before (ModelFamily): derive_default_model_family set context_window: None for unknown models.
    (Base ref: codex-rs/core/src/models_manager/model_family.rs)
  • Now (ModelInfo): unknown models set context_window: 0 as a sentinel in find_model_info_for_slug, and get_model_context_window treats <= 0 as “unknown/none”.
    (Current: codex-rs/core/src/models_manager/model_info.rs, codex-rs/core/src/client.rs)

Impact: Behavior is functionally similar (unknown models still yield no effective window), but the representation changed from an Option to a numeric sentinel that is checked at runtime.


4) Auto‑compaction threshold derivation now uses the context_window sentinel

  • Before (ModelFamily): run_task called auto_compact_token_limit() on the model family, which derived a default from context_window only when it was Some(...).
    (Base ref: codex-rs/core/src/codex.rs, codex-rs/core/src/models_manager/model_family.rs)
  • Now (ModelInfo): run_task derives the default by checking context_window > 0 and computing 90% of it, otherwise falls back to i64::MAX.
    (Current: codex-rs/core/src/codex.rs)

Impact: The threshold derivation relies on the numeric sentinel instead of Option, which aligns with the new representation (though effective behavior is similar for unknown models).


5) Model metadata shape changes how base_instructions is handled

  • Before (ModelFamily): remote ModelInfo’s base_instructions was optional in the override path and only applied when Some(...).
    (Base ref: codex-rs/core/src/models_manager/model_family.rs)
  • Now (ModelInfo): base_instructions is a required String in the model metadata and is always carried through in the local model info and remote merges.
    (Current: codex-rs/protocol/src/openai_models.rs, codex-rs/core/src/models_manager/model_info.rs)

Impact: With the replace‑all merge and required base_instructions, the remote entry’s instructions fully determine the prompt, rather than being conditional on presence.


Sources & commands used

Files inspected (current):

  • codex-rs/core/src/models_manager/model_info.rs
  • codex-rs/core/src/client_common.rs
  • codex-rs/core/src/client.rs
  • codex-rs/core/src/codex.rs
  • codex-rs/protocol/src/openai_models.rs

Files inspected (base ref 3389465):

  • codex-rs/core/src/models_manager/model_family.rs
  • codex-rs/core/src/client_common.rs
  • codex-rs/core/src/client.rs
  • codex-rs/core/src/codex.rs

Commands run:

  • sed -n '1,240p' codex-rs/core/src/models_manager/model_info.rs
  • sed -n '240,520p' codex-rs/core/src/models_manager/model_info.rs
  • git show 3389465c8d7e04c2a431a57fb7c0e5a5924c25ae:codex-rs/core/src/models_manager/model_family.rs
  • sed -n '1,240p' codex-rs/core/src/client_common.rs
  • git show 3389465c8d7e04c2a431a57fb7c0e5a5924c25ae:codex-rs/core/src/client_common.rs
  • sed -n '1,260p' codex-rs/core/src/client.rs
  • git show 3389465c8d7e04c2a431a57fb7c0e5a5924c25ae:codex-rs/core/src/client.rs | sed -n '1,260p'
  • rg -n "auto_compact" codex-rs/core/src/codex.rs
  • sed -n '2320,2410p' codex-rs/core/src/codex.rs
  • git show 3389465c8d7e04c2a431a57fb7c0e5a5924c25ae:codex-rs/core/src/codex.rs | sed -n '2320,2410p'
  • rg -n "struct ModelInfo" -n codex-rs/protocol/src/openai_models.rs
  • sed -n '160,260p' codex-rs/protocol/src/openai_models.rs

View task →

@aibrahim-oai
Copy link
Collaborator Author

@codex list differences in behavior between declarative model info and previous model family

@chatgpt-codex-connector

This comment was marked as outdated.

@aibrahim-oai
Copy link
Collaborator Author

@codex list differences in behavior between declarative model info and previous model family

@chatgpt-codex-connector

This comment was marked as outdated.

@aibrahim-oai
Copy link
Collaborator Author

@codex list differences in behavior between declarative model info and previous model family

@chatgpt-codex-connector

This comment was marked as outdated.

@aibrahim-oai
Copy link
Collaborator Author

@codex list differences in behavior between declarative model info and previous model family

@chatgpt-codex-connector
Copy link
Contributor

Below are the behavioral differences I can confirm between the new declarative ModelInfo flow and the previous ModelFamily flow, with precise locations and references.


1) Apply‑patch instructions are no longer conditionally appended

Before (ModelFamily):
Prompt::get_full_instructions appended APPLY_PATCH_TOOL_INSTRUCTIONS only when no base override, the model family required special instructions, and no apply_patch tool was present. That meant apply‑patch instructions were conditional on tool availability.

  • Source (base ref): codex-rs/core/src/client_common.rs【git show 3389465:codex-rs/core/src/client_common.rs】

Now (ModelInfo):
Prompt::get_full_instructions simply returns model.base_instructions (or override) with no conditional append. Models that need apply‑patch guidance now embed it by using BASE_INSTRUCTIONS_WITH_APPLY_PATCH in find_model_info_for_slug, so the text is always present when that base is selected.

  • Sources (current):
    • Prompt::get_full_instructions in codex-rs/core/src/client_common.rs【codex-rs/core/src/client_common.rs】
    • find_model_info_for_slug in codex-rs/core/src/models_manager/model_info.rs【codex-rs/core/src/models_manager/model_info.rs】

Impact: apply‑patch instructions are always present for those model entries now, even if the tool is available.


2) Remote model metadata is now “replace‑all” instead of “selective overlay”

Before (ModelFamily):
The manager built a local ModelFamily and then applied remote overrides. The override logic only updated selected fields and only replaced base_instructions when the remote value was Some(...).

  • Sources (base ref):
    • construct_model_family in codex-rs/core/src/models_manager/manager.rs【git show 3389465:codex-rs/core/src/models_manager/manager.rs】
    • ModelFamily::apply_remote_overrides in codex-rs/core/src/models_manager/model_family.rs【git show 3389465:codex-rs/core/src/models_manager/model_family.rs】

Now (ModelInfo):
construct_model_info uses the remote ModelInfo directly when available, otherwise falls back to the local find_model_info_for_slug. There’s no selective merge; the remote object is authoritative (only config overrides are applied afterward).

  • Source (current): construct_model_info in codex-rs/core/src/models_manager/manager.rs【codex-rs/core/src/models_manager/manager.rs】

Impact: Remote metadata now fully replaces local defaults instead of partially overlaying them.


3) Verbosity warning now reports model slug instead of family name

Before (ModelFamily):
When verbosity is configured but unsupported, the warning used the family name.

  • Source (base ref): stream_responses_api in codex-rs/core/src/client.rs【git show 3389465:codex-rs/core/src/client.rs】

Now (ModelInfo):
The warning uses the full model slug.

  • Source (current): stream_responses_api in codex-rs/core/src/client.rs【codex-rs/core/src/client.rs】

Impact: Log output changes (family → slug), which can affect log filtering/alerting.


4) Model info now always carries explicit reasoning‑preset metadata (affects presets/UI)

Now (ModelInfo):
ModelInfo includes supported_reasoning_levels plus an optional default_reasoning_level, and the conversion to ModelPreset uses these fields to compute supported efforts and defaults.

  • Source (current): codex-rs/protocol/src/openai_models.rs (ModelInfo + ModelPreset conversion)【codex-rs/protocol/src/openai_models.rs】

Before (ModelFamily):
ModelFamily had only default_reasoning_effort and no supported‑levels list, so available reasoning‑effort presets were not driven by a declarative list.

  • Source (base ref): codex-rs/core/src/models_manager/model_family.rs【git show 3389465:codex-rs/core/src/models_manager/model_family.rs】

Impact: Reasoning‑effort presets for UI/selection are now explicitly defined per model in metadata rather than inferred or absent.


Commands used

  • sed -n '1,220p' codex-rs/core/src/models_manager/model_info.rs
  • sed -n '220,520p' codex-rs/core/src/models_manager/model_info.rs
  • sed -n '1,220p' codex-rs/core/src/client_common.rs
  • sed -n '1,260p' codex-rs/core/src/client.rs
  • sed -n '160,260p' codex-rs/protocol/src/openai_models.rs
  • git show 3389465c8d7e04c2a431a57fb7c0e5a5924c25ae:codex-rs/core/src/models_manager/model_family.rs | sed -n '1,260p'
  • git show 3389465c8d7e04c2a431a57fb7c0e5a5924c25ae:codex-rs/core/src/models_manager/model_family.rs | sed -n '360,430p'
  • git show 3389465c8d7e04c2a431a57fb7c0e5a5924c25ae:codex-rs/core/src/client_common.rs | sed -n '1,240p'
  • git show 3389465c8d7e04c2a431a57fb7c0e5a5924c25ae:codex-rs/core/src/client.rs | sed -n '1,260p'
  • git show 3389465c8d7e04c2a431a57fb7c0e5a5924c25ae:codex-rs/core/src/models_manager/manager.rs | sed -n '120,200p'
  • sed -n '120,200p' codex-rs/core/src/models_manager/manager.rs

If you want a model‑by‑model diff (e.g., o3, o4-mini, gpt-5.*, gpt-oss) between the old model_family! table and the new find_model_info_for_slug table, I can enumerate those too.

View task →

@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.

Reviewed commit: f9ea8021ac

ℹ️ 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 178 to 181
pub priority: i32,
pub upgrade: Option<String>,
pub base_instructions: Option<String>,
pub base_instructions: String,
pub supports_reasoning_summaries: bool,
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 Handle missing base_instructions in /models responses

This field was made mandatory with no serde default, so any older /models responses or cached models_cache.json entries that omit base_instructions or send it as null will now fail to deserialize, causing list_models to error and remote model metadata to be skipped. That’s a compatibility regression for clients talking to older backends or reading existing caches. Consider keeping it optional or adding a serde default/fallback so older payloads still load.

Useful? React with 👍 / 👎.

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.

5 participants