1use std::future::Future;
2use std::pin::Pin;
3use std::sync::Arc;
4
5use super::*;
6
7pub type PluginFuture<T> = Pin<Box<dyn Future<Output = Result<T, PluginError>> + Send>>;
8pub type PluginRuntimeEventHook = Arc<dyn Fn(PluginRuntimeEvent) -> PluginFuture<()> + Send + Sync>;
9pub type PluginSessionTask = PluginFuture<()>;
10pub type SessionConfigMutator = Arc<
11 dyn Fn(SessionConfigChangedContext, SessionPolicy) -> PluginFuture<SessionPolicy> + Send + Sync,
12>;
13pub type BeforeTurnHook =
14 Arc<dyn Fn(TurnHookContext) -> PluginFuture<Vec<PluginDirective>> + Send + Sync>;
15pub type BeforeToolCallHook =
16 Arc<dyn Fn(ToolCallHookContext) -> PluginFuture<Vec<PluginDirective>> + Send + Sync>;
17pub type AfterToolCallHook =
18 Arc<dyn Fn(ToolResultHookContext) -> PluginFuture<Vec<PluginDirective>> + Send + Sync>;
19pub type ToolResultProjector =
20 Arc<dyn Fn(ToolResultProjectionContext) -> PluginFuture<crate::ModelToolReturn> + Send + Sync>;
21pub type AfterTurnHook =
22 Arc<dyn Fn(TurnResultHookContext) -> PluginFuture<Vec<PluginDirective>> + Send + Sync>;
23pub type CheckpointHook =
24 Arc<dyn Fn(CheckpointHookContext) -> PluginFuture<Vec<PluginDirective>> + Send + Sync>;
25pub type PromptContributor =
26 Arc<dyn Fn(PromptHookContext) -> PluginFuture<Vec<PromptContribution>> + Send + Sync>;
27pub type ToolSurfaceContributor =
28 Arc<dyn Fn(ToolSurfaceContext) -> Result<ToolSurfaceContribution, PluginError> + Send + Sync>;
29pub type ToolDiscoveryContributor = Arc<
30 dyn Fn(ToolDiscoveryContext) -> Result<ToolDiscoveryContribution, PluginError> + Send + Sync,
31>;
32pub type AssistantStreamHook =
33 Arc<dyn Fn(AssistantStreamHookContext) -> PluginFuture<AssistantStreamTransform> + Send + Sync>;
34pub type AssistantResponseHook = Arc<
35 dyn Fn(AssistantResponseHookContext) -> PluginFuture<AssistantResponseTransform> + Send + Sync,
36>;
37
38#[derive(Clone)]
39pub struct PromptHookContext {
40 pub session_id: String,
41 pub host: Arc<dyn PromptHookHost>,
42 pub state: SessionReadView,
43 pub mode_turn_options: ModeTurnOptions,
44 pub turn_context: crate::TurnContext,
45}
46
47#[derive(Clone)]
48pub struct TurnHookContext {
49 pub session_id: String,
50 pub state: SessionReadView,
51 pub host: Arc<dyn TurnHookHost>,
52 pub turn_context: crate::TurnContext,
53}
54
55#[derive(Clone)]
56pub struct SessionConfigChangedContext {
57 pub session_id: String,
58 pub previous: SessionPolicy,
59 pub current: SessionPolicy,
60 pub host: Arc<dyn TaskHost>,
61}
62
63#[derive(Clone)]
64pub struct SessionStateChangedContext {
65 pub session_id: String,
66 pub state: SessionReadView,
67 pub host: Arc<dyn HistoryHost>,
68}
69
70#[derive(Clone)]
71pub enum PluginRuntimeEvent {
72 TurnCommitted(Arc<AssembledTurn>),
73 TurnPersisted(SessionStateChangedContext),
74 SessionRestored(SessionReadView),
75 SessionConfigChanged(Box<SessionConfigChangedContext>),
76}
77
78#[derive(Clone, Debug)]
79pub struct TurnResultSummary {
80 pub outcome: crate::TurnOutcome,
81 pub assistant_output: crate::runtime::AssistantOutput,
82 pub execution: crate::runtime::ExecutionSummary,
83 pub token_usage: crate::TokenUsage,
84 pub tool_calls: Arc<Vec<crate::ToolCallRecord>>,
85 pub errors: Arc<Vec<crate::runtime::TurnIssue>>,
86}
87
88impl TurnResultSummary {
89 pub fn from_assembled(turn: &AssembledTurn) -> Self {
90 Self {
91 outcome: turn.outcome.clone(),
92 assistant_output: turn.assistant_output.clone(),
93 execution: turn.execution.clone(),
94 token_usage: turn.token_usage.clone(),
95 tool_calls: Arc::new(turn.tool_calls.clone()),
96 errors: Arc::new(turn.errors.clone()),
97 }
98 }
99}
100
101#[derive(Clone)]
102pub struct ToolCallHookContext {
103 pub session_id: String,
104 pub tool_name: String,
105 pub args: serde_json::Value,
106 pub turn_context: crate::TurnContext,
107 pub(crate) host: Arc<dyn ToolHookHost>,
108}
109
110impl ToolCallHookContext {
111 pub fn new(
112 session_id: String,
113 tool_name: String,
114 args: serde_json::Value,
115 turn_context: crate::TurnContext,
116 host: Arc<dyn ToolHookHost>,
117 ) -> Self {
118 Self {
119 session_id,
120 tool_name,
121 args,
122 turn_context,
123 host,
124 }
125 }
126
127 pub async fn session_snapshot(&self) -> Result<SessionSnapshot, PluginError> {
128 self.host.snapshot_session(&self.session_id).await
129 }
130
131 pub async fn set_tools_availability(
132 &self,
133 names: &[String],
134 availability: Option<crate::ToolAvailability>,
135 ) -> Result<u64, PluginError> {
136 self.host
137 .set_tools_availability(&self.session_id, names, availability)
138 .await
139 }
140}
141
142#[derive(Clone)]
143pub struct ToolResultHookContext {
144 pub session_id: String,
145 pub tool_name: String,
146 pub args: serde_json::Value,
147 pub result: ToolResult,
148 pub duration_ms: u64,
149 pub turn_context: crate::TurnContext,
150 pub(crate) host: Arc<dyn ToolHookHost>,
151}
152
153impl ToolResultHookContext {
154 pub fn new(
155 session_id: String,
156 tool_name: String,
157 args: serde_json::Value,
158 result: ToolResult,
159 duration_ms: u64,
160 turn_context: crate::TurnContext,
161 host: Arc<dyn ToolHookHost>,
162 ) -> Self {
163 Self {
164 session_id,
165 tool_name,
166 args,
167 result,
168 duration_ms,
169 turn_context,
170 host,
171 }
172 }
173
174 pub async fn session_snapshot(&self) -> Result<SessionSnapshot, PluginError> {
175 self.host.snapshot_session(&self.session_id).await
176 }
177
178 pub async fn set_tools_availability(
179 &self,
180 names: &[String],
181 availability: Option<crate::ToolAvailability>,
182 ) -> Result<u64, PluginError> {
183 self.host
184 .set_tools_availability(&self.session_id, names, availability)
185 .await
186 }
187}
188
189#[derive(Clone)]
190pub struct ToolResultProjectionContext {
191 pub session_id: String,
192 pub call_id: String,
193 pub tool_name: String,
194 pub args: serde_json::Value,
195 pub output: crate::ToolCallOutput,
196 pub duration_ms: u64,
197}
198
199#[derive(Clone)]
200pub struct TurnResultHookContext {
201 pub session_id: String,
202 pub turn: Arc<TurnResultSummary>,
203 pub host: Arc<dyn TurnResultHookHost>,
204}
205
206#[derive(Clone)]
207pub struct CheckpointHookContext {
208 pub session_id: String,
209 pub checkpoint: CheckpointKind,
210 pub state: SessionReadView,
211 pub host: Arc<dyn CheckpointHookHost>,
212}
213
214#[derive(Clone)]
215pub struct AssistantStreamHookContext {
216 pub session_id: String,
217 pub chunk: String,
218}
219
220#[derive(Clone, Debug, Default)]
221pub struct AssistantStreamTransform {
222 pub chunk: String,
223 pub reasoning_deltas: Vec<String>,
224 pub events: Vec<PluginSurfaceEvent>,
225 pub abort_stream: bool,
232}
233
234#[derive(Clone)]
235pub struct AssistantResponseHookContext {
236 pub session_id: String,
237 pub response: crate::LlmResponse,
238}
239
240#[derive(Clone, Debug)]
241pub struct AssistantResponseTransform {
242 pub response: crate::LlmResponse,
243 pub events: Vec<PluginSurfaceEvent>,
244}