use crate::compaction::CompactionConfig;
use crate::config::ApiProvider;
use crate::models::{Message, SystemPrompt};
use crate::route_runtime::ResolvedRuntimeRoute;
use crate::tools::goal::GoalStatus;
use crate::tui::app::AppMode;
use crate::tui::approval::ApprovalMode;
use codewhale_protocol::runtime::DynamicToolSpec;
use std::path::PathBuf;
pub const USER_SHELL_TOOL_ID_PREFIX: &str = "user_shell_";
#[derive(Debug, Clone)]
pub struct SessionSnapshot {
pub messages: Vec<Message>,
pub total_tokens: u64,
pub model: String,
pub model_provider: String,
pub model_provider_id: Option<String>,
pub workspace: PathBuf,
pub system_prompt: Option<SystemPrompt>,
pub mode: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProviderRuntimeStatus {
pub provider: ApiProvider,
pub request_concurrency_limit: Option<usize>,
pub active_provider_requests: usize,
}
#[allow(dead_code)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UserInputProvenance {
ExternalUser,
Runtime,
SubAgentHandoff,
ImportedTranscript,
MemoryRecall,
AssistantGenerated,
}
impl UserInputProvenance {
pub fn as_str(self) -> &'static str {
match self {
Self::ExternalUser => "external_user",
Self::Runtime => "runtime",
Self::SubAgentHandoff => "subagent_handoff",
Self::ImportedTranscript => "imported_transcript",
Self::MemoryRecall => "memory_recall",
Self::AssistantGenerated => "assistant_generated",
}
}
pub fn can_authorize_work(self) -> bool {
matches!(self, Self::ExternalUser)
}
}
#[derive(Debug)]
pub enum Op {
SendMessage {
content: String,
mode: AppMode,
route: Box<ResolvedRuntimeRoute>,
compaction: Box<CompactionConfig>,
goal_objective: Option<String>,
goal_token_budget: Option<u32>,
goal_status: GoalStatus,
reasoning_effort: Option<String>,
reasoning_effort_auto: bool,
auto_model: bool,
allow_shell: bool,
trust_mode: bool,
auto_approve: bool,
approval_mode: ApprovalMode,
translation_enabled: bool,
show_thinking: bool,
allowed_tools: Option<Vec<String>>,
dynamic_tools: Vec<DynamicToolSpec>,
hook_executor: Option<std::sync::Arc<crate::hooks::HookExecutor>>,
verbosity: Option<String>,
provenance: UserInputProvenance,
},
RunShellCommand {
command: String,
mode: AppMode,
allow_shell: bool,
trust_mode: bool,
auto_approve: bool,
approval_mode: ApprovalMode,
},
SetGoalStatus {
status: GoalStatus,
clear: bool,
},
#[allow(dead_code)]
CancelRequest,
#[allow(dead_code)]
ApproveToolCall { id: String },
#[allow(dead_code)]
DenyToolCall { id: String },
#[allow(dead_code)]
SpawnSubAgent { prompt: String },
ListSubAgents,
CancelSubAgent { agent_id: String },
#[allow(dead_code)]
ChangeMode {
mode: AppMode,
allow_shell: bool,
trust_mode: bool,
auto_approve: bool,
approval_mode: ApprovalMode,
},
#[allow(dead_code)]
SetModel {
model: String,
mode: AppMode,
route_limits: Option<codewhale_config::route::RouteLimits>,
},
SetCompaction { config: CompactionConfig },
SetStreamChunkTimeout { timeout_secs: u64 },
SetSubagentRuntimeConfig {
enabled: bool,
max_subagents: usize,
launch_concurrency: usize,
max_spawn_depth: u32,
api_timeout_secs: u64,
heartbeat_timeout_secs: u64,
},
SetFleetRoster {
roster: std::sync::Arc<crate::fleet::roster::FleetRoster>,
},
SyncSession {
session_id: Option<String>,
messages: Vec<Message>,
system_prompt: Option<SystemPrompt>,
system_prompt_override: bool,
model: String,
workspace: PathBuf,
mode: AppMode,
},
CompactContext {
route: Box<ResolvedRuntimeRoute>,
compaction: Box<CompactionConfig>,
},
GetSessionSnapshot {
tx: std::sync::Arc<std::sync::Mutex<Option<tokio::sync::oneshot::Sender<SessionSnapshot>>>>,
},
GetProviderRuntimeStatus {
tx: std::sync::Arc<
std::sync::Mutex<Option<tokio::sync::oneshot::Sender<ProviderRuntimeStatus>>>,
>,
},
PurgeContext,
#[allow(dead_code)]
EditLastTurn { new_message: String },
Shutdown,
}