use super::*;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ReadyPayload {
pub machine_name: String,
pub sessions: Vec<SessionRecord>,
pub swarms: Vec<SwarmRecord>,
pub providers: Vec<ProviderStatus>,
pub provider_instances: Vec<ProviderInstance>,
pub default_config: Option<VersionedAgentConfig>,
pub models: Vec<ModelChoice>,
pub model_providers: BTreeMap<String, String>,
pub middleware_features: Vec<MiddlewareFeature>,
pub extensions: Vec<ExtensionRecord>,
pub contributions: Vec<FrontendContribution>,
pub max_active_sessions: usize,
pub session_file_limits: SessionFileLimits,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SwarmRecord {
pub id: String,
pub title: String,
pub leader_session_id: String,
pub members: Vec<SwarmMemberRecord>,
pub messages: Vec<SwarmMessageRecord>,
pub updated_at_ms: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SwarmMemberRecord {
pub session_id: String,
pub handle: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SwarmMessageRecord {
pub id: String,
pub sequence: u64,
pub author_session_id: String,
pub author_handle: String,
pub body: String,
pub created_at_ms: i64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SessionReadyPayload {
pub latest_sequence: u64,
pub next_before_sequence: Option<u64>,
pub workspace: WorkspaceInfo,
pub git: Option<GitStatus>,
pub session: SessionConfiguredEvent,
pub contributions: Vec<FrontendContribution>,
pub widgets: Vec<SessionWidget>,
pub tool_count: usize,
pub compaction_count: u64,
pub context_limit_tokens: Option<i64>,
pub run_stats: RunStats,
pub config: VersionedAgentConfig,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SessionWidget {
pub capability: String,
pub item: FrontendWidget,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SessionRecord {
pub session_id: String,
pub session_context: mobius::protocol::SessionContext,
pub parent_session_id: Option<String>,
pub parent_sequence: Option<u64>,
pub sequence: u64,
pub first_user_message: Option<String>,
pub execution_stats: mobius::backend::checkpoint::ExecutionStats,
pub title: Option<String>,
pub pinned: bool,
pub activity: SessionActivity,
pub created_at: i64,
pub updated_at: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct SessionActivity {
pub state: SessionActivityState,
pub turn_id: Option<String>,
pub started_at: Option<i64>,
pub last_outcome: Option<SessionOutcome>,
pub message: Option<String>,
}
impl Default for SessionActivity {
fn default() -> Self {
Self {
state: SessionActivityState::Idle,
turn_id: None,
started_at: None,
last_outcome: None,
message: None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SessionActivityState {
Idle,
Running,
AwaitingApproval,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SessionOutcome {
Completed,
Aborted,
Failed,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct WorkspaceInfo {
pub id: String,
pub path: PathBuf,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct GitStatus {
pub current_branch: String,
pub branches: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct SshIdentityRecord {
pub label: String,
pub algorithm: String,
pub fingerprint: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum GitDiffScope {
Staged,
Unstaged,
Committed,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum WorkspaceFileScope {
Modified,
All,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct WorkspaceFileRecord {
pub path: String,
pub size: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DirectoryListing {
pub path: PathBuf,
pub parent: Option<PathBuf>,
pub entries: Vec<DirectoryEntry>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DirectoryEntry {
pub name: String,
pub path: PathBuf,
pub is_directory: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct VersionedAgentConfig {
pub revision: u64,
pub config: AgentComposition,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct AgentComposition {
pub provider: ProviderConfig,
pub middleware: MiddlewareConfig,
pub extensions: BTreeSet<String>,
pub system_prompt: String,
pub max_model_steps: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ExtensionKind {
Skill,
Plugin,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ExtensionHookRecord {
pub event: String,
pub matcher: Option<String>,
pub command: String,
pub timeout_seconds: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ExtensionRecord {
pub id: String,
pub capability: String,
pub kind: ExtensionKind,
pub name: String,
pub description: String,
pub version: Option<String>,
pub source: String,
pub reference: Option<String>,
pub subdirectory: Option<String>,
pub resolved_revision: String,
pub digest: String,
pub skills: Vec<String>,
pub hooks: Vec<ExtensionHookRecord>,
pub hooks_trusted: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ProviderConfig {
pub instance: String,
pub provider: String,
pub model: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub base_url: Option<String>,
pub endpoint_auth: ProviderEndpointAuth,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reasoning_effort: Option<String>,
pub web_search: HostedWebSearch,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ProviderEndpointAuth {
ProviderDefault,
Credentialless,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProviderStatus {
pub provider: String,
pub label: String,
pub symbol: FrontendSymbol,
pub description: String,
pub model_ids_configurable: bool,
pub auth: ProviderAuthKind,
pub default_base_url: Option<String>,
pub default_api_key_env: Option<String>,
pub models: Vec<ProviderModel>,
pub web_search: Vec<FrontendSettingOption>,
pub tool_discovery: ToolDiscoveryMode,
pub custom_endpoint_tool_discovery: Option<ToolDiscoveryMode>,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ProviderTint {
#[default]
Blue,
Teal,
Green,
Yellow,
Orange,
Red,
Purple,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProviderInstance {
pub label: String,
pub tint: ProviderTint,
pub configured: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub credential_hint: Option<String>,
pub selection: ProviderConfig,
pub model_ids: Vec<String>,
pub reasoning_efforts: Vec<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ClientKind {
Cli,
Macos,
Ios,
Ipados,
GatewayDashboard,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ClientStatus {
pub client_id: String,
pub label: String,
pub kinds: Vec<ClientKind>,
pub connections: usize,
}
impl ProviderStatus {
#[must_use]
pub fn configurable_base_url(&self) -> bool {
self.default_base_url.is_some()
}
#[must_use]
pub fn default_model(&self) -> Option<&ProviderModel> {
self.models.first()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProviderModel {
pub id: String,
pub label: String,
pub description: String,
pub context_window: i64,
pub reasoning: Vec<ReasoningChoice>,
pub default_reasoning: Option<String>,
pub tool_discovery: ToolDiscoveryMode,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ReasoningChoice {
pub id: String,
pub label: String,
pub description: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ProviderAuthKind {
ApiKey,
DeviceCode,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct MiddlewareConfig {
pub(crate) enabled: BTreeSet<String>,
pub settings: BTreeMap<String, BTreeMap<String, FrontendSettingValue>>,
}
impl MiddlewareConfig {
#[must_use]
pub fn enabled(&self, id: &str) -> bool {
self.enabled.contains(id)
}
pub fn set_enabled(&mut self, id: impl Into<String>, enabled: bool) {
let id = id.into();
if enabled {
self.enabled.insert(id);
} else {
self.enabled.remove(&id);
}
}
#[must_use]
pub fn setting(&self, middleware: &str, setting: &str) -> Option<&FrontendSettingValue> {
self.settings.get(middleware)?.get(setting)
}
pub fn set_setting(
&mut self,
middleware: impl Into<String>,
setting: impl Into<String>,
value: Option<FrontendSettingValue>,
) {
let middleware = middleware.into();
let setting = setting.into();
if let Some(value) = value {
self.settings
.entry(middleware)
.or_default()
.insert(setting, value);
} else if let Some(settings) = self.settings.get_mut(&middleware) {
settings.remove(&setting);
if settings.is_empty() {
self.settings.remove(&middleware);
}
}
}
pub(crate) fn entries(&self) -> impl Iterator<Item = &str> {
self.enabled.iter().map(String::as_str)
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RenderedPreview {
pub id: String,
pub title: String,
pub subtitle: String,
pub page_id: String,
pub update: FrontendPreviewUpdate,
pub events: Vec<RenderedEvent>,
pub next: Option<Op>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RenderedEvent {
pub recorded_at_ms: i64,
pub event: EventMsg,
pub blocks: Vec<RenderedBlock>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RecordedEvent {
pub sequence: u64,
pub recorded_at_ms: i64,
pub event: Event,
pub stream_metrics: Vec<StreamMetrics>,
pub blocks: Vec<RenderedBlock>,
pub preview: Option<RenderedPreview>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProfileSnapshot {
pub user_name: Option<String>,
pub daily_usage: Vec<DailyUsage>,
pub run_stats: RunStats,
pub recent_run_groups: Vec<SessionRunGroup>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SessionRunGroup {
pub session_id: String,
pub title: String,
pub runs: Vec<RunSummary>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct RunStats {
pub run_count: u64,
pub failed_run_count: u64,
pub aborted_run_count: u64,
pub model_calls: u64,
pub tool_calls: u64,
pub failed_tool_calls: u64,
pub elapsed_ms: u64,
pub usage: TokenUsage,
pub active: Option<RunSummary>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RunSummary {
pub session_id: String,
pub submission_id: String,
pub turn_id: String,
pub started_at_ms: i64,
pub finished_at_ms: Option<i64>,
pub elapsed_ms: u64,
pub outcome: Option<SessionOutcome>,
pub model_calls: u64,
pub tool_calls: u64,
pub failed_tool_calls: u64,
pub usage: TokenUsage,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DailyUsage {
pub unix_day: u64,
pub provider: String,
pub usage: TokenUsage,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CronTask {
pub id: String,
pub source_session_id: String,
pub task: String,
pub schedule: CronSchedule,
pub ends_at: Option<i64>,
pub enabled: bool,
pub finished: bool,
pub next_run_at: Option<i64>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CronSchedule {
pub kind: CronScheduleKind,
pub at: Option<i64>,
pub every_seconds: Option<u64>,
pub expression: Option<String>,
pub time_zone: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CronScheduleKind {
Once,
Interval,
Cron,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CronRunPreview {
pub task: CronTask,
pub run: CronRun,
pub records: Vec<RecordedEvent>,
pub next_before_sequence: Option<u64>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CronRun {
pub id: String,
pub task_id: String,
pub source_session_id: String,
pub started_at: i64,
pub finished_at: Option<i64>,
pub status: CronRunStatus,
pub session_id: Option<String>,
pub message: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CronRunStatus {
Running,
Succeeded,
Failed,
Skipped,
}