Mountain/ProcessManagement/
InitializationData.rs1use std::{collections::HashMap, env, fs, path::PathBuf, sync::Arc};
136
137use CommonLibrary::{
138 Environment::Requires::Requires,
139 Error::CommonError::CommonError,
140 ExtensionManagement::ExtensionManagementService::ExtensionManagementService,
141 Workspace::WorkspaceProvider::WorkspaceProvider,
142};
143use log::info;
144use serde_json::{Value, json};
145use tauri::{AppHandle, Manager, Wry};
146use uuid::Uuid;
147
148use crate::{ApplicationState::ApplicationState, Environment::MountainEnvironment::MountainEnvironment};
149
150fn get_or_generate_machine_id(app_data_dir:&PathBuf) -> String {
161 let machine_id_path = app_data_dir.join("machine-id.txt");
162
163 if let Ok(content) = fs::read_to_string(&machine_id_path) {
165 let trimmed = content.trim();
166 if !trimmed.is_empty() {
167 log::info!("[InitializationData] Loaded existing machine ID from disk");
168 return trimmed.to_string();
169 }
170 }
171
172 let new_machine_id = Uuid::new_v4().to_string();
174
175 if let Some(parent) = machine_id_path.parent() {
177 if let Err(e) = fs::create_dir_all(parent) {
178 log::warn!("[InitializationData] Failed to create machine ID directory: {}", e);
179 }
180 }
181
182 if let Err(e) = fs::write(&machine_id_path, &new_machine_id) {
184 log::warn!("[InitializationData] Failed to persist machine ID to disk: {}", e);
185 } else {
186 log::info!("[InitializationData] Generated and persisted new machine ID");
187 }
188
189 new_machine_id
190}
191
192pub async fn ConstructSandboxConfiguration(
194 ApplicationHandle:&AppHandle<Wry>,
195
196 ApplicationState:&Arc<ApplicationState>,
197) -> Result<Value, CommonError> {
198 info!("[InitializationData] Constructing ISandboxConfiguration for Sky.");
199
200 let PathResolver = ApplicationHandle.path();
201
202 let AppRootUri = PathResolver.resource_dir().map_err(|Error| {
203 CommonError::ConfigurationLoad {
204 Description:format!("Failed to resolve resource directory (app root): {}", Error),
205 }
206 })?;
207
208 let AppDataDir = PathResolver.app_data_dir().map_err(|Error| {
209 CommonError::ConfigurationLoad { Description:format!("Failed to resolve app data directory: {}", Error) }
210 })?;
211
212 let HomeDir = PathResolver.home_dir().map_err(|Error| {
213 CommonError::ConfigurationLoad { Description:format!("Failed to resolve home directory: {}", Error) }
214 })?;
215
216 let TmpDir = env::temp_dir();
217
218 let BackupPath = AppDataDir.join("Backups").join(ApplicationState.GetWorkspaceIdentifier()?);
219
220 let Platform = match env::consts::OS {
221 "windows" => "win32",
222
223 "macos" => "darwin",
224
225 "linux" => "linux",
226
227 _ => "unknown",
228 };
229
230 let Arch = match env::consts::ARCH {
231 "x86_64" => "x64",
232
233 "aarch64" => "arm64",
234
235 "x86" => "ia32",
236
237 _ => "unknown",
238 };
239
240 let Versions = json!({
241 "mountain": ApplicationHandle.package_info().version.to_string(),
242
243 "electron": "0.0.0-tauri",
245
246 "chrome": "120.0.0.0",
248
249 "node": "18.18.2"
251 });
252
253 let machine_id = get_or_generate_machine_id(&AppDataDir);
255
256 Ok(json!({
257 "windowId": ApplicationHandle.get_webview_window("main").unwrap().label(),
258
259 "machineId": machine_id,
264
265 "sessionId": Uuid::new_v4().to_string(),
266
267 "logLevel": log::max_level() as i32,
268
269 "userEnv": env::vars().collect::<HashMap<_,_>>(),
270
271 "appRoot": url::Url::from_directory_path(AppRootUri).unwrap().to_string(),
272
273 "appName": ApplicationHandle.package_info().name.clone(),
274
275 "appUriScheme": "mountain",
276
277 "appLanguage": "en",
278
279 "appHost": "desktop",
280
281 "platform": Platform,
282
283 "arch": Arch,
284
285 "versions": Versions,
286
287 "execPath": env::current_exe().unwrap_or_default().to_string_lossy(),
288
289 "homeDir": url::Url::from_directory_path(HomeDir).unwrap().to_string(),
290
291 "tmpDir": url::Url::from_directory_path(TmpDir).unwrap().to_string(),
292
293 "userDataDir": url::Url::from_directory_path(AppDataDir).unwrap().to_string(),
294
295 "backupPath": url::Url::from_directory_path(BackupPath).unwrap().to_string(),
296
297 "nls": { "messages": {}, "language": "en", "availableLanguages": { "en": "English" } },
298
299 "productConfiguration": {
300
301 "nameShort": "Mountain",
302
303 "nameLong": "Mountain Editor",
304
305 "applicationName": "mountain",
306
307 "embedderIdentifier": "mountain-desktop"
308 },
309
310 "resourcesPath": PathResolver.resource_dir().unwrap_or_default().to_string_lossy(),
311
312 "VSCODE_CWD": env::current_dir().unwrap_or_default().to_string_lossy(),
313 }))
314}
315
316pub async fn ConstructExtensionHostInitializationData(Environment:&MountainEnvironment) -> Result<Value, CommonError> {
318 info!("[InitializationData] Constructing IExtensionHostInitData for Cocoon.");
319
320 let ApplicationState = &Environment.ApplicationState;
321
322 let ApplicationHandle = &Environment.ApplicationHandle;
323
324 let ExtensionManagementProvider:Arc<dyn ExtensionManagementService> = Environment.Require();
325
326 let ExtensionsDTO = ExtensionManagementProvider.GetExtensions().await?;
327
328 let WorkspaceProvider:Arc<dyn WorkspaceProvider> = Environment.Require();
329
330 let WorkspaceName = WorkspaceProvider
331 .GetWorkspaceName()
332 .await?
333 .unwrap_or_else(|| "Mountain Workspace".to_string());
334
335 let WorkspaceFoldersGuard = ApplicationState.Workspace.WorkspaceFolders.lock().unwrap();
336
337 let WorkspaceDTO = if WorkspaceFoldersGuard.is_empty() {
338 Value::Null
339 } else {
340 json!({
341
342 "id": ApplicationState.GetWorkspaceIdentifier()?,
343
344 "name": WorkspaceName,
345
346 "configuration": ApplicationState.Workspace.WorkspaceConfigurationPath.lock().unwrap().as_ref().map(|p| p.to_string_lossy()),
347
348 "isUntitled": ApplicationState.Workspace.WorkspaceConfigurationPath.lock().unwrap().is_none(),
349
350 "transient": false
351 })
352 };
353
354 let PathResolver = ApplicationHandle.path();
355
356 let AppRoot = PathResolver
357 .resource_dir()
358 .map_err(|Error| CommonError::ConfigurationLoad { Description:Error.to_string() })?;
359
360 let AppData = PathResolver
361 .app_data_dir()
362 .map_err(|Error| CommonError::ConfigurationLoad { Description:Error.to_string() })?;
363
364 let LogsLocation = PathResolver
365 .app_log_dir()
366 .map_err(|Error| CommonError::ConfigurationLoad { Description:Error.to_string() })?;
367
368 let GlobalStorage = AppData.join("User/globalStorage");
369
370 let WorkspaceStorage = AppData.join("User/workspaceStorage");
371
372 Ok(json!({
373
374 "commit": "dev-commit-hash",
375
376 "version": ApplicationHandle.package_info().version.to_string(),
377
378 "quality": "development",
379
380 "parentPid": std::process::id(),
381
382 "environment": {
383
384 "isExtensionDevelopmentDebug": false,
385
386 "appName": "Mountain",
387
388 "appHost": "desktop",
389
390 "appUriScheme": "mountain",
391
392 "appLanguage": "en",
393
394 "isExtensionTelemetryLoggingOnly": true,
395
396 "appRoot": url::Url::from_directory_path(AppRoot.clone()).unwrap(),
397
398 "globalStorageHome": url::Url::from_directory_path(GlobalStorage).unwrap(),
399
400 "workspaceStorageHome": url::Url::from_directory_path(WorkspaceStorage).unwrap(),
401
402 "extensionDevelopmentLocationURI": [],
403
404 "extensionTestsLocationURI": Value::Null,
405
406 "extensionLogLevel": [["info", "Default"]],
407
408 },
409
410 "workspace": WorkspaceDTO,
411
412 "remote": {
413
414 "isRemote": false,
415
416 "authority": Value::Null,
417
418 "connectionData": Value::Null,
419
420 },
421
422 "consoleForward": { "includeStack": true, "logNative": true },
423
424 "logLevel": log::max_level() as i32,
425
426 "logsLocation": url::Url::from_directory_path(LogsLocation).unwrap(),
427
428 "telemetryInfo": {
429
430 "sessionId": Uuid::new_v4().to_string(),
431
432 "machineId": get_or_generate_machine_id(&AppData),
433
434 "firstSessionDate": "2024-01-01T00:00:00.000Z",
435
436 "msftInternal": false
437 },
438
439 "extensions": ExtensionsDTO,
440
441 "autoStart": true,
442
443 "uiKind": 1,
445 }))
446}