From 125ff9d114479ccb5c84023780eba10cb62dad2b Mon Sep 17 00:00:00 2001 From: IanShaw027 <131567472+IanShaw027@users.noreply.github.com> Date: Sat, 7 Mar 2026 11:16:50 +0800 Subject: [PATCH] fix: seed enterprise creator skills in background --- .../desktop/src-tauri/src/workspace/files.rs | 61 +++++++++++++++++-- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/packages/desktop/src-tauri/src/workspace/files.rs b/packages/desktop/src-tauri/src/workspace/files.rs index cf2ad5ac6..304b9572f 100644 --- a/packages/desktop/src-tauri/src/workspace/files.rs +++ b/packages/desktop/src-tauri/src/workspace/files.rs @@ -2,6 +2,8 @@ use std::collections::HashSet; use std::fs; use std::io::{Cursor, Read}; use std::path::{Path, PathBuf}; +use std::sync::{LazyLock, Mutex}; +use std::time::Duration; use zip::ZipArchive; @@ -179,9 +181,56 @@ Incremental adoption loop const ENTERPRISE_ARCHIVE_URL: &str = "https://github.com/different-ai/openwork-enterprise/archive/refs/heads/main.zip"; const ENTERPRISE_SEED_MARKER: &str = ".openwork-enterprise-creators"; +static ENTERPRISE_SEED_IN_FLIGHT: LazyLock>> = + LazyLock::new(|| Mutex::new(HashSet::new())); + +fn enterprise_seed_marker_path(root: &Path) -> PathBuf { + root.join(".opencode").join(ENTERPRISE_SEED_MARKER) +} + +fn spawn_enterprise_creator_skills_seed(root: PathBuf, skill_root: PathBuf) { + let marker_path = enterprise_seed_marker_path(&root); + if marker_path.exists() { + return; + } + + let key = root.to_string_lossy().to_string(); + { + let mut in_flight = ENTERPRISE_SEED_IN_FLIGHT + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()); + if !in_flight.insert(key.clone()) { + return; + } + } + + std::thread::spawn(move || { + println!( + "[workspace] Seeding creator skills in background for {}", + root.display() + ); + + let result = seed_enterprise_creator_skills(&root, &skill_root); + match result { + Ok(()) => println!( + "[workspace] Finished seeding creator skills for {}", + root.display() + ), + Err(err) => println!( + "[workspace] Failed to seed creator skills in background for {}: {err}", + root.display() + ), + } + + let mut in_flight = ENTERPRISE_SEED_IN_FLIGHT + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()); + in_flight.remove(&key); + }); +} fn seed_enterprise_creator_skills(root: &PathBuf, skill_root: &PathBuf) -> Result<(), String> { - let marker_path = root.join(".opencode").join(ENTERPRISE_SEED_MARKER); + let marker_path = enterprise_seed_marker_path(root); if marker_path.exists() { return Ok(()); } @@ -196,7 +245,11 @@ fn seed_enterprise_creator_skills(root: &PathBuf, skill_root: &PathBuf) -> Resul } } - let agent = ureq::AgentBuilder::new().redirects(5).build(); + let agent = ureq::AgentBuilder::new() + .redirects(5) + .timeout_connect(Duration::from_secs(5)) + .timeout_read(Duration::from_secs(20)) + .build(); let response = agent .get(ENTERPRISE_ARCHIVE_URL) .call() @@ -352,9 +405,7 @@ pub fn ensure_workspace_files(workspace_path: &str, preset: &str) -> Result<(), seed_workspace_guide(&skill_root)?; if preset == "starter" { seed_get_started_skill(&skill_root)?; - if let Err(err) = seed_enterprise_creator_skills(&root, &skill_root) { - println!("[workspace] Failed to seed creator skills: {err}"); - } + spawn_enterprise_creator_skills_seed(root.clone(), skill_root.clone()); } let agents_dir = root.join(".opencode").join("agents");