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