use serde::{Deserialize, Serialize};
pub use crate::storage::SessionMeta;
#[derive(Debug, Deserialize)]
#[serde(tag = "type")]
pub enum WsInbound {
#[serde(rename = "send_message")]
SendMessage { content: String },
#[serde(rename = "tool_confirm")]
ToolConfirm {
action: String,
#[serde(default)]
reason: Option<String>,
},
#[serde(rename = "ask_response")]
AskResponse {
answers: std::collections::HashMap<String, String>,
},
#[serde(rename = "cancel")]
Cancel,
#[serde(rename = "sync")]
Sync,
#[serde(rename = "key_exchange")]
KeyExchange { client_pk: String },
#[serde(rename = "ping")]
Ping,
#[serde(rename = "list_sessions")]
ListSessions,
#[serde(rename = "switch_session")]
SwitchSession { session_id: String },
#[serde(rename = "new_session")]
NewSession,
#[serde(rename = "select_model")]
SelectModel { index: usize },
#[serde(rename = "select_theme")]
SelectTheme { index: usize },
#[serde(rename = "request_config")]
RequestConfig { tab: String },
#[serde(rename = "config_edit_submit")]
ConfigEditSubmit { value: String },
#[serde(rename = "config_toggle")]
ConfigToggle { index: usize },
#[serde(rename = "start_archive")]
StartArchive,
#[serde(rename = "archive_with_default")]
ArchiveWithDefault,
#[serde(rename = "archive_with_custom")]
ArchiveWithCustom { name: String },
#[serde(rename = "clear_session")]
ClearSession,
#[serde(rename = "start_archive_list")]
StartArchiveList,
#[serde(rename = "restore_archive")]
RestoreArchive { index: usize },
#[serde(rename = "delete_archive")]
DeleteArchive { index: usize },
#[serde(rename = "delete_session")]
DeleteSession { index: usize },
#[serde(rename = "agent_perm_confirm")]
AgentPermConfirm { approve: bool },
#[serde(rename = "plan_approval")]
PlanApproval {
approve: bool,
#[serde(default)]
content: Option<String>,
},
#[serde(rename = "toggle_auto_approve")]
ToggleAutoApprove,
#[serde(rename = "file_list")]
FileList { path: String },
#[serde(rename = "file_read")]
FileRead { path: String },
#[serde(rename = "file_write")]
FileWrite { path: String, content: String },
#[serde(rename = "terminal_exec")]
TerminalExec { command: String },
#[serde(rename = "terminal_interrupt")]
TerminalInterrupt,
}
#[derive(Debug, Clone, Serialize)]
#[serde(tag = "type")]
#[allow(dead_code)]
pub enum WsOutbound {
#[serde(rename = "stream_chunk")]
StreamChunk { content: String },
#[serde(rename = "message")]
Message { role: String, content: String },
#[serde(rename = "tool_confirm_request")]
ToolConfirmRequest { tools: Vec<ToolConfirmInfo> },
#[serde(rename = "ask_request")]
AskRequest { questions: Vec<AskQuestionInfo> },
#[serde(rename = "tool_call")]
ToolCall {
id: String,
name: String,
arguments: String,
},
#[serde(rename = "tool_result")]
ToolResult {
id: String,
name: String,
output: String,
is_error: bool,
},
#[serde(rename = "status")]
Status { state: String },
#[serde(rename = "session_sync")]
SessionSync {
messages: Vec<SyncMessage>,
status: String,
model: String,
#[serde(default)]
context_tokens: usize,
#[serde(default)]
message_count: usize,
#[serde(default)]
auto_approve: bool,
},
#[serde(rename = "pong")]
Pong,
#[serde(rename = "server_hello")]
ServerHello { server_pk: String },
#[serde(rename = "key_exchange_ok")]
KeyExchangeOk,
#[serde(rename = "error")]
Error { message: String },
#[serde(rename = "session_list")]
SessionList { sessions: Vec<SessionMeta> },
#[serde(rename = "session_switched")]
SessionSwitched { session_id: String },
#[serde(rename = "model_list")]
ModelList {
models: Vec<ModelInfo>,
active_index: usize,
},
#[serde(rename = "theme_list")]
ThemeList {
themes: Vec<ThemeInfo>,
active_index: usize,
},
#[serde(rename = "config_data")]
ConfigData {
tab: String,
fields: Vec<ConfigField>,
},
#[serde(rename = "archive_list")]
ArchiveList { archives: Vec<ArchiveInfo> },
#[serde(rename = "agent_perm_request")]
AgentPermRequest {
agent_name: String,
tool_name: String,
arguments: String,
},
#[serde(rename = "plan_approval_request")]
PlanApprovalRequest {
agent_name: String,
plan_summary: String,
},
#[serde(rename = "file_list_result")]
FileListResult {
path: String,
entries: Vec<FileEntry>,
},
#[serde(rename = "file_read_result")]
FileReadResult {
path: String,
content: String,
#[serde(default)]
error: Option<String>,
},
#[serde(rename = "file_write_result")]
FileWriteResult {
path: String,
success: bool,
#[serde(default)]
error: Option<String>,
},
#[serde(rename = "terminal_output")]
TerminalOutput {
output: String,
exit_code: Option<i32>,
},
}
#[derive(Debug, Clone, Serialize)]
pub struct ToolConfirmInfo {
pub id: String,
pub name: String,
pub arguments: String,
pub confirm_message: String,
}
#[derive(Debug, Clone, Serialize)]
pub struct AskQuestionInfo {
pub question: String,
pub header: String,
pub options: Vec<AskOptionInfo>,
pub multi_select: bool,
}
#[derive(Debug, Clone, Serialize)]
pub struct AskOptionInfo {
pub label: String,
pub description: String,
}
#[derive(Debug, Clone, Serialize)]
pub struct SyncToolCall {
pub id: String,
pub name: String,
pub arguments: String,
}
#[derive(Debug, Clone, Serialize)]
pub struct SyncMessage {
pub role: String,
#[serde(default)]
pub content: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub tool_calls: Option<Vec<SyncToolCall>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tool_call_id: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
pub struct ModelInfo {
pub name: String,
pub model: String,
pub provider: String,
pub supports_vision: bool,
}
#[derive(Debug, Clone, Serialize)]
pub struct ThemeInfo {
pub name: String,
pub display_name: String,
}
#[derive(Debug, Clone, Serialize)]
pub struct ConfigField {
pub key: String,
pub label: String,
pub value: String,
pub field_type: String,
pub editable: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub options: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize)]
pub struct ArchiveInfo {
pub name: String,
pub created_at: String,
pub message_count: usize,
}
#[derive(Debug, Clone, Serialize)]
pub struct FileEntry {
pub name: String,
pub is_dir: bool,
pub size: u64,
pub modified: String,
}