use crate::io::items::ThreadItem;
use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum UserInput {
Text { text: String },
Image { data: String },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ClientInfo {
pub name: String,
pub version: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct InitializeCapabilities {
#[serde(default)]
pub experimental_api: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub opt_out_notification_methods: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct InitializeParams {
pub client_info: ClientInfo,
#[serde(skip_serializing_if = "Option::is_none")]
pub capabilities: Option<InitializeCapabilities>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct InitializeResponse {
pub user_agent: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThreadStartParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub instructions: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<Value>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThreadInfo {
pub id: String,
#[serde(flatten)]
pub extra: Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThreadStartResponse {
pub thread: ThreadInfo,
#[serde(default)]
pub model: Option<String>,
#[serde(flatten)]
pub extra: Value,
}
impl ThreadStartResponse {
pub fn thread_id(&self) -> &str {
&self.thread.id
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThreadArchiveParams {
pub thread_id: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThreadArchiveResponse {}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TurnStartParams {
pub thread_id: String,
pub input: Vec<UserInput>,
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reasoning_effort: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sandbox_policy: Option<Value>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TurnStartResponse {}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TurnInterruptParams {
pub thread_id: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TurnInterruptResponse {}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum TurnStatus {
Completed,
Interrupted,
Failed,
InProgress,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TurnError {
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub codex_error_info: Option<Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Turn {
pub id: String,
#[serde(default)]
pub items: Vec<ThreadItem>,
pub status: TurnStatus,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<TurnError>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TokenCounts {
#[serde(default)]
pub input_tokens: u64,
#[serde(default)]
pub output_tokens: u64,
#[serde(default)]
pub cached_input_tokens: u64,
#[serde(default)]
pub reasoning_output_tokens: u64,
#[serde(default)]
pub total_tokens: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TokenUsage {
pub last: TokenCounts,
pub total: TokenCounts,
pub model_context_window: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum ThreadStatus {
NotLoaded,
Idle,
Active {
#[serde(default, skip_serializing_if = "Vec::is_empty")]
active_flags: Vec<Value>,
},
SystemError,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThreadStartedNotification {
pub thread: ThreadInfo,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThreadStatusChangedNotification {
pub thread_id: String,
pub status: ThreadStatus,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TurnStartedNotification {
pub thread_id: String,
pub turn: Turn,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TurnCompletedNotification {
pub thread_id: String,
pub turn: Turn,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemStartedNotification {
pub thread_id: String,
pub turn_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub started_at_ms: Option<i64>,
pub item: ThreadItem,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemCompletedNotification {
pub thread_id: String,
pub turn_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub completed_at_ms: Option<i64>,
pub item: ThreadItem,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AgentMessageDeltaNotification {
pub thread_id: String,
pub item_id: String,
pub delta: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CmdOutputDeltaNotification {
pub thread_id: String,
pub item_id: String,
pub delta: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FileChangeOutputDeltaNotification {
pub thread_id: String,
pub item_id: String,
pub delta: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ReasoningDeltaNotification {
pub thread_id: String,
pub item_id: String,
pub delta: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ErrorNotification {
pub error: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub thread_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub turn_id: Option<String>,
#[serde(default)]
pub will_retry: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThreadTokenUsageUpdatedNotification {
pub thread_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub turn_id: Option<String>,
pub token_usage: TokenUsage,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RateLimitWindow {
pub resets_at: i64,
pub used_percent: i32,
pub window_duration_mins: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RateLimits {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub credits: Option<Value>,
pub limit_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub limit_name: Option<String>,
pub plan_type: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub primary: Option<RateLimitWindow>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub secondary: Option<RateLimitWindow>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rate_limit_reached_type: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AccountRateLimitsUpdatedNotification {
pub rate_limits: RateLimits,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct McpServerStartupStatusUpdatedNotification {
pub name: String,
pub status: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RemoteControlStatusChangedNotification {
pub status: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub environment_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FileChangePatchUpdatedNotification {
pub thread_id: String,
pub turn_id: String,
pub item_id: String,
pub changes: Vec<crate::FileUpdateChange>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlanDeltaNotification {
pub thread_id: String,
pub turn_id: String,
pub item_id: String,
pub delta: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TurnPlanStep {
pub step: String,
pub status: TurnPlanStepStatus,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum TurnPlanStepStatus {
Pending,
InProgress,
Completed,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TurnPlanUpdatedNotification {
pub thread_id: String,
pub turn_id: String,
pub plan: Vec<TurnPlanStep>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub explanation: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TurnDiffUpdatedNotification {
pub thread_id: String,
pub turn_id: String,
pub diff: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ReasoningSummaryPartAddedNotification {
pub thread_id: String,
pub turn_id: String,
pub item_id: String,
pub summary_index: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ReasoningTextDeltaNotification {
pub thread_id: String,
pub turn_id: String,
pub item_id: String,
pub content_index: i64,
pub delta: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct McpServerOauthLoginCompletedNotification {
pub name: String,
pub success: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AccountLoginCompletedNotification {
pub success: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub login_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DeprecationNoticeNotification {
pub summary: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub details: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GuardianWarningNotification {
pub thread_id: String,
pub message: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WarningNotification {
pub message: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub thread_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThreadArchivedNotification {
pub thread_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThreadClosedNotification {
pub thread_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThreadUnarchivedNotification {
pub thread_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThreadGoalClearedNotification {
pub thread_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThreadNameUpdatedNotification {
pub thread_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub thread_name: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SkillsChangedNotification {}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FsChangedNotification {
pub watch_id: String,
pub changed_paths: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ConfigWarningNotification {
pub summary: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub details: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub range: Option<Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct AccountUpdatedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct AppListUpdatedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct CommandExecOutputDeltaNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ExternalAgentConfigImportCompletedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct FuzzyFileSearchSessionCompletedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct FuzzyFileSearchSessionUpdatedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct HookCompletedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct HookStartedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ItemGuardianApprovalReviewCompletedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ItemGuardianApprovalReviewStartedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct TerminalInteractionNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct McpToolCallProgressNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ModelReroutedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ModelVerificationNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ProcessExitedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ProcessOutputDeltaNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ServerRequestResolvedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ContextCompactedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ThreadGoalUpdatedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ThreadRealtimeClosedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ThreadRealtimeErrorNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ThreadRealtimeItemAddedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ThreadRealtimeOutputAudioDeltaNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ThreadRealtimeSdpNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ThreadRealtimeStartedNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ThreadRealtimeTranscriptDeltaNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct ThreadRealtimeTranscriptDoneNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct WindowsWorldWritableWarningNotification(pub Value);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct WindowsSandboxSetupCompletedNotification(pub Value);
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum CommandApprovalDecision {
Accept,
AcceptForSession,
Decline,
Cancel,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommandExecutionApprovalParams {
pub thread_id: String,
pub turn_id: String,
pub call_id: String,
pub command: String,
pub cwd: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommandExecutionApprovalResponse {
pub decision: CommandApprovalDecision,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum FileChangeApprovalDecision {
Accept,
AcceptForSession,
Decline,
Cancel,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FileChangeApprovalParams {
pub thread_id: String,
pub turn_id: String,
pub call_id: String,
pub changes: Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FileChangeApprovalResponse {
pub decision: FileChangeApprovalDecision,
}
pub mod methods {
pub const INITIALIZE: &str = "initialize";
pub const INITIALIZED: &str = "initialized";
pub const THREAD_START: &str = "thread/start";
pub const THREAD_ARCHIVE: &str = "thread/archive";
pub const TURN_START: &str = "turn/start";
pub const TURN_INTERRUPT: &str = "turn/interrupt";
pub const TURN_STEER: &str = "turn/steer";
pub const THREAD_RESUME: &str = "thread/resume";
pub const THREAD_FORK: &str = "thread/fork";
pub const THREAD_UNSUBSCRIBE: &str = "thread/unsubscribe";
pub const THREAD_NAME_SET: &str = "thread/name/set";
pub const THREAD_METADATA_UPDATE: &str = "thread/metadata/update";
pub const THREAD_UNARCHIVE: &str = "thread/unarchive";
pub const THREAD_COMPACT_START: &str = "thread/compact/start";
pub const THREAD_SHELLCOMMAND: &str = "thread/shellCommand";
pub const THREAD_APPROVEGUARDIANDENIEDACTION: &str = "thread/approveGuardianDeniedAction";
pub const THREAD_ROLLBACK: &str = "thread/rollback";
pub const THREAD_LIST: &str = "thread/list";
pub const THREAD_LOADED_LIST: &str = "thread/loaded/list";
pub const THREAD_READ: &str = "thread/read";
pub const THREAD_INJECT_ITEMS: &str = "thread/inject_items";
pub const SKILLS_LIST: &str = "skills/list";
pub const HOOKS_LIST: &str = "hooks/list";
pub const MARKETPLACE_ADD: &str = "marketplace/add";
pub const MARKETPLACE_REMOVE: &str = "marketplace/remove";
pub const MARKETPLACE_UPGRADE: &str = "marketplace/upgrade";
pub const PLUGIN_LIST: &str = "plugin/list";
pub const PLUGIN_READ: &str = "plugin/read";
pub const PLUGIN_SKILL_READ: &str = "plugin/skill/read";
pub const PLUGIN_SHARE_SAVE: &str = "plugin/share/save";
pub const PLUGIN_SHARE_UPDATETARGETS: &str = "plugin/share/updateTargets";
pub const PLUGIN_SHARE_LIST: &str = "plugin/share/list";
pub const PLUGIN_SHARE_CHECKOUT: &str = "plugin/share/checkout";
pub const PLUGIN_SHARE_DELETE: &str = "plugin/share/delete";
pub const APP_LIST: &str = "app/list";
pub const FS_READFILE: &str = "fs/readFile";
pub const FS_WRITEFILE: &str = "fs/writeFile";
pub const FS_CREATEDIRECTORY: &str = "fs/createDirectory";
pub const FS_GETMETADATA: &str = "fs/getMetadata";
pub const FS_READDIRECTORY: &str = "fs/readDirectory";
pub const FS_REMOVE: &str = "fs/remove";
pub const FS_COPY: &str = "fs/copy";
pub const FS_WATCH: &str = "fs/watch";
pub const FS_UNWATCH: &str = "fs/unwatch";
pub const SKILLS_CONFIG_WRITE: &str = "skills/config/write";
pub const PLUGIN_INSTALL: &str = "plugin/install";
pub const PLUGIN_UNINSTALL: &str = "plugin/uninstall";
pub const REVIEW_START: &str = "review/start";
pub const MODEL_LIST: &str = "model/list";
pub const MODELPROVIDER_CAPABILITIES_READ: &str = "modelProvider/capabilities/read";
pub const EXPERIMENTALFEATURE_LIST: &str = "experimentalFeature/list";
pub const EXPERIMENTALFEATURE_ENABLEMENT_SET: &str = "experimentalFeature/enablement/set";
pub const MCPSERVER_OAUTH_LOGIN: &str = "mcpServer/oauth/login";
pub const CONFIG_MCPSERVER_RELOAD: &str = "config/mcpServer/reload";
pub const MCPSERVERSTATUS_LIST: &str = "mcpServerStatus/list";
pub const MCPSERVER_RESOURCE_READ: &str = "mcpServer/resource/read";
pub const MCPSERVER_TOOL_CALL: &str = "mcpServer/tool/call";
pub const WINDOWSSANDBOX_SETUPSTART: &str = "windowsSandbox/setupStart";
pub const WINDOWSSANDBOX_READINESS: &str = "windowsSandbox/readiness";
pub const ACCOUNT_LOGIN_START: &str = "account/login/start";
pub const ACCOUNT_LOGIN_CANCEL: &str = "account/login/cancel";
pub const ACCOUNT_LOGOUT: &str = "account/logout";
pub const ACCOUNT_RATELIMITS_READ: &str = "account/rateLimits/read";
pub const ACCOUNT_SENDADDCREDITSNUDGEEMAIL: &str = "account/sendAddCreditsNudgeEmail";
pub const FEEDBACK_UPLOAD: &str = "feedback/upload";
pub const COMMAND_EXEC: &str = "command/exec";
pub const COMMAND_EXEC_WRITE: &str = "command/exec/write";
pub const COMMAND_EXEC_TERMINATE: &str = "command/exec/terminate";
pub const COMMAND_EXEC_RESIZE: &str = "command/exec/resize";
pub const CONFIG_READ: &str = "config/read";
pub const EXTERNALAGENTCONFIG_DETECT: &str = "externalAgentConfig/detect";
pub const EXTERNALAGENTCONFIG_IMPORT: &str = "externalAgentConfig/import";
pub const CONFIG_VALUE_WRITE: &str = "config/value/write";
pub const CONFIG_BATCHWRITE: &str = "config/batchWrite";
pub const CONFIGREQUIREMENTS_READ: &str = "configRequirements/read";
pub const ACCOUNT_READ: &str = "account/read";
pub const FUZZYFILESEARCH: &str = "fuzzyFileSearch";
pub const THREAD_STARTED: &str = "thread/started";
pub const THREAD_STATUS_CHANGED: &str = "thread/status/changed";
pub const THREAD_TOKEN_USAGE_UPDATED: &str = "thread/tokenUsage/updated";
pub const TURN_STARTED: &str = "turn/started";
pub const TURN_COMPLETED: &str = "turn/completed";
pub const ITEM_STARTED: &str = "item/started";
pub const ITEM_COMPLETED: &str = "item/completed";
pub const AGENT_MESSAGE_DELTA: &str = "item/agentMessage/delta";
pub const CMD_OUTPUT_DELTA: &str = "item/commandExecution/outputDelta";
pub const FILE_CHANGE_OUTPUT_DELTA: &str = "item/fileChange/outputDelta";
pub const REASONING_DELTA: &str = "item/reasoning/summaryTextDelta";
pub const ERROR: &str = "error";
pub const ACCOUNT_RATE_LIMITS_UPDATED: &str = "account/rateLimits/updated";
pub const MCP_SERVER_STARTUP_STATUS_UPDATED: &str = "mcpServer/startupStatus/updated";
pub const MCP_SERVER_OAUTH_LOGIN_COMPLETED: &str = "mcpServer/oauthLogin/completed";
pub const REMOTE_CONTROL_STATUS_CHANGED: &str = "remoteControl/status/changed";
pub const FILE_CHANGE_PATCH_UPDATED: &str = "item/fileChange/patchUpdated";
pub const PLAN_DELTA: &str = "item/plan/delta";
pub const TURN_PLAN_UPDATED: &str = "turn/plan/updated";
pub const TURN_DIFF_UPDATED: &str = "turn/diff/updated";
pub const REASONING_SUMMARY_PART_ADDED: &str = "item/reasoning/summaryPartAdded";
pub const REASONING_TEXT_DELTA: &str = "item/reasoning/textDelta";
pub const ACCOUNT_LOGIN_COMPLETED: &str = "account/login/completed";
pub const DEPRECATION_NOTICE: &str = "deprecationNotice";
pub const GUARDIAN_WARNING: &str = "guardianWarning";
pub const WARNING: &str = "warning";
pub const THREAD_ARCHIVED: &str = "thread/archived";
pub const THREAD_CLOSED: &str = "thread/closed";
pub const THREAD_UNARCHIVED: &str = "thread/unarchived";
pub const THREAD_GOAL_CLEARED: &str = "thread/goal/cleared";
pub const THREAD_NAME_UPDATED: &str = "thread/name/updated";
pub const SKILLS_CHANGED: &str = "skills/changed";
pub const FS_CHANGED: &str = "fs/changed";
pub const CONFIG_WARNING: &str = "configWarning";
pub const ACCOUNT_UPDATED: &str = "account/updated";
pub const APP_LIST_UPDATED: &str = "app/list/updated";
pub const COMMAND_EXEC_OUTPUT_DELTA: &str = "command/exec/outputDelta";
pub const EXTERNAL_AGENT_CONFIG_IMPORT_COMPLETED: &str = "externalAgentConfig/import/completed";
pub const FUZZY_FILE_SEARCH_SESSION_COMPLETED: &str = "fuzzyFileSearch/sessionCompleted";
pub const FUZZY_FILE_SEARCH_SESSION_UPDATED: &str = "fuzzyFileSearch/sessionUpdated";
pub const HOOK_COMPLETED: &str = "hook/completed";
pub const HOOK_STARTED: &str = "hook/started";
pub const ITEM_AUTO_APPROVAL_REVIEW_COMPLETED: &str = "item/autoApprovalReview/completed";
pub const ITEM_AUTO_APPROVAL_REVIEW_STARTED: &str = "item/autoApprovalReview/started";
pub const ITEM_COMMAND_EXEC_TERMINAL_INTERACTION: &str =
"item/commandExecution/terminalInteraction";
pub const ITEM_MCP_TOOL_CALL_PROGRESS: &str = "item/mcpToolCall/progress";
pub const MODEL_REROUTED: &str = "model/rerouted";
pub const MODEL_VERIFICATION: &str = "model/verification";
pub const PROCESS_EXITED: &str = "process/exited";
pub const PROCESS_OUTPUT_DELTA: &str = "process/outputDelta";
pub const SERVER_REQUEST_RESOLVED: &str = "serverRequest/resolved";
pub const THREAD_COMPACTED: &str = "thread/compacted";
pub const THREAD_GOAL_UPDATED: &str = "thread/goal/updated";
pub const THREAD_REALTIME_CLOSED: &str = "thread/realtime/closed";
pub const THREAD_REALTIME_ERROR: &str = "thread/realtime/error";
pub const THREAD_REALTIME_ITEM_ADDED: &str = "thread/realtime/itemAdded";
pub const THREAD_REALTIME_OUTPUT_AUDIO_DELTA: &str = "thread/realtime/outputAudio/delta";
pub const THREAD_REALTIME_SDP: &str = "thread/realtime/sdp";
pub const THREAD_REALTIME_STARTED: &str = "thread/realtime/started";
pub const THREAD_REALTIME_TRANSCRIPT_DELTA: &str = "thread/realtime/transcript/delta";
pub const THREAD_REALTIME_TRANSCRIPT_DONE: &str = "thread/realtime/transcript/done";
pub const WINDOWS_WORLD_WRITABLE_WARNING: &str = "windows/worldWritableWarning";
pub const WINDOWS_SANDBOX_SETUP_COMPLETED: &str = "windowsSandbox/setupCompleted";
pub const CMD_EXEC_APPROVAL: &str = "item/commandExecution/requestApproval";
pub const FILE_CHANGE_APPROVAL: &str = "item/fileChange/requestApproval";
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_initialize_params() {
let params = InitializeParams {
client_info: ClientInfo {
name: "my-app".to_string(),
version: "1.0.0".to_string(),
title: Some("My App".to_string()),
},
capabilities: None,
};
let json = serde_json::to_string(¶ms).unwrap();
assert!(json.contains("clientInfo"));
assert!(json.contains("my-app"));
assert!(!json.contains("capabilities"));
}
#[test]
fn test_initialize_response() {
let json = r#"{"userAgent":"codex-cli/0.104.0"}"#;
let resp: InitializeResponse = serde_json::from_str(json).unwrap();
assert_eq!(resp.user_agent, "codex-cli/0.104.0");
}
#[test]
fn test_initialize_capabilities() {
let params = InitializeParams {
client_info: ClientInfo {
name: "test".to_string(),
version: "0.1.0".to_string(),
title: None,
},
capabilities: Some(InitializeCapabilities {
experimental_api: true,
opt_out_notification_methods: Some(vec!["thread/started".to_string()]),
}),
};
let json = serde_json::to_string(¶ms).unwrap();
assert!(json.contains("experimentalApi"));
assert!(json.contains("optOutNotificationMethods"));
}
#[test]
fn test_user_input_text() {
let input = UserInput::Text {
text: "Hello".to_string(),
};
let json = serde_json::to_string(&input).unwrap();
assert!(json.contains(r#""type":"text""#));
let parsed: UserInput = serde_json::from_str(&json).unwrap();
assert!(matches!(parsed, UserInput::Text { text } if text == "Hello"));
}
#[test]
fn test_thread_start_params() {
let params = ThreadStartParams {
instructions: Some("Be helpful".to_string()),
tools: None,
};
let json = serde_json::to_string(¶ms).unwrap();
assert!(json.contains("instructions"));
assert!(!json.contains("tools"));
}
#[test]
fn test_thread_start_response() {
let json = r#"{"thread":{"id":"th_abc123"},"model":"gpt-4","approvalPolicy":"never","cwd":"/tmp","modelProvider":"openai","sandbox":{}}"#;
let resp: ThreadStartResponse = serde_json::from_str(json).unwrap();
assert_eq!(resp.thread_id(), "th_abc123");
assert_eq!(resp.model.as_deref(), Some("gpt-4"));
}
#[test]
fn test_turn_start_params() {
let params = TurnStartParams {
thread_id: "th_1".to_string(),
input: vec![UserInput::Text {
text: "What is 2+2?".to_string(),
}],
model: None,
reasoning_effort: None,
sandbox_policy: None,
};
let json = serde_json::to_string(¶ms).unwrap();
assert!(json.contains("threadId"));
assert!(json.contains("input"));
}
#[test]
fn test_turn_status() {
let json = r#""completed""#;
let status: TurnStatus = serde_json::from_str(json).unwrap();
assert_eq!(status, TurnStatus::Completed);
}
#[test]
fn test_turn_completed_notification() {
let json = r#"{
"threadId": "th_1",
"turnId": "t_1",
"turn": {
"id": "t_1",
"items": [],
"status": "completed"
}
}"#;
let notif: TurnCompletedNotification = serde_json::from_str(json).unwrap();
assert_eq!(notif.thread_id, "th_1");
assert_eq!(notif.turn.status, TurnStatus::Completed);
}
#[test]
fn test_agent_message_delta() {
let json = r#"{"threadId":"th_1","itemId":"msg_1","delta":"Hello "}"#;
let notif: AgentMessageDeltaNotification = serde_json::from_str(json).unwrap();
assert_eq!(notif.delta, "Hello ");
}
#[test]
fn test_command_approval_decision() {
let json = r#""accept""#;
let decision: CommandApprovalDecision = serde_json::from_str(json).unwrap();
assert_eq!(decision, CommandApprovalDecision::Accept);
let json = r#""acceptForSession""#;
let decision: CommandApprovalDecision = serde_json::from_str(json).unwrap();
assert_eq!(decision, CommandApprovalDecision::AcceptForSession);
}
#[test]
fn test_command_approval_params() {
let json = r#"{
"threadId": "th_1",
"turnId": "t_1",
"callId": "call_1",
"command": "rm -rf /tmp/test",
"cwd": "/home/user"
}"#;
let params: CommandExecutionApprovalParams = serde_json::from_str(json).unwrap();
assert_eq!(params.command, "rm -rf /tmp/test");
}
#[test]
fn test_error_notification() {
let json = r#"{"error":"something failed","willRetry":true}"#;
let notif: ErrorNotification = serde_json::from_str(json).unwrap();
assert_eq!(notif.error, "something failed");
assert!(notif.will_retry);
}
#[test]
fn test_thread_status_idle() {
let json = r#"{"type":"idle"}"#;
let status: ThreadStatus = serde_json::from_str(json).unwrap();
assert!(matches!(status, ThreadStatus::Idle));
}
#[test]
fn test_thread_status_active_with_flags() {
let json = r#"{"type":"active","activeFlags":[]}"#;
let status: ThreadStatus = serde_json::from_str(json).unwrap();
match status {
ThreadStatus::Active { active_flags } => assert!(active_flags.is_empty()),
other => panic!("expected Active, got {:?}", other),
}
}
#[test]
fn test_token_usage() {
let json = r#"{
"last":{"inputTokens":100,"outputTokens":200,"cachedInputTokens":50,"reasoningOutputTokens":0,"totalTokens":300},
"total":{"inputTokens":1000,"outputTokens":2000,"cachedInputTokens":500,"reasoningOutputTokens":10,"totalTokens":3000},
"modelContextWindow":200000
}"#;
let usage: TokenUsage = serde_json::from_str(json).unwrap();
assert_eq!(usage.last.input_tokens, 100);
assert_eq!(usage.last.output_tokens, 200);
assert_eq!(usage.last.cached_input_tokens, 50);
assert_eq!(usage.total.input_tokens, 1000);
assert_eq!(usage.model_context_window, 200000);
}
}