chore: 提交所有工作进度 — SaaS 后端增强、Admin UI、桌面端集成

包含大量 SaaS 平台改进、Admin 管理后台更新、桌面端集成完善、
文档同步、测试文件重构等内容。为 QA 测试准备干净工作树。
This commit is contained in:
iven
2026-03-29 10:46:26 +08:00
parent 9a5fad2b59
commit 5fdf96c3f5
268 changed files with 22011 additions and 3886 deletions

View File

@@ -1,6 +1,7 @@
//! Agent configuration and state types
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use crate::{AgentId, Capability, ModelConfig};
/// Agent configuration
@@ -31,6 +32,13 @@ pub struct AgentConfig {
/// Temperature (0.0 - 1.0)
#[serde(default)]
pub temperature: Option<f32>,
/// Workspace directory for file access tools
#[serde(default)]
pub workspace: Option<PathBuf>,
/// Optional compaction threshold override (tokens).
/// Overrides the dynamic calculation from context_window * 0.6.
#[serde(default)]
pub compaction_threshold: Option<u32>,
/// Whether the agent is active
#[serde(default = "default_enabled")]
pub enabled: bool,
@@ -52,6 +60,8 @@ impl Default for AgentConfig {
tools: Vec::new(),
max_tokens: None,
temperature: None,
workspace: None,
compaction_threshold: None,
enabled: true,
}
}

View File

@@ -0,0 +1,196 @@
//! Hand execution tracking types
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Unique identifier for a hand execution run
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct HandRunId(pub Uuid);
impl HandRunId {
pub fn new() -> Self {
Self(Uuid::new_v4())
}
pub fn as_uuid(&self) -> &Uuid {
&self.0
}
}
impl Default for HandRunId {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Display for HandRunId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl std::str::FromStr for HandRunId {
type Err = uuid::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Uuid::parse_str(s).map(HandRunId)
}
}
/// Status of a hand execution run
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum HandRunStatus {
/// Created but not yet started
Pending,
/// Currently executing
Running,
/// Completed successfully
Completed,
/// Failed with an error
Failed,
/// Cancelled by user
Cancelled,
}
impl std::fmt::Display for HandRunStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
HandRunStatus::Pending => write!(f, "pending"),
HandRunStatus::Running => write!(f, "running"),
HandRunStatus::Completed => write!(f, "completed"),
HandRunStatus::Failed => write!(f, "failed"),
HandRunStatus::Cancelled => write!(f, "cancelled"),
}
}
}
impl std::str::FromStr for HandRunStatus {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"pending" => Ok(HandRunStatus::Pending),
"running" => Ok(HandRunStatus::Running),
"completed" => Ok(HandRunStatus::Completed),
"failed" => Ok(HandRunStatus::Failed),
"cancelled" => Ok(HandRunStatus::Cancelled),
other => Err(format!("Unknown HandRunStatus: {}", other)),
}
}
}
/// What triggered the hand execution
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TriggerSource {
/// Manual invocation from user
Manual,
/// Scheduled trigger
Scheduled { trigger_id: String },
/// Event-based trigger
Event { trigger_id: String },
/// Approval response
Approval { approval_id: String },
}
/// A single hand execution run record
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HandRun {
/// Unique run identifier
pub id: HandRunId,
/// Which hand was executed
pub hand_name: String,
/// What triggered this run
pub trigger_source: TriggerSource,
/// Input parameters
pub params: serde_json::Value,
/// Current status
pub status: HandRunStatus,
/// Output result (set on completion)
pub result: Option<serde_json::Value>,
/// Error message (set on failure)
pub error: Option<String>,
/// Duration in milliseconds (set on completion/failure)
pub duration_ms: Option<u64>,
/// When the run was created (entered Pending)
pub created_at: String,
/// When execution started (Pending → Running)
pub started_at: Option<String>,
/// When execution finished (Running → Completed/Failed/Cancelled)
pub completed_at: Option<String>,
}
/// Filter parameters for listing hand runs
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct HandRunFilter {
/// Filter by hand name
pub hand_name: Option<String>,
/// Filter by status
pub status: Option<HandRunStatus>,
/// Maximum number of results
pub limit: Option<u32>,
/// Number of results to skip
pub offset: Option<u32>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hand_run_id_unique() {
let id1 = HandRunId::new();
let id2 = HandRunId::new();
assert_ne!(id1, id2);
}
#[test]
fn test_hand_run_id_display() {
let id = HandRunId::new();
assert_eq!(id.to_string().len(), 36);
}
#[test]
fn test_hand_run_id_from_str() {
let id = HandRunId::new();
let parsed: HandRunId = id.to_string().parse().unwrap();
assert_eq!(id, parsed);
}
#[test]
fn test_hand_run_status_roundtrip() {
for status in [
HandRunStatus::Pending,
HandRunStatus::Running,
HandRunStatus::Completed,
HandRunStatus::Failed,
HandRunStatus::Cancelled,
] {
let s = status.to_string();
let parsed: HandRunStatus = s.parse().unwrap();
assert_eq!(status, parsed);
}
}
#[test]
fn test_hand_run_serialization() {
let run = HandRun {
id: HandRunId::new(),
hand_name: "browser".to_string(),
trigger_source: TriggerSource::Manual,
params: serde_json::json!({"url": "https://example.com"}),
status: HandRunStatus::Completed,
result: Some(serde_json::json!({"title": "Example"})),
error: None,
duration_ms: Some(1500),
created_at: "2026-01-01T00:00:00Z".to_string(),
started_at: Some("2026-01-01T00:00:00Z".to_string()),
completed_at: Some("2026-01-01T00:00:01Z".to_string()),
};
let json = serde_json::to_string(&run).unwrap();
let deserialized: HandRun = serde_json::from_str(&json).unwrap();
assert_eq!(run.id, deserialized.id);
assert_eq!(run.hand_name, deserialized.hand_name);
}
}

View File

@@ -10,6 +10,7 @@ pub mod error;
pub mod event;
pub mod tool;
pub mod config;
pub mod hand_run;
pub use id::*;
pub use message::*;
@@ -19,6 +20,7 @@ pub use error::*;
pub use event::*;
pub use tool::*;
pub use config::*;
pub use hand_run::*;
// Re-export commonly used external types
pub use serde_json::Value as JsonValue;