mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
83bbb4f326
## Why The app-server thread lifecycle API should no longer expose the full `PermissionProfile` value. After the permissions-profile migration, clients should round-trip only the active profile identity through `activePermissionProfile` and `permissions` when that identity is known. The full profile is server-side config. Treating a response-derived legacy sandbox projection as a new local profile can lose named-profile restrictions and accidentally widen permissions on the next turn. The legacy `sandbox` response field remains only as the compatibility/display fallback. ## What Changed - Removed `permissionProfile` from `ThreadStartResponse`, `ThreadResumeResponse`, and `ThreadForkResponse`. - Stopped populating that field in app-server thread start/resume/fork responses. - Updated embedded exec/TUI response mapping to derive display permission state from local config or the legacy sandbox fallback instead of a response profile value. - Added a TUI turn override shape that distinguishes preserving server permissions, selecting an active profile id, and sending a legacy sandbox for an explicit local override. - Preserved remote app-server permissions across turns by sending `permissions` only when an `activePermissionProfile` id is known, and otherwise sending no sandbox override unless the user selected a local override. - Kept embedded `thread/resume` hydration server-authored when `activePermissionProfile` is absent, which matches the live-thread attach path where the server ignores requested overrides. - Updated the app-server README to remove the obsolete lifecycle response `permissionProfile` reference. The remaining `permissionProfile` README references are request-side permission overrides. - Regenerated app-server JSON schema and TypeScript fixtures. - Kept the generated typed response enum exempt from `large_enum_variant`, matching the existing payload enum exemption after the lifecycle response variants shrank. ## How To Review Start with `codex-rs/app-server-protocol/src/protocol/v2/thread.rs` to confirm the response shape, then check the response construction in `codex-rs/app-server/src/request_processors`. The generated schema and TypeScript fixture changes are mechanical follow-through from the protocol removal. The TUI behavior is the delicate part: review `codex-rs/tui/src/app_server_session.rs` for response hydration and turn-start override projection, then `codex-rs/tui/src/app/thread_routing.rs` for the decision about whether the next turn should preserve the server snapshot, send an active profile id, or send a legacy sandbox for an explicit local override. ## Verification - `just write-app-server-schema` - `cargo test -p codex-app-server-protocol thread_lifecycle_responses_default_missing_optional_fields` - `cargo test -p codex-exec session_configured_from_thread_response_uses_permission_profile_from_config` - `cargo test -p codex-tui --lib thread_response` - `cargo test -p codex-tui turn_permissions_` - `cargo test -p codex-tui resume_response_restores_turns_from_thread_items` - `cargo test -p codex-analytics track_response_only_enqueues_analytics_relevant_responses` - `just fix -p codex-analytics` - `just fix -p codex-app-server-protocol` - `just fix -p codex-tui` - `just argument-comment-lint` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/22792). * #22795 * __->__ #22792
1201 lines
43 KiB
Rust
1201 lines
43 KiB
Rust
use super::ActivePermissionProfile;
|
|
use super::ApprovalsReviewer;
|
|
use super::AskForApproval;
|
|
use super::PermissionProfileSelectionParams;
|
|
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;
|
|
use codex_protocol::config_types::Personality;
|
|
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,
|
|
}
|
|
|
|
#[derive(Serialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[ts(export_to = "v2/")]
|
|
pub struct DynamicToolSpec {
|
|
#[ts(optional)]
|
|
pub namespace: Option<String>,
|
|
pub name: String,
|
|
pub description: String,
|
|
pub input_schema: JsonValue,
|
|
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
|
pub defer_loading: bool,
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
struct DynamicToolSpecDe {
|
|
namespace: Option<String>,
|
|
name: String,
|
|
description: String,
|
|
input_schema: JsonValue,
|
|
defer_loading: Option<bool>,
|
|
expose_to_context: Option<bool>,
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for DynamicToolSpec {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: serde::Deserializer<'de>,
|
|
{
|
|
let DynamicToolSpecDe {
|
|
namespace,
|
|
name,
|
|
description,
|
|
input_schema,
|
|
defer_loading,
|
|
expose_to_context,
|
|
} = DynamicToolSpecDe::deserialize(deserializer)?;
|
|
|
|
Ok(Self {
|
|
namespace,
|
|
name,
|
|
description,
|
|
input_schema,
|
|
defer_loading: defer_loading
|
|
.unwrap_or_else(|| expose_to_context.map(|visible| !visible).unwrap_or(false)),
|
|
})
|
|
}
|
|
}
|
|
|
|
// === 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. Relative paths are
|
|
/// resolved against the effective cwd for the thread.
|
|
#[experimental("thread/start.runtimeWorkspaceRoots")]
|
|
#[ts(optional = nullable)]
|
|
pub runtime_workspace_roots: Option<Vec<PathBuf>>,
|
|
#[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")]
|
|
#[schemars(with = "Option<String>")]
|
|
#[ts(type = "string | null")]
|
|
#[ts(optional = nullable)]
|
|
pub permissions: Option<PermissionProfileSelectionParams>,
|
|
#[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")]
|
|
#[ts(optional = nullable)]
|
|
pub dynamic_tools: Option<Vec<DynamicToolSpec>>,
|
|
/// 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)]
|
|
pub experimental_raw_events: bool,
|
|
/// Deprecated and ignored by app-server. Kept only so older clients can
|
|
/// continue sending the field while rollout persistence always uses the
|
|
/// limited history policy.
|
|
#[experimental("thread/start.persistFullHistory")]
|
|
#[serde(default)]
|
|
pub persist_extended_history: 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/")]
|
|
/// 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.
|
|
///
|
|
/// The precedence is: history > path > thread_id.
|
|
/// If using history or path, the thread_id param will be ignored.
|
|
///
|
|
/// 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, the thread_id param will be ignored.
|
|
#[experimental("thread/resume.path")]
|
|
#[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. Relative paths are
|
|
/// resolved against the effective cwd for the thread.
|
|
#[experimental("thread/resume.runtimeWorkspaceRoots")]
|
|
#[ts(optional = nullable)]
|
|
pub runtime_workspace_roots: Option<Vec<PathBuf>>,
|
|
#[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")]
|
|
#[schemars(with = "Option<String>")]
|
|
#[ts(type = "string | null")]
|
|
#[ts(optional = nullable)]
|
|
pub permissions: Option<PermissionProfileSelectionParams>,
|
|
#[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,
|
|
/// Deprecated and ignored by app-server. Kept only so older clients can
|
|
/// continue sending the field while rollout persistence always uses the
|
|
/// limited history policy.
|
|
#[experimental("thread/resume.persistFullHistory")]
|
|
#[serde(default)]
|
|
pub persist_extended_history: bool,
|
|
}
|
|
|
|
#[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>,
|
|
}
|
|
|
|
#[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 path, the thread_id param will be ignored.
|
|
///
|
|
/// 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")]
|
|
#[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. Relative paths are
|
|
/// resolved against the effective cwd for the thread.
|
|
#[experimental("thread/fork.runtimeWorkspaceRoots")]
|
|
#[ts(optional = nullable)]
|
|
pub runtime_workspace_roots: Option<Vec<PathBuf>>,
|
|
#[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")]
|
|
#[schemars(with = "Option<String>")]
|
|
#[ts(type = "string | null")]
|
|
#[ts(optional = nullable)]
|
|
pub permissions: Option<PermissionProfileSelectionParams>,
|
|
#[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,
|
|
/// Deprecated and ignored by app-server. Kept only so older clients can
|
|
/// continue sending the field while rollout persistence always uses the
|
|
/// limited history policy.
|
|
#[experimental("thread/fork.persistFullHistory")]
|
|
#[serde(default)]
|
|
pub persist_extended_history: 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 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,
|
|
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 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)]
|
|
#[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>,
|
|
}
|
|
|
|
#[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, 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)]
|
|
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 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,
|
|
}
|