From 39f6162c12a67370d8ce3afb779a4d58cc6b3bc3 Mon Sep 17 00:00:00 2001 From: Arnaud Ritti <77437157+arnaud-ritti@users.noreply.github.com> Date: Sat, 7 Nov 2026 02:39:18 +0100 Subject: [PATCH] feat(plugins): services views in the Services tool window (#1760) A plugin view declared with `location = "services"` (plugin API 1.3, `engines.openidea ^1.3`) shows its tree in the Services tool window, next to Docker and the run configurations. The nodes, the toolbar (acting on one selected node) and their events come from `view-provider`; `viewItem.context` menus give the nodes a right-click menu. The pane beside the tree comes from a new optional export, `service-provider.detail(view, key)` (worlds `plugin-services` / `services`), which returns typed tabs: a message, read-only text or a process log. The IDE switches tabs without calling the plugin. For a log, the UI names only the node and tab (`plugin_service_log`); the host asks the plugin for the pane again and runs its program with the plugin's `process:` grant in the project root, with the arguments of the toggles that are on, streaming its output into the log pane Docker uses until it exits (the exit code is shown), the pane closes or the Services window is hidden. A cancelled request starts nothing, lines are cut at 16 KiB, and revoking the grant or cancelling kills the program and what it started. The log pane moves to `src/ui/LogPane` and drops output that arrives after its source was stopped. The Rust SDK gains `openidea_plugin::services` (`Services`, `Tab`, `Pane`, `ProcessLog`). All components are rebuilt for the WIT change. Closes #1736 Co-authored-by: arnaud-ritti <77437157+arnaud-ritti@users.noreply.github.com> --- crates/ide-host/src/plugins/api.rs | 123 ++++++++++++ crates/ide-host/src/plugins/mod.rs | 76 +++++++- crates/ide-host/src/plugins/remote_host.rs | 37 +++- crates/ide-host/src/plugins/types.rs | 8 + crates/ide-host/src/plugins/ui_points.rs | 15 +- crates/ide-host/src/plugins/views.rs | 48 ++++- crates/ide-host/tests/plugins.rs | 182 ++++++++++++++++++ crates/ide-plugin/src/runtime.rs | 73 ++++++- crates/ide-plugin/src/types.rs | 36 ++++ crates/ide-plugin/src/wit_host.rs | 13 ++ .../tests/fixtures/hello/dist/plugin.wasm | Bin 132262 -> 143243 bytes .../fixtures/hello/dist/plugin.wasm.sources | 2 +- .../tests/fixtures/hello/src/lib.rs | 11 +- .../tests/fixtures/indexer/dist/plugin.wasm | Bin 79945 -> 83007 bytes .../fixtures/indexer/dist/plugin.wasm.sources | 2 +- .../tests/fixtures/jobs/dist/plugin.wasm | Bin 141233 -> 144327 bytes .../fixtures/jobs/dist/plugin.wasm.sources | 2 +- .../tests/fixtures/misbehave/dist/plugin.wasm | Bin 98289 -> 97252 bytes .../misbehave/dist/plugin.wasm.sources | 2 +- .../fixtures/semantic-tokens/dist/plugin.wasm | Bin 88961 -> 91811 bytes .../semantic-tokens/dist/plugin.wasm.sources | 2 +- plugins/README.md | 78 ++++++-- .../official/ai-completion/dist/plugin.wasm | Bin 169206 -> 173087 bytes .../ai-completion/dist/plugin.wasm.sources | 2 +- plugins/official/checkstyle/dist/plugin.wasm | Bin 166547 -> 169534 bytes .../checkstyle/dist/plugin.wasm.sources | 2 +- plugins/official/csv-editor/dist/plugin.wasm | Bin 130679 -> 133397 bytes .../csv-editor/dist/plugin.wasm.sources | 2 +- plugins/official/git-toolbox/dist/plugin.wasm | Bin 108521 -> 110071 bytes .../git-toolbox/dist/plugin.wasm.sources | 2 +- plugins/official/graphviz/dist/plugin.wasm | Bin 126140 -> 129105 bytes .../graphviz/dist/plugin.wasm.sources | 2 +- .../official/key-promoter/dist/plugin.wasm | Bin 97396 -> 100187 bytes .../key-promoter/dist/plugin.wasm.sources | 2 +- .../official/license-header/dist/plugin.wasm | Bin 150804 -> 152606 bytes .../license-header/dist/plugin.wasm.sources | 2 +- plugins/official/mybatis/dist/plugin.wasm | Bin 166796 -> 168346 bytes .../official/mybatis/dist/plugin.wasm.sources | 2 +- .../official/regex-tester/dist/plugin.wasm | Bin 932668 -> 931730 bytes .../regex-tester/dist/plugin.wasm.sources | 2 +- plugins/official/solidity/dist/plugin.wasm | Bin 105071 -> 108029 bytes .../solidity/dist/plugin.wasm.sources | 2 +- .../official/string-tools/dist/plugin.wasm | Bin 162872 -> 165787 bytes .../string-tools/dist/plugin.wasm.sources | 2 +- sdk/rust/openidea-plugin/src/lib.rs | 69 +++++++ sdk/rust/openidea-plugin/src/services.rs | 76 ++++++++ sdk/rust/openidea-plugin/wit/plugin.wit | 12 ++ sdk/rust/openidea-plugin/wit/services.wit | 50 +++++ src-tauri/src/commands/mod.rs | 2 + src-tauri/src/commands/plugin.rs | 48 +++++ src/bindings.ts | 40 ++++ .../plugins/__tests__/servicePane.test.tsx | 81 ++++++++ .../__tests__/serviceProvider.test.tsx | 132 +++++++++++++ src/features/plugins/backend.ts | 35 +++- src/features/plugins/uiPoints.tsx | 8 +- src/features/plugins/views/PluginView.tsx | 14 +- .../plugins/views/ServicePane.module.css | 29 +++ src/features/plugins/views/ServicePane.tsx | 87 +++++++++ .../plugins/views/serviceProvider.tsx | 94 +++++++++ src/features/services/Services.module.css | 15 +- src/features/services/ServicesTree.test.tsx | 43 ++++- src/features/services/ServicesTree.tsx | 35 +++- src/features/services/docker.tsx | 115 ++--------- src/features/services/tree.ts | 4 +- src/ui/LogPane.module.css | 48 +++++ src/ui/LogPane.test.tsx | 108 +++++++++++ src/ui/LogPane.tsx | 152 +++++++++++++++ src/ui/index.ts | 1 + src/workbench/contributions.ts | 11 ++ src/workbench/toolwindows/ToolWindows.tsx | 11 +- wit/plugin.wit | 12 ++ wit/services.wit | 50 +++++ 72 files changed, 1936 insertions(+), 178 deletions(-) create mode 100644 sdk/rust/openidea-plugin/src/services.rs create mode 100644 sdk/rust/openidea-plugin/wit/services.wit create mode 100644 src/features/plugins/__tests__/servicePane.test.tsx create mode 100644 src/features/plugins/__tests__/serviceProvider.test.tsx create mode 100644 src/features/plugins/views/ServicePane.module.css create mode 100644 src/features/plugins/views/ServicePane.tsx create mode 100644 src/features/plugins/views/serviceProvider.tsx create mode 100644 src/ui/LogPane.module.css create mode 100644 src/ui/LogPane.test.tsx create mode 100644 src/ui/LogPane.tsx create mode 100644 wit/services.wit diff --git a/crates/ide-host/src/plugins/api.rs b/crates/ide-host/src/plugins/api.rs index 11624cf1d..e2f6977e9 100644 --- a/crates/ide-host/src/plugins/api.rs +++ b/crates/ide-host/src/plugins/api.rs @@ -417,6 +417,129 @@ impl PluginApi { } } +impl PluginApi { + /// Runs an approved program until it exits or `cancel` fires, passing + /// each output line to `on_line`; returns its exit code. + pub(super) fn stream_process( + &self, + program: &str, + args: Vec, + cwd: Option<&Path>, + cancel: &CancellationToken, + on_line: &dyn Fn(super::PluginOutputLine), + ) -> Result, HostError> { + let binary = self.approved_program(program)?; + let cwd = cwd.map(Path::to_path_buf).unwrap_or_else(|| self.shared.data_dir.join(self.id())); + let _ = std::fs::create_dir_all(&cwd); + let mut cmd = std::process::Command::new(&binary); + ide_core::process::prepare(ide_core::process::own_group(&mut cmd)); + let mut child = cmd + .args(&args) + .current_dir(&cwd) + .stdin(std::process::Stdio::null()) + .stdout(std::process::Stdio::piped()) + .stderr(std::process::Stdio::piped()) + .spawn() + .map_err(|e| HostError::Failed(format!("{}: {e}", binary.display())))?; + // Bounded: a program printing faster than the lines are sent waits on its pipe. + let (tx, rx) = std::sync::mpsc::sync_channel(1024); + let read = |pipe: Box, stderr: bool| { + let tx = tx.clone(); + std::thread::spawn(move || { + read_lines(pipe, MAX_OUTPUT_LINE, &mut |text| { + tx.send(super::PluginOutputLine { stderr, text }).is_ok() + }); + }); + }; + if let Some(out) = child.stdout.take() { + read(Box::new(out), false); + } + if let Some(err) = child.stderr.take() { + read(Box::new(err), true); + } + drop(tx); + // Revoking the grant removes the pin: stop then. + let cap = format!("process:{program}"); + let pin = (self.id().to_owned(), cap.clone()); + let stop = |child: &mut std::process::Child| -> Option { + if cancel.is_cancelled() { + kill_group(child); + return Some(HostError::Cancelled); + } + if !self.shared.pins.read().contains_key(&pin) { + kill_group(child); + return Some(HostError::Denied(cap.clone())); + } + None + }; + loop { + if let Some(e) = stop(&mut child) { + return Err(e); + } + match rx.recv_timeout(Duration::from_millis(50)) { + Ok(line) => on_line(line), + // Both pipes closed: the program is done (or detached them). + Err(std::sync::mpsc::RecvTimeoutError::Disconnected) => break, + Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {} + } + } + loop { + if let Some(status) = child.try_wait().map_err(failed)? { + return Ok(status.code()); + } + if let Some(e) = stop(&mut child) { + return Err(e); + } + std::thread::sleep(Duration::from_millis(50)); + } + } +} + +/// Longest output line a followed program sends; the rest of the line is dropped. +const MAX_OUTPUT_LINE: usize = 16 << 10; + +/// Passes `pipe`'s lines (without `\r\n`, at most `max` bytes each) to `line` +/// until it returns false or the pipe closes, holding at most one line. +fn read_lines(pipe: Box, max: usize, line: &mut dyn FnMut(String) -> bool) { + use std::io::{BufRead, Read}; + let mut reader = std::io::BufReader::new(pipe); + let mut buf = Vec::new(); + loop { + buf.clear(); + match (&mut reader).take(max as u64).read_until(b'\n', &mut buf) { + Ok(0) | Err(_) => return, + Ok(_) => {} + } + if buf.last() != Some(&b'\n') && buf.len() == max { + // Too long: skip to the end of the line. + let mut rest = Vec::new(); + loop { + rest.clear(); + match (&mut reader).take(max as u64).read_until(b'\n', &mut rest) { + Ok(0) | Err(_) => break, + Ok(_) if rest.last() == Some(&b'\n') => break, + Ok(_) => {} + } + } + } + let end = buf.strip_suffix(b"\n").unwrap_or(&buf); + let end = end.strip_suffix(b"\r").unwrap_or(end); + if !line(String::from_utf8_lossy(end).into_owned()) { + return; + } + } +} + +/// Kills a program spawned in its own group and what it started. A kill that +/// lands while the program forks can miss the new process, so the group is +/// signalled again before the program is reaped (until then its group id +/// can't be reused). +fn kill_group(child: &mut std::process::Child) { + ide_core::process::kill_tree_of(child.id()); + std::thread::sleep(Duration::from_millis(50)); + ide_core::process::kill_tree(child); +} + fn failed(e: impl std::fmt::Display) -> HostError { HostError::Failed(e.to_string()) } diff --git a/crates/ide-host/src/plugins/mod.rs b/crates/ide-host/src/plugins/mod.rs index 80dd5ee74..7d2d13c38 100644 --- a/crates/ide-host/src/plugins/mod.rs +++ b/crates/ide-host/src/plugins/mod.rs @@ -61,7 +61,8 @@ use ide_extension::{ use ide_language::plugin_point::PluginLanguages; use ide_language::{LanguageConfig, ProgramPin}; use ide_plugin::{ - Actor, ActorError, CANCELLED, CallError, HostApi, Invocation, Limits, PluginEngine, Runtime, RuntimeSetup, + Actor, ActorError, CANCELLED, CallError, HostApi, HostError, Invocation, Limits, PluginEngine, Runtime, + RuntimeSetup, }; use parking_lot::{Condvar, Mutex, RwLock}; use serde::{Deserialize, Serialize}; @@ -1076,6 +1077,66 @@ impl PluginHost { }) } + /// The Services pane of node `key` of the plugin's `location = "services"` + /// view `view`. + pub fn service_detail( + &self, + id: &str, + view: &str, + key: &str, + invocation: Invocation, + ) -> IdeResult> { + self.services_view(id, view)?; + let (view, key) = (view.to_owned(), key.to_owned()); + self.code_call(id, invocation, "rendering the service's pane", move |rt, inv| { + rt.service_detail(&view, &key, inv) + }) + } + + /// Runs the program of the log tab `tab` of node `key`'s pane, with the + /// arguments of the toggles in `on`, streaming its output until it exits + /// or `cancel` fires; returns its exit code. The pane is asked of the + /// plugin again, so the UI never names what runs. Needs the plugin's + /// `process:` grant. + #[allow(clippy::too_many_arguments)] + pub fn stream_service_log( + &self, + id: &str, + view: &str, + key: &str, + tab: &str, + on: &[String], + invocation: Invocation, + cancel: &ide_core::CancellationToken, + on_line: &dyn Fn(PluginOutputLine), + ) -> IdeResult> { + if cancel.is_cancelled() { + return Err(IdeError::cancelled()); + } + let cwd = invocation.workspace_root.clone(); + let tabs = self.service_detail(id, view, key, invocation)?; + let Some(ide_plugin::ServicePane::Log(log)) = tabs.into_iter().find(|t| t.id == tab).map(|t| t.body) else { + return Err(IdeError::not_found(format!("the pane of {key:?} has no log tab {tab:?}"))); + }; + let toggled = log.toggles.into_iter().filter(|t| on.contains(&t.id)).flat_map(|t| t.args); + let args: Vec = log.args.into_iter().chain(toggled).collect(); + let plugin = + self.plugins.read().get(id).cloned().ok_or_else(|| IdeError::not_found(format!("plugin {id:?}")))?; + let cap = Capability::Process(log.program.clone()); + if !plugin.meta.lock().granted.iter().any(|g| g.covers(&cap)) { + let denied = HostError::Denied(cap.to_string()).to_string(); + return Err(IdeError::new(ide_core::error::ErrorKind::PermissionDenied, denied)); + } + let api = api::PluginApi { pkg: plugin.pkg.clone(), shared: self.shared.clone() }; + api.stream_process(&log.program, args, cwd.as_deref(), cancel, on_line).map_err(|e| match e { + HostError::Cancelled => IdeError::cancelled(), + e @ HostError::Denied(_) => IdeError::new(ide_core::error::ErrorKind::PermissionDenied, e.to_string()), + HostError::NotFound(m) => IdeError::not_found(m), + HostError::Invalid(m) => IdeError::invalid(m), + e => IdeError::unavailable(e.to_string()), + }) + } + fn declared_view(&self, id: &str, view: &str) -> IdeResult<()> { let declared = [ui_points::VIEWS, ui_points::CUSTOM_EDITORS] .iter() @@ -1083,6 +1144,19 @@ impl PluginHost { if declared { Ok(()) } else { Err(IdeError::not_found(format!("plugin {id:?} declares no view {view:?}"))) } } + fn services_view(&self, id: &str, view: &str) -> IdeResult<()> { + let services = self + .ui + .items(ui_points::VIEWS, Some(id)) + .iter() + .any(|i| i.key == view && i.decl["location"].as_str() == Some(ui_points::SERVICES_LOCATION)); + if services { + Ok(()) + } else { + Err(IdeError::not_found(format!("plugin {id:?} declares no services view {view:?}"))) + } + } + /// One call into a plugin's code for the UI: checks it may run (asking /// for missing consent), activates it, retries once when the instance was /// reclaimed meanwhile, and reports crashes. diff --git a/crates/ide-host/src/plugins/remote_host.rs b/crates/ide-host/src/plugins/remote_host.rs index 60379b13d..6815ca382 100644 --- a/crates/ide-host/src/plugins/remote_host.rs +++ b/crates/ide-host/src/plugins/remote_host.rs @@ -14,7 +14,8 @@ //! The commands a window needs at run time (`plugin_run_command`, //! `plugin_post_events`, `plugin_event_kinds`, `plugin_status_items`, //! `plugin_context_keys`, `plugin_cancel_task`, `plugin_answer_prompt`, `plugin_set_active_file`, -//! `plugin_line_markers`, `plugin_view_render`, `plugin_view_event`) +//! `plugin_line_markers`, `plugin_view_render`, `plugin_view_event`, `plugin_service_detail`, +//! `plugin_service_log`) //! carry the desktop commands' names and arguments, so a remote window's UI //! routes them here unchanged. Plugin results come back as `plugin` //! notifications ([`PluginEventMessage`]); secrets stay in the desktop's @@ -465,6 +466,40 @@ impl RemotePlugins { } }); let h = host.clone(); + d.add("plugin_service_detail", move |c| { + let h = h.clone(); + async move { + super::views::service_detail( + &c.host, + alive(&h)?, + &c.window, + c.arg("pluginId")?, + c.arg("view")?, + c.arg("key")?, + ) + .await + } + }); + let h = host.clone(); + d.add("plugin_service_log", move |c| { + let h = h.clone(); + async move { + super::views::service_log( + &c.host, + alive(&h)?, + &c.window, + c.arg("pluginId")?, + c.arg("view")?, + c.arg("key")?, + c.arg("tab")?, + c.arg("on")?, + c.arg("request")?, + c.sender("onLine")?, + ) + .await + } + }); + let h = host.clone(); d.add("plugin_navigation_files", move |c| { let h = h.clone(); async move { super::index_ops::plugin_navigation_files(&c.host, alive(&h)?, &c.window).await } diff --git a/crates/ide-host/src/plugins/types.rs b/crates/ide-host/src/plugins/types.rs index ffd3bf262..5090998a8 100644 --- a/crates/ide-host/src/plugins/types.rs +++ b/crates/ide-host/src/plugins/types.rs @@ -9,6 +9,14 @@ pub use ide_plugin::{ use serde::{Deserialize, Serialize}; use specta::Type; +/// A line a view's `process` body printed. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Type)] +#[serde(rename_all = "camelCase")] +pub struct PluginOutputLine { + pub stderr: bool, + pub text: String, +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Type)] #[serde(rename_all = "camelCase")] pub enum PluginSource { diff --git a/crates/ide-host/src/plugins/ui_points.rs b/crates/ide-host/src/plugins/ui_points.rs index 0fa1dd92f..b5bd0047e 100644 --- a/crates/ide-host/src/plugins/ui_points.rs +++ b/crates/ide-host/src/plugins/ui_points.rs @@ -26,7 +26,7 @@ //! id = "jobs" //! title = "Jobs" //! icon = "server" -//! location = "right" # left, right, bottom +//! location = "right" # left, right, bottom, services (nodes of the Services tool window) //! //! [[contributes.customEditors]] //! id = "table" @@ -55,6 +55,9 @@ use serde_json::Value; use std::collections::BTreeSet; use std::path::PathBuf; +/// A view whose tree shows in the Services tool window; the plugin's +/// `service-provider` renders the selected node's pane. +pub const SERVICES_LOCATION: &str = "services"; pub const MENUS: &str = "menus"; pub const KEYMAPS: &str = "keymaps"; pub const STATUS_BAR: &str = "statusBar"; @@ -395,8 +398,14 @@ pub(super) fn view(pkg: &Package, decl: toml::Value) -> Result { validate_item_id(&d.id, "view id")?; title(VIEWS, &d.title)?; let files = web_or_code(pkg, d.web.as_deref(), &format!("view {:?}", d.id))?; - if !["left", "right", "bottom"].contains(&d.location.as_str()) { - return Err(format!("view {:?}: `location` is left, right or bottom", d.id)); + if !["left", "right", "bottom", SERVICES_LOCATION].contains(&d.location.as_str()) { + return Err(format!("view {:?}: `location` is left, right, bottom or services", d.id)); + } + if d.location == SERVICES_LOCATION { + pkg.manifest.needs_api(&format!("view {:?}: `location = \"services\"`", d.id), 3)?; + if d.web.is_some() { + return Err(format!("view {:?}: a services view is rendered by the plugin's code (no `web`)", d.id)); + } } if d.icon.as_ref().is_some_and(|i| i.len() > 64) { return Err(format!("view {:?}: icon names are up to 64 bytes", d.id)); diff --git a/crates/ide-host/src/plugins/views.rs b/crates/ide-host/src/plugins/views.rs index f12e31572..bef19f922 100644 --- a/crates/ide-host/src/plugins/views.rs +++ b/crates/ide-host/src/plugins/views.rs @@ -1,10 +1,11 @@ //! Declarative views and custom editors as the -//! window commands `plugin_view_render` / `plugin_view_event` serve them — +//! window commands `plugin_view_render` / `plugin_view_event` (and, for services views, +//! `plugin_service_detail` / `plugin_service_log`) serve them — //! the desktop for local projects, `openidea-server` for remote ones. -use super::{PluginEditor, PluginHost}; +use super::{PluginEditor, PluginHost, PluginOutputLine}; use ide_core::{DocId, IdeError, IdeResult}; -use ide_plugin::{EditorContext, Invocation, View, ViewEvent, Viewport}; +use ide_plugin::{EditorContext, Invocation, ServiceTab, View, ViewEvent, Viewport}; use std::sync::Arc; /// The window's project, plus the editor the call is about: the document a @@ -67,6 +68,47 @@ pub async fn event( blocking(move || plugins.view_event(&plugin_id, &view, event, invocation)).await } +/// The Services pane of node `key` of a plugin's services view. +pub async fn service_detail( + host: &crate::Host, + plugins: Arc, + window: &str, + plugin_id: String, + view: String, + key: String, +) -> IdeResult> { + let invocation = view_invocation(host, window, None, None)?; + blocking(move || plugins.service_detail(&plugin_id, &view, &key, invocation)).await +} + +/// Runs the program of the log tab `tab` of node `key`'s pane in the window's +/// project root, streaming its lines until it exits or request `request` is +/// cancelled; returns its exit code. +#[allow(clippy::too_many_arguments)] +pub async fn service_log( + host: &crate::Host, + plugins: Arc, + window: &str, + plugin_id: String, + view: String, + key: String, + tab: String, + on: Vec, + request: ide_core::RequestId, + on_line: crate::ops::Channel, +) -> IdeResult> { + let invocation = view_invocation(host, window, None, None)?; + let cancel = host.begin_project_read_request(window, request); + let result = blocking(move || { + plugins.stream_service_log(&plugin_id, &view, &key, &tab, &on, invocation, &cancel, &|line| { + let _ = on_line.send(line); + }) + }) + .await; + host.end_request(request); + result +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/ide-host/tests/plugins.rs b/crates/ide-host/tests/plugins.rs index 7ce801f62..a6cf5b29c 100644 --- a/crates/ide-host/tests/plugins.rs +++ b/crates/ide-host/tests/plugins.rs @@ -2811,6 +2811,188 @@ fn completion_quick_fixes_problems_and_event_kinds_of_api_1() { assert_eq!((d[0].unnecessary, d[0].deprecated, d[0].source.as_deref()), (true, false, Some("lint"))); } +/// `hello` as a services view, which needs API 1.3. +fn services_variant(text: &str) -> String { + text.replace("location = \"right\"", "location = \"services\"") + .replace("engines.openidea = \"^1.0\"", "engines.openidea = \"^1.3\"") +} + +#[test] +fn services_views_need_api_1_3_and_code() { + let f = fixture(Limits::default()); + let tmp = tempfile::tempdir().unwrap(); + let info = f.install(&hello_variant(tmp.path(), services_variant)); + assert!(info.error.is_none(), "{:?}", info.error); + assert_eq!(f.host.ui_items("views").remove(0).decl["location"].as_str(), Some("services")); + + for (edit, message) in [ + ( + Box::new(|t: &str| t.replace("location = \"right\"", "location = \"services\"")) + as Box String>, + "new in plugin API 1.3", + ), + ( + Box::new(|t: &str| t.replace("location = \"right\"", "location = \"middle\"")), + "left, right, bottom or services", + ), + ( + Box::new(|t: &str| { + services_variant(t) + .replace("location = \"services\"", "location = \"services\"\nweb = \"web/index.html\"") + }), + "a services view is rendered by the plugin's code (no `web`)", + ), + ] { + let tmp = tempfile::tempdir().unwrap(); + let pkg = hello_variant(tmp.path(), edit); + std::fs::create_dir_all(pkg.join("web")).unwrap(); + std::fs::write(pkg.join("web/index.html"), "

x

").unwrap(); + let err = f.host.install_from_dir(&pkg, &Consent::all()).unwrap_err(); + assert!(err.message.contains(message), "{message}: {err:?}"); + } +} + +#[test] +fn services_views_have_a_detail_pane() { + let f = fixture(Limits::default()); + let tmp = tempfile::tempdir().unwrap(); + f.install(&hello_variant(tmp.path(), services_variant)); + let tabs = f.host.service_detail("hello", "greetings", "pod:default/nginx", f.inv()).unwrap(); + assert_eq!(tabs.iter().map(|t| t.id.as_str()).collect::>(), ["log", "info"]); + assert_eq!(tabs[1].body, ide_plugin::ServicePane::Text("greetings: pod:default/nginx".into())); + let ide_plugin::ServicePane::Log(log) = &tabs[0].body else { panic!("a log: {:?}", tabs[0].body) }; + assert_eq!( + (log.program.as_str(), log.args.as_slice()), + ("sh", ["-c".to_owned(), "pod:default/nginx".to_owned()].as_slice()) + ); + + let f = fixture(Limits::default()); + f.install(&sample("hello")); + let err = f.host.service_detail("hello", "greetings", "x", f.inv()).unwrap_err(); + assert!(err.message.contains("declares no services view"), "a right view has no pane: {err:?}"); +} + +/// `hello` as a services view that may run `sh`, granted or not. +#[cfg(unix)] +fn services_with_sh(f: &Fixture, dir: &Path, grant: bool) { + let sh = PathBuf::from("/bin"); + f.host.set_program_path(Arc::new(move || Some(sh.clone().into_os_string()))); + let pkg = hello_variant(dir, |t| { + services_variant(t).replace( + "required = [\"editor.read\", \"editor.write\"]", + "required = [\"editor.read\", \"editor.write\"]\noptional = [\"process:sh\"]", + ) + }); + f.install(&pkg); + f.host.set_capability("hello", "process:sh", grant).unwrap(); +} + +/// Follows the Log tab of the node whose key is `script`. +#[cfg(unix)] +fn stream( + f: &Fixture, + script: &str, + on: &[&str], + cancel: &ide_core::CancellationToken, + lines: impl Fn(PluginOutputLine), +) -> ide_core::IdeResult> { + let on: Vec = on.iter().map(|s| (*s).to_owned()).collect(); + f.host.stream_service_log("hello", "greetings", script, "log", &on, f.inv(), cancel, &lines) +} + +#[cfg(unix)] +#[test] +fn service_logs_stream_lines_with_the_toggles_args() { + let f = fixture(Limits::default()); + let tmp = tempfile::tempdir().unwrap(); + services_with_sh(&f, tmp.path(), true); + let lines = Mutex::new(Vec::new()); + let script = "printf 'a\\nb\\n'; printf 'e\\n' >&2; exit 3"; + let status = stream(&f, script, &[], &Default::default(), |l| lines.lock().push(l)); + assert_eq!(status.unwrap(), Some(3)); + let mut lines = lines.into_inner(); + lines.sort_by_key(|l| l.stderr); + let line = |stderr: bool, text: &str| PluginOutputLine { stderr, text: text.into() }; + assert_eq!(lines, [line(false, "a"), line(false, "b"), line(true, "e")]); + + // `sh -c script arg` names the script `arg` ($0): the toggle's args are appended. + let named = Mutex::new(Vec::new()); + stream(&f, "echo $0", &["named"], &Default::default(), |l| named.lock().push(l.text)).unwrap(); + assert_eq!(named.into_inner(), ["named"]); + + let long = Mutex::new(Vec::new()); + stream(&f, "head -c 40000 /dev/zero | tr '\\0' x; echo; echo next", &[], &Default::default(), |l| { + long.lock().push(l.text.len()) + }) + .unwrap(); + assert_eq!(long.into_inner(), [16 << 10, 4], "a long line is cut, the next one is whole"); +} + +#[cfg(unix)] +#[test] +fn service_logs_need_the_grant_and_a_log_tab() { + let f = fixture(Limits::default()); + let tmp = tempfile::tempdir().unwrap(); + services_with_sh(&f, tmp.path(), false); + let marker = tmp.path().join("ran"); + let script = format!("touch {}", marker.display()); + let err = stream(&f, &script, &[], &Default::default(), |_| {}).unwrap_err(); + assert_eq!(err.kind, ErrorKind::PermissionDenied); + assert!(err.message.contains("permission denied: process:sh is not granted"), "{err:?}"); + assert!(!marker.exists(), "nothing was started"); + + f.host.set_capability("hello", "process:sh", true).unwrap(); + let info = + f.host.stream_service_log("hello", "greetings", &script, "info", &[], f.inv(), &Default::default(), &|_| {}); + assert_eq!(info.unwrap_err().kind, ErrorKind::NotFound, "a text tab runs nothing"); + let cancelled = ide_core::CancellationToken::default(); + cancelled.cancel(); + assert_eq!(stream(&f, &script, &[], &cancelled, |_| {}).unwrap_err().kind, ErrorKind::Cancelled); + assert!(!marker.exists(), "a cancelled request starts nothing"); +} + +#[cfg(unix)] +#[test] +fn service_log_cancel_kills_the_child() { + let f = fixture(Limits::default()); + let tmp = tempfile::tempdir().unwrap(); + services_with_sh(&f, tmp.path(), true); + let cancel = ide_core::CancellationToken::default(); + let started = Instant::now(); + let result = stream(&f, "echo up; sleep 30.4321", &[], &cancel, |l| { + if l.text == "up" { + cancel.cancel(); + } + }); + assert!(started.elapsed() < Duration::from_secs(2), "{:?}", started.elapsed()); + assert_eq!(result.unwrap_err().kind, ErrorKind::Cancelled); + let orphan = || std::process::Command::new("pgrep").args(["-f", "sleep 30.4321"]).status().unwrap().success(); + assert!(eventually(|| !orphan()), "what the program started is killed too"); +} + +#[cfg(unix)] +#[test] +fn service_log_stops_when_the_grant_is_revoked() { + let f = fixture(Limits::default()); + let tmp = tempfile::tempdir().unwrap(); + services_with_sh(&f, tmp.path(), true); + let started = Instant::now(); + let watchdog = ide_core::CancellationToken::default(); + let timer = watchdog.clone(); + std::thread::spawn(move || { + std::thread::sleep(Duration::from_secs(3)); + timer.cancel(); + }); + let result = stream(&f, "while :; do echo tick; sleep 0.05; done", &[], &watchdog, |l| { + if l.text == "tick" && started.elapsed() < Duration::from_secs(1) { + f.host.set_capability("hello", "process:sh", false).unwrap(); + } + }); + assert!(started.elapsed() < Duration::from_secs(3), "{:?}", started.elapsed()); + let err = result.unwrap_err(); + assert_eq!(err.kind, ErrorKind::PermissionDenied, "{err:?}"); +} + #[test] fn plugins_set_their_own_context_keys() { let f = fixture(Limits::default()); diff --git a/crates/ide-plugin/src/runtime.rs b/crates/ide-plugin/src/runtime.rs index e418109cb..c66014520 100644 --- a/crates/ide-plugin/src/runtime.rs +++ b/crates/ide-plugin/src/runtime.rs @@ -11,10 +11,12 @@ use crate::types::{ RepositoryStatus, StatusItem, SyntaxFold, SyntaxSymbol, SyntaxToken, WorkbenchEvent, }; use crate::types::{ - FieldValue, View, ViewBody, ViewButton, ViewEvent, ViewField, ViewListItem, ViewTable, ViewTreeItem, Viewport, + FieldValue, ServiceLog, ServiceLogToggle, ServicePane, ServiceTab, View, ViewBody, ViewButton, ViewEvent, + ViewField, ViewListItem, ViewTable, ViewTreeItem, Viewport, }; use crate::wit_host::{ - bindings, indexing_bindings, providers_bindings, semantic_bindings, syntax_bindings, views_bindings, + bindings, indexing_bindings, providers_bindings, semantic_bindings, services_bindings, syntax_bindings, + views_bindings, }; use ide_core::CancellationToken; use ide_core::ipc_path::to_ipc; @@ -34,6 +36,8 @@ use bindings::openidea::plugin::types as wit_types; use indexing_bindings::exports::openidea::plugin::document_indexer as wit_index; use providers_bindings::exports::openidea::plugin::providers as wit_prov; use semantic_bindings::exports::openidea::plugin::semantic_tokens_provider as wit_sem; +use services_bindings::exports::openidea::plugin::service_provider as wit_svc; +use services_bindings::openidea::plugin::service_types as wit_st; use syntax_bindings::exports::openidea::plugin::syntax_provider as wit_syntax; use views_bindings::exports::openidea::plugin::view_provider as wit_view; use views_bindings::openidea::plugin::view_types as wit_vt; @@ -519,6 +523,7 @@ struct Exports { indexer: Option, views: Option, semantic: Option, + services: Option, } /// Most results one syntax call may return (more are dropped). @@ -599,6 +604,7 @@ impl Runtime { let provider_indices = wit_prov::GuestIndices::new(&pre).ok(); let view_indices = wit_view::GuestIndices::new(&pre).ok(); let semantic_indices = wit_sem::GuestIndices::new(&pre).ok(); + let service_indices = wit_svc::GuestIndices::new(&pre).ok(); let instance = pre.instantiate(&mut store).map_err(api_hint)?; let plugin = plugin_indices.load(&mut store, &instance).map_err(api_hint)?; let syntax = match syntax_indices { @@ -621,9 +627,13 @@ impl Runtime { Some(indices) => Some(indices.load(&mut store, &instance).map_err(api_hint)?), None => None, }; + let services = match service_indices { + Some(indices) => Some(indices.load(&mut store, &instance).map_err(api_hint)?), + None => None, + }; Ok(Self { store, - exports: Exports { plugin, syntax, providers, views, indexer, semantic }, + exports: Exports { plugin, syntax, providers, views, indexer, semantic, services }, limits: setup.limits, version: setup.version, }) @@ -946,6 +956,29 @@ impl Runtime { } } + /// The Services pane of node `key` of the plugin's services view `view`. + pub fn service_detail( + &mut self, + view: &str, + key: &str, + invocation: Invocation, + ) -> Result, CallError> { + if self.exports.services.is_none() { + return Err(CallError::missing_export("service-provider")); + } + let result = self.call(invocation, self.limits.timeout, |e, store| { + let ctx = store.data_mut().new_invocation()?; + let services = e.services.as_ref().expect("checked"); + let r = services.call_detail(&mut *store, view, key, wasmtime::component::Resource::new_borrow(ctx.rep())); + store.data_mut().drop_invocation(ctx); + r + })?; + match result { + Ok(tabs) => Ok(tabs.into_iter().take(MAX_SERVICE_TABS).map(service_tab_from_wit).collect()), + Err(e) => Err(CallError::Guest(e.into())), + } + } + /// A user action in a view or custom editor. pub fn view_event(&mut self, view: &str, event: ViewEvent, invocation: Invocation) -> Result<(), CallError> { if self.exports.views.is_none() { @@ -1143,6 +1176,40 @@ fn opt_clip(s: Option, max: usize) -> Option { s.map(|s| clip(s, max)) } +const MAX_SERVICE_TABS: usize = 8; +const MAX_LOG_TOGGLES: usize = 8; +const MAX_LOG_ARGS: usize = 256; +const MAX_LOG_ARG: usize = 4096; + +fn service_tab_from_wit(t: wit_st::Tab) -> ServiceTab { + let body = match t.body { + wit_st::Pane::Message(m) => ServicePane::Message(clip(m, 16 << 10)), + wit_st::Pane::Text(text) => ServicePane::Text(clip(text, MAX_TEXT)), + wit_st::Pane::Log(log) => { + let args_fit = |args: &[String]| args.len() <= MAX_LOG_ARGS && args.iter().all(|a| a.len() <= MAX_LOG_ARG); + if args_fit(&log.args) + && log.toggles.len() <= MAX_LOG_TOGGLES + && log.toggles.iter().all(|t| args_fit(&t.args)) + { + ServicePane::Log(ServiceLog { + program: clip(log.program, 256), + args: log.args, + toggles: log + .toggles + .into_iter() + .map(|t| ServiceLogToggle { id: clip(t.id, 64), label: clip(t.label, MAX_TITLE), args: t.args }) + .collect(), + }) + } else { + ServicePane::Message(format!( + "This log asks for more than {MAX_LOG_ARGS} arguments of {MAX_LOG_ARG} bytes or {MAX_LOG_TOGGLES} toggles." + )) + } + } + }; + ServiceTab { id: clip(t.id, 64), label: clip(t.label, MAX_TITLE), body } +} + fn view_from_wit(v: wit_vt::View) -> View { let body = match v.body { wit_vt::Body::Message(m) => ViewBody::Message(clip(m, 16 << 10)), diff --git a/crates/ide-plugin/src/types.rs b/crates/ide-plugin/src/types.rs index e41eb314d..cd101ab59 100644 --- a/crates/ide-plugin/src/types.rs +++ b/crates/ide-plugin/src/types.rs @@ -505,6 +505,42 @@ pub struct View { pub status: Option, } +/// A tab of the Services pane of a plugin's node (`service-provider.detail`). +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Type)] +#[serde(rename_all = "camelCase")] +pub struct ServiceTab { + pub id: String, + pub label: String, + pub body: ServicePane, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Type)] +#[serde(tag = "kind", content = "value", rename_all = "camelCase")] +pub enum ServicePane { + Message(String), + /// Read-only text that can be selected and copied. + Text(String), + /// A program the IDE runs (with the plugin's `process:` grant), followed in a log. + Log(ServiceLog), +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Type)] +#[serde(rename_all = "camelCase")] +pub struct ServiceLog { + pub program: String, + pub args: Vec, + pub toggles: Vec, +} + +/// A switch above the log; when on, `args` are appended and the program restarts. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Type)] +#[serde(rename_all = "camelCase")] +pub struct ServiceLogToggle { + pub id: String, + pub label: String, + pub args: Vec, +} + /// The table rows the UI shows. #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Type)] #[serde(rename_all = "camelCase")] diff --git a/crates/ide-plugin/src/wit_host.rs b/crates/ide-plugin/src/wit_host.rs index 4414a996a..f2326035a 100644 --- a/crates/ide-plugin/src/wit_host.rs +++ b/crates/ide-plugin/src/wit_host.rs @@ -815,6 +815,19 @@ pub(crate) mod indexing_bindings { }); } +/// The optional `service-provider` export. +pub(crate) mod services_bindings { + wasmtime::component::bindgen!({ + world: "services", path: "../../wit", + with: { + "openidea:plugin/types": super::bindings::openidea::plugin::types, + "openidea:plugin/workspace": super::bindings::openidea::plugin::workspace, + "openidea:plugin/editor": super::bindings::openidea::plugin::editor, + "openidea:plugin/invocation": super::bindings::openidea::plugin::invocation, + }, + }); +} + pub(crate) mod semantic_bindings { wasmtime::component::bindgen!({ world: "semantic-tokens", path: "../../wit", diff --git a/crates/ide-plugin/tests/fixtures/hello/dist/plugin.wasm b/crates/ide-plugin/tests/fixtures/hello/dist/plugin.wasm index b10eabd0e5d6b76cbe4349a28b40217c2e73c9c2..8baad7a882dd7d52fae25d0797ea74ec7b2cde48 100644 GIT binary patch delta 46822 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 delta 37631 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 diff --git a/crates/ide-plugin/tests/fixtures/hello/dist/plugin.wasm.sources b/crates/ide-plugin/tests/fixtures/hello/dist/plugin.wasm.sources index 0dd381428..aaa350d53 100644 --- a/crates/ide-plugin/tests/fixtures/hello/dist/plugin.wasm.sources +++ b/crates/ide-plugin/tests/fixtures/hello/dist/plugin.wasm.sources @@ -1 +1 @@ -31c58d5da122b9ec92bc18c2ea0aa5a153075125f9df995eb458ca854d4693ba +670aec4d79e92537efb7048698bbb8f236cd6006524c74459891b03c9b613450 diff --git a/crates/ide-plugin/tests/fixtures/hello/src/lib.rs b/crates/ide-plugin/tests/fixtures/hello/src/lib.rs index 414c223e0..4f1253592 100644 --- a/crates/ide-plugin/tests/fixtures/hello/src/lib.rs +++ b/crates/ide-plugin/tests/fixtures/hello/src/lib.rs @@ -1,6 +1,7 @@ //! Sample OpenIDEA plugin, written with the `openidea-plugin` SDK. //! Build with `openidea-plugin build crates/ide-plugin/tests/fixtures/hello` (see plugins/README.md). +use openidea_plugin::services::{Pane, ProcessLog, Services, Tab}; use openidea_plugin::views::{Body, Button, TreeItem, View, ViewEvent, Viewport, Views}; use openidea_plugin::{Context, Error, Invocation, LogLevel, NotificationLevel, Plugin, host, register_plugin}; use std::collections::BTreeSet; @@ -96,7 +97,15 @@ impl Views for Hello { } } -register_plugin!(Hello, views); +/// As a services view (tests): a node's key is the `sh -c` script its Log tab runs. +impl Services for Hello { + fn detail(&mut self, view: &str, key: &str, _ctx: &Invocation) -> Result, Error> { + let log = ProcessLog::new("sh", &["-c", key]).toggle("named", "Named", &["named"]); + Ok(vec![Tab::new("log", "Log", log), Tab::new("info", "Info", Pane::Text(format!("{view}: {key}")))]) + } +} + +register_plugin!(Hello, views, services); /// Today's UTC date as `YYYY-MM-DD` (WASI wall clock). fn today() -> String { diff --git a/crates/ide-plugin/tests/fixtures/indexer/dist/plugin.wasm b/crates/ide-plugin/tests/fixtures/indexer/dist/plugin.wasm index 377c739e305b979126f8ee89991cfc62e2f73d87..473c8cfe12f56474968795329e771ae15bf529b6 100644 GIT binary patch delta 18355 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 b74N#K8+(}jf2jnWSZ!)g)>-Y^x#0f*p=Gxz delta 15558 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 diff --git a/crates/ide-plugin/tests/fixtures/indexer/dist/plugin.wasm.sources b/crates/ide-plugin/tests/fixtures/indexer/dist/plugin.wasm.sources index 8e761b2f9..14301c47f 100644 --- a/crates/ide-plugin/tests/fixtures/indexer/dist/plugin.wasm.sources +++ b/crates/ide-plugin/tests/fixtures/indexer/dist/plugin.wasm.sources @@ -1 +1 @@ -1a8d4b16e31b4904b6a82c5d37ba71731bda3ff8a5ddb31846960fdb117f3e3b +c913c2c94fecb43d00f73f3171cc2fda54caf7a28f170424b0addb1d40ed4cae diff --git a/crates/ide-plugin/tests/fixtures/jobs/dist/plugin.wasm b/crates/ide-plugin/tests/fixtures/jobs/dist/plugin.wasm index 62bbd1544c293af911f9a15d67d9c1ea7e3c285f..7c32737006dee78ba88d15f37871942d8fdad82e 100644 GIT binary patch delta 28381 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 delta 25321 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 diff --git a/crates/ide-plugin/tests/fixtures/jobs/dist/plugin.wasm.sources b/crates/ide-plugin/tests/fixtures/jobs/dist/plugin.wasm.sources index 8b2281a54..cb880be2a 100644 --- a/crates/ide-plugin/tests/fixtures/jobs/dist/plugin.wasm.sources +++ b/crates/ide-plugin/tests/fixtures/jobs/dist/plugin.wasm.sources @@ -1 +1 @@ -c3e25003bb5cae1ba412becc31b9c9e1ee542de42898c425fa24899b0572822a +911388ae62843d7b1e4c40d91307fbe507535c60680a9626cc07d724b75a9dfb diff --git a/crates/ide-plugin/tests/fixtures/misbehave/dist/plugin.wasm b/crates/ide-plugin/tests/fixtures/misbehave/dist/plugin.wasm index 1c84e19be570e9dcbde9c422afe58e2aba67f9ed..f7e985dc9bd752709292935c820cec3f3a7594a1 100644 GIT binary patch delta 22529 zcmdUXd3;nww*RfVy{5a9897rm zifAc~iV7nNC=6(H5JioM5D*ZBr--`(gE}fIiVMQ~o~qlOgvF=7kMqYbP`7Svr%s)% zPAz@EKJMIi#JT2fSL<}9wfgU&lSWmI8doxY+?X-drJcHTsuYjAZq(Z|O}v{DWR>DP zcMnI9Y1!g7cUEDgGsPWXHO!$oM^2nLZlcZ-GMJVU10wSjl=@xnsZ7sg+Jb791~8+& z{V640Z$+t{-u@1x(xTN9SSr$86Z$&ZFfCO~OGrU-K|+C^i^@HdGm&~fA=EYA%kVLy zN=9BkYO?CZnd@#X(Mg;m~!Q5Zb?Fv`w#cn(lO2Cn;WM+;x*h zu`fHi`ex=s2Y36f&{g%6=+2v20{neIq+xfs(?hQC0- zKqE!v4-4W=q*4>`@kFPqC-j zKiOLL3|q&ZWvkg5_5^#9Eo1kx``G<#J)6cBvE{6uJS!?sf9Jo`gYGfkGm$Bn&qf1 zLGsXHZPLX0p}D;nKeS3LH**lxH=6Bb@=%bH!UzdAtA1&ykOh`M-B731T49r0yBozj zc|A)A=AjMiUbSHsBl!tH2DH3sb#--Gh+C`Y$u?fJ+1DuglNkDj+zfE}B6?EDs)2q;|hR;Mxlr(SCqDkF0aaFsE+06R-c8M%=I)5?I3Nk{CoRql!&D=N4ap=i9|ucz##h9?$GfRC-pYLOe%xqWoE%rsC-+A!yx8sC2M=MoRL0 z5}PESZz$8ngsrLKr4s7r!;*F$g{N<+xU;xeRF(RX-KUf~7+Xp}(M>qkN6W1Y=F?k8PjU`mubfZihF1>YR*mPOp+MsT_3iNQ$ z>(_i>-3dY+(qm%XE0C>9Kic!e&k*@|K_CTiv~pf*x@riA2CagJ^=b>R9^)tRQRl4e z(vaJ9g?SjVF8ee#5hgy$D-s!93JtWC1?7Ap!^=W(QI}2;sG6!xP|>hh3-<~*Wus7n zDuHC#B_U^kS&^XZr0~*+ImjkWRFZ_$CmYt?PxPRY{d-UnXk|GF5z9ft@n@Wjg0upV zNOVI;U~FM7kw`;b@Wkffqw^vSq`F?CUX7E+B!?Cbxvfa=K&n3lEGy8onr}b5<^HwX z-hJw0ZI-FQx^za~er?vwfq`VdVb|IB#;oTKeDTh@{n|x=B+F&|M0y$W_X;>nzun`s zJE%h%rK7usY`>|40_7N)1FS45OYfl?`FaIhmd}Qu_X@a8-G(q*L2!pPce#da(+%`0 z0Kg3Z)61&ZUE=w&wviEvJVU_uKsg_zQdfXijtYJbB3{9Jpv+g!yCL;A4BxCE2{ZlW zya=^jE0VW&kUZBwxsai6nSo zzLb^o`KS+703#~&Im}EX;2sreVqDjA0tl@-p^G9hx}vPQG?Y*d z$|wpIm18h?Mb;wb_o7?VX_rFGWs!%9lnxRr7K#rlF78+sgsO&lY0yJWVgOOK2^tl+ zss7+@!JMTmh;*1J=YdAj>l~#b)*MzV7Iy2xZW7zNwd)`elW=0~2|WnRB4+vxX(`PB z%zQ>=Zh0LQK_nmrd5QwkaMYIb+n6o4-%oFVF}8Al1YCQHXclt!3UKsf zTRK7*a%k#O4&y2t(yhC<5Fk^x6hyQD-o~p0BS0o-5rck7l9WTd@K(UX6?Wm$>H4>`3D-Nm8v!1I|PmD6LK=6{AsVYs-bI2y+V? z;{Xocie`LQBY&1gZbEVjbTS!!x35K83!OMHy)@74SPO`h4+tJG)My67Lol38)kWvC zQWD~5aN#>ED@AWArf~q6E-pALE6iKwTMp`)wai3ir?}~?%yK(h+RHVpRyhz5F4b3( zT^xeU#oSnzb+}O^_3Xr7m?j!Jz)JMI)Obe;s`9Hm#xM0ddp^Je_sVI&%EM$dbBp+E zjm2h)^)=%;T#qM)W+JLT_w0=vE_+h%Zp?AW#XO>apX{8Iy%w+SwRp*EnbjvRk`TaT z6!gK|ddZ)3!@wqBc2Y`;c?pv4Atmhr8waWAhR9pa%fMx5Fr+o;wLC$;=?W(3)znhD z+W|9yyzWHQ@|qqf3VA9XtE^UeDwNfYivOuJt+*lTz&l?Q_6xyTKfho81$&e(K|zRS z`L&=a#_LUVF|IqDuDJNw^+@NM)Inv2yhAtzPwkg6oussdCC zbg3$FU5MA#Rc!;cMdx!f3+#?tDnq=sQ`OF(+LO->r>cUaxCyo#C|GlDTH(pUsoBD* z+3q$O33$<;iLcIWcM4hd+tvLf%U$}{+0Ik|9vFN)jdIPLN_=gdfTBw*c?65&(r zmD5hFoY?=la^g1MIPvZM%U352G8rl36^N3dn&P1=`a}$Am(pQil1Y71g2|>4w@c}u z0oLYZm#`9HW_mfln_{${&tP;?lxZR-GJ_z%G^LsuwIM94wO|{QTdC4aW#Y|{Z&`Tr z%eQR2d1}KERBVe^WzTW|GudQeKqpJatoiUko|f|zGVf-=bf1}S8tA~xBm>4Rh<~Py1^@;#%oHnQeB=pBc^NG40$>avcr31E37m_h8uo6kIoNqtyapHQ1Bt%1sX75o{B zLF%W(!YhN35T{k=fj8JBlUtmY`_>QGg0hYu*9p1U8jq6-a$A-DtrXU<*LYBIOa!#V z%V^Sjmz8ZNGO?_7Al0a*c`FGkog}-AN1(wmxS?e08wEL|Kyz1M?Z-{L(b~_JzZFXU ztPjE1$K<v>FwemQrjl%~p3t#St58W!Xz)ig*h z4VCgE#jJyHj4}&2plDPY=Ab%eO>2=jFeuk6tqa(fDG~=~k|`-1oE=eUVCRk|DG>TJ z{IVM1;VY$5jvFMbK<`_@9a1(jq$3%(T+%~>pjK(vA~PWplJyV?V!hSS43v0faJr2H zVc?HBZVD|EVvwP_jjux?E%RA03%Ry38RS2Z8p3)&jmJoY449D+u!3&Dx^NO$Wch=c z6d6RrFi#C;Q@er)#}d2+hTU3@6`d96-H51?0%o?AF~(jMD{OKAha)?COl=5OLrOJx zBLyE!oDVY?%z(0I!|0hgL4#Mr+>xaVWrA>(0kno01LK0Zc=O9Q6C;A@AwwAFs3~zE zf;NJXW~NBFsxXoPGXTTGVTNGb+DL2AMh%(rl<@)W7gG~pLnD>eaha6JEV6hWGmDI& z--39NtwJ?26CmdZ#ZI@Jjv=6Z6-lisFCtVSB~1!_Ve3m^e1PARRh}mD)ODd5~6BrY`*` z(QU-pc{ItIn(-VtPMWU-=r&0TBpVVD74t_FV;}d05e5A1I?=u1R*D)Mc4pc;29Ptg zP2h7tOX*Q4hFsl^@7pTwyE;4XrzK=Z$i#8$CHN7T_f5@u_eqrtiO-uU-oAP?U$d>g z_g|iLI9CxW^&gBCOvf5QTsOXxgPWcKV%hj&er&mTbNmAoT{odmWSiPdXzKqKC-=Zl zvN~E3n%F#80%Fi?LdcyJ^ngxjQ$PupWjbqvUS17NmgNqbag=pIM0;V_7{ti2ub~Hh zP;sn*iZIQ*7&%w2he%P~CYBwM+K>+`BOfYw0g;v-*lN!T`Xy|ysg*E)$TJ|eNu_%8 zpf{{~yrY8w^oGTB&_mTFGHs_=`h-LW*O&(V4Fo;Jtblb4lcL3@$ek$6kjJ$NL5A^_ za0eDX7^fz&bj!&TIM5tAAOKaS#hZ<+33otrytZv5aT$^1_ze@RHHi5{7!6sGz=Whb z;0VF#0FQLzOOlv?PH0MuCFGzN6tVmAp4g35N^XFW3>MaD2z44L>38^ivJao>jkEyG zu`YF(PSXpUo-C`&2fX)y=^3rMBi6WeqL1CFhNYpUB`J{2$9Hnadc0%m1(^9SZr%-u zXePqK#Gy$dxQV0=(4sjJXq$v!_*!BbOaSx6y<_`|?GrBMN0*4u#5#(WPL!!1Cx+X6 zK~%t21&0;Nm%}r4-wr2EQIgM26&FkzS-)Y@1jbg1vg;niLGG^Wf_Q#+oylg4)>CpX z(PMv(*oz%ANQh?D757e(@rN3{aLATM&R0mYX0hIQU(9+>3_^-nY+J;_>ENAHQd{}n zD_z@1GTNm=4P^5fR5rQ+ce2pS}pr?de*b zq9`IEHuZq1Q14B`*ss=f01}mioP=H4lpwc`JL!}Wvf;3D`(x}VaZrhFI%sDAj_6Ht zD7MnjzASMfGO3m{Tr=6|poRfQYJ(0?Lf5Nn;^zS$+}8lJWlG!It9sor&2xbiz`*xA40RtxD-7mcUPMet>&h4u){k0rg3;)aC52XaC3Y4_9mIp zo(qPFIaAxy>zb+kDf(q<2eZkd8ch~8%f7r|y|zT06R8A@sgdfWebPfPo+KNr`3{Ng zkpT%WD#m%O^`d><Fn%FC$mt+fz8+L)TB2IEx z9W7@%%yKSF*|rCT0}4z@nDsZ+-#9Is0j2k+2gSPS`SPtV?jm%UQA*i8|JF-9Fw@W9 zm@AAKsr4_;jHuj8_|jV`N38f;j%?FQ1ZLOrl}p5zvrE|`kvk`YeIZ_+UBFg|FJ^aE zIoXmtFn%@`u#YtJk(oQXTx8$XMvR#=NWln-&*%8!aEx2R5>BW^Zrv@P^94R}?c5x3 z$K2K_9vdo5C&ARL=_>#;GeTAs3qS1mnDCL|)X^qyDl)MtgPrshWIV7R$>Ce8gRBs< zUAXKcifxm+&L+rn^E88xT@5mH8@9-zYNBF9EU|yyec~_F?KQEaH zaqO-v#>EZu@>nBEvaWQ*2puEy?j1B*IZuY=;DU7HF(m7iC5tyvtC7lRp z3y{f*=oZ5yg}J6mg9}YNF4!1IRdqwUwRG(Xy#<}9l2; z_?8;mF5lEr&ei^OpiV>gHn+D)T14*gCxf;aMXW@ZtAxx*kXUTX0d}oh%7Na*Iy&i( z%KI9#XT$ZsEsVUI)#VzY59RluDfR2iuXxh8Vw)0WiJjfOOpcId^~aiZAaghHsvI ze+d^3bx1ZdA4L1z?^+t!B&>n;tqd@T6SLTi7zP7H<>AVoYx0Pm6=>HgRlm`^0ItOBOn<28?X3 zSiQIy#qTXP?c%Rm7I#_FnWLMLOU^MA77_!H+qg}vTQWcY>2JT=+4%PQW5=~wrl;n$ zC*OYZ(A`^CeSteeHQI%sKDUlODX#r{`8l`K$gu>VQ`Fd8j%jDp8o~zGzG&e<|A6#z zIb0lrhZ1UV$tWfcYj%sz|K5fpay?wim+uzc9_|d(Yai|k)E7UT#cmhtA3neMDakW{ zX^f3zr=v+&oyFQA7|K|0qSMlxcJ{@HRSb=mDvsMe3Z^XDJBPe5F=1(&9<+!d06<*t z4NJ#R+=tGJ;afCP?li{$9BMf&bcyG2`2?L!X3PVni^Qa*t;KUo%Q9NvHdm2`0E-8g z=7<{~$!B+n#gA0rx#y7*-mp!0A1(B~CP`&Iz`(V$9xXA}Nix}c%p?mpKiVcCwmrXS zw^;mW$Tz2+$ZNf$L?e8mF<%Lwai@wcGTL?aq-h;igFm9g-JaB#wNu?$-A;9%*-ijs zKAdrvIBVHieA`wrby-DX6CE9(qj-5)9oTcu@@qp+I=lB>f^j_awq z?TBOJv^J4zZrCB*GxmYq4dVO9 ziddbDAPit&)_nAP^Z&Ot2pY=&rjy!C*WBvqWvZxp+loWP)4-6)0? zkoUgme&UHYieuGfktkkS%s+fp3|iTf?}Wp$vTs(S5+Pg4K)*O5L$G6-M&4@`&V6)y zMw&;1tCcg7Zn^Cl38HA5=!O{$D8`(M8A&OU-UJX9ceWaD`}p*U&6sUZQ5)+kh=w(% zg+QZ$PpB4n-5`?xF`VBsO*}We<~MBLit^R%*nBZ)b!WCt%v+t&`UT~5IE;fd2H(97 z?#70wcy@K?2$aq~{-RAe$OmR&+Tucl8yYCZq%5aPjMR9UFbdcs#_SNEYMQeH8<*G? z`#;!0yIyTLm@`&F)ZKI1GQgESf zwko-3Q$|}wySV@)RnJ>ASCwQWkF4fF%iU;V>EZ6f!z@a zzr|2XPTnAgg?nCV|2!mV=aTrz+&BQG=4Q;Wy{^n)GVY;rf5??wC(@rtj$jAL7NU<; z`5s`|Y)evJXTc&8U21R+2u)3;$dicSM^0T#f=!pN!Oc7|TQ}b`I>c?)h+HNM=FfA~ zrzz~PD~_hf#Rcc@iRPBpSGqCMyHeJP{3sf`j;YDPR>meB$&}b zC(zUM>bQv`IHtV49db3`z7~Nuou)P#``X}C5BNsdGS;hQb5w+6sU;B@rA@TzrcIxD z{RG@2q4fd!bzrL(i1@5&Jm?Y0om0iYz3#}yhZ`VMrmL2W+SJ-aU1J=VG|5c~;igGH zSUGH}(@Ct%@-}6;PR_#Z28pyQ?vlwHf-+Bfaq*La#po(ghf=fnp9Y?It%oA#;##3j z;_9|?Yo&4a)BPp4HFbhD7IzL&sk(1Khe1_uoaFGtE{KRwrupc`$uv!)A4RyWBn6N6 z$3eJ+!XtEp(Q6%oIiYEww4Yo%BIgd^A+dmKZc_pb1|?)>i&35jCQoz7BB}vGVY3Oe z19MuE<2-EtPjjInJPxllWP-Ig0xgq1Hnmdy;DqDER^*q^c?C{xa90)fh0M$xd-nkL zF#bCYZp|T)vG#0}Ox3J|^2OM$CKwO|r!Azfl9{BF5xf$nT9X)&vkg(hqCwUQk&&TO z2dYRS1Q*_REpXvUS>kr6`Ge}p_PjuSJ$}DPsyU8<7(htM=`<_T;(|qRGGc4Jy(~tz zCok!PE&@oFHfFv6XuhY`R!)~ZYqJW24ApQO1LAIN#U69a^*p*x(Sw9s?%(^|fMjL$ z_C>aGrpNT%Xr}HccEHr0v>!1;IaA(KA!)DI17Hx=>ogr;--f0GFa=9-)e>}6Gb7y1 zJL<;OLHpDi7FD7#;I=WJFXztYOWXi9&#`Xzhcp~SC?ZQ2NiK4c##V?HV#Qj5g_FA2 z_~GTqEeG9_J2I`M!BsqLDw0d!45CgmdkAAa!S@f2)!Vf8nWA`hFk*`jIS{(#4Qfqt z1M6X%L_>~dvlMBCR7(l0iFE`&w$QQ~B}FY}Mp`t5hQhsgNV*q_$Jnp3wMQLJ$97$} zC;$-5=3R5y37)hah->L`CxI@XLQid8s$*ff{YblI5nQ&UjVKOVDrK9F?G2zoLStiM zHw`j!Lg)%kY%7e?sV(>FF0snar;Iw znQV_b2IH2G)EP#m*&dLzFF0bE41uRrKLlI^CV3-N6|=mlH;FS@U$R3w@YAIFcww_^ zf2;aHseVO+6ewsAL<3z)Kh0L5mVG9+?DN+(=-2yHpyGWhtyN0ou?@5)vY%d!1w{S! zr~l4qAu(a?ApX==@!Hx_Ht)%2su-Imy04o^E78^Ky7I;+#PJu?2UlxEdvFfRM6&+a z4##Rq-SNf>k32d^9)mdA7cxQ|v#DV(08H+q`2q^^I4OwcOHrwnl)}ol^>gi7KO@)R z^5<>v$S`Apb+|!s;d6ZgdvB9Gm2y2-Jn~$DTW*11-{gOu>l*kewvh&@pDWVWcg0%& zeEFQQzOuzqfAjj{oMuaXqDxF*eLi4h{6n;Q{=)1K>&%~vYx1L|hXTBqEvcghQ};)a)pC&~i|SV;?Z-S|*^_Oiu37DXEe zuo>c}josNR;+c*8*e1bWsX$KED;+M|^9GTHtUs5Mpn;{__=frp(UNKgNt;y)6zSdp zi3*CP?+u#@x5lop5e}2Af$?zTYq9nfGq*wV9$FDI+Lp?ZLSXC@-@np5XQM42;7SN0 z2)@KkytQ$+7_g}zr4D1#LL{9weUN|arYeqT^Cpv`Pd9bJXtFn#<^5`xpb0~_lQxIW zRNbOCxT8LM2yp%EF~<9`Ndx2M$0a*5Dl}m6#^&DaP0^-t0DDV}YAj}ZM6@vk44!Qa zpZ7LV4v_x=zcVoOx)Nm!aFbP^e*M$MkIbKq?lGk@)f}k z9^O$UWLnXLmL0}xV&%@6gWjV8`BMSR;l@r%Sqzg4CSmzg_V-meBM-!5ydE!ymB#Ji zTH^y%4vT_8H7h3(7q`7`g?3Q|Or099wt2FCSA$Z2xgBAAA-;OOu*(}%EhekvPSHgj zX6=@`D*Xl6SS(+$-2q%+e2$C$Z}f#_yZen$mikE`;RB*$n+z9V0)GSAwi8J{Zz@5i?kBF4WdLA)b+TW1;Go;+299^lr5XJo`z z!%3}X{4BEe_ULptjsoZ#=g77_)EoJ>aN`xSaGSR65wrH@@x!~tV|%ZrsMR~?Q8eV8 zc>x7Sy27aT^E;PO!Nu=(rD*QEWfV2MJ1`XM&J*&SPg-Wu6;0x@O%YV<^4^(Ld%}Bv zqG;QDT@c;%es4Ti7C$EePn4=$$Yy$@cYXz7QeC`$V1L5fy? zlt$5}k495;#>ed_`t!#H6wUg$b5VTQq*aO?u`G}Dv`;|__a}W}bq9WumKnqB89f9a zvWb`g9{HqgMbjkKboEy?Dc06w$uuE=-{{gmxvw1`nAr76dDf4Tx$<}5_*r5QHY1Ln z$lup1PLwq|`M^zW>-OcdAH^f`xpiN64%WE$cR*Ij{YBp!mSQE+wdk{}m>La}Ji4#7JwlhNdmpd|V0F7cAo7A04FJ%O6O`t=ry7JMV2Z~Epr zO3nCI;_=UKB_3sm&!Egvhqtg};*9SuqQva)LKHpzoox2bcN;0Sc*MUD}Q#AG`IhrLu-AJjNpDQW))6b0*14qycO>#((}2Cioxz(lt(mmh>+? zHjgSid+bVz(vM3ve0-cpcTX$!UQ)bAbj6IH?>WY**|BI(#)$q=!5GzyzRVbrK6(ph zMEhtXSNXR)S#~s4XE(=tZ-HL)QJs-KN8i&~Zd_$gAayjw!HCw;>m2L=#eEZihRkKQNtz@U%(cC25!ODA95trvaQ zY|79vqefhH-T12}kCWdtyK2nHu@{URJM!Xj*N%+NXvYRdJesB%2+0UZc4%d%{fNB? zRPIAaKnOI8shrwT{X~S;2$V;42`;szcM8;w$|z8MDo2}$%%F}_5Smw}cj}NjcOnpg zKOWi0@51(vM;86dQU3=>`4fdAx;z!otGr!a^6CrXtQlAkb|QUeQ(AEJ$$sX6boIQ`;Pb!D!!) zr(n)>Mmqo8d8XB7BYz`3VninxSPO6d`m&un;ap7=&;&!X$*75#}N+Kv;&b4q-FGdkCK* z97Z^b;B0MZ20|7>7@-WI8sQ>@KOI?sN|U5<*A))nV?Zo z5YR${A_|Bry1KFk1Xt0Z2nZ^u;ELjkiZ?8vh`ONszE4&6B;k7X)%TxY@~N(_>#3)n ztDZV~c7NwNaMZJWp0{l}Qc)Q^e|I$8orv$vO1S_^(4oISRbYelPReUYz#}L z`m^H;b(1Msyeuh$(%a+1=`kFreeE@)r?{;X0$Kd>KpH-^riVh_I2IoY#rZ;^kS`9|XvqJTG8nl0 zHznKd-P@xvCCPiHKg#U7x+WzMRc!HK^tNZU%-ObG#`~T0)@?Ff_ip1QsWWx;uZ&xn zrL1Se+G>``k7k6U{s>cS7U*@wfZEHinHIf~-OO%bv)K51S(i)y_@@!W$6htAX5^^9 zviWQwdw@O27O}-_344hBgFVF>*$TFjJ09FY&v_GEoc8^ zAF+?wZuSZLlzqnHSAL*<%v2?C0n?(UQlRPZaxJIt@o8pjSdewo!%V^8z;dEvJ0 zrq|WgDfUydo9dK^sn}j)4|0^on!LVDUGaCm%*;j9xY6t&lKU-6awE*yO^r*#oml9b zmDJKMFjc#L1AnjG8O09B)dHmLkpM%A%nqye8d=~+i+LM(|NL&zn+OM!*}jOehI+T7 z{bKbMd+8?Xp+HqEwOu{c?2cDWtu|HQJ6{x@eO&ceQ3c3gGE?hg-cqThJ4h(@%%=#b zU4&lK6KUWp1R%U@+r;DB7j{`D(odjSAGIDWQPQ$at0wC<@tXD*up1j!wohQ0bvFV> zi`j~)7N|j!Wmzo90;Xbo-}ruqpBSs-I}1vZ57R(R)$)ikQ!{>=&T|Xf`8&XWYKsB5=XdLEEohnfCJMrvNWZ`{Ck=3e|>C`T8;(W9^ z&^guLc`Rk9Nd3L2H`?tf%E2?fb57e>pAepWs)X1?z0*5Wjp5>Xop{dgOucXEO#L3{ zoQtPXT!m-Mot|9MgsJZ|yP-Pj3l9>s>;n ze-h8>CGGJ3a7iybKPqXDr?0dc&;F$ZXF@5p1+-#`ap1FTO^dQ={%AW$N}Xaiu`yw9 zzIa!w9m#xiJAbz{Q$=*BbY`^F^xCBnOEbNNTB+p^Dgp57gfiSWlpQO%XO55`SGtn{ zM5$1#Om83Rt4XO;OSNhnuRh~@;&fQ+8%i)Wn~X}G??^xaKfMKNRX8(_;!+5_z{6ON za!4%l%6U%LP6j}Vf(msR!^<*$N!KpGS(UX>8B*jeR!aMZJfcxJUY4L!rzGqNF*|CB zeyV7k0Br?=8R(>sQmFwf0b9l*Mhx0A=74*gSz6Ew;dB3~uX3(;>l$@Pv_KNVu^U2E zoRY<@NBRMZ8F9I%f{^AYtMjdF-I95JfW zaGV`IJCqVkZsy=45(&SwLVZI?K?8+_iqdEIn>RoE>E8FA`9wKClnA>g*%a&>(#@dL z)pF4|td%JGX$rDUtw2#K6vft!?|F53+g`Fwpl`@)2b%dDXKD_BrzL>60wu0OLADu( zo+|+$4gh$0Pqvo7UY-*jE6H*tSRJZRFO#VeV2@s@4nm|>s%N1rP(eb|=N1gxtRz`8 zgB5ByYI`eGNHLhHPC<(GRBk{NtxzwtVJPtm$(#q_iHYVclBD@8Vy{z-4Rv*CBq#;y zd=^e17>X$(AHTPI`GpV*+n`FQ;{$c27%gK~BG_pFemvnsj0z_So)xOgndJxkS!jtF z&-k0mrMWC@P}Ot!7#{Dc}wc)2%WvkD9muQMDNw6~s~f zXqA<@f>}rx5D9%`@$q`UP=z-9`Kqq!EXEI1weKjf5