Codex Handbook
app-server-protocol/src/protocol/v2/thread.rs 1412 lines
use super::ActivePermissionProfile;use super::ApprovalsReviewer;use super::AskForApproval;use super::SandboxMode;use super::SandboxPolicy;use super::Thread;use super::ThreadItem;use super::ThreadSource;use super::Turn;use super::TurnEnvironmentParams;use super::TurnItemsView;use super::shared::v2_enum_from_core;use codex_experimental_api_macros::ExperimentalApi;pub use codex_protocol::capabilities::CapabilityRootLocation;pub use codex_protocol::capabilities::SelectedCapabilityRoot;use codex_protocol::config_types::CollaborationMode;use codex_protocol::config_types::Personality;use codex_protocol::config_types::ReasoningSummary;pub use codex_protocol::dynamic_tools::DynamicToolFunctionSpec;pub use codex_protocol::dynamic_tools::DynamicToolNamespaceSpec;pub use codex_protocol::dynamic_tools::DynamicToolNamespaceTool;pub use codex_protocol::dynamic_tools::DynamicToolSpec;use codex_protocol::models::ResponseItem;use codex_protocol::openai_models::ReasoningEffort;use codex_protocol::protocol::ThreadGoalStatus as CoreThreadGoalStatus;use codex_protocol::protocol::TokenUsage as CoreTokenUsage;use codex_protocol::protocol::TokenUsageInfo as CoreTokenUsageInfo;use codex_utils_absolute_path::AbsolutePathBuf;use schemars::JsonSchema;use serde::Deserialize;use serde::Serialize;use serde_json::Value as JsonValue;use std::collections::HashMap;use std::path::PathBuf;use ts_rs::TS;#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(rename_all = "camelCase", export_to = "v2/")]pub enum ThreadStartSource {    Startup,    Clear,}// === Threads, Turns, and Items ===// Thread APIs#[derive(    Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema, TS, ExperimentalApi,)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadStartParams {    #[ts(optional = nullable)]    pub model: Option<String>,    #[ts(optional = nullable)]    pub model_provider: Option<String>,    #[serde(        default,        deserialize_with = "crate::protocol::serde_helpers::deserialize_double_option",        serialize_with = "crate::protocol::serde_helpers::serialize_double_option",        skip_serializing_if = "Option::is_none"    )]    #[ts(optional = nullable)]    pub service_tier: Option<Option<String>>,    #[ts(optional = nullable)]    pub cwd: Option<String>,    /// Replace the thread's runtime workspace roots. Paths must be absolute.    #[experimental("thread/start.runtimeWorkspaceRoots")]    #[ts(optional = nullable)]    pub runtime_workspace_roots: Option<Vec<AbsolutePathBuf>>,    #[experimental(nested)]    #[ts(optional = nullable)]    pub approval_policy: Option<AskForApproval>,    /// Override where approval requests are routed for review on this thread    /// and subsequent turns.    #[ts(optional = nullable)]    pub approvals_reviewer: Option<ApprovalsReviewer>,    #[ts(optional = nullable)]    pub sandbox: Option<SandboxMode>,    /// Named profile id for this thread. Cannot be combined with `sandbox`.    #[experimental("thread/start.permissions")]    #[ts(optional = nullable)]    pub permissions: Option<String>,    #[ts(optional = nullable)]    pub config: Option<HashMap<String, JsonValue>>,    #[ts(optional = nullable)]    pub service_name: Option<String>,    #[ts(optional = nullable)]    pub base_instructions: Option<String>,    #[ts(optional = nullable)]    pub developer_instructions: Option<String>,    #[ts(optional = nullable)]    pub personality: Option<Personality>,    #[ts(optional = nullable)]    pub ephemeral: Option<bool>,    #[ts(optional = nullable)]    pub session_start_source: Option<ThreadStartSource>,    /// Optional client-supplied analytics source classification for this thread.    #[ts(optional = nullable)]    pub thread_source: Option<ThreadSource>,    /// Optional sticky environments for this thread.    ///    /// Omitted selects the default environment when environment access is    /// enabled. Empty disables environment access for turns that do not    /// provide a turn override. Non-empty selects the first environment as the    /// current turn environment.    #[experimental("thread/start.environments")]    #[ts(optional = nullable)]    pub environments: Option<Vec<TurnEnvironmentParams>>,    #[experimental("thread/start.dynamicTools")]    #[serde(        default,        deserialize_with = "codex_protocol::dynamic_tools::deserialize_dynamic_tool_specs"    )]    #[ts(optional = nullable)]    pub dynamic_tools: Option<Vec<DynamicToolSpec>>,    /// Capability roots selected for this thread by the hosting platform.    #[experimental("thread/start.selectedCapabilityRoots")]    #[ts(optional = nullable)]    pub selected_capability_roots: Option<Vec<SelectedCapabilityRoot>>,    /// Test-only experimental field used to validate experimental gating and    /// schema filtering behavior in a stable way.    #[experimental("thread/start.mockExperimentalField")]    #[ts(optional = nullable)]    pub mock_experimental_field: Option<String>,    /// If true, opt into emitting raw Responses API items on the event stream.    /// This is for internal use only (e.g. Codex Cloud).    #[experimental("thread/start.experimentalRawEvents")]    #[serde(default, skip_serializing_if = "std::ops::Not::not")]    pub experimental_raw_events: bool,}#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct MockExperimentalMethodParams {    /// Test-only payload field.    #[ts(optional = nullable)]    pub value: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct MockExperimentalMethodResponse {    /// Echoes the input `value`.    pub echoed: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS, ExperimentalApi)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadStartResponse {    pub thread: Thread,    pub model: String,    pub model_provider: String,    pub service_tier: Option<String>,    pub cwd: AbsolutePathBuf,    /// Thread-scoped runtime workspace roots used to materialize    /// `:workspace_roots`.    #[experimental("thread/start.runtimeWorkspaceRoots")]    #[serde(default)]    pub runtime_workspace_roots: Vec<AbsolutePathBuf>,    /// Instruction source files currently loaded for this thread.    #[serde(default)]    pub instruction_sources: Vec<AbsolutePathBuf>,    #[experimental(nested)]    pub approval_policy: AskForApproval,    /// Reviewer currently used for approval requests on this thread.    pub approvals_reviewer: ApprovalsReviewer,    /// Legacy sandbox policy retained for compatibility. Experimental clients    /// should prefer `activePermissionProfile` for profile provenance.    pub sandbox: SandboxPolicy,    /// Named or implicit built-in profile that produced the active    /// permissions, when known.    #[experimental("thread/start.activePermissionProfile")]    #[serde(default)]    pub active_permission_profile: Option<ActivePermissionProfile>,    pub reasoning_effort: Option<ReasoningEffort>,}#[derive(    Serialize, Deserialize, Debug, Default, Clone, PartialEq, JsonSchema, TS, ExperimentalApi,)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadSettingsUpdateParams {    pub thread_id: String,    /// Override the working directory for subsequent turns.    #[ts(optional = nullable)]    pub cwd: Option<PathBuf>,    /// Override the approval policy for subsequent turns.    #[experimental(nested)]    #[ts(optional = nullable)]    pub approval_policy: Option<AskForApproval>,    /// Override where approval requests are routed for subsequent turns.    #[ts(optional = nullable)]    pub approvals_reviewer: Option<ApprovalsReviewer>,    /// Override the sandbox policy for subsequent turns.    #[ts(optional = nullable)]    pub sandbox_policy: Option<SandboxPolicy>,    /// Select a named permissions profile id for subsequent turns. Cannot be    /// combined with `sandboxPolicy`.    #[experimental("thread/settings/update.permissions")]    #[ts(optional = nullable)]    pub permissions: Option<String>,    /// Override the model for subsequent turns.    #[ts(optional = nullable)]    pub model: Option<String>,    /// Override the service tier for subsequent turns. `null` clears the    /// current service tier; omission leaves it unchanged.    #[serde(        default,        deserialize_with = "crate::protocol::serde_helpers::deserialize_double_option",        serialize_with = "crate::protocol::serde_helpers::serialize_double_option",        skip_serializing_if = "Option::is_none"    )]    #[ts(optional = nullable)]    pub service_tier: Option<Option<String>>,    /// Override the reasoning effort for subsequent turns.    #[ts(optional = nullable)]    pub effort: Option<ReasoningEffort>,    /// Override the reasoning summary for subsequent turns.    #[ts(optional = nullable)]    pub summary: Option<ReasoningSummary>,    /// EXPERIMENTAL - Set a pre-set collaboration mode for subsequent turns.    ///    /// For `collaboration_mode.settings.developer_instructions`, `null` means    /// "use the built-in instructions for the selected mode".    #[experimental("thread/settings/update.collaborationMode")]    #[ts(optional = nullable)]    pub collaboration_mode: Option<CollaborationMode>,    /// Override the personality for subsequent turns.    #[ts(optional = nullable)]    pub personality: Option<Personality>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadSettingsUpdateResponse {}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadSettings {    pub cwd: AbsolutePathBuf,    pub approval_policy: AskForApproval,    pub approvals_reviewer: ApprovalsReviewer,    pub sandbox_policy: SandboxPolicy,    pub active_permission_profile: Option<ActivePermissionProfile>,    pub model: String,    pub model_provider: String,    pub service_tier: Option<String>,    pub effort: Option<ReasoningEffort>,    pub summary: Option<ReasoningSummary>,    pub collaboration_mode: CollaborationMode,    pub personality: Option<Personality>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadSettingsUpdatedNotification {    pub thread_id: String,    pub thread_settings: ThreadSettings,}#[derive(    Serialize, Deserialize, Debug, Default, Clone, PartialEq, JsonSchema, TS, ExperimentalApi,)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]/// There are three ways to resume a thread:/// 1. By thread_id: load the thread from disk by thread_id and resume it./// 2. By history: instantiate the thread from memory and resume it./// 3. By path: load the thread from disk by path and resume it.////// For non-running threads, the precedence is: history > non-empty path > thread_id./// If using history or a non-empty path for a non-running thread, the thread_id/// param will be ignored.////// If thread_id identifies a running thread, app-server rejoins that thread and/// treats a non-empty path as a consistency check against the active rollout path./// Empty string path values are treated as absent.////// Prefer using thread_id whenever possible.pub struct ThreadResumeParams {    pub thread_id: String,    /// [UNSTABLE] FOR CODEX CLOUD - DO NOT USE.    /// If specified, the thread will be resumed with the provided history    /// instead of loaded from disk.    #[experimental("thread/resume.history")]    #[ts(optional = nullable)]    pub history: Option<Vec<ResponseItem>>,    /// [UNSTABLE] Specify the rollout path to resume from.    /// If specified for a non-running thread, the thread_id param will be ignored.    /// If thread_id identifies a running thread, the path must match the active    /// rollout path.    #[experimental("thread/resume.path")]    #[serde(        default,        deserialize_with = "crate::protocol::serde_helpers::deserialize_empty_path_as_none"    )]    #[ts(optional = nullable)]    pub path: Option<PathBuf>,    /// Configuration overrides for the resumed thread, if any.    #[ts(optional = nullable)]    pub model: Option<String>,    #[ts(optional = nullable)]    pub model_provider: Option<String>,    #[serde(        default,        deserialize_with = "crate::protocol::serde_helpers::deserialize_double_option",        serialize_with = "crate::protocol::serde_helpers::serialize_double_option",        skip_serializing_if = "Option::is_none"    )]    #[ts(optional = nullable)]    pub service_tier: Option<Option<String>>,    #[ts(optional = nullable)]    pub cwd: Option<String>,    /// Replace the thread's runtime workspace roots. Paths must be absolute.    #[experimental("thread/resume.runtimeWorkspaceRoots")]    #[ts(optional = nullable)]    pub runtime_workspace_roots: Option<Vec<AbsolutePathBuf>>,    #[experimental(nested)]    #[ts(optional = nullable)]    pub approval_policy: Option<AskForApproval>,    /// Override where approval requests are routed for review on this thread    /// and subsequent turns.    #[ts(optional = nullable)]    pub approvals_reviewer: Option<ApprovalsReviewer>,    #[ts(optional = nullable)]    pub sandbox: Option<SandboxMode>,    /// Named profile id for the resumed thread. Cannot be combined with    /// `sandbox`.    #[experimental("thread/resume.permissions")]    #[ts(optional = nullable)]    pub permissions: Option<String>,    #[ts(optional = nullable)]    pub config: Option<HashMap<String, serde_json::Value>>,    #[ts(optional = nullable)]    pub base_instructions: Option<String>,    #[ts(optional = nullable)]    pub developer_instructions: Option<String>,    #[ts(optional = nullable)]    pub personality: Option<Personality>,    /// When true, return only thread metadata and live-resume state without    /// populating `thread.turns`. This is useful when the client plans to call    /// `thread/turns/list` immediately after resuming.    #[experimental("thread/resume.excludeTurns")]    #[serde(default, skip_serializing_if = "std::ops::Not::not")]    pub exclude_turns: bool,    /// When present, include a `thread/turns/list` page in the resume response    /// so clients can bootstrap recent turns without a second request.    #[experimental("thread/resume.initialTurnsPage")]    #[ts(optional = nullable)]    pub initial_turns_page: Option<ThreadResumeInitialTurnsPageParams>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS, ExperimentalApi)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadResumeResponse {    pub thread: Thread,    pub model: String,    pub model_provider: String,    pub service_tier: Option<String>,    pub cwd: AbsolutePathBuf,    /// Thread-scoped runtime workspace roots used to materialize    /// `:workspace_roots`.    #[experimental("thread/resume.runtimeWorkspaceRoots")]    #[serde(default)]    pub runtime_workspace_roots: Vec<AbsolutePathBuf>,    /// Instruction source files currently loaded for this thread.    #[serde(default)]    pub instruction_sources: Vec<AbsolutePathBuf>,    #[experimental(nested)]    pub approval_policy: AskForApproval,    /// Reviewer currently used for approval requests on this thread.    pub approvals_reviewer: ApprovalsReviewer,    /// Legacy sandbox policy retained for compatibility. Experimental clients    /// should prefer `activePermissionProfile` for profile provenance.    pub sandbox: SandboxPolicy,    /// Named or implicit built-in profile that produced the active    /// permissions, when known.    #[experimental("thread/resume.activePermissionProfile")]    #[serde(default)]    pub active_permission_profile: Option<ActivePermissionProfile>,    pub reasoning_effort: Option<ReasoningEffort>,    /// `thread/turns/list` page returned when requested by `initialTurnsPage`.    #[experimental("thread/resume.initialTurnsPage")]    #[serde(default)]    pub initial_turns_page: Option<TurnsPage>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadResumeInitialTurnsPageParams {    /// Optional turn page size.    #[ts(optional = nullable)]    pub limit: Option<u32>,    /// Optional turn pagination direction; defaults to descending.    #[ts(optional = nullable)]    pub sort_direction: Option<SortDirection>,    /// How much item detail to include for each returned turn; defaults to summary.    #[ts(optional = nullable)]    pub items_view: Option<TurnItemsView>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct TurnsPage {    pub data: Vec<Turn>,    pub next_cursor: Option<String>,    pub backwards_cursor: Option<String>,}impl From<ThreadTurnsListResponse> for TurnsPage {    fn from(response: ThreadTurnsListResponse) -> Self {        Self {            data: response.data,            next_cursor: response.next_cursor,            backwards_cursor: response.backwards_cursor,        }    }}#[derive(    Serialize, Deserialize, Debug, Default, Clone, PartialEq, JsonSchema, TS, ExperimentalApi,)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]/// There are two ways to fork a thread:/// 1. By thread_id: load the thread from disk by thread_id and fork it into a new thread./// 2. By path: load the thread from disk by path and fork it into a new thread.////// If using a non-empty path, the thread_id param will be ignored./// Empty string path values are treated as absent.////// Prefer using thread_id whenever possible.pub struct ThreadForkParams {    pub thread_id: String,    /// [UNSTABLE] Specify the rollout path to fork from.    /// If specified, the thread_id param will be ignored.    #[experimental("thread/fork.path")]    #[serde(        default,        deserialize_with = "crate::protocol::serde_helpers::deserialize_empty_path_as_none"    )]    #[ts(optional = nullable)]    pub path: Option<PathBuf>,    /// Configuration overrides for the forked thread, if any.    #[ts(optional = nullable)]    pub model: Option<String>,    #[ts(optional = nullable)]    pub model_provider: Option<String>,    #[serde(        default,        deserialize_with = "crate::protocol::serde_helpers::deserialize_double_option",        serialize_with = "crate::protocol::serde_helpers::serialize_double_option",        skip_serializing_if = "Option::is_none"    )]    #[ts(optional = nullable)]    pub service_tier: Option<Option<String>>,    #[ts(optional = nullable)]    pub cwd: Option<String>,    /// Replace the thread's runtime workspace roots. Paths must be absolute.    #[experimental("thread/fork.runtimeWorkspaceRoots")]    #[ts(optional = nullable)]    pub runtime_workspace_roots: Option<Vec<AbsolutePathBuf>>,    #[experimental(nested)]    #[ts(optional = nullable)]    pub approval_policy: Option<AskForApproval>,    /// Override where approval requests are routed for review on this thread    /// and subsequent turns.    #[ts(optional = nullable)]    pub approvals_reviewer: Option<ApprovalsReviewer>,    #[ts(optional = nullable)]    pub sandbox: Option<SandboxMode>,    /// Named profile id for the forked thread. Cannot be combined with    /// `sandbox`.    #[experimental("thread/fork.permissions")]    #[ts(optional = nullable)]    pub permissions: Option<String>,    #[ts(optional = nullable)]    pub config: Option<HashMap<String, serde_json::Value>>,    #[ts(optional = nullable)]    pub base_instructions: Option<String>,    #[ts(optional = nullable)]    pub developer_instructions: Option<String>,    #[serde(default, skip_serializing_if = "std::ops::Not::not")]    pub ephemeral: bool,    /// Optional client-supplied analytics source classification for this forked thread.    #[ts(optional = nullable)]    pub thread_source: Option<ThreadSource>,    /// When true, return only thread metadata and live fork state without    /// populating `thread.turns`. This is useful when the client plans to call    /// `thread/turns/list` immediately after forking.    #[experimental("thread/fork.excludeTurns")]    #[serde(default, skip_serializing_if = "std::ops::Not::not")]    pub exclude_turns: bool,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS, ExperimentalApi)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadForkResponse {    pub thread: Thread,    pub model: String,    pub model_provider: String,    pub service_tier: Option<String>,    pub cwd: AbsolutePathBuf,    /// Thread-scoped runtime workspace roots used to materialize    /// `:workspace_roots`.    #[experimental("thread/fork.runtimeWorkspaceRoots")]    #[serde(default)]    pub runtime_workspace_roots: Vec<AbsolutePathBuf>,    /// Instruction source files currently loaded for this thread.    #[serde(default)]    pub instruction_sources: Vec<AbsolutePathBuf>,    #[experimental(nested)]    pub approval_policy: AskForApproval,    /// Reviewer currently used for approval requests on this thread.    pub approvals_reviewer: ApprovalsReviewer,    /// Legacy sandbox policy retained for compatibility. Experimental clients    /// should prefer `activePermissionProfile` for profile provenance.    pub sandbox: SandboxPolicy,    /// Named or implicit built-in profile that produced the active    /// permissions, when known.    #[experimental("thread/fork.activePermissionProfile")]    #[serde(default)]    pub active_permission_profile: Option<ActivePermissionProfile>,    pub reasoning_effort: Option<ReasoningEffort>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadArchiveParams {    pub thread_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadArchiveResponse {}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadDeleteParams {    pub thread_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadDeleteResponse {}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadUnsubscribeParams {    pub thread_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadUnsubscribeResponse {    pub status: ThreadUnsubscribeStatus,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub enum ThreadUnsubscribeStatus {    NotLoaded,    NotSubscribed,    Unsubscribed,}/// Parameters for `thread/increment_elicitation`.#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadIncrementElicitationParams {    /// Thread whose out-of-band elicitation counter should be incremented.    pub thread_id: String,}/// Response for `thread/increment_elicitation`.#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadIncrementElicitationResponse {    /// Current out-of-band elicitation count after the increment.    pub count: u64,    /// Whether timeout accounting is paused after applying the increment.    pub paused: bool,}/// Parameters for `thread/decrement_elicitation`.#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadDecrementElicitationParams {    /// Thread whose out-of-band elicitation counter should be decremented.    pub thread_id: String,}/// Response for `thread/decrement_elicitation`.#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadDecrementElicitationResponse {    /// Current out-of-band elicitation count after the decrement.    pub count: u64,    /// Whether timeout accounting remains paused after applying the decrement.    pub paused: bool,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadSetNameParams {    pub thread_id: String,    pub name: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadUnarchiveParams {    pub thread_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadSetNameResponse {}v2_enum_from_core! {    pub enum ThreadGoalStatus from CoreThreadGoalStatus {        Active,        Paused,        Blocked,        UsageLimited,        BudgetLimited,        Complete,    }}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadGoal {    pub thread_id: String,    pub objective: String,    pub status: ThreadGoalStatus,    #[ts(type = "number | null")]    pub token_budget: Option<i64>,    #[ts(type = "number")]    pub tokens_used: i64,    #[ts(type = "number")]    pub time_used_seconds: i64,    #[ts(type = "number")]    pub created_at: i64,    #[ts(type = "number")]    pub updated_at: i64,}impl From<codex_protocol::protocol::ThreadGoal> for ThreadGoal {    fn from(value: codex_protocol::protocol::ThreadGoal) -> Self {        Self {            thread_id: value.thread_id.to_string(),            objective: value.objective,            status: value.status.into(),            token_budget: value.token_budget,            tokens_used: value.tokens_used,            time_used_seconds: value.time_used_seconds,            created_at: value.created_at,            updated_at: value.updated_at,        }    }}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadGoalSetParams {    pub thread_id: String,    #[ts(optional = nullable)]    pub objective: Option<String>,    #[ts(optional = nullable)]    pub status: Option<ThreadGoalStatus>,    #[serde(        default,        deserialize_with = "crate::protocol::serde_helpers::deserialize_double_option",        serialize_with = "crate::protocol::serde_helpers::serialize_double_option",        skip_serializing_if = "Option::is_none"    )]    #[ts(optional = nullable, type = "number | null")]    pub token_budget: Option<Option<i64>>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadGoalSetResponse {    pub goal: ThreadGoal,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadGoalGetParams {    pub thread_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadGoalGetResponse {    pub goal: Option<ThreadGoal>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadGoalClearParams {    pub thread_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadGoalClearResponse {    pub cleared: bool,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadMetadataUpdateParams {    pub thread_id: String,    /// Patch the stored Git metadata for this thread.    /// Omit a field to leave it unchanged, set it to `null` to clear it, or    /// provide a string to replace the stored value.    #[ts(optional = nullable)]    pub git_info: Option<ThreadMetadataGitInfoUpdateParams>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadMetadataGitInfoUpdateParams {    /// Omit to leave the stored commit unchanged, set to `null` to clear it,    /// or provide a non-empty string to replace it.    #[serde(        default,        skip_serializing_if = "Option::is_none",        serialize_with = "crate::protocol::serde_helpers::serialize_double_option",        deserialize_with = "crate::protocol::serde_helpers::deserialize_double_option"    )]    #[ts(optional = nullable, type = "string | null")]    pub sha: Option<Option<String>>,    /// Omit to leave the stored branch unchanged, set to `null` to clear it,    /// or provide a non-empty string to replace it.    #[serde(        default,        skip_serializing_if = "Option::is_none",        serialize_with = "crate::protocol::serde_helpers::serialize_double_option",        deserialize_with = "crate::protocol::serde_helpers::deserialize_double_option"    )]    #[ts(optional = nullable, type = "string | null")]    pub branch: Option<Option<String>>,    /// Omit to leave the stored origin URL unchanged, set to `null` to clear it,    /// or provide a non-empty string to replace it.    #[serde(        default,        skip_serializing_if = "Option::is_none",        serialize_with = "crate::protocol::serde_helpers::serialize_double_option",        deserialize_with = "crate::protocol::serde_helpers::deserialize_double_option"    )]    #[ts(optional = nullable, type = "string | null")]    pub origin_url: Option<Option<String>>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadMetadataUpdateResponse {    pub thread: Thread,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "lowercase")]#[ts(rename_all = "lowercase")]pub enum ThreadMemoryMode {    Enabled,    Disabled,}impl ThreadMemoryMode {    pub fn as_str(self) -> &'static str {        match self {            Self::Enabled => "enabled",            Self::Disabled => "disabled",        }    }    pub fn to_core(self) -> codex_protocol::protocol::ThreadMemoryMode {        match self {            Self::Enabled => codex_protocol::protocol::ThreadMemoryMode::Enabled,            Self::Disabled => codex_protocol::protocol::ThreadMemoryMode::Disabled,        }    }}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadMemoryModeSetParams {    pub thread_id: String,    pub mode: ThreadMemoryMode,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadMemoryModeSetResponse {}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct MemoryResetResponse {}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadUnarchiveResponse {    pub thread: Thread,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadCompactStartParams {    pub thread_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadCompactStartResponse {}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadShellCommandParams {    pub thread_id: String,    /// Shell command string evaluated by the thread's configured shell.    /// Unlike `command/exec`, this intentionally preserves shell syntax    /// such as pipes, redirects, and quoting. This runs unsandboxed with full    /// access rather than inheriting the thread sandbox policy.    pub command: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadShellCommandResponse {}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadApproveGuardianDeniedActionParams {    pub thread_id: String,    /// Serialized `codex_protocol::protocol::GuardianAssessmentEvent`.    pub event: JsonValue,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadApproveGuardianDeniedActionResponse {}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadBackgroundTerminalsCleanParams {    pub thread_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadBackgroundTerminalsCleanResponse {}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadBackgroundTerminalsListParams {    pub thread_id: String,    /// Opaque pagination cursor returned by a previous call.    #[ts(optional = nullable)]    pub cursor: Option<String>,    /// Optional page size.    #[ts(optional = nullable)]    pub limit: Option<u32>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadBackgroundTerminal {    pub item_id: String,    pub process_id: String,    pub command: String,    pub cwd: AbsolutePathBuf,    pub os_pid: Option<u32>,    pub cpu_percent: Option<f64>,    pub rss_kb: Option<u64>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadBackgroundTerminalsListResponse {    pub data: Vec<ThreadBackgroundTerminal>,    /// 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, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadBackgroundTerminalsTerminateParams {    pub thread_id: String,    pub process_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadBackgroundTerminalsTerminateResponse {    pub terminated: bool,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadRollbackParams {    pub thread_id: String,    /// The number of turns to drop from the end of the thread. Must be >= 1.    ///    /// This only modifies the thread's history and does not revert local file changes    /// that have been made by the agent. Clients are responsible for reverting these changes.    pub num_turns: u32,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadRollbackResponse {    /// The updated thread after applying the rollback, with `turns` populated.    ///    /// The ThreadItems stored in each Turn are lossy since we explicitly do not    /// persist all agent interactions, such as command executions. This is the same    /// behavior as `thread/resume`.    pub thread: Thread,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS, ExperimentalApi)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadListParams {    /// 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>,    /// Optional sort key; defaults to created_at.    #[ts(optional = nullable)]    pub sort_key: Option<ThreadSortKey>,    /// Optional sort direction; defaults to descending (newest first).    #[ts(optional = nullable)]    pub sort_direction: Option<SortDirection>,    /// Optional provider filter; when set, only sessions recorded under these    /// providers are returned. When present but empty, includes all providers.    #[ts(optional = nullable)]    pub model_providers: Option<Vec<String>>,    /// Optional source filter; when set, only sessions from these source kinds    /// are returned. When omitted or empty, defaults to interactive sources.    #[ts(optional = nullable)]    pub source_kinds: Option<Vec<ThreadSourceKind>>,    /// Optional archived filter; when set to true, only archived threads are returned.    /// If false or null, only non-archived threads are returned.    #[ts(optional = nullable)]    pub archived: Option<bool>,    /// Optional cwd filter or filters; when set, only threads whose session cwd    /// exactly matches one of these paths are returned.    #[ts(optional = nullable, type = "string | Array<string> | null")]    pub cwd: Option<ThreadListCwdFilter>,    /// If true, return from the state DB without scanning JSONL rollouts to    /// repair thread metadata. Omitted or false preserves scan-and-repair    /// behavior.    #[serde(default, skip_serializing_if = "std::ops::Not::not")]    pub use_state_db_only: bool,    /// Optional substring filter for the extracted thread title.    #[ts(optional = nullable)]    pub search_term: Option<String>,    /// Optional direct parent thread filter.    #[experimental("thread/list.parentThreadId")]    #[ts(optional = nullable)]    pub parent_thread_id: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadSearchParams {    /// 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>,    /// Optional sort key; defaults to created_at.    #[ts(optional = nullable)]    pub sort_key: Option<ThreadSortKey>,    /// Optional sort direction; defaults to descending (newest first).    #[ts(optional = nullable)]    pub sort_direction: Option<SortDirection>,    /// Optional source filter; when set, only sessions from these source kinds    /// are returned. When omitted or empty, defaults to interactive sources.    #[ts(optional = nullable)]    pub source_kinds: Option<Vec<ThreadSourceKind>>,    /// Optional archived filter; when set to true, only archived threads are returned.    /// If false or null, only non-archived threads are returned.    #[ts(optional = nullable)]    pub archived: Option<bool>,    /// Required substring/full-text query for thread search.    pub search_term: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema)]#[serde(untagged)]pub enum ThreadListCwdFilter {    One(String),    Many(Vec<String>),}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(rename_all = "camelCase", export_to = "v2/")]pub enum ThreadSourceKind {    Cli,    #[serde(rename = "vscode")]    #[ts(rename = "vscode")]    VsCode,    Exec,    AppServer,    SubAgent,    SubAgentReview,    SubAgentCompact,    SubAgentThreadSpawn,    SubAgentOther,    Unknown,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, JsonSchema, TS)]#[serde(rename_all = "snake_case")]#[ts(export_to = "v2/")]pub enum ThreadSortKey {    CreatedAt,    UpdatedAt,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, JsonSchema, TS)]#[serde(rename_all = "snake_case")]#[ts(export_to = "v2/")]pub enum SortDirection {    Asc,    Desc,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadListResponse {    pub data: Vec<Thread>,    /// 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>,    /// Opaque cursor to pass as `cursor` when reversing `sortDirection`.    /// This is only populated when the page contains at least one thread.    /// Use it with the opposite `sortDirection`; for timestamp sorts it anchors    /// at the start of the page timestamp so same-second updates are not skipped.    pub backwards_cursor: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadSearchResult {    pub thread: Thread,    pub snippet: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadSearchResponse {    pub data: Vec<ThreadSearchResult>,    /// 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>,    /// Opaque cursor to pass as `cursor` when reversing `sortDirection`.    /// This is only populated when the page contains at least one thread.    /// Use it with the opposite `sortDirection`; for timestamp sorts it anchors    /// at the start of the page timestamp so same-second updates are not skipped.    pub backwards_cursor: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadLoadedListParams {    /// Opaque pagination cursor returned by a previous call.    #[ts(optional = nullable)]    pub cursor: Option<String>,    /// Optional page size; defaults to no limit.    #[ts(optional = nullable)]    pub limit: Option<u32>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadLoadedListResponse {    /// Thread ids for sessions currently loaded in memory.    pub data: Vec<String>,    /// 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, JsonSchema, TS)]#[serde(tag = "type", rename_all = "camelCase")]#[ts(tag = "type")]#[ts(export_to = "v2/")]pub enum ThreadStatus {    NotLoaded,    Idle,    SystemError,    #[serde(rename_all = "camelCase")]    #[ts(rename_all = "camelCase")]    Active {        active_flags: Vec<ThreadActiveFlag>,    },}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub enum ThreadActiveFlag {    WaitingOnApproval,    WaitingOnUserInput,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadReadParams {    pub thread_id: String,    /// When true, include turns and their items from rollout history.    #[serde(default, skip_serializing_if = "std::ops::Not::not")]    pub include_turns: bool,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadReadResponse {    pub thread: Thread,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadInjectItemsParams {    pub thread_id: String,    /// Raw Responses API items to append to the thread's model-visible history.    pub items: Vec<JsonValue>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadInjectItemsResponse {}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadTurnsListParams {    pub thread_id: String,    /// Opaque cursor to pass to the next call to continue after the last turn.    #[ts(optional = nullable)]    pub cursor: Option<String>,    /// Optional turn page size.    #[ts(optional = nullable)]    pub limit: Option<u32>,    /// Optional turn pagination direction; defaults to descending.    #[ts(optional = nullable)]    pub sort_direction: Option<SortDirection>,    /// How much item detail to include for each returned turn; defaults to summary.    #[ts(optional = nullable)]    pub items_view: Option<TurnItemsView>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadTurnsListResponse {    pub data: Vec<Turn>,    /// Opaque cursor to pass to the next call to continue after the last turn.    /// if None, there are no more turns to return.    pub next_cursor: Option<String>,    /// Opaque cursor to pass as `cursor` when reversing `sortDirection`.    /// This is only populated when the page contains at least one turn.    /// Use it with the opposite `sortDirection` to include the anchor turn again    /// and catch updates to that turn.    pub backwards_cursor: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadTurnsItemsListParams {    pub thread_id: String,    pub turn_id: String,    /// Opaque cursor to pass to the next call to continue after the last item.    #[ts(optional = nullable)]    pub cursor: Option<String>,    /// Optional item page size.    #[ts(optional = nullable)]    pub limit: Option<u32>,    /// Optional item pagination direction; defaults to ascending.    #[ts(optional = nullable)]    pub sort_direction: Option<SortDirection>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadTurnsItemsListResponse {    pub data: Vec<ThreadItem>,    /// 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>,    /// Opaque cursor to pass as `cursor` when reversing `sortDirection`.    /// This is only populated when the page contains at least one item.    pub backwards_cursor: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadTokenUsageUpdatedNotification {    pub thread_id: String,    pub turn_id: String,    pub token_usage: ThreadTokenUsage,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadTokenUsage {    pub total: TokenUsageBreakdown,    pub last: TokenUsageBreakdown,    // TODO(aibrahim): make this not optional    #[ts(type = "number | null")]    pub model_context_window: Option<i64>,}impl From<CoreTokenUsageInfo> for ThreadTokenUsage {    fn from(value: CoreTokenUsageInfo) -> Self {        Self {            total: value.total_token_usage.into(),            last: value.last_token_usage.into(),            model_context_window: value.model_context_window,        }    }}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct TokenUsageBreakdown {    #[ts(type = "number")]    pub total_tokens: i64,    #[ts(type = "number")]    pub input_tokens: i64,    #[ts(type = "number")]    pub cached_input_tokens: i64,    #[ts(type = "number")]    pub output_tokens: i64,    #[ts(type = "number")]    pub reasoning_output_tokens: i64,}impl From<CoreTokenUsage> for TokenUsageBreakdown {    fn from(value: CoreTokenUsage) -> Self {        Self {            total_tokens: value.total_tokens,            input_tokens: value.input_tokens,            cached_input_tokens: value.cached_input_tokens,            output_tokens: value.output_tokens,            reasoning_output_tokens: value.reasoning_output_tokens,        }    }}// Thread/Turn lifecycle notifications and item progress events#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadStartedNotification {    pub thread: Thread,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadStatusChangedNotification {    pub thread_id: String,    pub status: ThreadStatus,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadArchivedNotification {    pub thread_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadDeletedNotification {    pub thread_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadUnarchivedNotification {    pub thread_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadClosedNotification {    pub thread_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadNameUpdatedNotification {    pub thread_id: String,    #[serde(default, skip_serializing_if = "Option::is_none")]    #[ts(optional)]    pub thread_name: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadGoalUpdatedNotification {    pub thread_id: String,    pub turn_id: Option<String>,    pub goal: ThreadGoal,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ThreadGoalClearedNotification {    pub thread_id: String,}/// Deprecated: Use `ContextCompaction` item type instead.#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ContextCompactedNotification {    pub thread_id: String,    pub turn_id: String,}