1use async_trait::async_trait;
4use serde::{Deserialize, Serialize};
5use thiserror::Error;
6
7#[derive(Error, Debug)]
9pub enum PluginError {
10 #[error("Plugin not found: {0}")]
12 NotFound(String),
13
14 #[error("Load failed: {0}")]
16 LoadFailed(String),
17
18 #[error("Hook failed: {0}")]
20 HookFailed(String),
21
22 #[error("Execution error: {0}")]
24 ExecutionError(String),
25
26 #[error("IPC error: {0}")]
28 Ipc(String),
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
33#[serde(rename_all = "camelCase")]
34pub enum PluginHook {
35 BeforeMessage,
37 AfterMessage,
39 BeforeToolCall,
41 AfterToolCall,
43 SessionStart,
45 SessionEnd,
47 AgentResponse,
49 Error,
51}
52
53#[async_trait]
55pub trait Plugin: Send + Sync {
56 fn id(&self) -> &str;
58
59 fn name(&self) -> &str;
61
62 fn version(&self) -> &str;
64
65 fn hooks(&self) -> &[PluginHook];
67
68 async fn execute_hook(
70 &self,
71 hook: PluginHook,
72 data: serde_json::Value,
73 ) -> Result<serde_json::Value, PluginError>;
74
75 async fn activate(&self) -> Result<(), PluginError>;
77
78 async fn deactivate(&self) -> Result<(), PluginError>;
80}
81
82pub struct PluginApi {
84 }
86
87impl PluginApi {
88 #[must_use]
90 pub const fn new() -> Self {
91 Self {}
92 }
93}
94
95impl Default for PluginApi {
96 fn default() -> Self {
97 Self::new()
98 }
99}