pub mod process;
pub mod restart;
pub use restart::RestartPolicy;
use async_trait::async_trait;
use serde_json::Value;
use crate::extensions::hooks::events::{HookEvent, HookResult};
use self::process::{ProviderCompleteParams, ProviderCompleteResult, ProviderStreamEvent};
use crate::extensions::info::PluginInfo;
use crate::extensions::commands::CommandOutputEvent;
use crate::extensions::tasks::TaskEvent;
#[derive(Debug, Clone, PartialEq)]
pub enum InvokeCommandEvent {
Output(CommandOutputEvent),
Task(TaskEvent),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ExtensionHealth {
Loaded,
FailedValidation,
FailedInitialize,
Running,
Restarting,
Degraded,
Failed,
}
impl ExtensionHealth {
pub fn as_str(self) -> &'static str {
match self {
Self::Loaded => "loaded",
Self::FailedValidation => "failed_validation",
Self::FailedInitialize => "failed_initialize",
Self::Running => "running",
Self::Restarting => "restarting",
Self::Degraded => "degraded",
Self::Failed => "failed",
}
}
}
#[cfg(test)]
mod health_tests {
use super::ExtensionHealth;
#[test]
fn as_str_covers_all_variants() {
assert_eq!(ExtensionHealth::Loaded.as_str(), "loaded");
assert_eq!(ExtensionHealth::FailedValidation.as_str(), "failed_validation");
assert_eq!(ExtensionHealth::FailedInitialize.as_str(), "failed_initialize");
assert_eq!(ExtensionHealth::Running.as_str(), "running");
assert_eq!(ExtensionHealth::Restarting.as_str(), "restarting");
assert_eq!(ExtensionHealth::Degraded.as_str(), "degraded");
assert_eq!(ExtensionHealth::Failed.as_str(), "failed");
}
}
#[async_trait]
pub trait ExtensionHandler: Send + Sync {
fn id(&self) -> &str;
async fn handle(&self, event: &HookEvent) -> HookResult;
async fn call_tool(&self, _name: &str, _input: Value) -> Result<Value, String> {
Err("extension runtime does not support tool.call".to_string())
}
async fn provider_complete(&self, _params: ProviderCompleteParams) -> Result<ProviderCompleteResult, String> {
Err("extension runtime does not support provider.complete".to_string())
}
async fn provider_stream(
&self,
_params: ProviderCompleteParams,
_sink: tokio::sync::mpsc::UnboundedSender<ProviderStreamEvent>,
) -> Result<ProviderCompleteResult, String> {
Err("provider.stream is not supported by this extension".to_string())
}
async fn invoke_command(
&self,
_command: &str,
_args: Vec<String>,
_request_id: &str,
_sink: tokio::sync::mpsc::UnboundedSender<InvokeCommandEvent>,
) -> Result<Value, String> {
Err("extension runtime does not support command.invoke".to_string())
}
async fn get_info(&self) -> Result<PluginInfo, String> {
Err("extension runtime does not support info.get".to_string())
}
async fn sidecar_spawn_args(&self) -> Result<crate::sidecar::spawn::SidecarSpawnArgs, String> {
Err("extension runtime does not support sidecar.spawn_args".to_string())
}
async fn settings_editor_open(&self, _category: &str, _field: &str) -> Result<Value, String> {
Err("extension runtime does not support settings.editor.open".to_string())
}
async fn settings_editor_key(&self, _category: &str, _field: &str, _key: &str) -> Result<Value, String> {
Err("extension runtime does not support settings.editor.key".to_string())
}
async fn settings_editor_commit(&self, _category: &str, _field: &str, _value: Value) -> Result<Value, String> {
Err("extension runtime does not support settings.editor.commit".to_string())
}
async fn shutdown(&self);
async fn health(&self) -> ExtensionHealth {
ExtensionHealth::Running
}
async fn restart_count(&self) -> usize {
0
}
}