use crate::config::Provider;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use tokio::sync::mpsc;
#[derive(Debug, Clone, Default)]
pub struct CancelFlag(Arc<AtomicBool>);
impl CancelFlag {
pub fn raise(&self) {
self.0.store(true, Ordering::SeqCst);
}
pub fn is_raised(&self) -> bool {
self.0.load(Ordering::SeqCst)
}
pub fn take(&self) -> bool {
self.0.swap(false, Ordering::SeqCst)
}
pub async fn wait(&self) {
while !self.is_raised() {
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
}
}
}
pub const STELLAR_BUILD_INSTALL_URL: &str =
"https://raw.githubusercontent.com/kaankacar/stellar-build/main/install.sh";
#[derive(Debug)]
pub enum UserCommand {
SendPrompt(String),
Quit,
SetExplain(bool),
#[allow(dead_code)]
ChangeProject(String),
SwitchModel {
provider: Provider,
model: String,
},
RunTool {
name: String,
input: serde_json::Value,
label: String,
},
InstallStellarBuild,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ApprovalDecision {
Once,
Always,
Deny,
}
#[derive(Debug, Clone, PartialEq)]
pub enum TranscriptEntry {
User(String),
Agent(String),
Tool {
name: String,
ok: bool,
},
Compacted,
}
#[derive(Debug, Clone)]
pub struct ApprovalRequest {
pub tool: String,
pub detail: String,
pub scope: String,
}
#[derive(Debug, Clone)]
pub struct McpServerStatus {
pub name: String,
pub connected: bool,
pub detail: String,
}
#[derive(Debug, Clone)]
pub struct WorkspaceSnapshot {
pub project_name: String,
pub contract_name: Option<String>,
pub network: String,
pub account: String,
pub mcp_servers: Vec<McpServerStatus>,
pub mainnet_allowed: bool,
}
#[allow(dead_code)]
#[derive(Debug)]
pub enum AgentUpdate {
ResponseChunk(String),
ResponseEnd,
Status(String),
Notice(String),
Error(String),
Ready {
provider: String,
model: String,
credential: bool,
},
Workspace(WorkspaceSnapshot),
McpStatus(Vec<McpServerStatus>),
Approval(ApprovalRequest),
ToolFinished {
name: String,
ok: bool,
},
History(Vec<TranscriptEntry>),
LocalModels(Vec<String>),
Context {
used: usize,
window: usize,
},
RetractResponse,
}
pub struct Channels {
pub user_tx: mpsc::UnboundedSender<UserCommand>,
pub user_rx: mpsc::UnboundedReceiver<UserCommand>,
pub agent_tx: mpsc::UnboundedSender<AgentUpdate>,
pub agent_rx: mpsc::UnboundedReceiver<AgentUpdate>,
pub cancel: CancelFlag,
pub approval_tx: mpsc::UnboundedSender<ApprovalDecision>,
pub approval_rx: mpsc::UnboundedReceiver<ApprovalDecision>,
}
impl Channels {
pub fn new() -> Self {
let (user_tx, user_rx) = mpsc::unbounded_channel();
let (agent_tx, agent_rx) = mpsc::unbounded_channel();
let (approval_tx, approval_rx) = mpsc::unbounded_channel();
Self {
user_tx,
user_rx,
agent_tx,
agent_rx,
cancel: CancelFlag::default(),
approval_tx,
approval_rx,
}
}
}