From 8f27bd27352c45248f1db80a3b6e0a0c39268d8c Mon Sep 17 00:00:00 2001 From: ooodc <549496103@qq.com> Date: Tue, 28 Apr 2026 14:16:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=87=8D=E6=9E=84=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E5=92=8C=E5=8D=8F=E8=AE=AE=E6=A8=A1=E5=9D=97=EF=BC=8C=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=B7=A5=E5=85=B7=E6=B3=A8=E5=86=8C=E5=92=8C=E4=BC=9A?= =?UTF-8?q?=E8=AF=9D=E7=AE=A1=E7=90=86=E9=80=BB=E8=BE=91=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=B6=88=E6=81=AF=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/channels/cli.rs | 2 +- src/domain/mod.rs | 1 + src/domain/tools.rs | 15 ++ src/gateway/mod.rs | 1 - src/{protocol.rs => protocol/mod.rs} | 2 + src/{gateway => protocol}/ws_adapter.rs | 3 +- src/providers/mod.rs | 5 +- src/providers/traits.rs | 15 +- src/skills/mod.rs | 2 +- src/storage/error.rs | 9 ++ src/storage/mod.rs | 184 +----------------------- src/storage/records.rs | 169 ++++++++++++++++++++++ src/tools/registry.rs | 2 +- 13 files changed, 211 insertions(+), 199 deletions(-) create mode 100644 src/domain/tools.rs rename src/{protocol.rs => protocol/mod.rs} (99%) rename src/{gateway => protocol}/ws_adapter.rs (99%) create mode 100644 src/storage/error.rs create mode 100644 src/storage/records.rs diff --git a/src/channels/cli.rs b/src/channels/cli.rs index 4571ced..8e0e82f 100644 --- a/src/channels/cli.rs +++ b/src/channels/cli.rs @@ -4,8 +4,8 @@ use std::sync::Arc; use tokio::sync::{RwLock, mpsc}; use crate::bus::{MessageBus, OutboundMessage}; -use crate::gateway::ws_adapter::ws_outbound_from_outbound_message; use crate::protocol::WsOutbound; +use crate::protocol::ws_adapter::ws_outbound_from_outbound_message; use super::base::{Channel, ChannelError}; diff --git a/src/domain/mod.rs b/src/domain/mod.rs index ba63992..0ec9794 100644 --- a/src/domain/mod.rs +++ b/src/domain/mod.rs @@ -1 +1,2 @@ pub mod messages; +pub mod tools; diff --git a/src/domain/tools.rs b/src/domain/tools.rs new file mode 100644 index 0000000..9ecd310 --- /dev/null +++ b/src/domain/tools.rs @@ -0,0 +1,15 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Tool { + #[serde(rename = "type")] + pub tool_type: String, + pub function: ToolFunction, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ToolFunction { + pub name: String, + pub description: String, + pub parameters: serde_json::Value, +} diff --git a/src/gateway/mod.rs b/src/gateway/mod.rs index ff50c3c..88a98ea 100644 --- a/src/gateway/mod.rs +++ b/src/gateway/mod.rs @@ -15,7 +15,6 @@ pub mod session_factory; pub mod session_pool; pub mod tool_registry_factory; pub mod ws; -pub mod ws_adapter; use axum::{Router, routing}; use std::collections::HashMap; diff --git a/src/protocol.rs b/src/protocol/mod.rs similarity index 99% rename from src/protocol.rs rename to src/protocol/mod.rs index a74a8c4..3382d12 100644 --- a/src/protocol.rs +++ b/src/protocol/mod.rs @@ -1,3 +1,5 @@ +pub mod ws_adapter; + use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/src/gateway/ws_adapter.rs b/src/protocol/ws_adapter.rs similarity index 99% rename from src/gateway/ws_adapter.rs rename to src/protocol/ws_adapter.rs index c59a5fb..9ae99dd 100644 --- a/src/gateway/ws_adapter.rs +++ b/src/protocol/ws_adapter.rs @@ -4,7 +4,8 @@ use crate::bus::OutboundMessage; use crate::bus::message::OutboundEventKind; #[cfg(test)] use crate::bus::message::{ToolMessageState, format_tool_call_content}; -use crate::protocol::WsOutbound; + +use super::WsOutbound; const TOOL_PENDING_RESUME_HINT: &str = "完成外部操作后,直接发一条继续消息即可。"; diff --git a/src/providers/mod.rs b/src/providers/mod.rs index 8e1f25a..fdf3804 100644 --- a/src/providers/mod.rs +++ b/src/providers/mod.rs @@ -7,9 +7,8 @@ pub use self::openai::OpenAIProvider; use crate::config::LLMProviderConfig; pub use crate::domain::messages::ToolCall; -pub use traits::{ - ChatCompletionRequest, ChatCompletionResponse, LLMProvider, Message, Tool, ToolFunction, Usage, -}; +pub use crate::domain::tools::{Tool, ToolFunction}; +pub use traits::{ChatCompletionRequest, ChatCompletionResponse, LLMProvider, Message, Usage}; pub fn create_provider(config: LLMProviderConfig) -> Result, ProviderError> { match config.provider_type.as_str() { diff --git a/src/providers/traits.rs b/src/providers/traits.rs index 9fd8ae8..ab0bbc3 100644 --- a/src/providers/traits.rs +++ b/src/providers/traits.rs @@ -1,4 +1,5 @@ use crate::domain::messages::{ContentBlock, ToolCall}; +use crate::domain::tools::Tool; use async_trait::async_trait; use serde::{Deserialize, Serialize}; @@ -77,20 +78,6 @@ impl Message { } } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Tool { - #[serde(rename = "type")] - pub tool_type: String, - pub function: ToolFunction, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ToolFunction { - pub name: String, - pub description: String, - pub parameters: serde_json::Value, -} - #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ChatCompletionRequest { pub messages: Vec, diff --git a/src/skills/mod.rs b/src/skills/mod.rs index 109189a..80999b9 100644 --- a/src/skills/mod.rs +++ b/src/skills/mod.rs @@ -6,7 +6,7 @@ use std::path::{Path, PathBuf}; use std::sync::RwLock; use crate::config::SkillsConfig; -use crate::providers::{Tool, ToolFunction}; +use crate::domain::tools::{Tool, ToolFunction}; #[derive(Debug, Clone)] pub struct Skill { diff --git a/src/storage/error.rs b/src/storage/error.rs new file mode 100644 index 0000000..5e67e53 --- /dev/null +++ b/src/storage/error.rs @@ -0,0 +1,9 @@ +#[derive(Debug, thiserror::Error)] +pub enum StorageError { + #[error("database error: {0}")] + Database(#[from] rusqlite::Error), + #[error("io error: {0}")] + Io(#[from] std::io::Error), + #[error("serialization error: {0}")] + Serialization(#[from] serde_json::Error), +} diff --git a/src/storage/mod.rs b/src/storage/mod.rs index 42a0dc7..2b29140 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -3,193 +3,23 @@ use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; use rusqlite::{Connection, OptionalExtension, params}; -use serde::{Deserialize, Serialize}; use crate::bus::ChatMessage; -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct SkillEventRecord { - pub id: String, - pub session_id: Option, - pub event_type: String, - pub skill_name: Option, - pub payload: serde_json::Value, - pub created_at: i64, -} +pub mod error; +pub mod records; -#[derive(Debug, thiserror::Error)] -pub enum StorageError { - #[error("database error: {0}")] - Database(#[from] rusqlite::Error), - #[error("io error: {0}")] - Io(#[from] std::io::Error), - #[error("serialization error: {0}")] - Serialization(#[from] serde_json::Error), -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct SessionRecord { - pub id: String, - pub title: String, - pub channel_name: String, - pub chat_id: String, - pub summary: Option, - pub created_at: i64, - pub updated_at: i64, - pub last_active_at: i64, - pub archived_at: Option, - pub deleted_at: Option, - pub message_count: i64, - pub reset_cutoff_seq: i64, - pub user_turn_count: i64, - pub agent_prompt_reinjection_count: i64, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct MemoryRecord { - pub id: String, - pub scope_kind: String, - pub scope_key: String, - pub namespace: String, - pub memory_key: String, - pub content: String, - pub source_type: String, - pub source_session_id: Option, - pub source_message_id: Option, - pub source_message_seq: Option, - pub source_channel_name: Option, - pub source_chat_id: Option, - pub created_at: i64, - pub updated_at: i64, -} - -#[derive(Debug, Clone)] -pub struct MemoryUpsert { - pub scope_kind: String, - pub scope_key: String, - pub namespace: String, - pub memory_key: String, - pub content: String, - pub source_type: String, - pub source_session_id: Option, - pub source_message_id: Option, - pub source_message_seq: Option, - pub source_channel_name: Option, - pub source_chat_id: Option, -} - -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -#[serde(rename_all = "snake_case")] -pub enum SchedulerJobState { - Scheduled, - Running, - Paused, - Completed, -} - -impl SchedulerJobState { - pub fn as_str(&self) -> &'static str { - match self { - SchedulerJobState::Scheduled => "scheduled", - SchedulerJobState::Running => "running", - SchedulerJobState::Paused => "paused", - SchedulerJobState::Completed => "completed", - } - } - - pub fn from_str(value: &str) -> Option { - match value { - "scheduled" => Some(Self::Scheduled), - "running" => Some(Self::Running), - "paused" => Some(Self::Paused), - "completed" => Some(Self::Completed), - _ => None, - } - } -} - -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -#[serde(rename_all = "snake_case")] -pub enum SchedulerJobStatus { - Ok, - Error, - Skipped, -} - -impl SchedulerJobStatus { - pub fn as_str(&self) -> &'static str { - match self { - SchedulerJobStatus::Ok => "ok", - SchedulerJobStatus::Error => "error", - SchedulerJobStatus::Skipped => "skipped", - } - } - - pub fn from_str(value: &str) -> Option { - match value { - "ok" => Some(Self::Ok), - "error" => Some(Self::Error), - "skipped" => Some(Self::Skipped), - _ => None, - } - } -} - -impl Default for SchedulerJobState { - fn default() -> Self { - Self::Scheduled - } -} +pub use error::StorageError; +pub use records::{ + MemoryRecord, MemoryUpsert, SchedulerJobRecord, SchedulerJobState, SchedulerJobStatus, + SchedulerJobUpsert, SessionRecord, SkillEventRecord, +}; #[derive(Clone)] pub struct SessionStore { conn: Arc>, } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct SchedulerJobRecord { - pub id: String, - pub kind: String, - pub schedule: serde_json::Value, - pub interval_secs: i64, - pub startup_delay_secs: i64, - pub target: serde_json::Value, - pub payload: serde_json::Value, - pub enabled: bool, - pub state: SchedulerJobState, - pub last_status: Option, - pub last_error: Option, - pub run_count: i64, - pub max_runs: Option, - pub last_fired_at: Option, - pub next_fire_at: Option, - pub paused_at: Option, - pub completed_at: Option, - pub created_at: i64, - pub updated_at: i64, -} - -#[derive(Debug, Clone)] -pub struct SchedulerJobUpsert { - pub id: String, - pub kind: String, - pub schedule: serde_json::Value, - pub interval_secs: i64, - pub startup_delay_secs: i64, - pub target: serde_json::Value, - pub payload: serde_json::Value, - pub enabled: bool, - pub state: SchedulerJobState, - pub last_status: Option, - pub last_error: Option, - pub run_count: i64, - pub max_runs: Option, - pub last_fired_at: Option, - pub next_fire_at: Option, - pub paused_at: Option, - pub completed_at: Option, -} - impl SessionStore { #[cfg(test)] pub fn new() -> Result { diff --git a/src/storage/records.rs b/src/storage/records.rs new file mode 100644 index 0000000..6e01384 --- /dev/null +++ b/src/storage/records.rs @@ -0,0 +1,169 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SkillEventRecord { + pub id: String, + pub session_id: Option, + pub event_type: String, + pub skill_name: Option, + pub payload: serde_json::Value, + pub created_at: i64, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SessionRecord { + pub id: String, + pub title: String, + pub channel_name: String, + pub chat_id: String, + pub summary: Option, + pub created_at: i64, + pub updated_at: i64, + pub last_active_at: i64, + pub archived_at: Option, + pub deleted_at: Option, + pub message_count: i64, + pub reset_cutoff_seq: i64, + pub user_turn_count: i64, + pub agent_prompt_reinjection_count: i64, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MemoryRecord { + pub id: String, + pub scope_kind: String, + pub scope_key: String, + pub namespace: String, + pub memory_key: String, + pub content: String, + pub source_type: String, + pub source_session_id: Option, + pub source_message_id: Option, + pub source_message_seq: Option, + pub source_channel_name: Option, + pub source_chat_id: Option, + pub created_at: i64, + pub updated_at: i64, +} + +#[derive(Debug, Clone)] +pub struct MemoryUpsert { + pub scope_kind: String, + pub scope_key: String, + pub namespace: String, + pub memory_key: String, + pub content: String, + pub source_type: String, + pub source_session_id: Option, + pub source_message_id: Option, + pub source_message_seq: Option, + pub source_channel_name: Option, + pub source_chat_id: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "snake_case")] +pub enum SchedulerJobState { + Scheduled, + Running, + Paused, + Completed, +} + +impl SchedulerJobState { + pub fn as_str(&self) -> &'static str { + match self { + SchedulerJobState::Scheduled => "scheduled", + SchedulerJobState::Running => "running", + SchedulerJobState::Paused => "paused", + SchedulerJobState::Completed => "completed", + } + } + + pub fn from_str(value: &str) -> Option { + match value { + "scheduled" => Some(Self::Scheduled), + "running" => Some(Self::Running), + "paused" => Some(Self::Paused), + "completed" => Some(Self::Completed), + _ => None, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "snake_case")] +pub enum SchedulerJobStatus { + Ok, + Error, + Skipped, +} + +impl SchedulerJobStatus { + pub fn as_str(&self) -> &'static str { + match self { + SchedulerJobStatus::Ok => "ok", + SchedulerJobStatus::Error => "error", + SchedulerJobStatus::Skipped => "skipped", + } + } + + pub fn from_str(value: &str) -> Option { + match value { + "ok" => Some(Self::Ok), + "error" => Some(Self::Error), + "skipped" => Some(Self::Skipped), + _ => None, + } + } +} + +impl Default for SchedulerJobState { + fn default() -> Self { + Self::Scheduled + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SchedulerJobRecord { + pub id: String, + pub kind: String, + pub schedule: serde_json::Value, + pub interval_secs: i64, + pub startup_delay_secs: i64, + pub target: serde_json::Value, + pub payload: serde_json::Value, + pub enabled: bool, + pub state: SchedulerJobState, + pub last_status: Option, + pub last_error: Option, + pub run_count: i64, + pub max_runs: Option, + pub last_fired_at: Option, + pub next_fire_at: Option, + pub paused_at: Option, + pub completed_at: Option, + pub created_at: i64, + pub updated_at: i64, +} + +#[derive(Debug, Clone)] +pub struct SchedulerJobUpsert { + pub id: String, + pub kind: String, + pub schedule: serde_json::Value, + pub interval_secs: i64, + pub startup_delay_secs: i64, + pub target: serde_json::Value, + pub payload: serde_json::Value, + pub enabled: bool, + pub state: SchedulerJobState, + pub last_status: Option, + pub last_error: Option, + pub run_count: i64, + pub max_runs: Option, + pub last_fired_at: Option, + pub next_fire_at: Option, + pub paused_at: Option, + pub completed_at: Option, +} diff --git a/src/tools/registry.rs b/src/tools/registry.rs index 64d0be7..cb72371 100644 --- a/src/tools/registry.rs +++ b/src/tools/registry.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use crate::providers::{Tool, ToolFunction}; +use crate::domain::tools::{Tool, ToolFunction}; use super::traits::Tool as ToolTrait;