Use shared service tier type in app-server protocol

This commit is contained in:
Ahmed Ibrahim
2026-05-03 07:24:43 +03:00
parent 405339b5d0
commit 6aaeebcecd
11 changed files with 38 additions and 125 deletions
@@ -11323,7 +11323,7 @@
"type": "string"
},
"id": {
"$ref": "#/definitions/v2/ServiceTierId"
"$ref": "#/definitions/v2/ServiceTier"
},
"name": {
"type": "string"
@@ -14258,13 +14258,7 @@
"type": "object"
},
"ServiceTier": {
"enum": [
"fast",
"flex"
],
"type": "string"
},
"ServiceTierId": {
"description": "String-backed service tier identifier. Known values include `priority` and `flex`, but other backend-provided ids are allowed.",
"type": "string"
},
"SessionMigration": {
@@ -7976,7 +7976,7 @@
"type": "string"
},
"id": {
"$ref": "#/definitions/ServiceTierId"
"$ref": "#/definitions/ServiceTier"
},
"name": {
"type": "string"
@@ -12144,13 +12144,7 @@
"type": "object"
},
"ServiceTier": {
"enum": [
"fast",
"flex"
],
"type": "string"
},
"ServiceTierId": {
"description": "String-backed service tier identifier. Known values include `priority` and `flex`, but other backend-provided ids are allowed.",
"type": "string"
},
"SessionMigration": {
@@ -135,7 +135,7 @@
"type": "string"
},
"id": {
"$ref": "#/definitions/ServiceTierId"
"$ref": "#/definitions/ServiceTier"
},
"name": {
"type": "string"
@@ -204,7 +204,8 @@
],
"type": "object"
},
"ServiceTierId": {
"ServiceTier": {
"description": "String-backed service tier identifier. Known values include `priority` and `flex`, but other backend-provided ids are allowed.",
"type": "string"
}
},
@@ -2,4 +2,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type ServiceTier = "fast" | "flex";
export type ServiceTier = string;
@@ -1,6 +1,6 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ServiceTierId } from "./ServiceTierId";
import type { ServiceTier } from "../ServiceTier";
export type ModelServiceTier = { id: ServiceTierId, name: string, description: string, };
export type ModelServiceTier = { id: ServiceTier, name: string, description: string, };
@@ -1,5 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type ServiceTierId = string;
@@ -242,7 +242,6 @@ export type { ModelAvailabilityNux } from "./ModelAvailabilityNux";
export type { ModelListParams } from "./ModelListParams";
export type { ModelListResponse } from "./ModelListResponse";
export type { ModelServiceTier } from "./ModelServiceTier";
export type { ServiceTierId } from "./ServiceTierId";
export type { ModelProviderCapabilitiesReadParams } from "./ModelProviderCapabilitiesReadParams";
export type { ModelProviderCapabilitiesReadResponse } from "./ModelProviderCapabilitiesReadResponse";
export type { ModelRerouteReason } from "./ModelRerouteReason";
@@ -25,10 +25,8 @@ use codex_protocol::config_types::ForcedLoginMethod;
use codex_protocol::config_types::ModeKind;
use codex_protocol::config_types::Personality;
use codex_protocol::config_types::ReasoningSummary;
use codex_protocol::config_types::SERVICE_TIER_FLEX;
use codex_protocol::config_types::SERVICE_TIER_PRIORITY;
use codex_protocol::config_types::SandboxMode as CoreSandboxMode;
use codex_protocol::config_types::ServiceTier as CoreServiceTier;
pub use codex_protocol::config_types::ServiceTier;
use codex_protocol::config_types::Verbosity;
use codex_protocol::config_types::WebSearchMode;
use codex_protocol::config_types::WebSearchToolConfig;
@@ -124,60 +122,6 @@ use serde_with::serde_as;
use thiserror::Error;
use ts_rs::TS;
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "lowercase")]
#[ts(export)]
pub enum ServiceTier {
Fast,
Flex,
}
impl From<ServiceTier> for CoreServiceTier {
fn from(value: ServiceTier) -> Self {
match value {
ServiceTier::Fast => SERVICE_TIER_PRIORITY.into(),
ServiceTier::Flex => SERVICE_TIER_FLEX.into(),
}
}
}
impl TryFrom<&CoreServiceTier> for ServiceTier {
type Error = ();
fn try_from(value: &CoreServiceTier) -> Result<Self, Self::Error> {
if value.as_ref() == SERVICE_TIER_PRIORITY {
Ok(ServiceTier::Fast)
} else if value.as_ref() == SERVICE_TIER_FLEX {
Ok(ServiceTier::Flex)
} else {
Err(())
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(transparent)]
#[ts(type = "string", export_to = "v2/")]
pub struct ServiceTierId(pub String);
impl From<ServiceTierId> for CoreServiceTier {
fn from(value: ServiceTierId) -> Self {
Self::from(value.0)
}
}
impl From<CoreServiceTier> for ServiceTierId {
fn from(value: CoreServiceTier) -> Self {
Self(value.to_string())
}
}
impl From<&CoreServiceTier> for ServiceTierId {
fn from(value: &CoreServiceTier) -> Self {
Self(value.to_string())
}
}
// Macro to declare a camelCased API v2 enum mirroring a core enum which
// tends to use either snake_case or kebab-case.
macro_rules! v2_enum_from_core {
@@ -2570,7 +2514,7 @@ impl From<CoreModelAvailabilityNux> for ModelAvailabilityNux {
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct ModelServiceTier {
pub id: ServiceTierId,
pub id: ServiceTier,
pub name: String,
pub description: String,
}
@@ -2578,7 +2522,7 @@ pub struct ModelServiceTier {
impl From<CoreModelServiceTier> for ModelServiceTier {
fn from(value: CoreModelServiceTier) -> Self {
Self {
id: value.id.into(),
id: value.id,
name: value.name,
description: value.description,
}
@@ -2588,7 +2532,7 @@ impl From<CoreModelServiceTier> for ModelServiceTier {
impl From<ModelServiceTier> for CoreModelServiceTier {
fn from(value: ModelServiceTier) -> Self {
Self {
id: value.id.into(),
id: value.id,
name: value.name,
description: value.description,
}
@@ -340,7 +340,6 @@ use codex_protocol::ThreadId;
use codex_protocol::config_types::CollaborationMode;
use codex_protocol::config_types::ForcedLoginMethod;
use codex_protocol::config_types::Personality;
use codex_protocol::config_types::ServiceTier as CoreServiceTier;
use codex_protocol::config_types::TrustLevel;
use codex_protocol::config_types::WindowsSandboxLevel;
use codex_protocol::dynamic_tools::DynamicToolSpec as CoreDynamicToolSpec;
@@ -2921,10 +2920,7 @@ impl CodexMessageProcessor {
thread: thread.clone(),
model: config_snapshot.model,
model_provider: config_snapshot.model_provider_id,
service_tier: config_snapshot
.service_tier
.as_ref()
.and_then(|service_tier| ServiceTier::try_from(service_tier).ok()),
service_tier: config_snapshot.service_tier,
cwd: config_snapshot.cwd,
instruction_sources,
approval_policy: config_snapshot.approval_policy.into(),
@@ -2972,7 +2968,7 @@ impl CodexMessageProcessor {
&self,
model: Option<String>,
model_provider: Option<String>,
service_tier: Option<Option<codex_protocol::config_types::ServiceTier>>,
service_tier: Option<Option<ServiceTier>>,
cwd: Option<String>,
approval_policy: Option<codex_app_server_protocol::AskForApproval>,
approvals_reviewer: Option<codex_app_server_protocol::ApprovalsReviewer>,
@@ -3026,8 +3022,8 @@ impl CodexMessageProcessor {
fn resolve_service_tier_override(
service_tier: Option<Option<ServiceTier>>,
) -> Option<Option<CoreServiceTier>> {
service_tier.map(|service_tier| service_tier.map(Into::into))
) -> Option<Option<ServiceTier>> {
service_tier
}
async fn thread_archive(&self, request_id: ConnectionRequestId, params: ThreadArchiveParams) {
@@ -4510,10 +4506,7 @@ impl CodexMessageProcessor {
thread,
model: session_configured.model,
model_provider: session_configured.model_provider_id,
service_tier: session_configured
.service_tier
.as_ref()
.and_then(|service_tier| ServiceTier::try_from(service_tier).ok()),
service_tier: session_configured.service_tier,
cwd: session_configured.cwd,
instruction_sources,
approval_policy: session_configured.approval_policy.into(),
@@ -5148,10 +5141,7 @@ impl CodexMessageProcessor {
thread: thread.clone(),
model: session_configured.model,
model_provider: session_configured.model_provider_id,
service_tier: session_configured
.service_tier
.as_ref()
.and_then(|service_tier| ServiceTier::try_from(service_tier).ok()),
service_tier: session_configured.service_tier,
cwd: session_configured.cwd,
instruction_sources,
approval_policy: session_configured.approval_policy.into(),
@@ -8509,9 +8499,7 @@ async fn handle_pending_thread_resume_request(
thread,
model,
model_provider: model_provider_id,
service_tier: service_tier
.as_ref()
.and_then(|service_tier| ServiceTier::try_from(service_tier).ok()),
service_tier,
cwd,
instruction_sources,
approval_policy: approval_policy.into(),
@@ -8681,15 +8669,11 @@ fn collect_resume_override_mismatches(
));
}
if let Some(requested_service_tier) = request.service_tier.as_ref()
&& requested_service_tier.map(CoreServiceTier::from).as_ref()
!= config_snapshot.service_tier.as_ref()
&& requested_service_tier != &config_snapshot.service_tier
{
let active_service_tier = config_snapshot
.service_tier
.as_ref()
.and_then(|service_tier| ServiceTier::try_from(service_tier).ok());
mismatch_details.push(format!(
"service_tier requested={requested_service_tier:?} active={active_service_tier:?}"
"service_tier requested={requested_service_tier:?} active={:?}",
config_snapshot.service_tier
));
}
if let Some(requested_cwd) = request.cwd.as_deref() {
@@ -10545,6 +10529,8 @@ mod tests {
#[test]
fn collect_resume_override_mismatches_includes_service_tier() {
use codex_protocol::config_types::SERVICE_TIER_PRIORITY;
let cwd = test_path_buf("/tmp").abs();
let request = ThreadResumeParams {
thread_id: "thread-1".to_string(),
@@ -10552,7 +10538,7 @@ mod tests {
path: None,
model: None,
model_provider: None,
service_tier: Some(Some(ServiceTier::Fast)),
service_tier: Some(Some(SERVICE_TIER_PRIORITY.into())),
cwd: None,
approval_policy: None,
approvals_reviewer: None,
@@ -14,7 +14,6 @@ use codex_app_server_protocol::McpServerStatusUpdatedNotification;
use codex_app_server_protocol::RequestId;
use codex_app_server_protocol::SandboxMode;
use codex_app_server_protocol::ServerNotification;
use codex_app_server_protocol::ServiceTier;
use codex_app_server_protocol::ThreadStartParams;
use codex_app_server_protocol::ThreadStartResponse;
use codex_app_server_protocol::ThreadStartedNotification;
@@ -27,6 +26,7 @@ use codex_core::config::set_project_trust_level;
use codex_exec_server::LOCAL_FS;
use codex_git_utils::resolve_root_git_project_for_trust;
use codex_login::REFRESH_TOKEN_URL_OVERRIDE_ENV_VAR;
use codex_protocol::config_types::SERVICE_TIER_FLEX;
use codex_protocol::config_types::TrustLevel;
use codex_protocol::openai_models::ReasoningEffort;
use pretty_assertions::assert_eq;
@@ -340,7 +340,7 @@ async fn thread_start_accepts_flex_service_tier() -> Result<()> {
let req_id = mcp
.send_thread_start_request(ThreadStartParams {
service_tier: Some(Some(ServiceTier::Flex)),
service_tier: Some(Some(SERVICE_TIER_FLEX.into())),
..Default::default()
})
.await?;
@@ -352,7 +352,7 @@ async fn thread_start_accepts_flex_service_tier() -> Result<()> {
.await??;
let ThreadStartResponse { service_tier, .. } = to_response::<ThreadStartResponse>(resp)?;
assert_eq!(service_tier, Some(ServiceTier::Flex));
assert_eq!(service_tier, Some(SERVICE_TIER_FLEX.into()));
Ok(())
}
@@ -3519,16 +3519,16 @@ class ServerRequestResolvedNotification(BaseModel):
thread_id: Annotated[str, Field(alias="threadId")]
class ServiceTier(Enum):
fast = "fast"
flex = "flex"
class ServiceTierId(RootModel[str]):
class ServiceTier(RootModel[str]):
model_config = ConfigDict(
populate_by_name=True,
)
root: str
root: Annotated[
str,
Field(
description="String-backed service tier identifier. Known values include `priority` and `flex`, but other backend-provided ids are allowed."
),
]
class SessionMigration(BaseModel):
@@ -6326,7 +6326,7 @@ class ModelServiceTier(BaseModel):
populate_by_name=True,
)
description: str
id: ServiceTierId
id: ServiceTier
name: str