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