diff --git a/apps/cli/src/domains/library/args.rs b/apps/cli/src/domains/library/args.rs index 781fcebb4..33ae219ff 100644 --- a/apps/cli/src/domains/library/args.rs +++ b/apps/cli/src/domains/library/args.rs @@ -106,10 +106,14 @@ pub struct SetupArgs { #[arg(long)] pub remote_library: Option, - /// Sync action: register-only (others coming in Phase 3) + /// Sync action: register-only, create-shared #[arg(long, default_value = "register-only")] pub action: String, + /// Library name for create-shared action + #[arg(long)] + pub name: Option, + /// DEPRICATED: Leader device: "local" or "remote" #[arg(long, default_value = "local")] pub leader: String, @@ -145,8 +149,18 @@ impl SetupArgs { // Parse action let action = match self.action.as_str() { "register-only" => LibrarySyncAction::RegisterOnly, + "create-shared" => { + let name = self + .name + .clone() + .ok_or_else(|| anyhow::anyhow!("--name is required for create-shared action"))?; + LibrarySyncAction::CreateShared { + leader_device_id, + name, + } + } _ => anyhow::bail!( - "Invalid action '{}'. Currently supported: register-only", + "Invalid action '{}'. Supported: register-only, create-shared", self.action ), }; diff --git a/core/src/library/manager.rs b/core/src/library/manager.rs index 56e78c77d..338121b0f 100644 --- a/core/src/library/manager.rs +++ b/core/src/library/manager.rs @@ -716,7 +716,7 @@ impl LibraryManager { id: sea_orm::ActiveValue::NotSet, uuid: Set(device.id), name: Set(device.name.clone()), - slug: Set(crate::domain::device::Device::generate_slug(&device.name)), + slug: Set(device.slug.clone()), os: Set(device.os.to_string()), os_version: Set(None), hardware_model: Set(device.hardware_model), diff --git a/core/src/ops/network/sync_setup/action.rs b/core/src/ops/network/sync_setup/action.rs index 0fdb3f75d..2b2b048d3 100644 --- a/core/src/ops/network/sync_setup/action.rs +++ b/core/src/ops/network/sync_setup/action.rs @@ -6,6 +6,7 @@ use std::sync::Arc; use tracing::{info, warn}; use uuid::Uuid; +#[derive(Clone)] pub struct LibrarySyncSetupAction { input: LibrarySyncSetupInput, } @@ -87,10 +88,8 @@ impl CoreAction for LibrarySyncSetupAction { leader_device_id, name, } => { - // Future implementation - Err(ActionError::Internal( - "CreateShared not yet implemented - requires sync system".to_string(), - )) + self.execute_create_shared(context.clone(), &local_library, name.clone()) + .await } } } @@ -277,6 +276,84 @@ impl LibrarySyncSetupAction { message: "Devices successfully registered for library access".to_string(), }) } + + /// Execute CreateShared action - create shared library on both devices + async fn execute_create_shared( + &self, + context: Arc, + local_library: &Arc, + _name: String, + ) -> Result { + info!( + "Creating shared library: local_library={}, remote_device={}", + self.input.local_library_id, self.input.remote_device_id + ); + + let library_id = local_library.id(); + let library_name = local_library.name().await; + let config = local_library.config().await; + + // Get networking + let networking = context + .get_networking() + .await + .ok_or_else(|| ActionError::Internal("Networking not available".to_string()))?; + + // Send CreateSharedLibraryRequest to remote device + use crate::service::network::protocol::library_messages::LibraryMessage; + + let request = LibraryMessage::CreateSharedLibraryRequest { + request_id: Uuid::new_v4(), + library_id, + library_name: library_name.clone(), + description: config.description.clone(), + }; + + info!( + "Sending CreateSharedLibraryRequest to remote device: library={}, name={}", + library_id, library_name + ); + + let response = networking + .send_library_request(self.input.remote_device_id, request) + .await + .map_err(|e| { + ActionError::Internal(format!("Failed to send create library request: {}", e)) + })?; + + // Check response + match response { + LibraryMessage::CreateSharedLibraryResponse { + request_id: _, + success: true, + message, + } => { + info!( + "Remote device successfully created shared library: {}", + message.unwrap_or_else(|| "No message".to_string()) + ); + + // Update remote_library_id to point to the newly created library + // (same UUID as local library since we shared it) + let mut modified_self = self.clone(); + modified_self.input.remote_library_id = Some(library_id); + + // Now register both devices in the library + modified_self.execute_register_only(context, local_library).await + } + LibraryMessage::CreateSharedLibraryResponse { + request_id: _, + success: false, + message, + } => Err(ActionError::Internal(format!( + "Remote device failed to create library: {}", + message.unwrap_or_else(|| "Unknown error".to_string()) + ))), + _ => Err(ActionError::Internal( + "Unexpected response from remote device".to_string(), + )), + } + } } crate::register_core_action!(LibrarySyncSetupAction, "network.sync_setup");