use super::ActivePermissionProfile; use super::ApprovalsReviewer; use super::AskForApproval; use super::SandboxMode; use super::SandboxPolicy; use super::Thread; use super::ThreadHistoryMode; use super::ThreadItem; use super::ThreadRealtimeItem; use super::ThreadSection; use super::ThreadSectionAppearance; use super::ThreadSource; use super::Turn; use super::TurnEnvironmentParams; use super::TurnError; use super::TurnItemsView; use super::TurnStatus; use super::UserInput; use super::shared::v2_enum_from_core; use crate::JsonSchema; use crate::TS; 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::MultiAgentMode; 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 codex_utils_path_uri::LegacyAppPathString; use codex_utils_path_uri::PathUri; use serde::Deserialize; use serde::Serialize; use serde_json::Value as JsonValue; use std::collections::HashMap; use std::path::PathBuf; #[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, #[ts(optional = nullable)] pub model_provider: Option, /// Allow a provider with an authoritative static model catalog to replace an unavailable /// requested model with its default. #[experimental("thread/start.allowProviderModelFallback")] #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub allow_provider_model_fallback: bool, #[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>, #[ts(optional = nullable)] pub cwd: Option, /// Replace the thread's runtime workspace roots. Paths must be absolute. #[experimental("thread/start.runtimeWorkspaceRoots")] #[ts(optional = nullable)] pub runtime_workspace_roots: Option>, #[experimental(nested)] #[ts(optional = nullable)] pub approval_policy: Option, /// Override where approval requests are routed for review on this thread /// and subsequent turns. #[ts(optional = nullable)] pub approvals_reviewer: Option, #[ts(optional = nullable)] pub sandbox: Option, /// Named profile id for this thread. Cannot be combined with `sandbox`. #[experimental("thread/start.permissions")] #[ts(optional = nullable)] pub permissions: Option, #[ts(optional = nullable)] pub config: Option>, #[ts(optional = nullable)] pub service_name: Option, #[ts(optional = nullable)] pub base_instructions: Option, #[ts(optional = nullable)] pub developer_instructions: Option, /// @deprecated `friendly` and `pragmatic` no longer select a style. #[ts(optional = nullable)] pub personality: Option, /// @deprecated Ignored. Use Ultra reasoning effort for proactive multi-agent behavior. #[experimental("thread/start.multiAgentMode")] #[ts(optional = nullable)] pub multi_agent_mode: Option, #[ts(optional = nullable)] pub ephemeral: Option, /// Persisted thread history contract to use for this new thread. #[experimental("thread/start.historyMode")] #[ts(optional = nullable)] pub history_mode: Option, #[ts(optional = nullable)] pub session_start_source: Option, /// Optional client-supplied analytics source classification for this thread. #[ts(optional = nullable)] pub thread_source: Option, /// Optional project identity for this new thread. Durable threads persist /// the assignment; ephemeral threads expose it only in live responses. #[experimental("thread/start.projectId")] #[ts(optional = nullable)] pub project_id: Option, /// Initial Daybreak choice for this persistent thread. Omitted or null /// leaves it unset. This does not select a turn's `cyberAccessProgram` /// or grant access. Not supported for ephemeral threads. #[experimental("thread/start.daybreakEnabled")] #[ts(optional = nullable)] pub daybreak_enabled: Option, /// 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>, #[experimental("thread/start.dynamicTools")] #[serde( default, deserialize_with = "codex_protocol::dynamic_tools::deserialize_dynamic_tool_specs" )] #[ts(optional = nullable)] pub dynamic_tools: Option>, /// Capability roots selected for this thread by the hosting platform. #[experimental("thread/start.selectedCapabilityRoots")] #[ts(optional = nullable)] pub selected_capability_roots: Option>, /// 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, /// 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, } #[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, } #[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, /// Saved list of disabled plugin IDs. Does not yet filter plugin capabilities. #[serde(default)] pub disabled_plugin_ids: Vec, pub cwd: AbsolutePathBuf, /// Thread-scoped runtime workspace roots used to materialize /// `:workspace_roots`. #[experimental("thread/start.runtimeWorkspaceRoots")] #[serde(default)] pub runtime_workspace_roots: Vec, /// Environment-native paths to instruction source files currently loaded for this thread. #[serde(default)] pub instruction_sources: Vec, #[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, pub reasoning_effort: Option, /// @deprecated Always `explicitRequestOnly`. Use `reasoningEffort` for Ultra behavior. #[experimental("thread/start.multiAgentMode")] #[serde(default)] pub multi_agent_mode: MultiAgentMode, } impl ThreadStartResponse { /// Parses valid absolute instruction source paths and omits malformed legacy values. pub fn instruction_source_path_uris(&self) -> Vec { instruction_source_path_uris(&self.instruction_sources) } } #[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, /// Replace this thread's disabled plugin IDs. /// Omitted/null preserves the list; [] clears it. #[ts(optional = nullable)] pub disabled_plugin_ids: Option>, /// Override the working directory for subsequent turns. #[ts(optional = nullable)] pub cwd: Option, /// Override the approval policy for subsequent turns. #[experimental(nested)] #[ts(optional = nullable)] pub approval_policy: Option, /// Override where approval requests are routed for subsequent turns. #[ts(optional = nullable)] pub approvals_reviewer: Option, /// Override the sandbox policy for subsequent turns. #[ts(optional = nullable)] pub sandbox_policy: Option, /// 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, /// Override the model for subsequent turns. #[ts(optional = nullable)] pub model: Option, /// 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>, /// Override the reasoning effort for subsequent turns. #[ts(optional = nullable)] pub effort: Option, /// Override the reasoning summary for subsequent turns. #[ts(optional = nullable)] pub summary: Option, /// 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, /// @deprecated Ignored. Use `effort: "ultra"` for proactive multi-agent behavior. #[experimental("thread/settings/update.multiAgentMode")] #[ts(optional = nullable)] pub multi_agent_mode: Option, /// @deprecated `friendly` and `pragmatic` no longer select a style. /// Changing this does not rewrite the thread's existing instructions. #[ts(optional = nullable)] pub personality: Option, } #[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, ExperimentalApi)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadSettings { /// Saved list of disabled plugin IDs. Does not yet filter plugin capabilities. #[serde(default)] pub disabled_plugin_ids: Vec, pub cwd: AbsolutePathBuf, pub approval_policy: AskForApproval, pub approvals_reviewer: ApprovalsReviewer, pub sandbox_policy: SandboxPolicy, pub active_permission_profile: Option, pub model: String, pub model_provider: String, pub service_tier: Option, pub effort: Option, pub summary: Option, pub collaboration_mode: CollaborationMode, /// @deprecated Always `explicitRequestOnly`. Use `effort` for Ultra behavior. #[experimental("thread/settings.multiAgentMode")] #[serde(default)] pub multi_agent_mode: MultiAgentMode, /// @deprecated Reports the saved setting; `friendly` and `pragmatic` no longer select a style. pub personality: Option, } #[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>, /// [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, /// Configuration overrides for the resumed thread, if any. #[ts(optional = nullable)] pub model: Option, #[ts(optional = nullable)] pub model_provider: Option, #[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>, #[ts(optional = nullable)] pub cwd: Option, /// Replace the thread's runtime workspace roots. Paths must be absolute. #[experimental("thread/resume.runtimeWorkspaceRoots")] #[ts(optional = nullable)] pub runtime_workspace_roots: Option>, #[experimental(nested)] #[ts(optional = nullable)] pub approval_policy: Option, /// Override where approval requests are routed for review on this thread /// and subsequent turns. #[ts(optional = nullable)] pub approvals_reviewer: Option, #[ts(optional = nullable)] pub sandbox: Option, /// Named profile id for the resumed thread. Cannot be combined with /// `sandbox`. #[experimental("thread/resume.permissions")] #[ts(optional = nullable)] pub permissions: Option, #[ts(optional = nullable)] pub config: Option>, #[ts(optional = nullable)] pub base_instructions: Option, #[ts(optional = nullable)] pub developer_instructions: Option, /// @deprecated `friendly` and `pragmatic` no longer select a style. /// Changing this does not rewrite the thread's existing instructions. #[ts(optional = nullable)] pub personality: Option, /// 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. Full-history hydration /// is deprecated for paginated threads; use this with `thread/turns/list` /// and `thread/items/list` instead. #[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, } #[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, /// Saved list of disabled plugin IDs. Does not yet filter plugin capabilities. #[serde(default)] pub disabled_plugin_ids: Vec, pub cwd: AbsolutePathBuf, /// Thread-scoped runtime workspace roots used to materialize /// `:workspace_roots`. #[experimental("thread/resume.runtimeWorkspaceRoots")] #[serde(default)] pub runtime_workspace_roots: Vec, /// Environment-native paths to instruction source files currently loaded for this thread. #[serde(default)] pub instruction_sources: Vec, #[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, pub reasoning_effort: Option, /// Effective collaboration mode. Absent when resuming from an older server. pub collaboration_mode: Option, /// @deprecated Always `explicitRequestOnly`. Use `reasoningEffort` for Ultra behavior. #[experimental("thread/resume.multiAgentMode")] #[serde(default)] pub multi_agent_mode: MultiAgentMode, /// `thread/turns/list` page returned when requested by `initialTurnsPage`. #[experimental("thread/resume.initialTurnsPage")] #[serde(default)] pub initial_turns_page: Option, /// Opaque cursor for hydrating paginated turns backwards. /// /// Pass this as `cursor` to `thread/turns/list` with /// `sortDirection: "desc"`. The first page includes the turn identified by the cursor. #[serde(default)] pub turns_backwards_cursor: Option, /// Opaque cursor for hydrating paginated items backwards. /// /// Pass this as `cursor` to `thread/items/list` with /// `sortDirection: "desc"`. The first page includes the item identified by the cursor. #[serde(default)] pub items_backwards_cursor: Option, } impl ThreadResumeResponse { /// Parses valid absolute instruction source paths and omits malformed legacy values. pub fn instruction_source_path_uris(&self) -> Vec { instruction_source_path_uris(&self.instruction_sources) } } #[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, /// Optional turn pagination direction; defaults to descending. #[ts(optional = nullable)] pub sort_direction: Option, /// How much item detail to include for each returned turn; defaults to summary. #[ts(optional = nullable)] pub items_view: Option, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct TurnsPage { pub data: Vec, pub next_cursor: Option, pub backwards_cursor: Option, } impl From 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, /// Optional last turn id to fork through, inclusive. /// /// When specified, turns after `last_turn_id` are omitted from the fork. /// The referenced turn cannot be in progress. #[ts(optional = nullable)] pub last_turn_id: Option, /// Optional turn id to fork before, excluding that turn and all later turns. /// Cannot be combined with `last_turn_id`. #[experimental("thread/fork.beforeTurnId")] #[ts(optional = nullable)] pub before_turn_id: Option, /// [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, /// Configuration overrides for the forked thread, if any. #[ts(optional = nullable)] pub model: Option, #[ts(optional = nullable)] pub model_provider: Option, #[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>, #[ts(optional = nullable)] pub cwd: Option, /// Replace the thread's runtime workspace roots. Paths must be absolute. #[experimental("thread/fork.runtimeWorkspaceRoots")] #[ts(optional = nullable)] pub runtime_workspace_roots: Option>, #[experimental(nested)] #[ts(optional = nullable)] pub approval_policy: Option, /// Override where approval requests are routed for review on this thread /// and subsequent turns. #[ts(optional = nullable)] pub approvals_reviewer: Option, #[ts(optional = nullable)] pub sandbox: Option, /// Named profile id for the forked thread. Cannot be combined with /// `sandbox`. #[experimental("thread/fork.permissions")] #[ts(optional = nullable)] pub permissions: Option, #[ts(optional = nullable)] pub config: Option>, #[ts(optional = nullable)] pub base_instructions: Option, #[ts(optional = nullable)] pub developer_instructions: Option, #[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, /// 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. Full-history hydration /// is deprecated for paginated threads; use this with `thread/turns/list` /// and `thread/items/list` instead. #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub exclude_turns: bool, /// When true, carry the source thread's current goal into the fork without /// starting its initial automatic continuation. The next explicit turn owns /// the goal lifecycle, and normal automatic continuation resumes after it. #[experimental("thread/fork.deferGoalContinuation")] #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub defer_goal_continuation: 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, /// Saved list of disabled plugin IDs. Does not yet filter plugin capabilities. #[serde(default)] pub disabled_plugin_ids: Vec, pub cwd: AbsolutePathBuf, /// Thread-scoped runtime workspace roots used to materialize /// `:workspace_roots`. #[experimental("thread/fork.runtimeWorkspaceRoots")] #[serde(default)] pub runtime_workspace_roots: Vec, /// Environment-native paths to instruction source files currently loaded for this thread. #[serde(default)] pub instruction_sources: Vec, #[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, pub reasoning_effort: Option, /// @deprecated Always `explicitRequestOnly`. Use `reasoningEffort` for Ultra behavior. #[experimental("thread/fork.multiAgentMode")] #[serde(default)] pub multi_agent_mode: MultiAgentMode, } impl ThreadForkResponse { /// Parses valid absolute instruction source paths and omits malformed legacy values. pub fn instruction_source_path_uris(&self) -> Vec { instruction_source_path_uris(&self.instruction_sources) } } fn instruction_source_path_uris(sources: &[LegacyAppPathString]) -> Vec { // Instruction sources are advisory diagnostics. Warn and fail open so a malformed legacy // path cannot fail thread start, resume, or fork. sources .iter() .filter_map(|source| { source.to_inferred_path_uri().or_else(|| { tracing::warn!( path = source.as_str(), "ignoring invalid instruction source path from app-server" ); None }) }) .collect() } #[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: i64, /// 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: i64, /// 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, #[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 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, #[ts(optional = nullable)] pub status: Option, #[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>, } #[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, } #[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, ExperimentalApi)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct QueuedSubmission { pub id: String, pub input: Vec, pub client_user_message_id: String, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadQueueAddParams { pub thread_id: String, pub input: Vec, pub client_user_message_id: String, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadQueueAddResponse { pub queued_submission: QueuedSubmission, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadQueueListParams { pub thread_id: String, /// Opaque pagination cursor returned by a previous call. #[ts(optional = nullable)] pub cursor: Option, /// Optional page size; defaults to the standard thread-list page size. #[ts(optional = nullable)] pub limit: Option, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadQueueListResponse { pub data: Vec, /// Opaque cursor for the next page, or `null` when no submissions remain. pub next_cursor: Option, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadQueueUpdateParams { pub thread_id: String, pub queued_submission_id: String, pub input: Vec, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadQueueUpdateResponse { pub queued_submission: QueuedSubmission, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadQueueDeleteParams { pub thread_id: String, pub queued_submission_id: String, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadQueueDeleteResponse { pub deleted: bool, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadQueueReorderParams { pub thread_id: String, pub queued_submission_ids: Vec, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadQueueReorderResponse {} #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadQueueStartParams { pub thread_id: String, #[ts(optional = nullable)] pub queued_submission_id: Option, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadQueueStartResponse { pub turn: Turn, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS, ExperimentalApi)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadMetadataUpdateParams { pub thread_id: String, /// Omit to leave the project unchanged, use an empty string to clear it, /// or provide an existing project ID to assign it. #[experimental("thread/metadata/update.projectId")] #[ts(optional = nullable)] pub project_id: Option, /// 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, /// Save the client's Daybreak choice for this persistent thread. /// Omitted or null leaves it unchanged. This does not select a turn's /// `cyberAccessProgram` or grant access. #[experimental("thread/metadata/update.daybreakEnabled")] #[ts(optional = nullable)] pub daybreak_enabled: Option, } #[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>, /// 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>, /// 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>, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadMetadataUpdateResponse { pub thread: Thread, } /// Parameters for moving a thread within a server-owned section ordering. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadSectionMoveParams { /// Thread to move into, within, or out of a section. pub thread_id: String, /// Destination section, or `null` to remove the thread from its section. #[serde(deserialize_with = "Option::deserialize")] #[schemars( required, schema_with = "crate::protocol::serde_helpers::nullable_string_schema" )] #[ts(type = "string | null")] pub section_id: Option, /// Existing thread to insert before; omission or null appends to the section. #[ts(optional = nullable)] pub before_thread_id: Option, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadSectionMoveResponse {} #[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, /// Maximum execution time in milliseconds. Defaults to one hour when omitted /// or null. Must be non-negative; zero requests an immediate timeout, not /// unlimited execution. Does not affect the immediate RPC acknowledgement. #[ts(type = "number | null")] #[ts(optional = nullable)] pub timeout_ms: Option, } #[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, /// Optional page size. #[ts(optional = nullable)] pub limit: Option, } #[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: LegacyAppPathString, pub os_pid: Option, pub cpu_percent: Option, pub rss_kb: Option, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadBackgroundTerminalsListResponse { pub data: Vec, /// 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, } #[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, } /// Replace a paginated thread's durable history with the prefix before one turn. /// /// This only changes persisted conversation history. It does not revert local file changes. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadRevertParams { pub thread_id: String, /// Turn excluded from the replacement history, together with every later turn. pub before_turn_id: String, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadRevertResponse { /// Updated loaded thread metadata. `turns` is always empty; hydrate retained history through /// `thread/turns/list`. pub thread: Thread, /// Opaque cursor for hydrating paginated turns backwards. /// /// Pass this as `cursor` to `thread/turns/list` with /// `sortDirection: "desc"`. The first page includes the turn identified by the cursor. pub turns_backwards_cursor: Option, /// Opaque cursor for hydrating paginated items backwards. /// /// Pass this as `cursor` to `thread/items/list` with /// `sortDirection: "desc"`. The first page includes the item identified by the cursor. pub items_backwards_cursor: Option, } /// Parameters for listing independently persisted thread sections. #[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadSectionListParams { /// Opaque pagination cursor returned by a previous call. #[ts(optional = nullable)] pub cursor: Option, /// Maximum number of sections to return. #[ts(optional = nullable)] pub limit: Option, } /// One page of independently persisted thread sections. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadSectionListResponse { pub data: Vec, /// Opaque cursor for the next page, or `null` when no sections remain. pub next_cursor: Option, } /// Parameters for creating an independently persisted thread section. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadSectionCreateParams { /// The user-visible name of the section. pub name: String, #[serde(default)] #[ts(optional = nullable)] pub appearance: Option, } /// The independently persisted section created by the server. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadSectionCreateResponse { pub section: ThreadSection, } /// Parameters for updating an independently persisted thread section. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadSectionUpdateParams { /// The stable, server-generated identity of the section to update. pub section_id: String, /// The updated user-visible name of the section. pub name: String, /// Omit to preserve appearance, use `null` to clear it, or provide a replacement. #[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" )] #[schemars(with = "Option")] #[ts(optional = nullable, as = "Option")] pub appearance: Option>, } /// The independently persisted section after its name is updated. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadSectionUpdateResponse { pub section: ThreadSection, } /// Parameters for deleting an independently persisted thread section. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadSectionDeleteParams { /// The stable, server-generated identity of the section to delete. pub section_id: String, } /// Successful deletion does not return additional section data. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadSectionDeleteResponse {} #[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, /// Optional page size; defaults to a reasonable server-side value. #[ts(optional = nullable)] pub limit: Option, /// Optional sort key; defaults to created_at. #[ts(optional = nullable)] pub sort_key: Option, /// Optional sort direction; defaults to descending (newest first). #[ts(optional = nullable)] pub sort_direction: Option, /// 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>, /// 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>, /// Optional originator allowlist, matching any supplied value exactly. /// Supported by hosted backends only; the local app-server rejects a nonempty list. /// Omitted or empty lists leave originators unrestricted. #[ts(optional = nullable)] pub originators: Option>, /// 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, /// Omit to include every section, set to `null` for unsectioned threads, /// or provide a section ID to return only threads in that section. #[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 section_id: Option>, /// Omit to include every project, set to null for unassigned threads, /// or provide a project ID to return only threads in that project. #[experimental("thread/list.projectId")] #[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 project_id: Option>, /// 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 | null")] pub cwd: Option, /// 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, /// Optional direct parent thread filter. Mutually exclusive with `ancestorThreadId`. #[experimental("thread/list.parentThreadId")] #[ts(optional = nullable)] pub parent_thread_id: Option, /// Optional ancestor thread filter. Returns spawned descendants at any depth, excluding the /// ancestor itself. Mutually exclusive with `parentThreadId`. #[experimental("thread/list.ancestorThreadId")] #[ts(optional = nullable)] pub ancestor_thread_id: Option, } #[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, /// Optional page size; defaults to a reasonable server-side value. #[ts(optional = nullable)] pub limit: Option, /// Optional sort key; defaults to created_at. #[ts(optional = nullable)] pub sort_key: Option, /// Optional sort direction; defaults to descending (newest first). #[ts(optional = nullable)] pub sort_direction: Option, /// 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>, /// 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, /// 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), } #[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, RecencyAt, SectionPosition, } #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, JsonSchema, TS)] #[serde(rename_all = "snake_case")] #[ts(export_to = "v2/")] pub enum ThreadSearchSortKey { CreatedAt, UpdatedAt, RecencyAt, } #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, 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, /// 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, /// 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, } #[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, /// 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, /// 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, } /// Parameters for searching visible message occurrences within one paginated thread. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadSearchOccurrencesParams { pub thread_id: String, /// Case-insensitive literal substring to find in visible user messages and final assistant /// messages. pub search_term: String, /// Opaque cursor returned by a previous call for the same thread and search term. #[ts(optional = nullable)] pub cursor: Option, /// Optional occurrence page size. #[ts(optional = nullable)] pub limit: Option, } /// UTF-16 code-unit range within `snippet`. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadSearchTextRange { /// Inclusive UTF-16 code-unit offset. pub start: u32, /// Exclusive UTF-16 code-unit offset. pub end: u32, } /// One visible message occurrence returned by [`ThreadSearchOccurrencesResponse`]. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadSearchOccurrence { pub turn_id: String, pub item_id: String, pub snippet: String, /// Match range within `snippet`, in UTF-16 code units. pub snippet_match_range: ThreadSearchTextRange, /// Opaque inclusive cursor accepted by `thread/turns/list` for this turn. pub turn_cursor: String, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadSearchOccurrencesResponse { /// Occurrences in chronological message order. pub data: Vec, /// Opaque cursor to continue after the last returned occurrence. pub next_cursor: Option, } #[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, /// Optional page size; defaults to no limit. #[ts(optional = nullable)] pub limit: Option, } #[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, /// 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, } #[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, }, } #[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. /// Full-history hydration is deprecated for paginated threads; prefer a /// metadata-only read and page with `thread/turns/list` and /// `thread/items/list`. #[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, } #[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, /// Optional turn page size. #[ts(optional = nullable)] pub limit: Option, /// Optional turn pagination direction; defaults to descending. #[ts(optional = nullable)] pub sort_direction: Option, /// How much item detail to include for each returned turn; defaults to summary. #[ts(optional = nullable)] pub items_view: Option, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadTurnsListResponse { pub data: Vec, /// 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, /// 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, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadItemsListParams { pub thread_id: String, /// Optional turn id to filter by. When omitted, returns items across the thread. #[ts(optional = nullable)] pub turn_id: Option, /// Opaque cursor to pass to the next call to continue after the last item. #[ts(optional = nullable)] pub cursor: Option, /// Optional item page size. #[ts(optional = nullable)] pub limit: Option, /// Optional item pagination direction; defaults to ascending. #[ts(optional = nullable)] pub sort_direction: Option, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadItemEntry { /// Turn containing this item. pub turn_id: String, pub item: ThreadItem, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadItemsListResponse { pub data: Vec, /// 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, /// 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, } /// EXPERIMENTAL - list ordinary and realtime thread history in rollout order. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadTimelineListParams { pub thread_id: String, #[ts(optional = nullable)] pub cursor: Option, #[ts(optional = nullable)] pub limit: Option, } /// EXPERIMENTAL - one item or turn boundary in canonical rollout order. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde( tag = "type", rename_all = "camelCase", rename_all_fields = "camelCase" )] #[ts(tag = "type", rename_all = "camelCase", export_to = "v2/")] pub enum ThreadTimelineEntry { Item { #[ts(type = "number")] position: u64, #[schemars(rename = "turnId")] #[serde(rename = "turnId")] #[ts(rename = "turnId")] turn_id: String, item: Box, }, Realtime { #[ts(type = "number")] position: u64, item: ThreadRealtimeItem, }, TurnStarted { #[ts(type = "number")] position: u64, #[ts(rename = "turnId")] turn_id: String, #[ts(rename = "startedAt", type = "number | null")] started_at: Option, }, TurnCompleted { #[ts(type = "number")] position: u64, #[ts(rename = "turnId")] turn_id: String, status: TurnStatus, error: Option, #[ts(rename = "startedAt", type = "number | null")] started_at: Option, #[ts(rename = "completedAt", type = "number | null")] completed_at: Option, #[ts(rename = "durationMs", type = "number | null")] duration_ms: Option, }, } /// EXPERIMENTAL - a bounded timeline page with its resolved opening voice state. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadTimelineListResponse { pub data: Vec, pub next_cursor: Option, pub active_realtime_session_at_page_start: Option, } #[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, } /// Internal-only notification containing the exact usage from one upstream /// Responses API completion. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct RawResponseCompletedNotification { pub thread_id: String, pub turn_id: String, pub response_id: String, pub usage: Option, pub usage_metadata: Option, } /// Usage metadata reported for one upstream response. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ResponseUsageMetadata { pub amount: Option, pub metadata: Option, } impl From for ResponseUsageMetadata { fn from(value: codex_protocol::ResponseUsageMetadata) -> Self { Self { amount: value.amount, metadata: value.metadata, } } } #[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, } impl From 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, #[serde(default)] #[ts(type = "number")] pub cache_write_input_tokens: i64, #[ts(type = "number")] pub output_tokens: i64, #[ts(type = "number")] pub reasoning_output_tokens: i64, } impl From 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, cache_write_input_tokens: value.cache_write_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 ThreadRevertedNotification { 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, } #[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, 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, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ThreadQueueChangedNotification { 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, }