Initial commit

This commit is contained in:
xggz
2026-03-06 22:56:13 +08:00
commit 54d1097b41
273 changed files with 92457 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AgentType {
ClaudeCode,
Codex,
OpenCode,
Auggie,
Autohand,
Cline,
CodebuddyCode,
CorustAgent,
Gemini,
GithubCopilot,
Goose,
Junie,
Qoder,
QwenCode,
FactoryDroid,
Kimi,
MinionCode,
MistralVibe,
OpenClaw,
Stakpak,
}
impl fmt::Display for AgentType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AgentType::ClaudeCode => write!(f, "Claude Code"),
AgentType::Codex => write!(f, "Codex CLI"),
AgentType::OpenCode => write!(f, "OpenCode"),
AgentType::Auggie => write!(f, "Auggie"),
AgentType::Autohand => write!(f, "Autohand"),
AgentType::Cline => write!(f, "Cline"),
AgentType::CodebuddyCode => write!(f, "Codebuddy Code"),
AgentType::CorustAgent => write!(f, "Corust Agent"),
AgentType::Gemini => write!(f, "Gemini CLI"),
AgentType::GithubCopilot => write!(f, "GitHub Copilot"),
AgentType::Goose => write!(f, "goose"),
AgentType::Junie => write!(f, "Junie"),
AgentType::Qoder => write!(f, "Qoder CLI"),
AgentType::QwenCode => write!(f, "Qwen Code"),
AgentType::FactoryDroid => write!(f, "Factory Droid"),
AgentType::Kimi => write!(f, "Kimi CLI"),
AgentType::MinionCode => write!(f, "Minion Code"),
AgentType::MistralVibe => write!(f, "Mistral Vibe"),
AgentType::OpenClaw => write!(f, "OpenClaw"),
AgentType::Stakpak => write!(f, "Stakpak"),
}
}
}

View File

@@ -0,0 +1,97 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use super::agent::AgentType;
use super::message::{MessageTurn, TurnUsage};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConversationSummary {
pub id: String,
pub agent_type: AgentType,
pub folder_path: Option<String>,
pub folder_name: Option<String>,
pub title: Option<String>,
pub started_at: DateTime<Utc>,
pub ended_at: Option<DateTime<Utc>>,
pub message_count: u32,
pub model: Option<String>,
pub git_branch: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
pub struct DbConversationSummary {
pub id: i32,
pub folder_id: i32,
pub title: Option<String>,
pub agent_type: AgentType,
pub status: String,
pub model: Option<String>,
pub git_branch: Option<String>,
pub external_id: Option<String>,
pub message_count: u32,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SessionStats {
pub total_usage: Option<TurnUsage>,
#[serde(skip_serializing_if = "Option::is_none")]
pub total_tokens: Option<u64>,
pub total_duration_ms: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub context_window_used_tokens: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub context_window_max_tokens: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub context_window_usage_percent: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConversationDetail {
pub summary: ConversationSummary,
pub turns: Vec<MessageTurn>,
#[serde(skip_serializing_if = "Option::is_none")]
pub session_stats: Option<SessionStats>,
}
#[derive(Debug, Clone, Serialize)]
pub struct DbConversationDetail {
pub summary: DbConversationSummary,
pub turns: Vec<MessageTurn>,
#[serde(skip_serializing_if = "Option::is_none")]
pub session_stats: Option<SessionStats>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FolderInfo {
pub path: String,
pub name: String,
pub agent_types: Vec<AgentType>,
pub conversation_count: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentStats {
pub total_conversations: u32,
pub total_messages: u32,
pub by_agent: Vec<AgentConversationCount>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentConversationCount {
pub agent_type: AgentType,
pub conversation_count: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SidebarData {
pub folders: Vec<FolderInfo>,
pub stats: AgentStats,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ImportResult {
pub imported: u32,
pub skipped: u32,
}

View File

@@ -0,0 +1,44 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use super::agent::AgentType;
#[derive(Debug, Clone, Serialize)]
pub struct FolderHistoryEntry {
pub id: i32,
pub path: String,
pub name: String,
pub last_opened_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize)]
pub struct FolderDetail {
pub id: i32,
pub name: String,
pub path: String,
pub git_branch: Option<String>,
pub parent_branch: Option<String>,
pub default_agent_type: Option<AgentType>,
pub last_opened_at: DateTime<Utc>,
pub opened_conversations: Vec<OpenedConversation>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OpenedConversation {
pub conversation_id: i32,
pub agent_type: AgentType,
pub position: i32,
pub is_active: bool,
pub is_pinned: bool,
}
#[derive(Debug, Clone, Serialize)]
pub struct FolderCommandInfo {
pub id: i32,
pub folder_id: i32,
pub name: String,
pub command: String,
pub sort_order: i32,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}

View File

@@ -0,0 +1,76 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum MessageRole {
User,
Assistant,
System,
Tool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ContentBlock {
Text {
text: String,
},
ToolUse {
tool_use_id: Option<String>,
tool_name: String,
input_preview: Option<String>,
},
ToolResult {
tool_use_id: Option<String>,
output_preview: Option<String>,
is_error: bool,
},
Thinking {
text: String,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TurnUsage {
pub input_tokens: u64,
pub output_tokens: u64,
pub cache_creation_input_tokens: u64,
pub cache_read_input_tokens: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UnifiedMessage {
pub id: String,
pub role: MessageRole,
pub content: Vec<ContentBlock>,
pub timestamp: DateTime<Utc>,
#[serde(skip_serializing_if = "Option::is_none")]
pub usage: Option<TurnUsage>,
#[serde(skip_serializing_if = "Option::is_none")]
pub duration_ms: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TurnRole {
User,
Assistant,
System,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageTurn {
pub id: String,
pub role: TurnRole,
pub blocks: Vec<ContentBlock>,
pub timestamp: DateTime<Utc>,
#[serde(skip_serializing_if = "Option::is_none")]
pub usage: Option<TurnUsage>,
#[serde(skip_serializing_if = "Option::is_none")]
pub duration_ms: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
}

View File

@@ -0,0 +1,15 @@
pub mod agent;
pub mod conversation;
pub mod folder;
pub mod message;
pub mod system;
pub use agent::AgentType;
pub use conversation::{
AgentConversationCount, AgentStats, ConversationDetail, ConversationSummary,
DbConversationDetail, DbConversationSummary, FolderInfo, ImportResult, SessionStats,
SidebarData,
};
pub use folder::{FolderCommandInfo, FolderDetail, FolderHistoryEntry, OpenedConversation};
pub use message::{ContentBlock, MessageRole, MessageTurn, TurnRole, TurnUsage, UnifiedMessage};
pub use system::SystemProxySettings;

View File

@@ -0,0 +1,7 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SystemProxySettings {
pub enabled: bool,
pub proxy_url: Option<String>,
}