From 49cbbbebaf0cd9cbdb0072bd077e0575c18efa14 Mon Sep 17 00:00:00 2001
From: Mega Mind <146339422+M3gA-Mind@users.noreply.github.com>
Date: Fri, 10 Apr 2026 20:16:08 +0530
Subject: [PATCH] Fix/skill start issue (#493)
* chore: update .gitignore and bump openhuman version to 0.52.2
- Added `overlay/src-tauri/target/` to .gitignore to prevent tracking of build artifacts.
- Updated the openhuman package version from 0.52.0 to 0.52.2 in Cargo.lock files for both the main and app/src-tauri directories.
- Enhanced entitlements for macOS Hardened Runtime to allow outbound HTTPS calls and server connections.
- Refactored registry operations to use rustls explicitly, improving network reliability on macOS.
* refactor(logging): improve debug message formatting in fetch_url_bytes function
- Updated the logging statement in the fetch_url_bytes function to enhance readability by formatting the debug message across multiple lines. This change improves clarity in log outputs, making it easier to track the number of bytes fetched from URLs.
---
.gitignore | 1 +
app/src-tauri/Cargo.lock | 2 +-
app/src-tauri/entitlements.sidecar.plist | 10 +++++
src/openhuman/skills/registry_ops.rs | 52 +++++++++++++++++++++---
4 files changed, 58 insertions(+), 7 deletions(-)
diff --git a/.gitignore b/.gitignore
index e60004bbc..4c4e2e7d0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,3 +59,4 @@ src-tauri/target/
workflow
.fastembed_cache
+overlay/src-tauri/target/
\ No newline at end of file
diff --git a/app/src-tauri/Cargo.lock b/app/src-tauri/Cargo.lock
index dcd33fa37..dd882444c 100644
--- a/app/src-tauri/Cargo.lock
+++ b/app/src-tauri/Cargo.lock
@@ -4,7 +4,7 @@ version = 4
[[package]]
name = "OpenHuman"
-version = "0.52.0"
+version = "0.52.2"
dependencies = [
"env_logger",
"log",
diff --git a/app/src-tauri/entitlements.sidecar.plist b/app/src-tauri/entitlements.sidecar.plist
index 46f675661..92a9edf6d 100644
--- a/app/src-tauri/entitlements.sidecar.plist
+++ b/app/src-tauri/entitlements.sidecar.plist
@@ -8,5 +8,15 @@
com.apple.security.cs.disable-library-validation
+
+ com.apple.security.network.client
+
+
+ com.apple.security.network.server
+
diff --git a/src/openhuman/skills/registry_ops.rs b/src/openhuman/skills/registry_ops.rs
index 599abf270..a426d6661 100644
--- a/src/openhuman/skills/registry_ops.rs
+++ b/src/openhuman/skills/registry_ops.rs
@@ -61,8 +61,11 @@ pub async fn registry_fetch(
log::info!("[registry] fetching registry from {url}");
+ // Use rustls explicitly so we never fall back to native-tls (which can hang
+ // on macOS under the Hardened Runtime when the system keychain is restricted).
let client = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(30))
+ .use_rustls_tls()
.build()
.map_err(|e| format!("failed to create HTTP client: {e}"))?;
@@ -150,8 +153,13 @@ async fn fetch_url_bytes(url: &str) -> Result, String> {
return read_local_file(url);
}
+ log::debug!("[registry] fetch_url_bytes: connecting to {url}");
+
+ // Use rustls explicitly so we never fall back to native-tls (which can hang
+ // on macOS under the Hardened Runtime when the system keychain is restricted).
let client = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(30))
+ .use_rustls_tls()
.build()
.map_err(|e| format!("failed to create HTTP client: {e}"))?;
@@ -159,16 +167,26 @@ async fn fetch_url_bytes(url: &str) -> Result, String> {
.get(url)
.send()
.await
- .map_err(|e| format!("failed to fetch {url}: {e}"))?;
+ .map_err(|e| format!("[registry] network error fetching {url}: {e}"))?;
if !resp.status().is_success() {
- return Err(format!("fetch {url} failed with status {}", resp.status()));
+ return Err(format!(
+ "[registry] fetch {url} returned HTTP {}",
+ resp.status()
+ ));
}
- resp.bytes()
+ let bytes = resp
+ .bytes()
.await
.map(|b| b.to_vec())
- .map_err(|e| format!("failed to read response from {url}: {e}"))
+ .map_err(|e| format!("[registry] failed to read response body from {url}: {e}"))?;
+
+ log::debug!(
+ "[registry] fetch_url_bytes: {} bytes from {url}",
+ bytes.len()
+ );
+ Ok(bytes)
}
/// Install a skill from the registry or local directory.
@@ -177,6 +195,11 @@ async fn fetch_url_bytes(url: &str) -> Result, String> {
/// directory (e.g. `$SKILLS_LOCAL_DIR//`) instead of downloading.
/// This also works when registry entry URLs are local file paths.
pub async fn skill_install(workspace_dir: &Path, skill_id: &str) -> Result<(), String> {
+ log::info!(
+ "[registry] skills_install: starting — skill_id={skill_id} workspace={}",
+ workspace_dir.display()
+ );
+
// --- Fast path: SKILLS_LOCAL_DIR copies directly from local dev directory ---
// This allows developers to work on skills locally and see changes reflected instantly
// in the app without having to publish to a registry.
@@ -199,7 +222,9 @@ pub async fn skill_install(workspace_dir: &Path, skill_id: &str) -> Result<(), S
}
// --- Standard path: fetch from registry (remote or local URLs) ---
+ log::debug!("[registry] skills_install: fetching registry for '{skill_id}'");
let registry = registry_fetch(workspace_dir, false).await?;
+ log::debug!("[registry] skills_install: registry fetched, looking up '{skill_id}'");
let entry = registry
.skills
@@ -210,22 +235,37 @@ pub async fn skill_install(workspace_dir: &Path, skill_id: &str) -> Result<(), S
.ok_or_else(|| format!("skill '{skill_id}' not found in registry"))?
.clone();
+ log::debug!(
+ "[registry] skills_install: found entry '{skill_id}' v{} manifest={} bundle={}",
+ entry.version,
+ entry.manifest_url,
+ entry.download_url
+ );
+
let skill_dir = workspace_dir.join("skills").join(skill_id);
std::fs::create_dir_all(&skill_dir).map_err(|e| format!("failed to create skill dir: {e}"))?;
// Fetch manifest (local or remote)
log::info!(
- "[registry] fetching manifest for '{skill_id}' from {}",
+ "[registry] skills_install: fetching manifest for '{skill_id}' from {}",
entry.manifest_url
);
let manifest_bytes = fetch_url_bytes(&entry.manifest_url).await?;
+ log::debug!(
+ "[registry] skills_install: manifest fetched ({} bytes)",
+ manifest_bytes.len()
+ );
// Fetch JS bundle (local or remote)
log::info!(
- "[registry] fetching JS bundle for '{skill_id}' from {}",
+ "[registry] skills_install: fetching JS bundle for '{skill_id}' from {}",
entry.download_url
);
let js_bytes = fetch_url_bytes(&entry.download_url).await?;
+ log::debug!(
+ "[registry] skills_install: JS bundle fetched ({} bytes)",
+ js_bytes.len()
+ );
// Verify checksum if present to ensure integrity of the downloaded bundle
if let Some(expected) = &entry.checksum_sha256 {