Skip to main content

mofa_plugins/
lib.rs

1#![allow(dead_code, unused_imports, improper_ctypes_definitions)]
2//! 插件机制模块
3//!
4//! 提供完整的插件系统,支持:
5//! - 插件生命周期管理
6//! - 多种插件类型(LLM、Tool、Storage、Memory 等)
7//! - 插件注册与发现
8//! - 插件间通信与依赖管理
9//! - 事件钩子机制
10//! - Agent Skills 支持
11
12pub mod hot_reload;
13pub mod skill;
14pub mod tool;
15pub mod tools;
16pub mod tts;
17pub mod wasm_runtime;
18
19pub use mofa_kernel::{
20    AgentPlugin, PluginConfig, PluginContext, PluginEvent, PluginMetadata, PluginResult,
21    PluginState, PluginType,
22};
23use serde::{Deserialize, Serialize};
24use std::any::Any;
25use std::collections::HashMap;
26use std::sync::Arc;
27use tokio::sync::RwLock;
28use tracing::{debug, error, info, warn};
29// ============================================================================
30// LLM 插件
31// ============================================================================
32
33/// LLM 客户端 trait
34#[async_trait::async_trait]
35pub trait LLMClient: Send + Sync {
36    /// 生成文本
37    async fn generate(&self, prompt: &str) -> PluginResult<String>;
38
39    /// 流式生成
40    async fn generate_stream(
41        &self,
42        prompt: &str,
43        callback: Box<dyn Fn(String) + Send + Sync>,
44    ) -> PluginResult<String>;
45
46    /// 聊天完成
47    async fn chat(&self, messages: Vec<ChatMessage>) -> PluginResult<String>;
48
49    /// 获取嵌入向量
50    async fn embedding(&self, text: &str) -> PluginResult<Vec<f32>>;
51}
52
53/// 聊天消息
54#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct ChatMessage {
56    pub role: String,
57    pub content: String,
58}
59
60impl ChatMessage {
61    pub fn system(content: &str) -> Self {
62        Self {
63            role: "system".to_string(),
64            content: content.to_string(),
65        }
66    }
67
68    pub fn user(content: &str) -> Self {
69        Self {
70            role: "user".to_string(),
71            content: content.to_string(),
72        }
73    }
74
75    pub fn assistant(content: &str) -> Self {
76        Self {
77            role: "assistant".to_string(),
78            content: content.to_string(),
79        }
80    }
81}
82
83/// LLM 插件配置
84#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct LLMPluginConfig {
86    /// 模型名称
87    pub model: String,
88    /// API 密钥
89    pub api_key: Option<String>,
90    /// API 基础 URL
91    pub base_url: Option<String>,
92    /// 最大 token 数
93    pub max_tokens: usize,
94    /// 温度参数
95    pub temperature: f32,
96    /// 超时时间(秒)
97    pub timeout_secs: u64,
98}
99
100impl Default for LLMPluginConfig {
101    fn default() -> Self {
102        Self {
103            model: "gpt-3.5-turbo".to_string(),
104            api_key: None,
105            base_url: None,
106            max_tokens: 2048,
107            temperature: 0.7,
108            timeout_secs: 30,
109        }
110    }
111}
112
113/// OpenAI 客户端实现
114pub struct OpenAIClient {
115    config: LLMPluginConfig,
116}
117
118impl OpenAIClient {
119    pub fn new(config: LLMPluginConfig) -> Self {
120        Self { config }
121    }
122}
123
124#[async_trait::async_trait]
125impl LLMClient for OpenAIClient {
126    async fn generate(&self, prompt: &str) -> PluginResult<String> {
127        // 模拟实现,实际应调用 OpenAI API
128        debug!(
129            "OpenAI generating response for prompt: {}...",
130            &prompt[..prompt.len().min(50)]
131        );
132        Ok(format!(
133            "[{}] Generated response to: {}",
134            self.config.model, prompt
135        ))
136    }
137
138    async fn generate_stream(
139        &self,
140        prompt: &str,
141        callback: Box<dyn Fn(String) + Send + Sync>,
142    ) -> PluginResult<String> {
143        // 模拟流式生成 TODO
144        let response = format!("[{}] Stream response to: {}", self.config.model, prompt);
145        for chunk in response.as_str().split_whitespace() {
146            callback(chunk.to_string());
147            tokio::time::sleep(std::time::Duration::from_millis(50)).await;
148        }
149        Ok(response)
150    }
151
152    async fn chat(&self, messages: Vec<ChatMessage>) -> PluginResult<String> {
153        let last_message = messages.last().map(|m| m.content.as_str()).unwrap_or("");
154        debug!("OpenAI chat with {} messages", messages.len());
155        Ok(format!(
156            "[{}] Chat response to: {}",
157            self.config.model, last_message
158        ))
159    }
160
161    async fn embedding(&self, text: &str) -> PluginResult<Vec<f32>> {
162        // 模拟嵌入向量
163        debug!(
164            "OpenAI generating embedding for text: {}...",
165            &text[..text.len().min(50)]
166        );
167        Ok(vec![0.1, 0.2, 0.3, 0.4, 0.5])
168    }
169}
170
171/// LLM 能力插件
172pub struct LLMPlugin {
173    metadata: PluginMetadata,
174    state: PluginState,
175    config: LLMPluginConfig,
176    client: Option<Arc<dyn LLMClient>>,
177    call_count: u64,
178    total_tokens: u64,
179}
180
181impl LLMPlugin {
182    pub fn new(plugin_id: &str) -> Self {
183        let metadata = PluginMetadata::new(plugin_id, "LLM Plugin", PluginType::LLM)
184            .with_description("Large Language Model integration plugin")
185            .with_capability("text_generation")
186            .with_capability("chat")
187            .with_capability("embedding");
188
189        Self {
190            metadata,
191            state: PluginState::Unloaded,
192            config: LLMPluginConfig::default(),
193            client: None,
194            call_count: 0,
195            total_tokens: 0,
196        }
197    }
198
199    pub fn with_config(mut self, config: LLMPluginConfig) -> Self {
200        self.config = config;
201        self
202    }
203
204    pub fn with_client<C: LLMClient + 'static>(mut self, client: C) -> Self {
205        self.client = Some(Arc::new(client));
206        self
207    }
208
209    /// 获取 LLM 客户端
210    pub fn client(&self) -> Option<&Arc<dyn LLMClient>> {
211        self.client.as_ref()
212    }
213
214    /// 聊天接口
215    pub async fn chat(&mut self, messages: Vec<ChatMessage>) -> PluginResult<String> {
216        let client = self
217            .client
218            .as_ref()
219            .ok_or_else(|| anyhow::anyhow!("LLM client not initialized"))?;
220        self.call_count += 1;
221        client.chat(messages).await
222    }
223
224    /// 生成嵌入向量
225    pub async fn embedding(&self, text: &str) -> PluginResult<Vec<f32>> {
226        let client = self
227            .client
228            .as_ref()
229            .ok_or_else(|| anyhow::anyhow!("LLM client not initialized"))?;
230        client.embedding(text).await
231    }
232}
233
234#[async_trait::async_trait]
235impl AgentPlugin for LLMPlugin {
236    fn metadata(&self) -> &PluginMetadata {
237        &self.metadata
238    }
239
240    fn state(&self) -> PluginState {
241        self.state.clone()
242    }
243
244    async fn load(&mut self, ctx: &PluginContext) -> PluginResult<()> {
245        self.state = PluginState::Loading;
246        info!("Loading LLM plugin: {}", self.metadata.id);
247
248        // 从上下文配置加载设置
249        if let Some(model) = ctx.config.get_string("model") {
250            self.config.model = model;
251        }
252        if let Some(api_key) = ctx.config.get_string("api_key") {
253            self.config.api_key = Some(api_key);
254        }
255
256        self.state = PluginState::Loaded;
257        Ok(())
258    }
259
260    async fn init_plugin(&mut self) -> PluginResult<()> {
261        info!("Initializing LLM plugin: {}", self.metadata.id);
262
263        // 初始化 LLM 客户端
264        if self.client.is_none() {
265            self.client = Some(Arc::new(OpenAIClient::new(self.config.clone())));
266        }
267
268        Ok(())
269    }
270
271    async fn start(&mut self) -> PluginResult<()> {
272        self.state = PluginState::Running;
273        info!("LLM plugin {} started", self.metadata.id);
274        Ok(())
275    }
276
277    async fn stop(&mut self) -> PluginResult<()> {
278        self.state = PluginState::Paused;
279        info!("LLM plugin {} stopped", self.metadata.id);
280        Ok(())
281    }
282
283    async fn unload(&mut self) -> PluginResult<()> {
284        self.client = None;
285        self.state = PluginState::Unloaded;
286        info!("LLM plugin {} unloaded", self.metadata.id);
287        Ok(())
288    }
289
290    async fn execute(&mut self, input: String) -> PluginResult<String> {
291        let client = self
292            .client
293            .as_ref()
294            .ok_or_else(|| anyhow::anyhow!("LLM client not initialized"))?;
295        self.call_count += 1;
296        client.generate(&input).await
297    }
298
299    fn stats(&self) -> HashMap<String, serde_json::Value> {
300        let mut stats = HashMap::new();
301        stats.insert("call_count".to_string(), serde_json::json!(self.call_count));
302        stats.insert(
303            "total_tokens".to_string(),
304            serde_json::json!(self.total_tokens),
305        );
306        stats.insert("model".to_string(), serde_json::json!(self.config.model));
307        stats
308    }
309
310    fn as_any(&self) -> &dyn Any {
311        self
312    }
313
314    fn as_any_mut(&mut self) -> &mut dyn Any {
315        self
316    }
317
318    fn into_any(self: Box<Self>) -> Box<dyn Any> {
319        self
320    }
321}
322
323// ============================================================================
324// 工具插件
325// ============================================================================
326
327pub mod rhai_runtime;
328
329pub use rhai_runtime::*;
330pub use tool::*;
331pub use tools::*;
332pub use tts::{
333    AudioPlaybackConfig, MockTTSEngine, TTSCommand, TTSEngine, TTSPlugin, TTSPluginConfig,
334    TextToSpeechTool, VoiceInfo, cache::ModelCache, model_downloader::HFHubClient, play_audio,
335    play_audio_async,
336};
337
338// Re-export KokoroTTSWrapper when kokoro feature is enabled
339#[cfg(feature = "kokoro")]
340pub use tts::kokoro_wrapper::KokoroTTS;
341
342/// 工具定义
343#[derive(Debug, Clone, Serialize, Deserialize)]
344pub struct ToolDefinition {
345    /// 工具名称
346    pub name: String,
347    /// 工具描述
348    pub description: String,
349    /// 参数 JSON Schema
350    pub parameters: serde_json::Value,
351    /// 是否需要确认
352    pub requires_confirmation: bool,
353}
354
355/// 工具调用请求
356#[derive(Debug, Clone, Serialize, Deserialize)]
357pub struct ToolCall {
358    /// 工具名称
359    pub name: String,
360    /// 调用参数
361    pub arguments: serde_json::Value,
362    /// 调用 ID
363    pub call_id: String,
364}
365
366/// 工具调用结果
367#[derive(Debug, Clone, Serialize, Deserialize)]
368pub struct ToolResult {
369    /// 调用 ID
370    pub call_id: String,
371    /// 是否成功
372    pub success: bool,
373    /// 结果数据
374    pub result: serde_json::Value,
375    /// 错误信息
376    pub error: Option<String>,
377}
378
379/// 工具执行器 trait
380#[async_trait::async_trait]
381pub trait ToolExecutor: Send + Sync {
382    /// 获取工具定义
383    fn definition(&self) -> &ToolDefinition;
384
385    /// 执行工具
386    async fn execute(&self, arguments: serde_json::Value) -> PluginResult<serde_json::Value>;
387
388    /// 验证参数
389    fn validate(&self, arguments: &serde_json::Value) -> PluginResult<()> {
390        let _ = arguments;
391        Ok(())
392    }
393}
394
395/// 工具插件
396pub struct ToolPlugin {
397    metadata: PluginMetadata,
398    state: PluginState,
399    tools: HashMap<String, Box<dyn ToolExecutor>>,
400    call_history: Vec<ToolCall>,
401}
402
403impl ToolPlugin {
404    pub fn new(plugin_id: &str) -> Self {
405        let metadata = PluginMetadata::new(plugin_id, "Tool Plugin", PluginType::Tool)
406            .with_description("Tool calling and execution plugin")
407            .with_capability("tool_call")
408            .with_capability("function_call");
409
410        Self {
411            metadata,
412            state: PluginState::Unloaded,
413            tools: HashMap::new(),
414            call_history: Vec::new(),
415        }
416    }
417
418    /// 注册工具
419    pub fn register_tool<T: ToolExecutor + 'static>(&mut self, tool: T) {
420        let name = tool.definition().name.clone();
421        self.tools.insert(name.clone(), Box::new(tool));
422        info!("Registered tool: {}", name);
423    }
424
425    /// 获取所有工具定义
426    pub fn list_tools(&self) -> Vec<ToolDefinition> {
427        self.tools
428            .values()
429            .map(|t| t.definition().clone())
430            .collect()
431    }
432
433    /// 调用工具
434    pub async fn call_tool(&mut self, call: ToolCall) -> PluginResult<ToolResult> {
435        let tool = self
436            .tools
437            .get(&call.name)
438            .ok_or_else(|| anyhow::anyhow!("Tool not found: {}", call.name))?;
439
440        // 验证参数
441        tool.validate(&call.arguments)?;
442
443        // 记录调用
444        self.call_history.push(call.clone());
445
446        // 执行工具
447        match tool.execute(call.arguments).await {
448            Ok(result) => Ok(ToolResult {
449                call_id: call.call_id,
450                success: true,
451                result,
452                error: None,
453            }),
454            Err(e) => Ok(ToolResult {
455                call_id: call.call_id,
456                success: false,
457                result: serde_json::Value::Null,
458                error: Some(e.to_string()),
459            }),
460        }
461    }
462}
463
464#[async_trait::async_trait]
465impl AgentPlugin for ToolPlugin {
466    fn metadata(&self) -> &PluginMetadata {
467        &self.metadata
468    }
469
470    fn state(&self) -> PluginState {
471        self.state.clone()
472    }
473
474    async fn load(&mut self, _ctx: &PluginContext) -> PluginResult<()> {
475        self.state = PluginState::Loading;
476        info!("Loading Tool plugin: {}", self.metadata.id);
477        self.state = PluginState::Loaded;
478        Ok(())
479    }
480
481    async fn init_plugin(&mut self) -> PluginResult<()> {
482        info!("Initializing Tool plugin: {}", self.metadata.id);
483        Ok(())
484    }
485
486    async fn start(&mut self) -> PluginResult<()> {
487        self.state = PluginState::Running;
488        info!(
489            "Tool plugin {} started with {} tools",
490            self.metadata.id,
491            self.tools.len()
492        );
493        Ok(())
494    }
495
496    async fn stop(&mut self) -> PluginResult<()> {
497        self.state = PluginState::Paused;
498        info!("Tool plugin {} stopped", self.metadata.id);
499        Ok(())
500    }
501
502    async fn unload(&mut self) -> PluginResult<()> {
503        self.tools.clear();
504        self.state = PluginState::Unloaded;
505        info!("Tool plugin {} unloaded", self.metadata.id);
506        Ok(())
507    }
508
509    async fn execute(&mut self, input: String) -> PluginResult<String> {
510        // 解析输入为工具调用
511        let call: ToolCall = serde_json::from_str(&input)
512            .map_err(|e| anyhow::anyhow!("Invalid tool call format: {}", e))?;
513        let result = self.call_tool(call).await?;
514        serde_json::to_string(&result)
515            .map_err(|e| anyhow::anyhow!("Failed to serialize result: {}", e))
516    }
517
518    fn stats(&self) -> HashMap<String, serde_json::Value> {
519        let mut stats = HashMap::new();
520        stats.insert(
521            "tool_count".to_string(),
522            serde_json::json!(self.tools.len()),
523        );
524        stats.insert(
525            "call_count".to_string(),
526            serde_json::json!(self.call_history.len()),
527        );
528        stats
529    }
530
531    fn as_any(&self) -> &dyn Any {
532        self
533    }
534
535    fn as_any_mut(&mut self) -> &mut dyn Any {
536        self
537    }
538
539    fn into_any(self: Box<Self>) -> Box<dyn Any> {
540        self
541    }
542}
543
544// ============================================================================
545// 存储插件
546// ============================================================================
547
548/// 存储后端 trait
549#[async_trait::async_trait]
550pub trait StorageBackend: Send + Sync {
551    /// 获取值
552    async fn get(&self, key: &str) -> PluginResult<Option<Vec<u8>>>;
553
554    /// 设置值
555    async fn set(&self, key: &str, value: Vec<u8>) -> PluginResult<()>;
556
557    /// 删除值
558    async fn delete(&self, key: &str) -> PluginResult<bool>;
559
560    /// 检查键是否存在
561    async fn exists(&self, key: &str) -> PluginResult<bool>;
562
563    /// 列出所有键
564    async fn keys(&self, prefix: Option<&str>) -> PluginResult<Vec<String>>;
565}
566
567/// 内存存储后端
568pub struct MemoryStorage {
569    data: Arc<RwLock<HashMap<String, Vec<u8>>>>,
570}
571
572impl MemoryStorage {
573    pub fn new() -> Self {
574        Self {
575            data: Arc::new(RwLock::new(HashMap::new())),
576        }
577    }
578}
579
580impl Default for MemoryStorage {
581    fn default() -> Self {
582        Self::new()
583    }
584}
585
586#[async_trait::async_trait]
587impl StorageBackend for MemoryStorage {
588    async fn get(&self, key: &str) -> PluginResult<Option<Vec<u8>>> {
589        let data = self.data.read().await;
590        Ok(data.get(key).cloned())
591    }
592
593    async fn set(&self, key: &str, value: Vec<u8>) -> PluginResult<()> {
594        let mut data = self.data.write().await;
595        data.insert(key.to_string(), value);
596        Ok(())
597    }
598
599    async fn delete(&self, key: &str) -> PluginResult<bool> {
600        let mut data = self.data.write().await;
601        Ok(data.remove(key).is_some())
602    }
603
604    async fn exists(&self, key: &str) -> PluginResult<bool> {
605        let data = self.data.read().await;
606        Ok(data.contains_key(key))
607    }
608
609    async fn keys(&self, prefix: Option<&str>) -> PluginResult<Vec<String>> {
610        let data = self.data.read().await;
611        Ok(match prefix {
612            Some(p) => data.keys().filter(|k| k.starts_with(p)).cloned().collect(),
613            None => data.keys().cloned().collect(),
614        })
615    }
616}
617
618/// 存储插件
619pub struct StoragePlugin {
620    metadata: PluginMetadata,
621    state: PluginState,
622    backend: Option<Arc<dyn StorageBackend>>,
623    read_count: u64,
624    write_count: u64,
625}
626
627impl StoragePlugin {
628    pub fn new(plugin_id: &str) -> Self {
629        let metadata = PluginMetadata::new(plugin_id, "Storage Plugin", PluginType::Storage)
630            .with_description("Key-value storage plugin")
631            .with_capability("storage")
632            .with_capability("persistence");
633
634        Self {
635            metadata,
636            state: PluginState::Unloaded,
637            backend: None,
638            read_count: 0,
639            write_count: 0,
640        }
641    }
642
643    pub fn with_backend<B: StorageBackend + 'static>(mut self, backend: B) -> Self {
644        self.backend = Some(Arc::new(backend));
645        self
646    }
647
648    /// 获取值
649    pub async fn get(&mut self, key: &str) -> PluginResult<Option<Vec<u8>>> {
650        let backend = self
651            .backend
652            .as_ref()
653            .ok_or_else(|| anyhow::anyhow!("Storage backend not initialized"))?;
654        self.read_count += 1;
655        backend.get(key).await
656    }
657
658    /// 设置值
659    pub async fn set(&mut self, key: &str, value: Vec<u8>) -> PluginResult<()> {
660        let backend = self
661            .backend
662            .as_ref()
663            .ok_or_else(|| anyhow::anyhow!("Storage backend not initialized"))?;
664        self.write_count += 1;
665        backend.set(key, value).await
666    }
667
668    /// 删除值
669    pub async fn delete(&mut self, key: &str) -> PluginResult<bool> {
670        let backend = self
671            .backend
672            .as_ref()
673            .ok_or_else(|| anyhow::anyhow!("Storage backend not initialized"))?;
674        self.write_count += 1;
675        backend.delete(key).await
676    }
677
678    /// 获取字符串值
679    pub async fn get_string(&mut self, key: &str) -> PluginResult<Option<String>> {
680        let data = self.get(key).await?;
681        Ok(data.map(|d| String::from_utf8_lossy(&d).to_string()))
682    }
683
684    /// 设置字符串值
685    pub async fn set_string(&mut self, key: &str, value: &str) -> PluginResult<()> {
686        self.set(key, value.as_bytes().to_vec()).await
687    }
688}
689
690#[async_trait::async_trait]
691impl AgentPlugin for StoragePlugin {
692    fn metadata(&self) -> &PluginMetadata {
693        &self.metadata
694    }
695
696    fn state(&self) -> PluginState {
697        self.state.clone()
698    }
699
700    async fn load(&mut self, _ctx: &PluginContext) -> PluginResult<()> {
701        self.state = PluginState::Loading;
702        info!("Loading Storage plugin: {}", self.metadata.id);
703        self.state = PluginState::Loaded;
704        Ok(())
705    }
706
707    async fn init_plugin(&mut self) -> PluginResult<()> {
708        info!("Initializing Storage plugin: {}", self.metadata.id);
709        if self.backend.is_none() {
710            self.backend = Some(Arc::new(MemoryStorage::new()));
711        }
712        Ok(())
713    }
714
715    async fn start(&mut self) -> PluginResult<()> {
716        self.state = PluginState::Running;
717        info!("Storage plugin {} started", self.metadata.id);
718        Ok(())
719    }
720
721    async fn stop(&mut self) -> PluginResult<()> {
722        self.state = PluginState::Paused;
723        info!("Storage plugin {} stopped", self.metadata.id);
724        Ok(())
725    }
726
727    async fn unload(&mut self) -> PluginResult<()> {
728        self.backend = None;
729        self.state = PluginState::Unloaded;
730        info!("Storage plugin {} unloaded", self.metadata.id);
731        Ok(())
732    }
733
734    async fn execute(&mut self, input: String) -> PluginResult<String> {
735        // 简单的 get/set 命令解析
736        let parts: Vec<&str> = input.as_str().splitn(3, ' ').collect();
737        match parts.as_slice() {
738            ["get", key] => {
739                let value = self.get_string(key).await?;
740                Ok(value.unwrap_or_else(|| "null".to_string()))
741            }
742            ["set", key, value] => {
743                self.set_string(key, value).await?;
744                Ok("OK".to_string())
745            }
746            ["delete", key] => {
747                let deleted = self.delete(key).await?;
748                Ok(if deleted { "1" } else { "0" }.to_string())
749            }
750            _ => Err(anyhow::anyhow!(
751                "Invalid command. Use: get <key>, set <key> <value>, delete <key>"
752            )),
753        }
754    }
755
756    fn stats(&self) -> HashMap<String, serde_json::Value> {
757        let mut stats = HashMap::new();
758        stats.insert("read_count".to_string(), serde_json::json!(self.read_count));
759        stats.insert(
760            "write_count".to_string(),
761            serde_json::json!(self.write_count),
762        );
763        stats
764    }
765
766    fn as_any(&self) -> &dyn Any {
767        self
768    }
769
770    fn as_any_mut(&mut self) -> &mut dyn Any {
771        self
772    }
773
774    fn into_any(self: Box<Self>) -> Box<dyn Any> {
775        self
776    }
777}
778
779// ============================================================================
780// 记忆插件
781// ============================================================================
782
783/// 记忆条目
784#[derive(Debug, Clone, Serialize, Deserialize)]
785pub struct MemoryEntry {
786    /// 记忆 ID
787    pub id: String,
788    /// 内容
789    pub content: String,
790    /// 嵌入向量
791    pub embedding: Option<Vec<f32>>,
792    /// 创建时间
793    pub created_at: u64,
794    /// 访问次数
795    pub access_count: u32,
796    /// 重要性分数
797    pub importance: f32,
798    /// 元数据
799    pub metadata: HashMap<String, String>,
800}
801
802/// 记忆插件
803pub struct MemoryPlugin {
804    metadata: PluginMetadata,
805    state: PluginState,
806    memories: Vec<MemoryEntry>,
807    max_memories: usize,
808}
809
810impl MemoryPlugin {
811    pub fn new(plugin_id: &str) -> Self {
812        let metadata = PluginMetadata::new(plugin_id, "Memory Plugin", PluginType::Memory)
813            .with_description("Agent memory management plugin")
814            .with_capability("short_term_memory")
815            .with_capability("long_term_memory")
816            .with_capability("memory_retrieval");
817
818        Self {
819            metadata,
820            state: PluginState::Unloaded,
821            memories: Vec::new(),
822            max_memories: 1000,
823        }
824    }
825
826    pub fn with_max_memories(mut self, max: usize) -> Self {
827        self.max_memories = max;
828        self
829    }
830
831    /// 添加记忆
832    pub fn add_memory(&mut self, content: &str, importance: f32) -> String {
833        let id = uuid::Uuid::now_v7().to_string();
834        let entry = MemoryEntry {
835            id: id.clone(),
836            content: content.to_string(),
837            embedding: None,
838            created_at: std::time::SystemTime::now()
839                .duration_since(std::time::UNIX_EPOCH)
840                .unwrap_or_default()
841                .as_secs(),
842            access_count: 0,
843            importance,
844            metadata: HashMap::new(),
845        };
846        self.memories.push(entry);
847
848        // 如果超过最大数量,移除最不重要的记忆
849        if self.memories.len() > self.max_memories {
850            // 按重要性降序排序
851            self.memories
852                .sort_by(|a, b| b.importance.partial_cmp(&a.importance).unwrap());
853            // 截断保留最重要的记忆
854            self.memories.truncate(self.max_memories);
855        }
856
857        id
858    }
859
860    /// 检索记忆
861    pub fn retrieve(&mut self, query: &str, limit: usize) -> Vec<&MemoryEntry> {
862        // 简单的关键词匹配,实际应用中应使用向量相似度
863        let mut results: Vec<&mut MemoryEntry> = self
864            .memories
865            .iter_mut()
866            .filter(|m| m.content.contains(query))
867            .collect();
868
869        // 更新访问次数
870        for entry in &mut results {
871            entry.access_count += 1;
872        }
873
874        results.into_iter().map(|m| &*m).take(limit).collect()
875    }
876
877    /// 获取所有记忆
878    pub fn all_memories(&self) -> &[MemoryEntry] {
879        &self.memories
880    }
881
882    /// 清除记忆
883    pub fn clear(&mut self) {
884        self.memories.clear();
885    }
886}
887
888#[async_trait::async_trait]
889impl AgentPlugin for MemoryPlugin {
890    fn metadata(&self) -> &PluginMetadata {
891        &self.metadata
892    }
893
894    fn state(&self) -> PluginState {
895        self.state.clone()
896    }
897
898    async fn load(&mut self, _ctx: &PluginContext) -> PluginResult<()> {
899        self.state = PluginState::Loading;
900        info!("Loading Memory plugin: {}", self.metadata.id);
901        self.state = PluginState::Loaded;
902        Ok(())
903    }
904
905    async fn init_plugin(&mut self) -> PluginResult<()> {
906        info!("Initializing Memory plugin: {}", self.metadata.id);
907        Ok(())
908    }
909
910    async fn start(&mut self) -> PluginResult<()> {
911        self.state = PluginState::Running;
912        info!("Memory plugin {} started", self.metadata.id);
913        Ok(())
914    }
915
916    async fn stop(&mut self) -> PluginResult<()> {
917        self.state = PluginState::Paused;
918        info!("Memory plugin {} stopped", self.metadata.id);
919        Ok(())
920    }
921
922    async fn unload(&mut self) -> PluginResult<()> {
923        self.memories.clear();
924        self.state = PluginState::Unloaded;
925        info!("Memory plugin {} unloaded", self.metadata.id);
926        Ok(())
927    }
928
929    async fn execute(&mut self, input: String) -> PluginResult<String> {
930        let parts: Vec<&str> = input.as_str().splitn(3, ' ').collect();
931        match parts.as_slice() {
932            ["add", content] => {
933                let id = self.add_memory(content, 0.5);
934                Ok(format!("Added memory: {}", id))
935            }
936            ["add", content, importance] => {
937                let imp: f32 = importance.parse().unwrap_or(0.5);
938                let id = self.add_memory(content, imp);
939                Ok(format!("Added memory: {}", id))
940            }
941            ["search", query] => {
942                let results = self.retrieve(query, 5);
943                let contents: Vec<&str> = results.iter().map(|m| m.content.as_str()).collect();
944                Ok(serde_json::to_string(&contents)?)
945            }
946            ["count"] => Ok(self.memories.len().to_string()),
947            ["clear"] => {
948                self.clear();
949                Ok("Cleared".to_string())
950            }
951            _ => Err(anyhow::anyhow!("Invalid command")),
952        }
953    }
954
955    fn stats(&self) -> HashMap<String, serde_json::Value> {
956        let mut stats = HashMap::new();
957        stats.insert(
958            "memory_count".to_string(),
959            serde_json::json!(self.memories.len()),
960        );
961        stats.insert(
962            "max_memories".to_string(),
963            serde_json::json!(self.max_memories),
964        );
965        stats
966    }
967
968    fn as_any(&self) -> &dyn Any {
969        self
970    }
971
972    fn as_any_mut(&mut self) -> &mut dyn Any {
973        self
974    }
975
976    fn into_any(self: Box<Self>) -> Box<dyn Any> {
977        self
978    }
979}
980
981// ============================================================================
982// 插件管理器
983// ============================================================================
984
985/// 插件注册表条目
986struct PluginEntry {
987    plugin: Box<dyn AgentPlugin>,
988    config: PluginConfig,
989}
990
991/// 插件管理器
992pub struct PluginManager {
993    /// 已注册的插件
994    plugins: Arc<RwLock<HashMap<String, PluginEntry>>>,
995    /// 插件执行上下文
996    context: PluginContext,
997    /// 事件接收器
998    event_rx: Option<tokio::sync::mpsc::Receiver<PluginEvent>>,
999    /// 事件发送器(用于克隆给插件)
1000    event_tx: tokio::sync::mpsc::Sender<PluginEvent>,
1001}
1002
1003impl PluginManager {
1004    /// 创建新的插件管理器
1005    pub fn new(agent_id: &str) -> Self {
1006        let (event_tx, event_rx) = tokio::sync::mpsc::channel(256);
1007        let context = PluginContext::new(agent_id).with_event_sender(event_tx.clone());
1008
1009        Self {
1010            plugins: Arc::new(RwLock::new(HashMap::new())),
1011            context,
1012            event_rx: Some(event_rx),
1013            event_tx,
1014        }
1015    }
1016
1017    /// 获取插件上下文
1018    pub fn context(&self) -> &PluginContext {
1019        &self.context
1020    }
1021
1022    /// 注册插件
1023    pub async fn register<P: AgentPlugin + 'static>(&self, plugin: P) -> PluginResult<()> {
1024        self.register_with_config(plugin, PluginConfig::new()).await
1025    }
1026
1027    /// 使用配置注册插件
1028    pub async fn register_with_config<P: AgentPlugin + 'static>(
1029        &self,
1030        plugin: P,
1031        config: PluginConfig,
1032    ) -> PluginResult<()> {
1033        let plugin_id = plugin.plugin_id().to_string();
1034        let mut plugins = self.plugins.write().await;
1035
1036        if plugins.contains_key(&plugin_id) {
1037            return Err(anyhow::anyhow!("Plugin {} already registered", plugin_id));
1038        }
1039
1040        let entry = PluginEntry {
1041            plugin: Box::new(plugin),
1042            config,
1043        };
1044        plugins.insert(plugin_id.clone(), entry);
1045
1046        info!("Plugin {} registered", plugin_id);
1047        Ok(())
1048    }
1049
1050    /// 卸载插件
1051    pub async fn unregister(&self, plugin_id: &str) -> PluginResult<()> {
1052        let mut plugins = self.plugins.write().await;
1053        if let Some(mut entry) = plugins.remove(plugin_id) {
1054            entry.plugin.unload().await?;
1055            info!("Plugin {} unregistered", plugin_id);
1056        }
1057        Ok(())
1058    }
1059
1060    /// 获取插件
1061    pub async fn get(
1062        &self,
1063        plugin_id: &str,
1064    ) -> Option<impl std::ops::Deref<Target = Box<dyn AgentPlugin>> + '_> {
1065        let plugins = self.plugins.read().await;
1066        if plugins.contains_key(plugin_id) {
1067            Some(tokio::sync::RwLockReadGuard::map(plugins, |p| {
1068                &p.get(plugin_id).unwrap().plugin
1069            }))
1070        } else {
1071            None
1072        }
1073    }
1074
1075    /// 获取可变插件引用
1076    pub async fn get_mut(
1077        &self,
1078        plugin_id: &str,
1079    ) -> Option<impl std::ops::DerefMut<Target = Box<dyn AgentPlugin>> + '_> {
1080        let plugins = self.plugins.write().await;
1081        if plugins.contains_key(plugin_id) {
1082            Some(tokio::sync::RwLockWriteGuard::map(plugins, |p| {
1083                &mut p.get_mut(plugin_id).unwrap().plugin
1084            }))
1085        } else {
1086            None
1087        }
1088    }
1089
1090    /// 获取指定类型的插件
1091    pub async fn get_by_type(&self, plugin_type: PluginType) -> Vec<String> {
1092        let plugins = self.plugins.read().await;
1093        plugins
1094            .iter()
1095            .filter(|(_, entry)| entry.plugin.plugin_type() == plugin_type)
1096            .map(|(id, _)| id.clone())
1097            .collect()
1098    }
1099
1100    /// 加载所有插件
1101    pub async fn load_all(&self) -> PluginResult<()> {
1102        let mut plugins = self.plugins.write().await;
1103        for (id, entry) in plugins.iter_mut() {
1104            let ctx = self.context.clone().with_config(entry.config.clone());
1105            if let Err(e) = entry.plugin.load(&ctx).await {
1106                error!("Failed to load plugin {}: {}", id, e);
1107                return Err(e);
1108            }
1109        }
1110        info!("All plugins loaded");
1111        Ok(())
1112    }
1113
1114    /// 初始化所有插件
1115    pub async fn init_all(&self) -> PluginResult<()> {
1116        let mut plugins = self.plugins.write().await;
1117
1118        // 按优先级排序
1119        let mut sorted: Vec<_> = plugins.iter_mut().collect();
1120        sorted.sort_by(|a, b| {
1121            b.1.plugin
1122                .metadata()
1123                .priority
1124                .cmp(&a.1.plugin.metadata().priority)
1125        });
1126
1127        for (id, entry) in sorted {
1128            if let Err(e) = entry.plugin.init_plugin().await {
1129                error!("Failed to initialize plugin {}: {}", id, e);
1130                return Err(e);
1131            }
1132        }
1133        info!("All plugins initialized");
1134        Ok(())
1135    }
1136
1137    /// 启动所有插件
1138    pub async fn start_all(&self) -> PluginResult<()> {
1139        let mut plugins = self.plugins.write().await;
1140        for (id, entry) in plugins.iter_mut() {
1141            if entry.config.auto_start
1142                && entry.config.enabled
1143                && let Err(e) = entry.plugin.start().await
1144            {
1145                error!("Failed to start plugin {}: {}", id, e);
1146                return Err(e);
1147            }
1148        }
1149        info!("All auto-start plugins started");
1150        Ok(())
1151    }
1152
1153    /// 停止所有插件
1154    pub async fn stop_all(&self) -> PluginResult<()> {
1155        let mut plugins = self.plugins.write().await;
1156        for (id, entry) in plugins.iter_mut() {
1157            if let Err(e) = entry.plugin.stop().await {
1158                warn!("Failed to stop plugin {}: {}", id, e);
1159            }
1160        }
1161        info!("All plugins stopped");
1162        Ok(())
1163    }
1164
1165    /// 卸载所有插件
1166    pub async fn unload_all(&self) -> PluginResult<()> {
1167        let mut plugins = self.plugins.write().await;
1168        for (id, entry) in plugins.iter_mut() {
1169            if let Err(e) = entry.plugin.unload().await {
1170                warn!("Failed to unload plugin {}: {}", id, e);
1171            }
1172        }
1173        plugins.clear();
1174        info!("All plugins unloaded");
1175        Ok(())
1176    }
1177
1178    /// 执行插件
1179    pub async fn execute(&self, plugin_id: &str, input: String) -> PluginResult<String> {
1180        let mut plugins = self.plugins.write().await;
1181        let entry = plugins
1182            .get_mut(plugin_id)
1183            .ok_or_else(|| anyhow::anyhow!("Plugin {} not found", plugin_id))?;
1184        entry.plugin.execute(input).await
1185    }
1186
1187    /// 获取所有插件 ID
1188    pub async fn plugin_ids(&self) -> Vec<String> {
1189        let plugins = self.plugins.read().await;
1190        plugins.keys().cloned().collect()
1191    }
1192
1193    /// 获取所有插件元数据
1194    pub async fn list_plugins(&self) -> Vec<PluginMetadata> {
1195        let plugins = self.plugins.read().await;
1196        plugins
1197            .values()
1198            .map(|e| e.plugin.metadata().clone())
1199            .collect()
1200    }
1201
1202    /// 获取插件统计信息
1203    pub async fn stats(&self, plugin_id: &str) -> Option<HashMap<String, serde_json::Value>> {
1204        let plugins = self.plugins.read().await;
1205        plugins.get(plugin_id).map(|e| e.plugin.stats())
1206    }
1207
1208    /// 健康检查所有插件
1209    pub async fn health_check_all(&self) -> HashMap<String, bool> {
1210        let plugins = self.plugins.read().await;
1211        let mut results = HashMap::new();
1212        for (id, entry) in plugins.iter() {
1213            let healthy = entry.plugin.health_check().await.unwrap_or(false);
1214            results.insert(id.clone(), healthy);
1215        }
1216        results
1217    }
1218
1219    /// 获取事件接收器
1220    pub fn take_event_receiver(&mut self) -> Option<tokio::sync::mpsc::Receiver<PluginEvent>> {
1221        self.event_rx.take()
1222    }
1223}
1224
1225// ============================================================================
1226// 测试
1227// ============================================================================
1228
1229#[cfg(test)]
1230mod tests {
1231    use super::*;
1232
1233    #[tokio::test]
1234    async fn test_plugin_manager() {
1235        let manager = PluginManager::new("test_agent");
1236
1237        // 注册 LLM 插件
1238        let llm = LLMPlugin::new("llm_001");
1239        manager.register(llm).await.unwrap();
1240
1241        // 注册存储插件
1242        let storage = StoragePlugin::new("storage_001");
1243        manager.register(storage).await.unwrap();
1244
1245        // 注册记忆插件
1246        let memory = MemoryPlugin::new("memory_001");
1247        manager.register(memory).await.unwrap();
1248
1249        // 获取所有插件
1250        let ids = manager.plugin_ids().await;
1251        assert_eq!(ids.len(), 3);
1252
1253        // 加载和初始化
1254        manager.load_all().await.unwrap();
1255        manager.init_all().await.unwrap();
1256        manager.start_all().await.unwrap();
1257
1258        // 执行 LLM 插件
1259        let result = manager
1260            .execute("llm_001", "Hello".to_string())
1261            .await
1262            .unwrap();
1263        assert!(result.contains("Hello"));
1264
1265        // 执行存储插件
1266        manager
1267            .execute("storage_001", "set foo bar".to_string())
1268            .await
1269            .unwrap();
1270        let value = manager
1271            .execute("storage_001", "get foo".to_string())
1272            .await
1273            .unwrap();
1274        assert_eq!(value, "bar");
1275
1276        // 停止和卸载
1277        manager.stop_all().await.unwrap();
1278        manager.unload_all().await.unwrap();
1279
1280        let ids = manager.plugin_ids().await;
1281        assert_eq!(ids.len(), 0);
1282    }
1283
1284    #[tokio::test]
1285    async fn test_llm_plugin() {
1286        let mut llm = LLMPlugin::new("llm_test");
1287        let ctx = PluginContext::new("test_agent");
1288
1289        llm.load(&ctx).await.unwrap();
1290        llm.init_plugin().await.unwrap();
1291        llm.start().await.unwrap();
1292
1293        assert_eq!(llm.state(), PluginState::Running);
1294
1295        let response = llm.execute("Test prompt".to_string()).await.unwrap();
1296        assert!(response.contains("Test prompt"));
1297
1298        llm.stop().await.unwrap();
1299        llm.unload().await.unwrap();
1300
1301        assert_eq!(llm.state(), PluginState::Unloaded);
1302    }
1303
1304    #[tokio::test]
1305    async fn test_storage_plugin() {
1306        let mut storage = StoragePlugin::new("storage_test").with_backend(MemoryStorage::new());
1307        let ctx = PluginContext::new("test_agent");
1308
1309        storage.load(&ctx).await.unwrap();
1310        storage.init_plugin().await.unwrap();
1311        storage.start().await.unwrap();
1312
1313        // 测试存储操作
1314        storage.set_string("key1", "value1").await.unwrap();
1315        let value = storage.get_string("key1").await.unwrap();
1316        assert_eq!(value, Some("value1".to_string()));
1317
1318        // 测试删除
1319        let deleted = storage.delete("key1").await.unwrap();
1320        assert!(deleted);
1321
1322        let value = storage.get_string("key1").await.unwrap();
1323        assert!(value.is_none());
1324
1325        storage.stop().await.unwrap();
1326        storage.unload().await.unwrap();
1327    }
1328
1329    #[tokio::test]
1330    async fn test_memory_plugin() {
1331        let mut memory = MemoryPlugin::new("memory_test").with_max_memories(100);
1332        let ctx = PluginContext::new("test_agent");
1333
1334        memory.load(&ctx).await.unwrap();
1335        memory.init_plugin().await.unwrap();
1336        memory.start().await.unwrap();
1337
1338        // 添加记忆
1339        let id1 = memory.add_memory("Important meeting tomorrow", 0.9);
1340        let id2 = memory.add_memory("Buy groceries", 0.3);
1341
1342        assert!(!id1.is_empty());
1343        assert!(!id2.is_empty());
1344
1345        // 检索记忆
1346        let results = memory.retrieve("meeting", 10);
1347        assert_eq!(results.len(), 1);
1348        assert!(results[0].content.contains("meeting"));
1349
1350        // 检查计数
1351        assert_eq!(memory.all_memories().len(), 2);
1352
1353        memory.stop().await.unwrap();
1354        memory.unload().await.unwrap();
1355    }
1356
1357    #[tokio::test]
1358    async fn test_plugin_context() {
1359        let ctx = PluginContext::new("test_agent");
1360
1361        // 测试共享状态
1362        ctx.set_state("counter", 42i32).await;
1363        let value: Option<i32> = ctx.get_state("counter").await;
1364        assert_eq!(value, Some(42));
1365
1366        // 测试配置
1367        let mut config = PluginConfig::new();
1368        config.set("timeout", 30);
1369        config.set("enabled", true);
1370
1371        assert_eq!(config.get_i64("timeout"), Some(30));
1372        assert_eq!(config.get_bool("enabled"), Some(true));
1373    }
1374}