codex-mobile-bridge 0.3.2

Remote bridge and service manager for codex-mobile.
Documentation
use super::*;

impl BridgeManagementRunner {
    pub(super) fn run_install_like(&mut self, operation: &str) -> Result<()> {
        let snapshot = self.snapshot_now();
        let release = snapshot
            .as_ref()
            .and_then(|value| value.available_release.clone())
            .or_else(|| self.resolve_latest_release().ok())
            .context("当前无法解析可安装的最新 bridge release")?;
        self.task.target_version = Some(release.version.clone());
        let current_version = snapshot
            .as_ref()
            .and_then(|value| value.install_record.as_ref())
            .and_then(|record| record.current_version.clone());
        self.task.current_version = current_version.clone();
        self.update_task(
            BridgeManagementStatus::Running,
            BridgeManagementPhase::ResolveTarget,
            format!("已解析目标版本 {}", release.version),
            Some(format!(
                "当前版本={},目标来源={}/{}",
                current_version.unwrap_or_else(|| "-".to_string()),
                release.registry,
                release.crate_name,
            )),
            None,
            true,
        )?;

        if snapshot.as_ref().is_some_and(|value| {
            value
                .install_record
                .as_ref()
                .and_then(|record| record.current_version.as_deref())
                == Some(release.version.as_str())
                && !value.needs_repair
        }) {
            self.update_task(
                BridgeManagementStatus::Running,
                BridgeManagementPhase::VerifyHealth,
                format!("bridge 已是目标版本 {}", release.version),
                Some("无需重复安装,改为直接校验本地健康状态".to_string()),
                None,
                false,
            )?;
            let health = wait_for_expected_health(
                &self.paths,
                Some(release.version.as_str()),
                Some(BRIDGE_PROTOCOL_VERSION),
            )?;
            self.complete_success(
                format!("远端 bridge {}完成", operation),
                Some(success_detail(&health)),
            )
        } else {
            self.update_task(
                BridgeManagementStatus::Running,
                BridgeManagementPhase::InstallRelease,
                format!("正在安装 bridge {}", release.version),
                Some("通过 cargo install 拉取最新 release".to_string()),
                None,
                false,
            )?;
            let release_root = release::install_release(
                &self.paths,
                &release.version,
                DEFAULT_MANAGEMENT_CARGO_BINARY,
                DEFAULT_MANAGEMENT_REGISTRY,
            )?;
            let metadata = release::load_release_metadata(&release_root)?;
            self.task.target_version = Some(metadata.version.clone());
            self.update_task(
                BridgeManagementStatus::Running,
                BridgeManagementPhase::ActivateRelease,
                format!("正在切换到 bridge {}", metadata.version),
                Some(format!("releaseRoot={}", metadata.release_root)),
                None,
                false,
            )?;
            let existing_record = environment::read_install_record(&self.paths)?;
            let existing_env = environment::read_env_file(&self.paths)?;
            let env_values = environment::merge_env_values(
                &self.paths,
                &existing_env,
                &EnvOverrides::default(),
            )?;
            release::activate_release(
                &self.paths,
                &metadata,
                &env_values,
                existing_record.as_ref(),
                operation,
            )?;
            self.update_task(
                BridgeManagementStatus::Running,
                BridgeManagementPhase::RestartService,
                format!("bridge {} 已切换,等待服务接管", metadata.version),
                Some(SERVICE_NAME.to_string()),
                None,
                true,
            )?;
            self.update_task(
                BridgeManagementStatus::Running,
                BridgeManagementPhase::VerifyHealth,
                format!("正在校验 bridge {}", metadata.version),
                Some("等待 /health 返回新的版本与协议".to_string()),
                None,
                false,
            )?;
            let health = wait_for_expected_health(
                &self.paths,
                Some(metadata.version.as_str()),
                Some(metadata.protocol_version as i32),
            )?;
            self.complete_success(
                format!("远端 bridge {}完成", operation),
                Some(success_detail(&health)),
            )
        }
    }

    pub(super) fn run_repair(&mut self) -> Result<()> {
        let snapshot = self.snapshot_now();
        let current_version = snapshot
            .as_ref()
            .and_then(|value| value.install_record.as_ref())
            .and_then(|record| record.current_version.clone());
        self.task.current_version = current_version.clone();
        self.update_task(
            BridgeManagementStatus::Running,
            BridgeManagementPhase::ResolveTarget,
            "正在解析需要修复的 release".to_string(),
            Some(format!(
                "当前版本={}",
                current_version.unwrap_or_else(|| "-".to_string())
            )),
            None,
            true,
        )?;
        self.update_task(
            BridgeManagementStatus::Running,
            BridgeManagementPhase::InstallRelease,
            "正在准备修复所需 release".to_string(),
            Some("如 current release 缺失,将自动重新安装记录中的版本".to_string()),
            None,
            false,
        )?;
        let existing_record = environment::read_install_record(&self.paths)?;
        let args = RepairArgs {
            env: EnvOverrides::default(),
            cargo_binary: DEFAULT_MANAGEMENT_CARGO_BINARY.to_string(),
            registry: DEFAULT_MANAGEMENT_REGISTRY.to_string(),
        };
        let metadata =
            commands::resolve_repair_metadata(&self.paths, existing_record.as_ref(), &args)?;
        self.task.target_version = Some(metadata.version.clone());
        self.update_task(
            BridgeManagementStatus::Running,
            BridgeManagementPhase::ActivateRelease,
            format!("正在修复 bridge {}", metadata.version),
            Some(format!("releaseRoot={}", metadata.release_root)),
            None,
            false,
        )?;
        let existing_env = environment::read_env_file(&self.paths)?;
        let env_values =
            environment::merge_env_values(&self.paths, &existing_env, &EnvOverrides::default())?;
        release::activate_release(
            &self.paths,
            &metadata,
            &env_values,
            existing_record.as_ref(),
            "repair",
        )?;
        self.update_task(
            BridgeManagementStatus::Running,
            BridgeManagementPhase::RestartService,
            format!("bridge {} 修复完成,等待服务接管", metadata.version),
            Some(SERVICE_NAME.to_string()),
            None,
            true,
        )?;
        self.update_task(
            BridgeManagementStatus::Running,
            BridgeManagementPhase::VerifyHealth,
            format!("正在校验 bridge {}", metadata.version),
            Some("等待 /health 返回修复后的状态".to_string()),
            None,
            false,
        )?;
        let health = wait_for_expected_health(
            &self.paths,
            Some(metadata.version.as_str()),
            Some(metadata.protocol_version as i32),
        )?;
        self.complete_success(
            "远端 bridge 修复完成".to_string(),
            Some(success_detail(&health)),
        )
    }

    pub(super) fn run_rollback(&mut self) -> Result<()> {
        let existing_record = environment::read_install_record(&self.paths)?
            .context("缺少 install record,无法执行回滚")?;
        let previous_version = existing_record
            .previous_version
            .as_deref()
            .filter(|value| !value.trim().is_empty())
            .context("当前没有可回滚的上一版")?
            .to_string();
        self.task.current_version = existing_record.current_version.clone();
        self.task.target_version = Some(previous_version.clone());
        self.update_task(
            BridgeManagementStatus::Running,
            BridgeManagementPhase::ResolveTarget,
            format!("已解析回滚目标 {}", previous_version),
            Some(format!(
                "当前版本={}",
                existing_record
                    .current_version
                    .clone()
                    .unwrap_or_else(|| "-".to_string())
            )),
            None,
            true,
        )?;
        self.update_task(
            BridgeManagementStatus::Running,
            BridgeManagementPhase::InstallRelease,
            format!("正在准备回滚版本 {}", previous_version),
            Some("如本地旧 release 缺失,将自动重新安装上一版".to_string()),
            None,
            false,
        )?;
        let target_release_root = existing_record
            .previous_release_path
            .as_deref()
            .map(PathBuf::from)
            .filter(|path| environment::release_binary_path(path).is_some())
            .unwrap_or_else(|| self.paths.release_root_for_version(&previous_version));
        let target_release_root =
            if environment::release_binary_path(&target_release_root).is_some() {
                target_release_root
            } else {
                release::install_release(
                    &self.paths,
                    &previous_version,
                    DEFAULT_MANAGEMENT_CARGO_BINARY,
                    DEFAULT_MANAGEMENT_REGISTRY,
                )?
            };
        let metadata =
            release::release_metadata_from_previous_record(&existing_record, &target_release_root)
                .unwrap_or(release::load_release_metadata(&target_release_root)?);
        self.update_task(
            BridgeManagementStatus::Running,
            BridgeManagementPhase::ActivateRelease,
            format!("正在回滚到 bridge {}", metadata.version),
            Some(format!("releaseRoot={}", metadata.release_root)),
            None,
            false,
        )?;
        let existing_env = environment::read_env_file(&self.paths)?;
        let env_values =
            environment::merge_env_values(&self.paths, &existing_env, &EnvOverrides::default())?;
        release::rollback_release(&self.paths, &metadata, &env_values, &existing_record)?;
        self.update_task(
            BridgeManagementStatus::Running,
            BridgeManagementPhase::RestartService,
            format!("bridge 已回滚到 {},等待服务接管", metadata.version),
            Some(SERVICE_NAME.to_string()),
            None,
            true,
        )?;
        self.update_task(
            BridgeManagementStatus::Running,
            BridgeManagementPhase::VerifyHealth,
            format!("正在校验 bridge {}", metadata.version),
            Some("等待 /health 返回回滚后的状态".to_string()),
            None,
            false,
        )?;
        let health = wait_for_expected_health(
            &self.paths,
            Some(metadata.version.as_str()),
            Some(metadata.protocol_version as i32),
        )?;
        self.complete_success(
            "远端 bridge 回滚完成".to_string(),
            Some(success_detail(&health)),
        )
    }

    fn resolve_latest_release(&self) -> Result<ManagedBridgeReleaseDescriptor> {
        let version = release::resolve_latest_registry_version(
            &self.paths,
            DEFAULT_MANAGEMENT_CARGO_BINARY,
            DEFAULT_MANAGEMENT_REGISTRY,
        )?;
        Ok(ManagedBridgeReleaseDescriptor {
            crate_name: CRATE_NAME.to_string(),
            version,
            registry: DEFAULT_MANAGEMENT_REGISTRY.to_string(),
        })
    }
}