Connection re-use for plugin networking and beta NTLM plugin (#295)

This commit is contained in:
Gregory Schier
2025-11-10 14:41:49 -08:00
committed by GitHub
parent d318546d0c
commit 6389fd3b8f
48 changed files with 941 additions and 554 deletions

View File

@@ -12,7 +12,7 @@ use crate::events::{
GetHttpAuthenticationSummaryResponse, GetHttpRequestActionsResponse,
GetTemplateFunctionConfigRequest, GetTemplateFunctionConfigResponse,
GetTemplateFunctionSummaryResponse, GetThemesRequest, GetThemesResponse, ImportRequest,
ImportResponse, InternalEvent, InternalEventPayload, JsonPrimitive, PluginWindowContext,
ImportResponse, InternalEvent, InternalEventPayload, JsonPrimitive, PluginContext,
RenderPurpose,
};
use crate::native_template_functions::{template_function_keyring, template_function_secure};
@@ -132,7 +132,7 @@ impl PluginManager {
Ok(_) => {
info!("Plugin runtime client connected!");
plugin_manager
.initialize_all_plugins(&app_handle, &PluginWindowContext::None)
.initialize_all_plugins(&app_handle, &PluginContext::new_empty())
.await
.expect("Failed to reload plugins");
}
@@ -195,19 +195,19 @@ impl PluginManager {
[bundled_plugin_dirs, installed_plugin_dirs].concat()
}
pub async fn uninstall(&self, window_context: &PluginWindowContext, dir: &str) -> Result<()> {
pub async fn uninstall(&self, plugin_context: &PluginContext, dir: &str) -> Result<()> {
let plugin = self.get_plugin_by_dir(dir).await.ok_or(PluginNotFoundErr(dir.to_string()))?;
self.remove_plugin(window_context, &plugin).await
self.remove_plugin(plugin_context, &plugin).await
}
async fn remove_plugin(
&self,
window_context: &PluginWindowContext,
plugin_context: &PluginContext,
plugin: &PluginHandle,
) -> Result<()> {
// Terminate the plugin
self.send_to_plugin_and_wait(
window_context,
plugin_context,
plugin,
&InternalEventPayload::TerminateRequest,
)
@@ -223,11 +223,7 @@ impl PluginManager {
Ok(())
}
pub async fn add_plugin_by_dir(
&self,
window_context: &PluginWindowContext,
dir: &str,
) -> Result<()> {
pub async fn add_plugin_by_dir(&self, plugin_context: &PluginContext, dir: &str) -> Result<()> {
info!("Adding plugin by dir {dir}");
let maybe_tx = self.ws_service.app_to_plugin_events_tx.lock().await;
@@ -244,7 +240,7 @@ impl PluginManager {
let event = timeout(
Duration::from_secs(5),
self.send_to_plugin_and_wait(
window_context,
plugin_context,
&plugin_handle,
&InternalEventPayload::BootRequest(BootRequest {
dir: dir.to_string(),
@@ -268,19 +264,19 @@ impl PluginManager {
pub async fn initialize_all_plugins<R: Runtime>(
&self,
app_handle: &AppHandle<R>,
window_context: &PluginWindowContext,
plugin_context: &PluginContext,
) -> Result<()> {
let start = Instant::now();
let candidates = self.list_plugin_dirs(app_handle).await;
for candidate in candidates.clone() {
// First remove the plugin if it exists
if let Some(plugin) = self.get_plugin_by_dir(candidate.dir.as_str()).await {
if let Err(e) = self.remove_plugin(window_context, &plugin).await {
if let Err(e) = self.remove_plugin(plugin_context, &plugin).await {
error!("Failed to remove plugin {} {e:?}", candidate.dir);
continue;
}
}
if let Err(e) = self.add_plugin_by_dir(window_context, candidate.dir.as_str()).await {
if let Err(e) = self.add_plugin_by_dir(plugin_context, candidate.dir.as_str()).await {
warn!("Failed to add plugin {} {e:?}", candidate.dir);
}
}
@@ -320,13 +316,13 @@ impl PluginManager {
source_event: &InternalEvent,
payload: &InternalEventPayload,
) -> Result<()> {
let window_context = source_event.to_owned().window_context;
let plugin_context = source_event.to_owned().context;
let reply_id = Some(source_event.to_owned().id);
let plugin = self
.get_plugin_by_ref_id(source_event.plugin_ref_id.as_str())
.await
.ok_or(PluginNotFoundErr(source_event.plugin_ref_id.to_string()))?;
let event = plugin.build_event_to_send_raw(&window_context, &payload, reply_id);
let event = plugin.build_event_to_send_raw(&plugin_context, &payload, reply_id);
plugin.send(&event).await
}
@@ -350,27 +346,27 @@ impl PluginManager {
async fn send_to_plugin_and_wait(
&self,
window_context: &PluginWindowContext,
plugin_context: &PluginContext,
plugin: &PluginHandle,
payload: &InternalEventPayload,
) -> Result<InternalEvent> {
let events =
self.send_to_plugins_and_wait(window_context, payload, vec![plugin.to_owned()]).await?;
self.send_to_plugins_and_wait(plugin_context, payload, vec![plugin.to_owned()]).await?;
Ok(events.first().unwrap().to_owned())
}
async fn send_and_wait(
&self,
window_context: &PluginWindowContext,
plugin_context: &PluginContext,
payload: &InternalEventPayload,
) -> Result<Vec<InternalEvent>> {
let plugins = { self.plugins.lock().await.clone() };
self.send_to_plugins_and_wait(window_context, payload, plugins).await
self.send_to_plugins_and_wait(plugin_context, payload, plugins).await
}
async fn send_to_plugins_and_wait(
&self,
window_context: &PluginWindowContext,
plugin_context: &PluginContext,
payload: &InternalEventPayload,
plugins: Vec<PluginHandle>,
) -> Result<Vec<InternalEvent>> {
@@ -380,7 +376,7 @@ impl PluginManager {
// 1. Build the events with IDs and everything
let events_to_send = plugins
.iter()
.map(|p| p.build_event_to_send(window_context, payload, None))
.map(|p| p.build_event_to_send(plugin_context, payload, None))
.collect::<Vec<InternalEvent>>();
// 2. Spawn thread to subscribe to incoming events and check reply ids
@@ -433,7 +429,7 @@ impl PluginManager {
) -> Result<Vec<GetThemesResponse>> {
let reply_events = self
.send_and_wait(
&PluginWindowContext::new(window),
&PluginContext::new(window),
&InternalEventPayload::GetThemesRequest(GetThemesRequest {}),
)
.await?;
@@ -454,7 +450,7 @@ impl PluginManager {
) -> Result<Vec<GetGrpcRequestActionsResponse>> {
let reply_events = self
.send_and_wait(
&PluginWindowContext::new(window),
&PluginContext::new(window),
&InternalEventPayload::GetGrpcRequestActionsRequest(EmptyPayload {}),
)
.await?;
@@ -475,7 +471,7 @@ impl PluginManager {
) -> Result<Vec<GetHttpRequestActionsResponse>> {
let reply_events = self
.send_and_wait(
&PluginWindowContext::new(window),
&PluginContext::new(window),
&InternalEventPayload::GetHttpRequestActionsRequest(EmptyPayload {}),
)
.await?;
@@ -520,11 +516,11 @@ impl PluginManager {
Some(v) => v,
};
let window_context = &PluginWindowContext::new(&window);
let plugin_context = &PluginContext::new(&window);
let vars = &make_vars_hashmap(environment_chain);
let cb = PluginTemplateCallback::new(
window.app_handle(),
&window_context,
&plugin_context,
RenderPurpose::Preview,
);
// We don't want to fail for this op because the UI will not be able to list any auth types then
@@ -536,7 +532,7 @@ impl PluginManager {
let event = self
.send_to_plugin_and_wait(
&PluginWindowContext::new(window),
&PluginContext::new(window),
&plugin,
&InternalEventPayload::GetTemplateFunctionConfigRequest(
GetTemplateFunctionConfigRequest {
@@ -566,7 +562,7 @@ impl PluginManager {
let plugin =
self.get_plugin_by_ref_id(ref_id.as_str()).await.ok_or(PluginNotFoundErr(ref_id))?;
let event = plugin.build_event_to_send(
&PluginWindowContext::new(window),
&PluginContext::new(window),
&InternalEventPayload::CallHttpRequestActionRequest(req),
None,
);
@@ -583,7 +579,7 @@ impl PluginManager {
let plugin =
self.get_plugin_by_ref_id(ref_id.as_str()).await.ok_or(PluginNotFoundErr(ref_id))?;
let event = plugin.build_event_to_send(
&PluginWindowContext::new(window),
&PluginContext::new(window),
&InternalEventPayload::CallGrpcRequestActionRequest(req),
None,
);
@@ -595,10 +591,10 @@ impl PluginManager {
&self,
window: &WebviewWindow<R>,
) -> Result<Vec<(PluginHandle, GetHttpAuthenticationSummaryResponse)>> {
let window_context = PluginWindowContext::new(window);
let plugin_context = PluginContext::new(window);
let reply_events = self
.send_and_wait(
&window_context,
&plugin_context,
&InternalEventPayload::GetHttpAuthenticationSummaryRequest(EmptyPayload {}),
)
.await?;
@@ -635,7 +631,7 @@ impl PluginManager {
let vars = &make_vars_hashmap(environment_chain);
let cb = PluginTemplateCallback::new(
window.app_handle(),
&PluginWindowContext::new(&window),
&PluginContext::new(&window),
RenderPurpose::Preview,
);
// We don't want to fail for this op because the UI will not be able to list any auth types then
@@ -646,7 +642,7 @@ impl PluginManager {
let context_id = format!("{:x}", md5::compute(model_id.to_string()));
let event = self
.send_to_plugin_and_wait(
&PluginWindowContext::new(window),
&PluginContext::new(window),
&plugin,
&InternalEventPayload::GetHttpAuthenticationConfigRequest(
GetHttpAuthenticationConfigRequest {
@@ -681,7 +677,7 @@ impl PluginManager {
vars,
&PluginTemplateCallback::new(
window.app_handle(),
&PluginWindowContext::new(&window),
&PluginContext::new(&window),
RenderPurpose::Preview,
),
&RenderOptions {
@@ -697,7 +693,7 @@ impl PluginManager {
let context_id = format!("{:x}", md5::compute(model_id.to_string()));
self.send_to_plugin_and_wait(
&PluginWindowContext::new(window),
&PluginContext::new(window),
&plugin,
&InternalEventPayload::CallHttpAuthenticationActionRequest(
CallHttpAuthenticationActionRequest {
@@ -719,6 +715,7 @@ impl PluginManager {
window: &WebviewWindow<R>,
auth_name: &str,
req: CallHttpAuthenticationRequest,
plugin_context: &PluginContext,
) -> Result<CallHttpAuthenticationResponse> {
let disabled = match req.values.get("disabled") {
Some(JsonPrimitive::Boolean(v)) => v.clone(),
@@ -742,7 +739,7 @@ impl PluginManager {
let event = self
.send_to_plugin_and_wait(
&PluginWindowContext::new(window),
plugin_context,
&plugin,
&InternalEventPayload::CallHttpAuthenticationRequest(req),
)
@@ -761,10 +758,10 @@ impl PluginManager {
&self,
window: &WebviewWindow<R>,
) -> Result<Vec<GetTemplateFunctionSummaryResponse>> {
let window_context = PluginWindowContext::new(window);
let plugin_context = PluginContext::new(window);
let reply_events = self
.send_and_wait(
&window_context,
&plugin_context,
&InternalEventPayload::GetTemplateFunctionSummaryRequest(EmptyPayload {}),
)
.await?;
@@ -787,7 +784,7 @@ impl PluginManager {
pub async fn call_template_function(
&self,
window_context: &PluginWindowContext,
plugin_context: &PluginContext,
fn_name: &str,
values: HashMap<String, serde_json::Value>,
purpose: RenderPurpose,
@@ -798,7 +795,7 @@ impl PluginManager {
};
let events = self
.send_and_wait(window_context, &InternalEventPayload::CallTemplateFunctionRequest(req))
.send_and_wait(plugin_context, &InternalEventPayload::CallTemplateFunctionRequest(req))
.await
.map_err(|e| RenderError(format!("Failed to call template function {e:}")))?;
@@ -832,7 +829,7 @@ impl PluginManager {
) -> Result<ImportResponse> {
let reply_events = self
.send_and_wait(
&PluginWindowContext::new(window),
&PluginContext::new(window),
&InternalEventPayload::ImportRequest(ImportRequest {
content: content.to_string(),
}),
@@ -872,7 +869,7 @@ impl PluginManager {
let event = self
.send_to_plugin_and_wait(
&PluginWindowContext::new(window),
&PluginContext::new(window),
&plugin,
&InternalEventPayload::FilterRequest(FilterRequest {
filter: filter.to_string(),