1use std::sync::Arc;
174
175#[cfg(feature = "AirIntegration")]
177use AirLibrary::Vine::Generated::air::air_service_client::AirServiceClient;
178#[cfg(feature = "AirIntegration")]
179use AirLibrary::Vine::Generated::air::HealthCheckRequest;
180use CommonLibrary::{
181 Command::CommandExecutor::CommandExecutor,
182 Configuration::{ConfigurationInspector::ConfigurationInspector, ConfigurationProvider::ConfigurationProvider},
183 CustomEditor::CustomEditorProvider::CustomEditorProvider,
184 Debug::DebugService::DebugService,
185 Diagnostic::DiagnosticManager::DiagnosticManager,
186 Document::DocumentProvider::DocumentProvider,
187 Environment::{Environment::Environment, Requires::Requires},
188 Error::CommonError::CommonError,
189 ExtensionManagement::ExtensionManagementService::ExtensionManagementService,
190 FileSystem::{FileSystemReader::FileSystemReader, FileSystemWriter::FileSystemWriter},
191 IPC::IPCProvider::IPCProvider,
192 Keybinding::KeybindingProvider::KeybindingProvider,
193 LanguageFeature::LanguageFeatureProviderRegistry::LanguageFeatureProviderRegistry,
194 Output::OutputChannelManager::OutputChannelManager,
195 Search::SearchProvider::SearchProvider,
196 Secret::SecretProvider::SecretProvider,
197 SourceControlManagement::SourceControlManagementProvider::SourceControlManagementProvider,
198 StatusBar::StatusBarProvider::StatusBarProvider,
199 Storage::StorageProvider::StorageProvider,
200 Synchronization::SynchronizationProvider::SynchronizationProvider,
201 Terminal::TerminalProvider::TerminalProvider,
202 Testing::TestController::TestController,
203 TreeView::TreeViewProvider::TreeViewProvider,
204 UserInterface::UserInterfaceProvider::UserInterfaceProvider,
205 Webview::WebviewProvider::WebviewProvider,
206 Workspace::{WorkspaceEditApplier::WorkspaceEditApplier, WorkspaceProvider::WorkspaceProvider},
207};
208use async_trait::async_trait;
209use log::{info, warn};
210use serde_json::Value;
211use tauri::{AppHandle, Manager, Wry};
212
213use crate::ApplicationState::{ApplicationState, DTO::ExtensionDescriptionStateDTO::ExtensionDescriptionStateDTO};
214use crate::impl_provider;
217
218#[derive(Clone)]
220pub struct MountainEnvironment {
221 pub ApplicationHandle:AppHandle<Wry>,
222
223 pub ApplicationState:Arc<ApplicationState>,
224
225 #[cfg(feature = "AirIntegration")]
229 pub AirClient:Option<AirServiceClient<tonic::transport::Channel>>,
230}
231
232impl MountainEnvironment {
233 #[allow(unused_mut)]
235 pub fn Create(ApplicationHandle:AppHandle<Wry>, ApplicationState:Arc<ApplicationState>) -> Self {
236 info!("[MountainEnvironment] New instance created.");
237
238 #[cfg(feature = "AirIntegration")]
239 {
240 Self { ApplicationHandle, ApplicationState, AirClient:None }
241 }
242
243 #[cfg(not(feature = "AirIntegration"))]
244 {
245 Self { ApplicationHandle, ApplicationState }
246 }
247 }
248
249 #[cfg(feature = "AirIntegration")]
253 pub fn CreateWithAir(
254 ApplicationHandle:AppHandle<Wry>,
255 ApplicationState:Arc<ApplicationState>,
256 AirClient:Option<AirServiceClient<tonic::transport::Channel>>,
257 ) -> Self {
258 info!(
259 "[MountainEnvironment] New instance created with Air client: {}",
260 AirClient.is_some()
261 );
262
263 Self { ApplicationHandle, ApplicationState, AirClient }
264 }
265
266 #[cfg(feature = "AirIntegration")]
269 pub fn SetAirClient(&mut self, AirClient:Option<AirServiceClient<tonic::transport::Channel>>) {
270 info!("[MountainEnvironment] Air client updated: {}", AirClient.is_some());
271
272 self.AirClient = AirClient;
273 }
274
275 #[cfg(feature = "AirIntegration")]
277 pub async fn IsAirAvailable(&self) -> bool {
278 if let Some(_AirClient) = &self.AirClient {
283 info!("[MountainEnvironment] Air client configured (health check disabled pending integration)");
285 true
286 } else {
287 info!("[MountainEnvironment] No Air client configured");
288 false
289 }
290 }
291
292 #[cfg(not(feature = "AirIntegration"))]
294 pub async fn IsAirAvailable(&self) -> bool { false }
295
296 async fn ScanExtensionDirectory(&self, path:&std::path::PathBuf) -> Result<Vec<serde_json::Value>, CommonError> {
298 use std::fs;
299
300 let mut extensions = Vec::new();
301
302 if !path.exists() || !path.is_dir() {
304 warn!("[ExtensionManagementService] Extension directory does not exist: {:?}", path);
305 return Ok(extensions);
306 }
307
308 let entries = fs::read_dir(path).map_err(|error| {
310 CommonError::FileSystemIO {
311 Path:path.clone(),
312 Description:format!("Failed to read extension directory: {}", error),
313 }
314 })?;
315
316 for entry in entries {
317 let entry = entry.map_err(|error| {
318 CommonError::FileSystemIO {
319 Path:path.clone(),
320 Description:format!("Failed to read directory entry: {}", error),
321 }
322 })?;
323
324 let entry_path = entry.path();
325 if entry_path.is_dir() {
326 let package_json_path = entry_path.join("package.json");
328 if package_json_path.exists() {
329 match fs::read_to_string(&package_json_path) {
330 Ok(content) => {
331 match serde_json::from_str::<Value>(&content) {
332 Ok(mut package_json) => {
333 if let Some(obj) = package_json.as_object_mut() {
335 obj.insert(
336 "ExtensionLocation".to_string(),
337 Value::String(entry_path.to_string_lossy().to_string()),
338 );
339 }
340 extensions.push(package_json);
341 info!("[ExtensionManagementService] Found extension at: {:?}", entry_path);
342 },
343 Err(error) => {
344 warn!(
345 "[ExtensionManagementService] Failed to parse package.json at {:?}: {}",
346 package_json_path, error
347 );
348 },
349 }
350 },
351 Err(error) => {
352 warn!(
353 "[ExtensionManagementService] Failed to read package.json at {:?}: {}",
354 package_json_path, error
355 );
356 },
357 }
358 }
359 }
360 }
361
362 Ok(extensions)
363 }
364}
365
366impl Environment for MountainEnvironment {}
367
368#[async_trait]
369impl ExtensionManagementService for MountainEnvironment {
370 async fn ScanForExtensions(&self) -> Result<(), CommonError> {
371 info!("[ExtensionManagementService] Scanning for extensions...");
372
373 let ScanPaths:Vec<std::path::PathBuf> = {
375 let ScanPathsGuard = self
376 .ApplicationState
377 .Extension
378 .Registry
379 .ExtensionScanPaths
380 .lock()
381 .map_err(|Error| CommonError::StateLockPoisoned { Context:Error.to_string() })?;
382 ScanPathsGuard.clone()
383 };
384
385 let mut extensions = Vec::new();
386
387 for path in ScanPaths {
389 if let Ok(mut scan_result) = self.ScanExtensionDirectory(&path).await {
390 extensions.append(&mut scan_result);
391 }
392 }
393
394 let mut ScannedExtensionsGuard = self
396 .ApplicationState
397 .Extension
398 .ScannedExtensions
399 .ScannedExtensions
400 .lock()
401 .map_err(|Error| CommonError::StateLockPoisoned { Context:Error.to_string() })?;
402
403 ScannedExtensionsGuard.clear();
404
405 for extension in extensions {
406 if let Some(identifier) = extension.get("Identifier").and_then(|v| v.as_str()) {
407 let extension_dto = ExtensionDescriptionStateDTO {
409 Identifier:serde_json::Value::String(identifier.to_string()),
410 Name:extension.get("Name").and_then(|v| v.as_str()).unwrap_or("Unknown").to_string(),
411 Version:extension.get("Version").and_then(|v| v.as_str()).unwrap_or("0.0.0").to_string(),
412 Publisher:extension
413 .get("Publisher")
414 .and_then(|v| v.as_str())
415 .unwrap_or("Unknown")
416 .to_string(),
417 Engines:extension.get("Engines").cloned().unwrap_or(serde_json::Value::Null),
418 Main:extension.get("Main").and_then(|v| v.as_str()).map(|s| s.to_string()),
419 Browser:extension.get("Browser").and_then(|v| v.as_str()).map(|s| s.to_string()),
420 ModuleType:extension.get("ModuleType").and_then(|v| v.as_str()).map(|s| s.to_string()),
421 IsBuiltin:extension.get("IsBuiltin").and_then(|v| v.as_bool()).unwrap_or(false),
422 IsUnderDevelopment:extension.get("IsUnderDevelopment").and_then(|v| v.as_bool()).unwrap_or(false),
423 ExtensionLocation:extension.get("ExtensionLocation").cloned().unwrap_or(serde_json::Value::Null),
424 ActivationEvents:extension
425 .get("ActivationEvents")
426 .and_then(|v| v.as_array())
427 .map(|arr| arr.iter().filter_map(|v| v.as_str().map(|s| s.to_string())).collect()),
428 Contributes:extension.get("Contributes").cloned(),
429 };
430
431 ScannedExtensionsGuard.insert(identifier.to_string(), extension_dto);
432 }
433 }
434
435 info!("[ExtensionManagementService] Found {} extensions", ScannedExtensionsGuard.len());
436 Ok(())
437 }
438
439 async fn GetExtensions(&self) -> Result<Vec<Value>, CommonError> {
440 let ScannedExtensionsGuard = self
441 .ApplicationState
442 .Extension
443 .ScannedExtensions
444 .ScannedExtensions
445 .lock()
446 .map_err(|Error| CommonError::StateLockPoisoned { Context:Error.to_string() })?;
447
448 let Extensions:Vec<Value> = ScannedExtensionsGuard
449 .values()
450 .map(|ext| serde_json::to_value(ext).unwrap_or(Value::Null))
451 .collect();
452
453 Ok(Extensions)
454 }
455
456 async fn GetExtension(&self, id:String) -> Result<Option<Value>, CommonError> {
457 let ScannedExtensionsGuard = self
458 .ApplicationState
459 .Extension
460 .ScannedExtensions
461 .ScannedExtensions
462 .lock()
463 .map_err(|Error| CommonError::StateLockPoisoned { Context:Error.to_string() })?;
464
465 if let Some(extension_dto) = ScannedExtensionsGuard.get(&id) {
466 let mut extension_value = serde_json::Map::new();
468 extension_value.insert("Identifier".to_string(), extension_dto.Identifier.clone());
469 extension_value.insert("Name".to_string(), Value::String(extension_dto.Name.clone()));
470 extension_value.insert("Version".to_string(), Value::String(extension_dto.Version.clone()));
471 extension_value.insert("Publisher".to_string(), Value::String(extension_dto.Publisher.clone()));
472 extension_value.insert("Engines".to_string(), extension_dto.Engines.clone());
473
474 if let Some(main) = &extension_dto.Main {
475 extension_value.insert("Main".to_string(), Value::String(main.clone()));
476 }
477
478 if let Some(browser) = &extension_dto.Browser {
479 extension_value.insert("Browser".to_string(), Value::String(browser.clone()));
480 }
481
482 if let Some(module_type) = &extension_dto.ModuleType {
483 extension_value.insert("ModuleType".to_string(), Value::String(module_type.clone()));
484 }
485
486 extension_value.insert("IsBuiltin".to_string(), Value::Bool(extension_dto.IsBuiltin));
487 extension_value.insert("IsUnderDevelopment".to_string(), Value::Bool(extension_dto.IsUnderDevelopment));
488 extension_value.insert("ExtensionLocation".to_string(), extension_dto.ExtensionLocation.clone());
489
490 if let Some(activation_events) = &extension_dto.ActivationEvents {
491 let events:Vec<Value> = activation_events.iter().map(|e| Value::String(e.clone())).collect();
492 extension_value.insert("ActivationEvents".to_string(), Value::Array(events));
493 }
494
495 if let Some(contributes) = &extension_dto.Contributes {
496 extension_value.insert("Contributes".to_string(), contributes.clone());
497 }
498
499 Ok(Some(Value::Object(extension_value)))
500 } else {
501 Ok(None)
502 }
503 }
504}
505
506impl_provider!(CommandExecutor);
511impl_provider!(ConfigurationProvider);
512impl_provider!(ConfigurationInspector);
513
514impl_provider!(CustomEditorProvider);
516impl_provider!(DebugService);
517
518impl_provider!(DocumentProvider);
520impl_provider!(DiagnosticManager);
521
522impl_provider!(FileSystemReader);
524impl_provider!(FileSystemWriter);
525
526impl_provider!(IPCProvider);
528impl_provider!(KeybindingProvider);
529
530impl_provider!(LanguageFeatureProviderRegistry);
532impl_provider!(OutputChannelManager);
533
534impl_provider!(SecretProvider);
536impl_provider!(SourceControlManagementProvider);
537
538impl_provider!(StatusBarProvider);
540impl_provider!(StorageProvider);
541
542impl_provider!(SynchronizationProvider);
544impl_provider!(TerminalProvider);
545
546impl_provider!(TestController);
548impl_provider!(TreeViewProvider);
549
550impl_provider!(UserInterfaceProvider);
552impl_provider!(WebviewProvider);
553
554impl_provider!(WorkspaceProvider);
556impl_provider!(WorkspaceEditApplier);
557
558impl_provider!(ExtensionManagementService);
560impl_provider!(SearchProvider);