From 52e697895836685fc55d0bb6bce7cd9a9cc9fefb Mon Sep 17 00:00:00 2001 From: lin Date: Wed, 21 Jan 2026 20:12:09 +0800 Subject: [PATCH 1/4] use opencode path in development, ensure opencode sidecar in release --- packages/desktop/package.json | 2 +- packages/desktop/scripts/prepare-release.mjs | 42 ++++++++++++++++++++ packages/desktop/scripts/restore-config.mjs | 21 ++++++++++ packages/desktop/src-tauri/build.rs | 20 ++++++++-- packages/desktop/src-tauri/tauri.conf.json | 3 -- packages/desktop/src/app/app.tsx | 3 +- 6 files changed, 82 insertions(+), 9 deletions(-) create mode 100755 packages/desktop/scripts/prepare-release.mjs create mode 100755 packages/desktop/scripts/restore-config.mjs diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 4dbbd37b..f5d35a28 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "dev": "tauri dev", - "build": "tauri build", + "build": "node scripts/prepare-release.mjs && tauri build && node scripts/restore-config.mjs", "dev:web": "vite", "build:web": "vite build", "preview": "vite preview", diff --git a/packages/desktop/scripts/prepare-release.mjs b/packages/desktop/scripts/prepare-release.mjs new file mode 100755 index 00000000..042341e1 --- /dev/null +++ b/packages/desktop/scripts/prepare-release.mjs @@ -0,0 +1,42 @@ +#!/usr/bin/env node + +import fs from 'fs'; +import path from 'path'; +import { execSync } from 'child_process'; + +const CONFIG_PATH = 'src-tauri/tauri.conf.json'; +const BACKUP_PATH = 'src-tauri/tauri.conf.json.backup'; + +function addExternalBin(config) { + if (config.bundle?.externalBin?.includes('sidecars/opencode')) { + return config; // Already has externalBin + } + + return { + ...config, + bundle: { + ...config.bundle, + externalBin: ['sidecars/opencode'] + } + }; +} + +function main() { + console.log('🔧 Preparing release build with sidecar...'); + + // Read current config + const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8')); + + // Backup original config + fs.writeFileSync(BACKUP_PATH, JSON.stringify(config, null, 2)); + console.log('✅ Backed up tauri.conf.json'); + + // Add externalBin + const releaseConfig = addExternalBin(config); + fs.writeFileSync(CONFIG_PATH, JSON.stringify(releaseConfig, null, 2)); + console.log('✅ Added externalBin to tauri.conf.json'); + + console.log('✨ Ready for release build'); +} + +main(); diff --git a/packages/desktop/scripts/restore-config.mjs b/packages/desktop/scripts/restore-config.mjs new file mode 100755 index 00000000..d079d202 --- /dev/null +++ b/packages/desktop/scripts/restore-config.mjs @@ -0,0 +1,21 @@ +#!/usr/bin/env node + +import fs from 'fs'; +import path from 'path'; + +const CONFIG_PATH = 'src-tauri/tauri.conf.json'; +const BACKUP_PATH = 'src-tauri/tauri.conf.json.backup'; + +function main() { + console.log('🔧 Restoring original config...'); + + if (fs.existsSync(BACKUP_PATH)) { + fs.copyFileSync(BACKUP_PATH, CONFIG_PATH); + fs.unlinkSync(BACKUP_PATH); + console.log('✅ Restored tauri.conf.json'); + } else { + console.log('⚠️ No backup found, skipping restore'); + } +} + +main(); diff --git a/packages/desktop/src-tauri/build.rs b/packages/desktop/src-tauri/build.rs index f6a8b9be..32fe5cec 100644 --- a/packages/desktop/src-tauri/build.rs +++ b/packages/desktop/src-tauri/build.rs @@ -6,7 +6,11 @@ use std::path::PathBuf; use std::os::unix::fs::PermissionsExt; fn main() { - ensure_opencode_sidecar(); + // Always create sidecar for production builds + let profile = env::var("PROFILE").unwrap_or_default(); + if profile == "release" { + ensure_opencode_sidecar(); + } tauri_build::build(); } @@ -108,9 +112,17 @@ fn create_debug_stub(dest_path: &PathBuf, sidecar_dir: &PathBuf, profile: &str, return; } - let stub = "#!/usr/bin/env bash\n\ -echo 'OpenCode sidecar missing. Install OpenCode or set OPENCODE_BIN_PATH.'\n\ -exit 1\n"; + let stub = format!("#!/usr/bin/env bash\n\ +echo 'ERROR: This is a stub file, not a real OpenCode binary.'\n\ +echo ''\n\ +echo 'To fix this issue:'\n\ +echo \" 1. Delete: sidecars/opencode-{}\"\n\ +echo \" 2. Delete: target/{}/opencode\"\n\ +echo \" 3. Run: pnpm dev\"\n\ +echo ''\n\ +echo 'For development, OpenWork uses opencode from your PATH.'\n\ +echo 'Install OpenCode or set OPENCODE_BIN_PATH.'\n\ +exit 1\n", target, profile); if fs::write(dest_path, stub).is_ok() { #[cfg(unix)] let _ = fs::set_permissions(dest_path, fs::Permissions::from_mode(0o755)); diff --git a/packages/desktop/src-tauri/tauri.conf.json b/packages/desktop/src-tauri/tauri.conf.json index 7b688f62..d50bbfb3 100644 --- a/packages/desktop/src-tauri/tauri.conf.json +++ b/packages/desktop/src-tauri/tauri.conf.json @@ -33,9 +33,6 @@ "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico" - ], - "externalBin": [ - "sidecars/opencode" ] }, "plugins": { diff --git a/packages/desktop/src/app/app.tsx b/packages/desktop/src/app/app.tsx index e13f4212..45337f80 100644 --- a/packages/desktop/src/app/app.tsx +++ b/packages/desktop/src/app/app.tsx @@ -129,7 +129,8 @@ export default function App() { const [themeMode, setThemeMode] = createSignal(getInitialThemeMode()); const [engineSource, setEngineSource] = createSignal<"path" | "sidecar">( - isTauriRuntime() ? "sidecar" : "path" + // Use PATH in development, sidecar in production (when bundled) + isTauriRuntime() && import.meta.env.PROD ? "sidecar" : "path" ); const [baseUrl, setBaseUrl] = createSignal("http://127.0.0.1:4096"); From b4712290445d6cc419dc70bd1816b2f4fdde8b4e Mon Sep 17 00:00:00 2001 From: lin Date: Wed, 21 Jan 2026 20:37:48 +0800 Subject: [PATCH 2/4] remove confuse create_debug_stub, just report build error --- packages/desktop/src-tauri/build.rs | 62 ++++++++--------------------- 1 file changed, 17 insertions(+), 45 deletions(-) diff --git a/packages/desktop/src-tauri/build.rs b/packages/desktop/src-tauri/build.rs index 32fe5cec..16df4201 100644 --- a/packages/desktop/src-tauri/build.rs +++ b/packages/desktop/src-tauri/build.rs @@ -6,21 +6,25 @@ use std::path::PathBuf; use std::os::unix::fs::PermissionsExt; fn main() { - // Always create sidecar for production builds + // Only create sidecar for production builds let profile = env::var("PROFILE").unwrap_or_default(); if profile == "release" { - ensure_opencode_sidecar(); + if let Err(e) = ensure_opencode_sidecar() { + eprintln!("Error: {}", e); + eprintln!("Install OpenCode or set OPENCODE_BIN_PATH."); + std::process::exit(1); + } } tauri_build::build(); } -fn ensure_opencode_sidecar() { +fn ensure_opencode_sidecar() -> Result<(), String> { let target = env::var("CARGO_CFG_TARGET_TRIPLE") .or_else(|_| env::var("TARGET")) .or_else(|_| env::var("TAURI_ENV_TARGET_TRIPLE")) .unwrap_or_default(); if target.is_empty() { - return; + return Ok(()); } let manifest_dir = env::var("CARGO_MANIFEST_DIR") @@ -35,7 +39,7 @@ fn ensure_opencode_sidecar() { let dest_path = sidecar_dir.join(file_name); if dest_path.exists() { - return; + return Ok(()); } let source_path = env::var("OPENCODE_BIN_PATH") @@ -44,20 +48,14 @@ fn ensure_opencode_sidecar() { .filter(|path| path.is_file()) .or_else(|| find_in_path(if target.contains("windows") { "opencode.exe" } else { "opencode" })); - let profile = env::var("PROFILE").unwrap_or_default(); - let Some(source_path) = source_path else { - println!( - "cargo:warning=OpenCode sidecar missing at {} (set OPENCODE_BIN_PATH or install OpenCode)", - dest_path.display() - ); - - create_debug_stub(&dest_path, &sidecar_dir, &profile, &target); - return; + return Err(format!( + "OpenCode not found. Install OpenCode or set OPENCODE_BIN_PATH." + )); }; if fs::create_dir_all(&sidecar_dir).is_err() { - return; + return Err(format!("Failed to create directory: {}", sidecar_dir.display())); } let mut copied = fs::copy(&source_path, &dest_path).is_ok(); @@ -81,13 +79,13 @@ fn ensure_opencode_sidecar() { { let _ = fs::set_permissions(&dest_path, fs::Permissions::from_mode(0o755)); } + Ok(()) } else { - println!( - "cargo:warning=Failed to copy OpenCode sidecar from {} to {}", + Err(format!( + "Failed to copy OpenCode from {} to {}", source_path.display(), dest_path.display() - ); - create_debug_stub(&dest_path, &sidecar_dir, &profile, &target); + )) } } @@ -102,29 +100,3 @@ fn find_in_path(binary: &str) -> Option { } }) } - -fn create_debug_stub(dest_path: &PathBuf, sidecar_dir: &PathBuf, profile: &str, target: &str) { - if profile != "debug" || target.contains("windows") { - return; - } - - if fs::create_dir_all(sidecar_dir).is_err() { - return; - } - - let stub = format!("#!/usr/bin/env bash\n\ -echo 'ERROR: This is a stub file, not a real OpenCode binary.'\n\ -echo ''\n\ -echo 'To fix this issue:'\n\ -echo \" 1. Delete: sidecars/opencode-{}\"\n\ -echo \" 2. Delete: target/{}/opencode\"\n\ -echo \" 3. Run: pnpm dev\"\n\ -echo ''\n\ -echo 'For development, OpenWork uses opencode from your PATH.'\n\ -echo 'Install OpenCode or set OPENCODE_BIN_PATH.'\n\ -exit 1\n", target, profile); - if fs::write(dest_path, stub).is_ok() { - #[cfg(unix)] - let _ = fs::set_permissions(dest_path, fs::Permissions::from_mode(0o755)); - } -} From 00188dacea67ad151207d393e7a01504247670cc Mon Sep 17 00:00:00 2001 From: lin Date: Thu, 22 Jan 2026 02:17:32 +0800 Subject: [PATCH 3/4] remove prepare-release and restore-config script --- packages/desktop/package.json | 2 +- packages/desktop/scripts/prepare-release.mjs | 42 -------------------- packages/desktop/scripts/restore-config.mjs | 21 ---------- packages/desktop/src-tauri/tauri.conf.json | 3 ++ 4 files changed, 4 insertions(+), 64 deletions(-) delete mode 100755 packages/desktop/scripts/prepare-release.mjs delete mode 100755 packages/desktop/scripts/restore-config.mjs diff --git a/packages/desktop/package.json b/packages/desktop/package.json index f5d35a28..4dbbd37b 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "dev": "tauri dev", - "build": "node scripts/prepare-release.mjs && tauri build && node scripts/restore-config.mjs", + "build": "tauri build", "dev:web": "vite", "build:web": "vite build", "preview": "vite preview", diff --git a/packages/desktop/scripts/prepare-release.mjs b/packages/desktop/scripts/prepare-release.mjs deleted file mode 100755 index 042341e1..00000000 --- a/packages/desktop/scripts/prepare-release.mjs +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env node - -import fs from 'fs'; -import path from 'path'; -import { execSync } from 'child_process'; - -const CONFIG_PATH = 'src-tauri/tauri.conf.json'; -const BACKUP_PATH = 'src-tauri/tauri.conf.json.backup'; - -function addExternalBin(config) { - if (config.bundle?.externalBin?.includes('sidecars/opencode')) { - return config; // Already has externalBin - } - - return { - ...config, - bundle: { - ...config.bundle, - externalBin: ['sidecars/opencode'] - } - }; -} - -function main() { - console.log('🔧 Preparing release build with sidecar...'); - - // Read current config - const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8')); - - // Backup original config - fs.writeFileSync(BACKUP_PATH, JSON.stringify(config, null, 2)); - console.log('✅ Backed up tauri.conf.json'); - - // Add externalBin - const releaseConfig = addExternalBin(config); - fs.writeFileSync(CONFIG_PATH, JSON.stringify(releaseConfig, null, 2)); - console.log('✅ Added externalBin to tauri.conf.json'); - - console.log('✨ Ready for release build'); -} - -main(); diff --git a/packages/desktop/scripts/restore-config.mjs b/packages/desktop/scripts/restore-config.mjs deleted file mode 100755 index d079d202..00000000 --- a/packages/desktop/scripts/restore-config.mjs +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env node - -import fs from 'fs'; -import path from 'path'; - -const CONFIG_PATH = 'src-tauri/tauri.conf.json'; -const BACKUP_PATH = 'src-tauri/tauri.conf.json.backup'; - -function main() { - console.log('🔧 Restoring original config...'); - - if (fs.existsSync(BACKUP_PATH)) { - fs.copyFileSync(BACKUP_PATH, CONFIG_PATH); - fs.unlinkSync(BACKUP_PATH); - console.log('✅ Restored tauri.conf.json'); - } else { - console.log('⚠️ No backup found, skipping restore'); - } -} - -main(); diff --git a/packages/desktop/src-tauri/tauri.conf.json b/packages/desktop/src-tauri/tauri.conf.json index d50bbfb3..7b688f62 100644 --- a/packages/desktop/src-tauri/tauri.conf.json +++ b/packages/desktop/src-tauri/tauri.conf.json @@ -33,6 +33,9 @@ "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico" + ], + "externalBin": [ + "sidecars/opencode" ] }, "plugins": { From dc979e4577c4c0309375f9dbb526e1005e18ebd7 Mon Sep 17 00:00:00 2001 From: lin Date: Thu, 22 Jan 2026 02:22:13 +0800 Subject: [PATCH 4/4] Ensure sidecar exists in all envs --- packages/desktop/src-tauri/build.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/desktop/src-tauri/build.rs b/packages/desktop/src-tauri/build.rs index 16df4201..cb770638 100644 --- a/packages/desktop/src-tauri/build.rs +++ b/packages/desktop/src-tauri/build.rs @@ -6,14 +6,11 @@ use std::path::PathBuf; use std::os::unix::fs::PermissionsExt; fn main() { - // Only create sidecar for production builds - let profile = env::var("PROFILE").unwrap_or_default(); - if profile == "release" { - if let Err(e) = ensure_opencode_sidecar() { - eprintln!("Error: {}", e); - eprintln!("Install OpenCode or set OPENCODE_BIN_PATH."); - std::process::exit(1); - } + // Ensure sidecar exists in all builds (debug and release) + if let Err(e) = ensure_opencode_sidecar() { + eprintln!("Error: {}", e); + eprintln!("Install OpenCode or set OPENCODE_BIN_PATH."); + std::process::exit(1); } tauri_build::build(); }