Skip to content

Commit ed7aa15

Browse files
committed
Honor client-resolved service tier defaults
1 parent 5a4202a commit ed7aa15

50 files changed

Lines changed: 624 additions & 150 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codex-rs/app-server-protocol/schema/json/v2/ModelListResponse.json

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codex-rs/app-server-protocol/schema/typescript/v2/Model.ts

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codex-rs/app-server-protocol/src/protocol/v2/model.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ pub struct Model {
9898
pub additional_speed_tiers: Vec<String>,
9999
#[serde(default)]
100100
pub service_tiers: Vec<ModelServiceTier>,
101+
/// Catalog default service tier id for this model, when one is configured.
102+
#[serde(default)]
103+
pub default_service_tier: Option<String>,
101104
// Only one model should be marked as default.
102105
pub is_default: bool,
103106
}

codex-rs/app-server/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ Example with notification opt-out:
186186
- `fs/watch` — subscribe this connection to filesystem change notifications for an absolute file or directory path and caller-provided `watchId`; returns the canonicalized `path`.
187187
- `fs/unwatch` — stop sending notifications for a prior `fs/watch`; returns `{}`.
188188
- `fs/changed` — notification emitted when watched paths change, including the `watchId` and `changedPaths`.
189-
- `model/list` — list available models (set `includeHidden: true` to include entries with `hidden: true`), with reasoning effort options, `additionalSpeedTiers`, optional legacy `upgrade` model ids, optional `upgradeInfo` metadata (`model`, `upgradeCopy`, `modelLink`, `migrationMarkdown`), and optional `availabilityNux` metadata.
189+
- `model/list` — list available models (set `includeHidden: true` to include entries with `hidden: true`), with reasoning effort options, `additionalSpeedTiers`, `serviceTiers`, optional `defaultServiceTier`, optional legacy `upgrade` model ids, optional `upgradeInfo` metadata (`model`, `upgradeCopy`, `modelLink`, `migrationMarkdown`), and optional `availabilityNux` metadata.
190190
- `modelProvider/capabilities/read` — read provider-level capabilities for the currently configured model provider.
191191
- `experimentalFeature/list` — list feature flags with stage metadata (`beta`, `underDevelopment`, `stable`, etc.), enabled/default-enabled state, and cursor pagination. Pass `threadId` when showing feature state for an existing loaded thread so `enabled` is computed from that thread's refreshed config, including project-local config for the thread's cwd; if omitted, the server uses its default config resolution context. For non-beta flags, `displayName`/`description`/`announcement` are `null`.
192192
- `permissionProfile/list` — beta; list available permission profile ids with optional display `description` text, using cursor pagination. Pass `cwd` when the caller needs project-local `[permissions.<id>]` entries to be included in the current catalog view.

codex-rs/app-server/src/models.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ fn model_from_preset(preset: ModelPreset) -> Model {
5353
description: service_tier.description,
5454
})
5555
.collect(),
56+
default_service_tier: preset.default_service_tier,
5657
is_default: preset.is_default,
5758
}
5859
}

codex-rs/app-server/tests/common/models_cache.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ fn preset_to_info(preset: &ModelPreset, priority: i32) -> ModelInfo {
3030
priority,
3131
additional_speed_tiers: preset.additional_speed_tiers.clone(),
3232
service_tiers: preset.service_tiers.clone(),
33+
default_service_tier: preset.default_service_tier.clone(),
3334
upgrade: preset.upgrade.as_ref().map(Into::into),
3435
base_instructions: "base instructions".to_string(),
3536
model_messages: None,

codex-rs/app-server/tests/suite/v2/model_list.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ fn model_from_preset(preset: &ModelPreset) -> Model {
6969
description: service_tier.description.clone(),
7070
})
7171
.collect(),
72+
default_service_tier: preset.default_service_tier.clone(),
7273
is_default: preset.is_default,
7374
}
7475
}

codex-rs/app-server/tests/suite/v2/thread_start.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use codex_core::config::set_project_trust_level;
2828
use codex_exec_server::LOCAL_FS;
2929
use codex_git_utils::resolve_root_git_project_for_trust;
3030
use codex_login::REFRESH_TOKEN_URL_OVERRIDE_ENV_VAR;
31+
use codex_protocol::config_types::ServiceTier;
3132
use codex_protocol::config_types::TrustLevel;
3233
use codex_protocol::openai_models::ReasoningEffort;
3334
use pretty_assertions::assert_eq;
@@ -484,7 +485,7 @@ model_reasoning_effort = "high"
484485
}
485486

486487
#[tokio::test]
487-
async fn thread_start_accepts_arbitrary_service_tier_id() -> Result<()> {
488+
async fn thread_start_drops_unsupported_service_tier_id() -> Result<()> {
488489
let server = create_mock_responses_server_repeating_assistant("Done").await;
489490

490491
let codex_home = TempDir::new()?;
@@ -508,7 +509,39 @@ async fn thread_start_accepts_arbitrary_service_tier_id() -> Result<()> {
508509
.await??;
509510
let ThreadStartResponse { service_tier, .. } = to_response::<ThreadStartResponse>(resp)?;
510511

511-
assert_eq!(service_tier, Some(service_tier_id));
512+
// Unsupported catalog ids are dropped at session config time instead of echoed back.
513+
assert_eq!(service_tier, None);
514+
Ok(())
515+
}
516+
517+
#[tokio::test]
518+
async fn thread_start_accepts_default_service_tier() -> Result<()> {
519+
let server = create_mock_responses_server_repeating_assistant("Done").await;
520+
521+
let codex_home = TempDir::new()?;
522+
create_config_toml_without_approval_policy(codex_home.path(), &server.uri())?;
523+
524+
let mut mcp = McpProcess::new(codex_home.path()).await?;
525+
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
526+
527+
let req_id = mcp
528+
.send_thread_start_request(ThreadStartParams {
529+
service_tier: Some(Some(ServiceTier::Default.request_value().to_string())),
530+
..Default::default()
531+
})
532+
.await?;
533+
534+
let resp: JSONRPCResponse = timeout(
535+
DEFAULT_READ_TIMEOUT,
536+
mcp.read_stream_until_response_message(RequestId::Integer(req_id)),
537+
)
538+
.await??;
539+
let ThreadStartResponse { service_tier, .. } = to_response::<ThreadStartResponse>(resp)?;
540+
541+
assert_eq!(
542+
service_tier,
543+
Some(ServiceTier::Default.request_value().to_string())
544+
);
512545
Ok(())
513546
}
514547

0 commit comments

Comments
 (0)