Expose multi-agent versions in model/list (#37433)

## What changed

- Add nullable `multiAgentVersion` metadata to v2 `model/list` responses.
- Represent supported values as `disabled`, `v1`, or `v2` in the Rust API and generated JSON Schema and TypeScript exports.
- Forward the value from model catalog presets through app-server responses.

## Testing

- Extend the remote model catalog test fixture with a `v2` multi-agent version.

GitOrigin-RevId: bd3b2bbe0a3b562b4d1f03df7da2a73a35713978
This commit is contained in:
acrognale-oai
2026-08-07 11:19:57 +00:00
committed by copyberry
parent 85e0661c3b
commit 51e36d2ec2
13 changed files with 91 additions and 2 deletions

View File

@@ -13590,6 +13590,17 @@
"null"
]
},
"multiAgentVersion": {
"anyOf": [
{
"$ref": "#/definitions/v2/MultiAgentVersion"
},
{
"type": "null"
}
],
"description": "Multi-agent runtime declared by this model, when available."
},
"serviceTiers": {
"default": [],
"items": {
@@ -13924,6 +13935,15 @@
}
]
},
"MultiAgentVersion": {
"description": "Multi-agent runtime supported by a model.",
"enum": [
"disabled",
"v1",
"v2"
],
"type": "string"
},
"NetworkAccess": {
"enum": [
"restricted",

View File

@@ -9927,6 +9927,17 @@
"null"
]
},
"multiAgentVersion": {
"anyOf": [
{
"$ref": "#/definitions/MultiAgentVersion"
},
{
"type": "null"
}
],
"description": "Multi-agent runtime declared by this model, when available."
},
"serviceTiers": {
"default": [],
"items": {
@@ -10261,6 +10272,15 @@
}
]
},
"MultiAgentVersion": {
"description": "Multi-agent runtime supported by a model.",
"enum": [
"disabled",
"v1",
"v2"
],
"type": "string"
},
"NetworkAccess": {
"enum": [
"restricted",

View File

@@ -93,6 +93,17 @@
"null"
]
},
"multiAgentVersion": {
"anyOf": [
{
"$ref": "#/definitions/MultiAgentVersion"
},
{
"type": "null"
}
],
"description": "Multi-agent runtime declared by this model, when available."
},
"serviceTiers": {
"default": [],
"items": {
@@ -198,6 +209,15 @@
],
"type": "object"
},
"MultiAgentVersion": {
"description": "Multi-agent runtime supported by a model.",
"enum": [
"disabled",
"v1",
"v2"
],
"type": "string"
},
"ReasoningEffort": {
"description": "A non-empty reasoning effort value advertised by the model.",
"minLength": 1,

View File

@@ -6,9 +6,14 @@ import type { ReasoningEffort } from "../ReasoningEffort";
import type { ModelAvailabilityNux } from "./ModelAvailabilityNux";
import type { ModelServiceTier } from "./ModelServiceTier";
import type { ModelUpgradeInfo } from "./ModelUpgradeInfo";
import type { MultiAgentVersion } from "./MultiAgentVersion";
import type { ReasoningEffortOption } from "./ReasoningEffortOption";
export type Model = { id: string, model: string, upgrade: string | null, upgradeInfo: ModelUpgradeInfo | null, availabilityNux: ModelAvailabilityNux | null, displayName: string, description: string, modelSpecialty: string | null, hidden: boolean, supportedReasoningEfforts: Array<ReasoningEffortOption>, defaultReasoningEffort: ReasoningEffort, inputModalities: Array<InputModality>, supportsPersonality: boolean,
/**
* Multi-agent runtime declared by this model, when available.
*/
multiAgentVersion: MultiAgentVersion | null,
/**
* Deprecated: use `serviceTiers` instead.
*/

View File

@@ -0,0 +1,8 @@
// 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.
/**
* Multi-agent runtime supported by a model.
*/
export type MultiAgentVersion = "disabled" | "v1" | "v2";

View File

@@ -288,6 +288,7 @@ export type { ModelUpgradeInfo } from "./ModelUpgradeInfo";
export type { ModelVerification } from "./ModelVerification";
export type { ModelVerificationNotification } from "./ModelVerificationNotification";
export type { ModelsRequirements } from "./ModelsRequirements";
export type { MultiAgentVersion } from "./MultiAgentVersion";
export type { NetworkAccess } from "./NetworkAccess";
export type { NetworkApprovalContext } from "./NetworkApprovalContext";
export type { NetworkApprovalProtocol } from "./NetworkApprovalProtocol";

View File

@@ -7,6 +7,7 @@ use codex_protocol::openai_models::ReasoningEffort;
use codex_protocol::openai_models::default_input_modalities;
use codex_protocol::protocol::ModelRerouteReason as CoreModelRerouteReason;
use codex_protocol::protocol::ModelVerification as CoreModelVerification;
use codex_protocol::protocol::MultiAgentVersion as CoreMultiAgentVersion;
use serde::Deserialize;
use serde::Serialize;
use serde_json::Value as JsonValue;
@@ -23,6 +24,15 @@ v2_enum_from_core!(
}
);
v2_enum_from_core!(
/// Multi-agent runtime supported by a model.
pub enum MultiAgentVersion from CoreMultiAgentVersion {
Disabled,
V1,
V2
}
);
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
@@ -96,6 +106,8 @@ pub struct Model {
pub input_modalities: Vec<InputModality>,
#[serde(default)]
pub supports_personality: bool,
/// Multi-agent runtime declared by this model, when available.
pub multi_agent_version: Option<MultiAgentVersion>,
/// Deprecated: use `serviceTiers` instead.
#[serde(default)]
pub additional_speed_tiers: Vec<String>,

View File

@@ -228,7 +228,7 @@ Example with notification opt-out:
- `fs/watch` — subscribe this connection to filesystem change notifications for an absolute file or directory path and caller-provided `watchId`; returns the canonicalized `path`.
- `fs/unwatch` — stop sending notifications for a prior `fs/watch`; returns `{}`.
- `fs/changed` — notification emitted when watched paths change, including the `watchId` and `changedPaths`.
- `model/list` — list available models (set `includeHidden: true` to include entries with `hidden: true`), with model-advertised string reasoning effort options in the catalog's intended progression order, optional `modelSpecialty`, `additionalSpeedTiers`, `serviceTiers`, optional `defaultServiceTier`, optional legacy `upgrade` model ids, optional `upgradeInfo` metadata (`model`, `upgradeCopy`, `modelLink`, `migrationMarkdown`), and optional `availabilityNux` metadata. Clients should preserve the `supportedReasoningEfforts` array order rather than deriving order from the effort names.
- `model/list` — list available models (set `includeHidden: true` to include entries with `hidden: true`), with model-advertised string reasoning effort options in the catalog's intended progression order, optional `modelSpecialty`, nullable `multiAgentVersion` (`disabled`, `v1`, or `v2`), `additionalSpeedTiers`, `serviceTiers`, optional `defaultServiceTier`, optional legacy `upgrade` model ids, optional `upgradeInfo` metadata (`model`, `upgradeCopy`, `modelLink`, `migrationMarkdown`), and optional `availabilityNux` metadata. Clients should preserve the `supportedReasoningEfforts` array order rather than deriving order from the effort names.
- `modelProvider/capabilities/read` — read provider-level capabilities for the currently configured model provider.
- `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`.
- `permissionProfile/list` — beta; list available permission profile ids with optional display `description` text and an `allowed` flag reflecting effective requirements, using cursor pagination. Pass `cwd` when the caller needs project-local `[permissions.<id>]` entries to be included in the current catalog view.

View File

@@ -46,6 +46,7 @@ fn model_from_preset(preset: ModelPreset) -> Model {
default_reasoning_effort: preset.default_reasoning_effort,
input_modalities: preset.input_modalities,
supports_personality: preset.supports_personality,
multi_agent_version: preset.multi_agent_version.map(Into::into),
additional_speed_tiers: preset.additional_speed_tiers,
service_tiers: preset
.service_tiers

View File

@@ -68,7 +68,7 @@ fn preset_to_info(preset: &ModelPreset, priority: i32) -> ModelInfo {
auto_review_model_override: None,
model_specialty: None,
tool_mode: None,
multi_agent_version: None,
multi_agent_version: preset.multi_agent_version,
}
}

View File

@@ -61,6 +61,7 @@ fn model_from_preset(preset: &ModelPreset) -> Model {
// cache report `supports_personality = false`.
// todo(sayan): fix, maybe make roundtrip use ModelInfo only
supports_personality: false,
multi_agent_version: preset.multi_agent_version.map(Into::into),
additional_speed_tiers: preset.additional_speed_tiers.clone(),
service_tiers: preset
.service_tiers
@@ -177,6 +178,7 @@ async fn list_models_uses_chatgpt_remote_catalog_as_source_of_truth() -> Result<
"truncation_policy": {"mode": "bytes", "limit": 10_000},
"supports_parallel_tool_calls": false,
"supports_image_detail_original": false,
"multi_agent_version": "v2",
"context_window": 272_000,
"max_context_window": 272_000,
"experimental_supported_tools": [],