mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
## Why
First-party backends can supply turn-scoped moderation metadata that
app-server clients need for client-side presentation. Exposing this as
an experimental typed notification lets opted-in clients consume it
without interpreting raw Responses API events.
## What changed
- forward `response.metadata.openai_chatgpt_moderation_metadata` from
Responses API SSE and WebSocket streams as turn-scoped moderation
metadata
- emit the experimental app-server v2 `turn/moderationMetadata`
notification with `{ threadId, turnId, metadata }`
- add app-server integration coverage for the typed moderation metadata
notification
## Testing
- `just test -p codex-core
build_ws_client_metadata_includes_window_lineage_and_turn_metadata`
- `just test -p codex-core` (fails locally: 46 failures and 1 timeout,
primarily missing `test_stdio_server` and shell snapshot timeouts)
- `just test -p codex-app-server-protocol`
- `just test -p codex-app-server
turn_moderation_metadata_emits_typed_notification_v2`
- `just test -p codex-app-server` (fails locally: 792 passed, 10 failed,
and 5 timed out; failures are in existing environment-sensitive tests,
primarily because nested macOS `sandbox-exec` is not permitted)
- `just write-app-server-schema --experimental --schema-root
/tmp/codex-app-server-schema-experimental`
165 lines
5.3 KiB
Rust
165 lines
5.3 KiB
Rust
use super::shared::v2_enum_from_core;
|
|
use codex_protocol::openai_models::InputModality;
|
|
use codex_protocol::openai_models::ModelAvailabilityNux as CoreModelAvailabilityNux;
|
|
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 schemars::JsonSchema;
|
|
use serde::Deserialize;
|
|
use serde::Serialize;
|
|
use serde_json::Value as JsonValue;
|
|
use ts_rs::TS;
|
|
|
|
v2_enum_from_core!(
|
|
pub enum ModelRerouteReason from CoreModelRerouteReason {
|
|
HighRiskCyberActivity
|
|
}
|
|
);
|
|
|
|
v2_enum_from_core!(
|
|
pub enum ModelVerification from CoreModelVerification {
|
|
TrustedAccessForCyber
|
|
}
|
|
);
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default, JsonSchema, TS)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[ts(export_to = "v2/")]
|
|
pub struct ModelProviderCapabilitiesReadParams {}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[ts(export_to = "v2/")]
|
|
pub struct ModelProviderCapabilitiesReadResponse {
|
|
pub namespace_tools: bool,
|
|
pub image_generation: bool,
|
|
pub web_search: bool,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema, TS)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[ts(export_to = "v2/")]
|
|
pub struct ModelListParams {
|
|
/// Opaque pagination cursor returned by a previous call.
|
|
#[ts(optional = nullable)]
|
|
pub cursor: Option<String>,
|
|
/// Optional page size; defaults to a reasonable server-side value.
|
|
#[ts(optional = nullable)]
|
|
pub limit: Option<u32>,
|
|
/// When true, include models that are hidden from the default picker list.
|
|
#[ts(optional = nullable)]
|
|
pub include_hidden: Option<bool>,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[ts(export_to = "v2/")]
|
|
pub struct ModelAvailabilityNux {
|
|
pub message: String,
|
|
}
|
|
|
|
impl From<CoreModelAvailabilityNux> for ModelAvailabilityNux {
|
|
fn from(value: CoreModelAvailabilityNux) -> Self {
|
|
Self {
|
|
message: value.message,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[ts(export_to = "v2/")]
|
|
pub struct ModelServiceTier {
|
|
pub id: String,
|
|
pub name: String,
|
|
pub description: String,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[ts(export_to = "v2/")]
|
|
pub struct Model {
|
|
pub id: String,
|
|
pub model: String,
|
|
pub upgrade: Option<String>,
|
|
pub upgrade_info: Option<ModelUpgradeInfo>,
|
|
pub availability_nux: Option<ModelAvailabilityNux>,
|
|
pub display_name: String,
|
|
pub description: String,
|
|
pub hidden: bool,
|
|
pub supported_reasoning_efforts: Vec<ReasoningEffortOption>,
|
|
pub default_reasoning_effort: ReasoningEffort,
|
|
#[serde(default = "default_input_modalities")]
|
|
pub input_modalities: Vec<InputModality>,
|
|
#[serde(default)]
|
|
pub supports_personality: bool,
|
|
/// Deprecated: use `serviceTiers` instead.
|
|
#[serde(default)]
|
|
pub additional_speed_tiers: Vec<String>,
|
|
#[serde(default)]
|
|
pub service_tiers: Vec<ModelServiceTier>,
|
|
/// Catalog default service tier id for this model, when one is configured.
|
|
#[serde(default)]
|
|
pub default_service_tier: Option<String>,
|
|
// Only one model should be marked as default.
|
|
pub is_default: bool,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[ts(export_to = "v2/")]
|
|
pub struct ModelUpgradeInfo {
|
|
pub model: String,
|
|
pub upgrade_copy: Option<String>,
|
|
pub model_link: Option<String>,
|
|
pub migration_markdown: Option<String>,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[ts(export_to = "v2/")]
|
|
pub struct ReasoningEffortOption {
|
|
pub reasoning_effort: ReasoningEffort,
|
|
pub description: String,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[ts(export_to = "v2/")]
|
|
pub struct ModelListResponse {
|
|
pub data: Vec<Model>,
|
|
/// Opaque cursor to pass to the next call to continue after the last item.
|
|
/// If None, there are no more items to return.
|
|
pub next_cursor: Option<String>,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[ts(export_to = "v2/")]
|
|
pub struct ModelReroutedNotification {
|
|
pub thread_id: String,
|
|
pub turn_id: String,
|
|
pub from_model: String,
|
|
pub to_model: String,
|
|
pub reason: ModelRerouteReason,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[ts(export_to = "v2/")]
|
|
pub struct ModelVerificationNotification {
|
|
pub thread_id: String,
|
|
pub turn_id: String,
|
|
pub verifications: Vec<ModelVerification>,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[ts(export_to = "v2/")]
|
|
pub struct TurnModerationMetadataNotification {
|
|
pub thread_id: String,
|
|
pub turn_id: String,
|
|
pub metadata: JsonValue,
|
|
}
|