mirror of
https://github.com/aljazceru/goose.git
synced 2025-12-24 01:24:28 +01:00
fix windows extensions (#1968)
This commit is contained in:
37
Justfile
37
Justfile
@@ -111,17 +111,34 @@ make-ui:
|
||||
make-ui-windows:
|
||||
@just release-windows
|
||||
#!/usr/bin/env sh
|
||||
set -e
|
||||
if [ -f "./target/x86_64-pc-windows-gnu/release/goosed.exe" ]; then \
|
||||
echo "Copying Windows binary and DLLs to ui/desktop/src/bin..."; \
|
||||
mkdir -p ./ui/desktop/src/bin; \
|
||||
cp -f ./target/x86_64-pc-windows-gnu/release/goosed.exe ./ui/desktop/src/bin/; \
|
||||
cp -f ./target/x86_64-pc-windows-gnu/release/*.dll ./ui/desktop/src/bin/; \
|
||||
echo "Building Windows package..."; \
|
||||
cd ui/desktop && \
|
||||
npm run bundle:windows && \
|
||||
mkdir -p out/Goose-win32-x64/resources/bin && \
|
||||
cp -f src/bin/goosed.exe out/Goose-win32-x64/resources/bin/ && \
|
||||
cp -f src/bin/*.dll out/Goose-win32-x64/resources/bin/; \
|
||||
echo "Cleaning destination directory..." && \
|
||||
rm -rf ./ui/desktop/src/bin && \
|
||||
mkdir -p ./ui/desktop/src/bin && \
|
||||
echo "Copying Windows binary and DLLs..." && \
|
||||
cp -f ./target/x86_64-pc-windows-gnu/release/goosed.exe ./ui/desktop/src/bin/ && \
|
||||
cp -f ./target/x86_64-pc-windows-gnu/release/*.dll ./ui/desktop/src/bin/ && \
|
||||
if [ -d "./ui/desktop/src/platform/windows/bin" ]; then \
|
||||
echo "Copying Windows platform files..." && \
|
||||
for file in ./ui/desktop/src/platform/windows/bin/*.{exe,dll,cmd}; do \
|
||||
if [ -f "$file" ] && [ "$(basename "$file")" != "goosed.exe" ]; then \
|
||||
cp -f "$file" ./ui/desktop/src/bin/; \
|
||||
fi; \
|
||||
done && \
|
||||
if [ -d "./ui/desktop/src/platform/windows/bin/goose-npm" ]; then \
|
||||
echo "Setting up npm environment..." && \
|
||||
rsync -a --delete ./ui/desktop/src/platform/windows/bin/goose-npm/ ./ui/desktop/src/bin/goose-npm/; \
|
||||
fi && \
|
||||
echo "Windows-specific files copied successfully"; \
|
||||
fi && \
|
||||
echo "Starting Windows package build..." && \
|
||||
(cd ui/desktop && echo "In desktop directory, running npm bundle:windows..." && npm run bundle:windows) && \
|
||||
echo "Creating resources directory..." && \
|
||||
(cd ui/desktop && mkdir -p out/Goose-win32-x64/resources/bin) && \
|
||||
echo "Copying final binaries..." && \
|
||||
(cd ui/desktop && rsync -av src/bin/ out/Goose-win32-x64/resources/bin/) && \
|
||||
echo "Windows package build complete!"; \
|
||||
else \
|
||||
echo "Windows binary not found."; \
|
||||
exit 1; \
|
||||
|
||||
@@ -108,6 +108,60 @@ async fn add_extension(
|
||||
return Err(StatusCode::UNAUTHORIZED);
|
||||
}
|
||||
|
||||
// If this is a Stdio extension that uses npx, check for Node.js installation
|
||||
#[cfg(target_os = "windows")]
|
||||
if let ExtensionConfigRequest::Stdio { cmd, .. } = &request {
|
||||
if cmd.ends_with("npx.cmd") || cmd.ends_with("npx") {
|
||||
// Check if Node.js is installed in standard locations
|
||||
let node_exists = std::path::Path::new(r"C:\Program Files\nodejs\node.exe").exists()
|
||||
|| std::path::Path::new(r"C:\Program Files (x86)\nodejs\node.exe").exists();
|
||||
|
||||
if !node_exists {
|
||||
// Get the directory containing npx.cmd
|
||||
let cmd_path = std::path::Path::new(&cmd);
|
||||
let script_dir = cmd_path.parent().ok_or(StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
|
||||
// Run the Node.js installer script
|
||||
let install_script = script_dir.join("install-node.cmd");
|
||||
|
||||
if install_script.exists() {
|
||||
eprintln!("Installing Node.js...");
|
||||
let output = std::process::Command::new(&install_script)
|
||||
.arg("https://nodejs.org/dist/v23.10.0/node-v23.10.0-x64.msi")
|
||||
.output()
|
||||
.map_err(|e| {
|
||||
eprintln!("Failed to run Node.js installer: {}", e);
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
})?;
|
||||
|
||||
if !output.status.success() {
|
||||
eprintln!(
|
||||
"Failed to install Node.js: {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
return Ok(Json(ExtensionResponse {
|
||||
error: true,
|
||||
message: Some(format!(
|
||||
"Failed to install Node.js: {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
)),
|
||||
}));
|
||||
}
|
||||
eprintln!("Node.js installation completed");
|
||||
} else {
|
||||
eprintln!(
|
||||
"Node.js installer script not found at: {}",
|
||||
install_script.display()
|
||||
);
|
||||
return Ok(Json(ExtensionResponse {
|
||||
error: true,
|
||||
message: Some("Node.js installer script not found".to_string()),
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load the configuration
|
||||
let config = Config::global();
|
||||
|
||||
@@ -419,20 +473,41 @@ fn is_command_allowed_with_allowlist(
|
||||
|
||||
// Check against the allowlist
|
||||
Some(extensions) => {
|
||||
// Strip out the Goose.app/Contents/Resources/bin/ prefix if present
|
||||
// Strip out the Goose app resources/bin prefix if present (handle both macOS and Windows paths)
|
||||
let mut cmd_to_check = cmd.to_string();
|
||||
let mut is_goose_path = false;
|
||||
|
||||
// Check if the command path contains Goose.app/Contents/Resources/bin/
|
||||
// Check for macOS-style Goose.app path
|
||||
if cmd_to_check.contains("Goose.app/Contents/Resources/bin/") {
|
||||
// Find the position of "Goose.app/Contents/Resources/bin/"
|
||||
if let Some(idx) = cmd_to_check.find("Goose.app/Contents/Resources/bin/") {
|
||||
// Extract only the part after "Goose.app/Contents/Resources/bin/"
|
||||
cmd_to_check = cmd_to_check
|
||||
[(idx + "Goose.app/Contents/Resources/bin/".len())..]
|
||||
.to_string();
|
||||
is_goose_path = true;
|
||||
}
|
||||
}
|
||||
// Check for Windows-style Goose path with resources\bin
|
||||
else if cmd_to_check.to_lowercase().contains("\\resources\\bin\\")
|
||||
|| cmd_to_check.contains("/resources/bin/")
|
||||
{
|
||||
// Also handle forward slashes
|
||||
if let Some(idx) = cmd_to_check
|
||||
.to_lowercase()
|
||||
.rfind("\\resources\\bin\\")
|
||||
.or_else(|| cmd_to_check.rfind("/resources/bin/"))
|
||||
{
|
||||
let path_len = if cmd_to_check.contains("/resources/bin/") {
|
||||
"/resources/bin/".len()
|
||||
} else {
|
||||
// Only apply the path check if we're not dealing with a Goose.app path
|
||||
"\\resources\\bin\\".len()
|
||||
};
|
||||
cmd_to_check = cmd_to_check[(idx + path_len)..].to_string();
|
||||
is_goose_path = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Only check current directory for non-Goose paths
|
||||
if !is_goose_path {
|
||||
// Check that the command exists as a peer command to current executable directory
|
||||
// Only apply this check if the command includes a path separator
|
||||
let current_exe = std::env::current_exe().unwrap();
|
||||
@@ -817,6 +892,79 @@ mod tests {
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_windows_paths() {
|
||||
let allowlist = create_test_allowlist(&["uvx mcp_snowflake", "uvx mcp_test"]);
|
||||
|
||||
// Test various Windows path formats
|
||||
let test_paths = vec![
|
||||
// Standard Windows path
|
||||
r"C:\Users\MaxNovich\Downloads\Goose-1.0.17\resources\bin\uvx.exe",
|
||||
// Path with different casing
|
||||
r"C:\Users\MaxNovich\Downloads\Goose-1.0.17\Resources\Bin\uvx.exe",
|
||||
// Path with forward slashes
|
||||
r"C:/Users/MaxNovich/Downloads/Goose-1.0.17/resources/bin/uvx.exe",
|
||||
// Path with spaces
|
||||
r"C:\Program Files\Goose 1.0.17\resources\bin\uvx.exe",
|
||||
// Path with version numbers
|
||||
r"C:\Users\MaxNovich\Downloads\Goose-1.0.17-block.202504072238-76ffe-win32-x64\Goose-1.0.17-block.202504072238-76ffe-win32-x64\resources\bin\uvx.exe",
|
||||
];
|
||||
|
||||
for path in test_paths {
|
||||
// Test with @latest version
|
||||
let cmd = format!("{} mcp_snowflake@latest", path);
|
||||
assert!(
|
||||
is_command_allowed_with_allowlist(&cmd, &allowlist),
|
||||
"Failed for path: {}",
|
||||
path
|
||||
);
|
||||
|
||||
// Test with specific version
|
||||
let cmd_version = format!("{} mcp_test@1.2.3", path);
|
||||
assert!(
|
||||
is_command_allowed_with_allowlist(&cmd_version, &allowlist),
|
||||
"Failed for path with version: {}",
|
||||
path
|
||||
);
|
||||
}
|
||||
|
||||
// Test invalid paths that should be rejected
|
||||
let invalid_paths = vec![
|
||||
// Path without resources\bin
|
||||
r"C:\Users\MaxNovich\Downloads\uvx.exe",
|
||||
// Path with modified resources\bin
|
||||
r"C:\Users\MaxNovich\Downloads\Goose-1.0.17\resources_modified\bin\uvx.exe",
|
||||
// Path with extra components
|
||||
r"C:\Users\MaxNovich\Downloads\Goose-1.0.17\resources\bin\extra\uvx.exe",
|
||||
];
|
||||
|
||||
for path in invalid_paths {
|
||||
let cmd = format!("{} mcp_snowflake@latest", path);
|
||||
assert!(
|
||||
!is_command_allowed_with_allowlist(&cmd, &allowlist),
|
||||
"Should have rejected path: {}",
|
||||
path
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_windows_uvx_path() {
|
||||
let allowlist = create_test_allowlist(&["uvx mcp_snowflake"]);
|
||||
|
||||
// Test Windows-style path with uvx.exe
|
||||
let windows_path = r"C:\Users\MaxNovich\Downloads\Goose-1.0.17-block.202504072238-76ffe-win32-x64\Goose-1.0.17-block.202504072238-76ffe-win32-x64\resources\bin\uvx.exe";
|
||||
let cmd = format!("{} mcp_snowflake@latest", windows_path);
|
||||
|
||||
// This should be allowed because it's a valid uvx command in the Goose resources/bin directory
|
||||
assert!(is_command_allowed_with_allowlist(&cmd, &allowlist));
|
||||
|
||||
// Test with different casing and backslashes
|
||||
let windows_path_alt = r"c:\Users\MaxNovich\Downloads\Goose-1.0.17-block.202504072238-76ffe-win32-x64\Goose-1.0.17-block.202504072238-76ffe-win32-x64\Resources\Bin\uvx.exe";
|
||||
let cmd_alt = format!("{} mcp_snowflake@latest", windows_path_alt);
|
||||
assert!(is_command_allowed_with_allowlist(&cmd_alt, &allowlist));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fetch_allowed_extensions_from_url() {
|
||||
// Start a mock server - we need to use a blocking approach since fetch_allowed_extensions is blocking
|
||||
|
||||
4
ui/desktop/.gitignore
vendored
4
ui/desktop/.gitignore
vendored
@@ -2,6 +2,8 @@ node_modules
|
||||
.vite/
|
||||
out
|
||||
src/bin/goosed
|
||||
/src/bin/goosed.exe
|
||||
src/bin/goose-npm/
|
||||
/src/bin/*.exe
|
||||
/src/bin/*.cmd
|
||||
/playwright-report/
|
||||
/test-results/
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"package": "electron-forge package",
|
||||
"make": "electron-forge make",
|
||||
"bundle:default": "npm run make && cd out/Goose-darwin-arm64 && ditto -c -k --sequesterRsrc --keepParent Goose.app Goose.zip",
|
||||
"bundle:windows": "node scripts/build-main.js && npm run make -- --platform=win32 --arch=x64 && node scripts/copy-windows-dlls.js",
|
||||
"bundle:windows": "node scripts/build-main.js && node scripts/prepare-platform.js && npm run make -- --platform=win32 --arch=x64 && node scripts/copy-windows-dlls.js",
|
||||
"bundle:intel": "npm run make -- --arch=x64 && cd out/Goose-darwin-x64 && ditto -c -k --sequesterRsrc --keepParent Goose.app Goose_intel_mac.zip",
|
||||
"debug": "echo 'run --remote-debugging-port=8315' && lldb out/Goose-darwin-arm64/Goose.app",
|
||||
"test-e2e": "npm run generate-api && playwright test",
|
||||
|
||||
@@ -1,84 +1,49 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
// Required DLLs that must be present
|
||||
const REQUIRED_DLLS = [
|
||||
'libstdc++-6.dll',
|
||||
'libgcc_s_seh-1.dll',
|
||||
'libwinpthread-1.dll'
|
||||
];
|
||||
// Paths
|
||||
const platformWinDir = path.join(__dirname, '..', 'src', 'platform', 'windows', 'bin');
|
||||
const outDir = path.join(__dirname, '..', 'out', 'Goose-win32-x64', 'resources', 'bin');
|
||||
const srcBinDir = path.join(__dirname, '..', 'src', 'bin');
|
||||
|
||||
// Source and target directories
|
||||
const sourceDir = path.join(__dirname, '../src/bin');
|
||||
const targetDir = path.join(__dirname, '../out/Goose-win32-x64/resources/bin');
|
||||
|
||||
function ensureDirectoryExists(dir) {
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
console.log(`Created directory: ${dir}`);
|
||||
}
|
||||
}
|
||||
|
||||
function copyDLLs() {
|
||||
// Helper function to copy files
|
||||
function copyFiles(sourceDir, targetDir) {
|
||||
// Ensure target directory exists
|
||||
ensureDirectoryExists(targetDir);
|
||||
|
||||
// Get list of DLLs in source directory
|
||||
const sourceDLLs = fs.readdirSync(sourceDir)
|
||||
.filter(file => file.toLowerCase().endsWith('.dll'));
|
||||
|
||||
console.log('Found DLLs in source directory:', sourceDLLs);
|
||||
|
||||
// Check for missing required DLLs
|
||||
const missingDLLs = REQUIRED_DLLS.filter(dll =>
|
||||
!sourceDLLs.includes(dll)
|
||||
);
|
||||
|
||||
if (missingDLLs.length > 0) {
|
||||
console.error('Missing required DLLs:', missingDLLs);
|
||||
process.exit(1);
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
fs.mkdirSync(targetDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Copy all DLLs and the executable to target directory
|
||||
sourceDLLs.forEach(dll => {
|
||||
const sourcePath = path.join(sourceDir, dll);
|
||||
const targetPath = path.join(targetDir, dll);
|
||||
// Copy all files from source to target directory
|
||||
console.log(`Copying files to ${targetDir}...`);
|
||||
fs.readdirSync(sourceDir).forEach(file => {
|
||||
const srcPath = path.join(sourceDir, file);
|
||||
const destPath = path.join(targetDir, file);
|
||||
|
||||
try {
|
||||
fs.copyFileSync(sourcePath, targetPath);
|
||||
console.log(`Copied ${dll} to ${targetDir}`);
|
||||
} catch (err) {
|
||||
console.error(`Error copying ${dll}:`, err);
|
||||
process.exit(1);
|
||||
// Skip .gitignore and README.md
|
||||
if (file === '.gitignore' || file === 'README.md') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle directories (like goose-npm)
|
||||
if (fs.statSync(srcPath).isDirectory()) {
|
||||
fs.cpSync(srcPath, destPath, { recursive: true, force: true });
|
||||
console.log(`Copied directory: ${file}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy individual file
|
||||
fs.copyFileSync(srcPath, destPath);
|
||||
console.log(`Copied: ${file}`);
|
||||
});
|
||||
|
||||
// Copy the executable
|
||||
const exeName = 'goosed.exe';
|
||||
const sourceExe = path.join(sourceDir, exeName);
|
||||
const targetExe = path.join(targetDir, exeName);
|
||||
|
||||
try {
|
||||
if (fs.existsSync(sourceExe)) {
|
||||
fs.copyFileSync(sourceExe, targetExe);
|
||||
console.log(`Copied ${exeName} to ${targetDir}`);
|
||||
} else {
|
||||
console.error(`${exeName} not found in source directory`);
|
||||
process.exit(1);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`Error copying ${exeName}:`, err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('All files copied successfully');
|
||||
}
|
||||
|
||||
// Main execution
|
||||
try {
|
||||
copyDLLs();
|
||||
} catch (err) {
|
||||
console.error('Error during copy process:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
// Copy to both directories
|
||||
console.log('Copying Windows-specific files...');
|
||||
|
||||
// Copy to src/bin for development
|
||||
copyFiles(platformWinDir, srcBinDir);
|
||||
|
||||
// Copy to output directory for distribution
|
||||
copyFiles(platformWinDir, outDir);
|
||||
|
||||
console.log('Windows-specific files copied successfully');
|
||||
|
||||
16
ui/desktop/scripts/prepare-platform.js
Normal file
16
ui/desktop/scripts/prepare-platform.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const { execSync } = require('child_process');
|
||||
const path = require('path');
|
||||
|
||||
try {
|
||||
if (process.platform === 'win32') {
|
||||
execSync(path.join(__dirname, 'prepare-windows-npm.bat'), { stdio: 'inherit' });
|
||||
} else {
|
||||
execSync(path.join(__dirname, 'prepare-windows-npm.sh'), {
|
||||
stdio: 'inherit',
|
||||
shell: '/bin/bash'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error preparing platform:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
101
ui/desktop/scripts/prepare-windows-npm.bat
Normal file
101
ui/desktop/scripts/prepare-windows-npm.bat
Normal file
@@ -0,0 +1,101 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
rem Script to prepare Windows npm bundle
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
set "PLATFORM_WIN_DIR=%SCRIPT_DIR%\..\src\platform\windows"
|
||||
set "WIN_BIN_DIR=%PLATFORM_WIN_DIR%\bin"
|
||||
set "DEST_BIN_DIR=%SCRIPT_DIR%\..\src\bin"
|
||||
|
||||
echo Preparing Windows npm bundle...
|
||||
echo SCRIPT_DIR: %SCRIPT_DIR%
|
||||
echo PLATFORM_WIN_DIR: %PLATFORM_WIN_DIR%
|
||||
echo WIN_BIN_DIR: %WIN_BIN_DIR%
|
||||
echo DEST_BIN_DIR: %DEST_BIN_DIR%
|
||||
|
||||
rem Ensure directories exist
|
||||
if not exist "%WIN_BIN_DIR%" mkdir "%WIN_BIN_DIR%"
|
||||
|
||||
rem Node.js version and paths
|
||||
set "NODE_VERSION=23.10.0"
|
||||
set "NODE_MSI_URL=https://nodejs.org/dist/v%NODE_VERSION%/node-v%NODE_VERSION%-x64.msi"
|
||||
|
||||
rem Create Windows Node.js installer script
|
||||
echo Creating install-node.cmd...
|
||||
(
|
||||
echo @echo off
|
||||
echo setlocal enabledelayedexpansion
|
||||
echo.
|
||||
echo REM Check if Node.js is installed in Program Files
|
||||
echo if exist "C:\Program Files\nodejs\node.exe" ^(
|
||||
echo echo Node.js found in Program Files
|
||||
echo set "NODE_EXE=C:\Program Files\nodejs\node.exe"
|
||||
echo goto :found
|
||||
echo ^)
|
||||
echo.
|
||||
echo REM Check if Node.js is installed in Program Files ^(x86^)
|
||||
echo if exist "C:\Program Files ^(x86^)\nodejs\node.exe" ^(
|
||||
echo echo Node.js found in Program Files ^(x86^)
|
||||
echo set "NODE_EXE=C:\Program Files ^(x86^)\nodejs\node.exe"
|
||||
echo goto :found
|
||||
echo ^)
|
||||
echo.
|
||||
echo echo Node.js not found in standard locations, installing...
|
||||
echo.
|
||||
echo REM Download Node.js MSI installer
|
||||
echo powershell -Command "^& {[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri '%%1' -OutFile '%%TEMP%%\node-setup.msi'}"
|
||||
echo.
|
||||
echo REM Install Node.js silently
|
||||
echo msiexec /i "%%TEMP%%\node-setup.msi" /qn
|
||||
echo.
|
||||
echo REM Wait a bit for installation to complete
|
||||
echo timeout /t 5 /nobreak
|
||||
echo.
|
||||
echo REM Clean up
|
||||
echo del "%%TEMP%%\node-setup.msi"
|
||||
echo.
|
||||
echo REM Set path to installed Node.js
|
||||
echo set "NODE_EXE=C:\Program Files\nodejs\node.exe"
|
||||
echo.
|
||||
echo :found
|
||||
echo echo Using Node.js: %%NODE_EXE%%
|
||||
echo exit /b 0
|
||||
) > "%WIN_BIN_DIR%\install-node.cmd"
|
||||
|
||||
rem Create a modified npx.cmd that checks for system Node.js first
|
||||
echo Creating npx.cmd...
|
||||
(
|
||||
echo @ECHO OFF
|
||||
echo SETLOCAL EnableDelayedExpansion
|
||||
echo.
|
||||
echo SET "SCRIPT_DIR=%%~dp0"
|
||||
echo.
|
||||
echo REM Try to find Node.js in standard locations first
|
||||
echo if exist "C:\Program Files\nodejs\npx.cmd" ^(
|
||||
echo "C:\Program Files\nodejs\npx.cmd" %%*
|
||||
echo exit /b %%errorlevel%%
|
||||
echo ^)
|
||||
echo.
|
||||
echo if exist "C:\Program Files ^(x86^)\nodejs\npx.cmd" ^(
|
||||
echo "C:\Program Files ^(x86^)\nodejs\npx.cmd" %%*
|
||||
echo exit /b %%errorlevel%%
|
||||
echo ^)
|
||||
echo.
|
||||
echo REM If Node.js not found, run installer
|
||||
echo call "%%SCRIPT_DIR%%install-node.cmd" "%NODE_MSI_URL%"
|
||||
echo if errorlevel 1 ^(
|
||||
echo echo Failed to install Node.js
|
||||
echo exit /b 1
|
||||
echo ^)
|
||||
echo.
|
||||
echo REM Try using the newly installed Node.js
|
||||
echo if exist "C:\Program Files\nodejs\npx.cmd" ^(
|
||||
echo "C:\Program Files\nodejs\npx.cmd" %%*
|
||||
echo exit /b %%errorlevel%%
|
||||
echo ^)
|
||||
echo.
|
||||
echo echo Failed to find npx after Node.js installation
|
||||
echo exit /b 1
|
||||
) > "%WIN_BIN_DIR%\npx.cmd"
|
||||
|
||||
echo Windows npm bundle prepared successfully
|
||||
101
ui/desktop/scripts/prepare-windows-npm.sh
Executable file
101
ui/desktop/scripts/prepare-windows-npm.sh
Executable file
@@ -0,0 +1,101 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Script to prepare Windows npm bundle
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PLATFORM_WIN_DIR="$SCRIPT_DIR/../src/platform/windows"
|
||||
WIN_BIN_DIR="$PLATFORM_WIN_DIR/bin"
|
||||
DEST_BIN_DIR="$SCRIPT_DIR/../src/bin"
|
||||
|
||||
echo "Preparing Windows npm bundle..."
|
||||
echo "SCRIPT_DIR: $SCRIPT_DIR"
|
||||
echo "PLATFORM_WIN_DIR: $PLATFORM_WIN_DIR"
|
||||
echo "WIN_BIN_DIR: $WIN_BIN_DIR"
|
||||
echo "DEST_BIN_DIR: $DEST_BIN_DIR"
|
||||
|
||||
# Ensure directories exist
|
||||
mkdir -p "$WIN_BIN_DIR"
|
||||
|
||||
# Node.js version and paths
|
||||
NODE_VERSION="23.10.0"
|
||||
NODE_MSI_URL="https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-x64.msi"
|
||||
|
||||
# Create Windows Node.js installer script
|
||||
echo "Creating install-node.cmd..."
|
||||
cat > "$WIN_BIN_DIR/install-node.cmd" << 'EOL'
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM Check if Node.js is installed in Program Files
|
||||
if exist "C:\Program Files\nodejs\node.exe" (
|
||||
echo Node.js found in Program Files
|
||||
set "NODE_EXE=C:\Program Files\nodejs\node.exe"
|
||||
goto :found
|
||||
)
|
||||
|
||||
REM Check if Node.js is installed in Program Files (x86)
|
||||
if exist "C:\Program Files (x86)\nodejs\node.exe" (
|
||||
echo Node.js found in Program Files (x86)
|
||||
set "NODE_EXE=C:\Program Files (x86)\nodejs\node.exe"
|
||||
goto :found
|
||||
)
|
||||
|
||||
echo Node.js not found in standard locations, installing...
|
||||
|
||||
REM Download Node.js MSI installer
|
||||
powershell -Command "& {[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri '%1' -OutFile '%TEMP%\node-setup.msi'}"
|
||||
|
||||
REM Install Node.js silently
|
||||
msiexec /i "%TEMP%\node-setup.msi" /qn
|
||||
|
||||
REM Wait a bit for installation to complete
|
||||
timeout /t 5 /nobreak
|
||||
|
||||
REM Clean up
|
||||
del "%TEMP%\node-setup.msi"
|
||||
|
||||
REM Set path to installed Node.js
|
||||
set "NODE_EXE=C:\Program Files\nodejs\node.exe"
|
||||
|
||||
:found
|
||||
echo Using Node.js: %NODE_EXE%
|
||||
exit /b 0
|
||||
EOL
|
||||
|
||||
# Create a modified npx.cmd that checks for system Node.js first
|
||||
echo "Creating npx.cmd..."
|
||||
cat > "$WIN_BIN_DIR/npx.cmd" << 'EOL'
|
||||
@ECHO OFF
|
||||
SETLOCAL EnableDelayedExpansion
|
||||
|
||||
SET "SCRIPT_DIR=%~dp0"
|
||||
|
||||
REM Try to find Node.js in standard locations first
|
||||
if exist "C:\Program Files\nodejs\npx.cmd" (
|
||||
"C:\Program Files\nodejs\npx.cmd" %*
|
||||
exit /b %errorlevel%
|
||||
)
|
||||
|
||||
if exist "C:\Program Files (x86)\nodejs\npx.cmd" (
|
||||
"C:\Program Files (x86)\nodejs\npx.cmd" %*
|
||||
exit /b %errorlevel%
|
||||
)
|
||||
|
||||
REM If Node.js not found, run installer
|
||||
call "%SCRIPT_DIR%install-node.cmd" "https://nodejs.org/dist/v23.10.0/node-v23.10.0-x64.msi"
|
||||
if errorlevel 1 (
|
||||
echo Failed to install Node.js
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Try using the newly installed Node.js
|
||||
if exist "C:\Program Files\nodejs\npx.cmd" (
|
||||
"C:\Program Files\nodejs\npx.cmd" %*
|
||||
exit /b %errorlevel%
|
||||
)
|
||||
|
||||
echo Failed to find npx after Node.js installation
|
||||
exit /b 1
|
||||
EOL
|
||||
|
||||
echo "Windows npm bundle prepared successfully"
|
||||
@@ -1,89 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Enable strict mode to exit on errors and unset variables
|
||||
set -euo pipefail
|
||||
|
||||
# Set log file
|
||||
LOG_FILE="/tmp/mcp.log"
|
||||
|
||||
# Clear the log file at the start
|
||||
> "$LOG_FILE"
|
||||
|
||||
# Function for logging
|
||||
log() {
|
||||
local MESSAGE="$1"
|
||||
echo "$(date +'%Y-%m-%d %H:%M:%S') - $MESSAGE" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
# Trap errors and log them before exiting
|
||||
trap 'log "An error occurred. Exiting with status $?."' ERR
|
||||
|
||||
log "Starting jbang setup script."
|
||||
|
||||
# Ensure ~/.config/goose/mcp-hermit/bin exists
|
||||
log "Creating directory ~/.config/goose/mcp-hermit/bin if it does not exist."
|
||||
mkdir -p ~/.config/goose/mcp-hermit/bin
|
||||
|
||||
# Change to the ~/.config/goose/mcp-hermit directory
|
||||
log "Changing to directory ~/.config/goose/mcp-hermit."
|
||||
cd ~/.config/goose/mcp-hermit
|
||||
|
||||
# Check if hermit binary exists and download if not
|
||||
if [ ! -f ~/.config/goose/mcp-hermit/bin/hermit ]; then
|
||||
log "Hermit binary not found. Downloading hermit binary."
|
||||
curl -fsSL "https://github.com/cashapp/hermit/releases/download/stable/hermit-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/').gz" \
|
||||
| gzip -dc > ~/.config/goose/mcp-hermit/bin/hermit && chmod +x ~/.config/goose/mcp-hermit/bin/hermit
|
||||
log "Hermit binary downloaded and made executable."
|
||||
else
|
||||
log "Hermit binary already exists. Skipping download."
|
||||
fi
|
||||
|
||||
log "setting hermit cache to be local for MCP servers"
|
||||
mkdir -p ~/.config/goose/mcp-hermit/cache
|
||||
export HERMIT_STATE_DIR=~/.config/goose/mcp-hermit/cache
|
||||
|
||||
# Update PATH
|
||||
export PATH=~/.config/goose/mcp-hermit/bin:$PATH
|
||||
log "Updated PATH to include ~/.config/goose/mcp-hermit/bin."
|
||||
|
||||
# Initialize hermit
|
||||
log "Initializing hermit."
|
||||
hermit init >> "$LOG_FILE"
|
||||
|
||||
# Install OpenJDK using hermit
|
||||
log "Installing OpenJDK with hermit."
|
||||
hermit install openjdk@17 >> "$LOG_FILE"
|
||||
|
||||
# Download and install jbang if not present
|
||||
if [ ! -f ~/.config/goose/mcp-hermit/bin/jbang ]; then
|
||||
log "Downloading and installing jbang."
|
||||
curl -Ls https://sh.jbang.dev | bash -s - app setup
|
||||
cp ~/.jbang/bin/jbang ~/.config/goose/mcp-hermit/bin/
|
||||
fi
|
||||
|
||||
# Verify installations
|
||||
log "Verifying installation locations:"
|
||||
log "hermit: $(which hermit)"
|
||||
log "java: $(which java)"
|
||||
log "jbang: $(which jbang)"
|
||||
|
||||
# Check for custom registry settings
|
||||
log "Checking for GOOSE_JBANG_REGISTRY environment variable for custom jbang registry setup..."
|
||||
if [ -n "${GOOSE_JBANG_REGISTRY:-}" ] && curl -s --head --fail "$GOOSE_JBANG_REGISTRY" > /dev/null; then
|
||||
log "Checking custom goose registry availability: $GOOSE_JBANG_REGISTRY"
|
||||
log "$GOOSE_JBANG_REGISTRY is accessible. Setting it as JBANG_REPO."
|
||||
export JBANG_REPO="$GOOSE_JBANG_REGISTRY"
|
||||
else
|
||||
log "GOOSE_JBANG_REGISTRY is not set or not accessible. Using default jbang repository."
|
||||
fi
|
||||
|
||||
# Trust all jbang scripts that a user might install. Without this, Jbang will attempt to
|
||||
# prompt the user to trust each script. However, Goose does not surfact this modal and without
|
||||
# user input, the addExtension method will timeout and fail.
|
||||
jbang --quiet trust add *
|
||||
|
||||
# Final step: Execute jbang with passed arguments, always including --fresh and --quiet
|
||||
log "Executing 'jbang' command with arguments: $*"
|
||||
jbang --fresh --quiet "$@" || log "Failed to execute 'jbang' with arguments: $*"
|
||||
|
||||
log "jbang setup script completed successfully."
|
||||
@@ -1,105 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Enable strict mode to exit on errors and unset variables
|
||||
set -euo pipefail
|
||||
|
||||
# Set log file
|
||||
LOG_FILE="/tmp/mcp.log"
|
||||
|
||||
# Clear the log file at the start
|
||||
> "$LOG_FILE"
|
||||
|
||||
# Function for logging
|
||||
log() {
|
||||
local MESSAGE="$1"
|
||||
echo "$(date +'%Y-%m-%d %H:%M:%S') - $MESSAGE" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
# Trap errors and log them before exiting
|
||||
trap 'log "An error occurred. Exiting with status $?."' ERR
|
||||
|
||||
log "Starting npx setup script."
|
||||
|
||||
# Ensure ~/.config/goose/mcp-hermit/bin exists
|
||||
log "Creating directory ~/.config/goose/mcp-hermit/bin if it does not exist."
|
||||
mkdir -p ~/.config/goose/mcp-hermit/bin
|
||||
|
||||
# Change to the ~/.config/goose/mcp-hermit directory
|
||||
log "Changing to directory ~/.config/goose/mcp-hermit."
|
||||
cd ~/.config/goose/mcp-hermit
|
||||
|
||||
|
||||
# Check if hermit binary exists and download if not
|
||||
if [ ! -f ~/.config/goose/mcp-hermit/bin/hermit ]; then
|
||||
log "Hermit binary not found. Downloading hermit binary."
|
||||
curl -fsSL "https://github.com/cashapp/hermit/releases/download/stable/hermit-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/').gz" \
|
||||
| gzip -dc > ~/.config/goose/mcp-hermit/bin/hermit && chmod +x ~/.config/goose/mcp-hermit/bin/hermit
|
||||
log "Hermit binary downloaded and made executable."
|
||||
else
|
||||
log "Hermit binary already exists. Skipping download."
|
||||
fi
|
||||
|
||||
|
||||
log "setting hermit cache to be local for MCP servers"
|
||||
mkdir -p ~/.config/goose/mcp-hermit/cache
|
||||
export HERMIT_STATE_DIR=~/.config/goose/mcp-hermit/cache
|
||||
|
||||
|
||||
# Update PATH
|
||||
export PATH=~/.config/goose/mcp-hermit/bin:$PATH
|
||||
log "Updated PATH to include ~/.config/goose/mcp-hermit/bin."
|
||||
|
||||
|
||||
# Verify hermit installation
|
||||
log "Checking for hermit in PATH."
|
||||
which hermit >> "$LOG_FILE"
|
||||
|
||||
# Initialize hermit
|
||||
log "Initializing hermit."
|
||||
hermit init >> "$LOG_FILE"
|
||||
|
||||
# Install Node.js using hermit
|
||||
log "Installing Node.js with hermit."
|
||||
hermit install node >> "$LOG_FILE"
|
||||
|
||||
# Verify installations
|
||||
log "Verifying installation locations:"
|
||||
log "hermit: $(which hermit)"
|
||||
log "node: $(which node)"
|
||||
log "npx: $(which npx)"
|
||||
|
||||
|
||||
log "Checking for GOOSE_NPM_REGISTRY and GOOSE_NPM_CERT environment variables for custom npm registry setup..."
|
||||
# Check if GOOSE_NPM_REGISTRY is set and accessible
|
||||
if [ -n "${GOOSE_NPM_REGISTRY:-}" ] && curl -s --head --fail "$GOOSE_NPM_REGISTRY" > /dev/null; then
|
||||
log "Checking custom goose registry availability: $GOOSE_NPM_REGISTRY"
|
||||
log "$GOOSE_NPM_REGISTRY is accessible. Using it for npm registry."
|
||||
export NPM_CONFIG_REGISTRY="$GOOSE_NPM_REGISTRY"
|
||||
|
||||
# Check if GOOSE_NPM_CERT is set and accessible
|
||||
if [ -n "${GOOSE_NPM_CERT:-}" ] && curl -s --head --fail "$GOOSE_NPM_CERT" > /dev/null; then
|
||||
log "Downloading certificate from: $GOOSE_NPM_CERT"
|
||||
curl -sSL -o ~/.config/goose/mcp-hermit/cert.pem "$GOOSE_NPM_CERT"
|
||||
if [ $? -eq 0 ]; then
|
||||
log "Certificate downloaded successfully."
|
||||
export NODE_EXTRA_CA_CERTS=~/.config/goose/mcp-hermit/cert.pem
|
||||
else
|
||||
log "Unable to download the certificate. Skipping certificate setup."
|
||||
fi
|
||||
else
|
||||
log "GOOSE_NPM_CERT is either not set or not accessible. Skipping certificate setup."
|
||||
fi
|
||||
|
||||
else
|
||||
log "GOOSE_NPM_REGISTRY is either not set or not accessible. Falling back to default npm registry."
|
||||
export NPM_CONFIG_REGISTRY="https://registry.npmjs.org/"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
# Final step: Execute npx with passed arguments
|
||||
log "Executing 'npx' command with arguments: $*"
|
||||
npx "$@" || log "Failed to execute 'npx' with arguments: $*"
|
||||
|
||||
log "npx setup script completed successfully."
|
||||
@@ -1,20 +0,0 @@
|
||||
:: Created by npm, please don't edit manually.
|
||||
@ECHO OFF
|
||||
|
||||
SETLOCAL
|
||||
|
||||
SET "NODE_EXE=%~dp0\node.exe"
|
||||
IF NOT EXIST "%NODE_EXE%" (
|
||||
SET "NODE_EXE=node"
|
||||
)
|
||||
|
||||
SET "NPM_PREFIX_JS=%~dp0\node_modules\npm\bin\npm-prefix.js"
|
||||
SET "NPX_CLI_JS=%~dp0\node_modules\npm\bin\npx-cli.js"
|
||||
FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_PREFIX_JS%"') DO (
|
||||
SET "NPM_PREFIX_NPX_CLI_JS=%%F\node_modules\npm\bin\npx-cli.js"
|
||||
)
|
||||
IF EXIST "%NPM_PREFIX_NPX_CLI_JS%" (
|
||||
SET "NPX_CLI_JS=%NPM_PREFIX_NPX_CLI_JS%"
|
||||
)
|
||||
|
||||
"%NODE_EXE%" "%NPX_CLI_JS%" %*
|
||||
@@ -1,89 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Enable strict mode to exit on errors and unset variables
|
||||
set -euo pipefail
|
||||
|
||||
# Set log file
|
||||
LOG_FILE="/tmp/mcp.log"
|
||||
|
||||
# Clear the log file at the start
|
||||
> "$LOG_FILE"
|
||||
|
||||
# Function for logging
|
||||
log() {
|
||||
local MESSAGE="$1"
|
||||
echo "$(date +'%Y-%m-%d %H:%M:%S') - $MESSAGE" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
# Trap errors and log them before exiting
|
||||
trap 'log "An error occurred. Exiting with status $?."' ERR
|
||||
|
||||
log "Starting uvx setup script."
|
||||
|
||||
# Ensure ~/.config/goose/mcp-hermit/bin exists
|
||||
log "Creating directory ~/.config/goose/mcp-hermit/bin if it does not exist."
|
||||
mkdir -p ~/.config/goose/mcp-hermit/bin
|
||||
|
||||
# Change to the ~/.config/goose/mcp-hermit directory
|
||||
log "Changing to directory ~/.config/goose/mcp-hermit."
|
||||
cd ~/.config/goose/mcp-hermit
|
||||
|
||||
# Check if hermit binary exists and download if not
|
||||
if [ ! -f ~/.config/goose/mcp-hermit/bin/hermit ]; then
|
||||
log "Hermit binary not found. Downloading hermit binary."
|
||||
curl -fsSL "https://github.com/cashapp/hermit/releases/download/stable/hermit-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/').gz" \
|
||||
| gzip -dc > ~/.config/goose/mcp-hermit/bin/hermit && chmod +x ~/.config/goose/mcp-hermit/bin/hermit
|
||||
log "Hermit binary downloaded and made executable."
|
||||
else
|
||||
log "Hermit binary already exists. Skipping download."
|
||||
fi
|
||||
|
||||
|
||||
log "setting hermit cache to be local for MCP servers"
|
||||
mkdir -p ~/.config/goose/mcp-hermit/cache
|
||||
export HERMIT_STATE_DIR=~/.config/goose/mcp-hermit/cache
|
||||
|
||||
# Update PATH
|
||||
export PATH=~/.config/goose/mcp-hermit/bin:$PATH
|
||||
log "Updated PATH to include ~/.config/goose/mcp-hermit/bin."
|
||||
|
||||
|
||||
# Verify hermit installation
|
||||
log "Checking for hermit in PATH."
|
||||
which hermit >> "$LOG_FILE"
|
||||
|
||||
# Initialize hermit
|
||||
log "Initializing hermit."
|
||||
hermit init >> "$LOG_FILE"
|
||||
|
||||
# Initialize python >= 3.10
|
||||
log "hermit install python 3.10"
|
||||
hermit install python3@3.10 >> "$LOG_FILE"
|
||||
|
||||
# Install UV for python using hermit
|
||||
log "Installing UV with hermit."
|
||||
hermit install uv >> "$LOG_FILE"
|
||||
|
||||
# Verify installations
|
||||
log "Verifying installation locations:"
|
||||
log "hermit: $(which hermit)"
|
||||
log "uv: $(which uv)"
|
||||
log "uvx: $(which uvx)"
|
||||
|
||||
|
||||
log "Checking for GOOSE_UV_REGISTRY environment variable for custom python/pip/UV registry setup..."
|
||||
# Check if GOOSE_UV_REGISTRY is set and accessible
|
||||
if [ -n "${GOOSE_UV_REGISTRY:-}" ] && curl -s --head --fail "$GOOSE_UV_REGISTRY" > /dev/null; then
|
||||
log "Checking custom goose registry availability: $GOOSE_UV_REGISTRY"
|
||||
log "$GOOSE_UV_REGISTRY is accessible, setting it as UV_INDEX_URL. Setting UV_NATIVE_TLS to true."
|
||||
export UV_INDEX_URL="$GOOSE_UV_REGISTRY"
|
||||
export UV_NATIVE_TLS=true
|
||||
else
|
||||
log "Neither GOOSE_UV_REGISTRY nor UV_INDEX_URL is set. Falling back to default configuration."
|
||||
fi
|
||||
|
||||
# Final step: Execute uvx with passed arguments
|
||||
log "Executing 'uvx' command with arguments: $*"
|
||||
uvx "$@" || log "Failed to execute 'uvx' with arguments: $*"
|
||||
|
||||
log "uvx setup script completed successfully."
|
||||
21
ui/desktop/src/platform/windows/bin/README.md
Normal file
21
ui/desktop/src/platform/windows/bin/README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Windows-Specific Binaries
|
||||
|
||||
This directory contains Windows-specific binaries and scripts that are only included during Windows builds.
|
||||
|
||||
## Components
|
||||
|
||||
### Node.js Installation
|
||||
- `install-node.cmd` - Script to check for and install Node.js if needed
|
||||
- `npx.cmd` - Wrapper script that ensures Node.js is installed and uses system npx
|
||||
|
||||
### Windows Binaries
|
||||
- `*.dll` files - Required Windows dynamic libraries
|
||||
- `*.exe` files - Windows executables
|
||||
|
||||
## Build Process
|
||||
|
||||
These files are generated during the Windows build process by:
|
||||
1. `prepare-windows-npm.sh` - Creates Node.js installation scripts
|
||||
2. `copy-windows-dlls.js` - Copies all Windows-specific files to the output directory
|
||||
|
||||
None of these files should be committed to the repository - they are generated fresh during each Windows build.
|
||||
37
ui/desktop/src/platform/windows/bin/install-node.cmd
Normal file
37
ui/desktop/src/platform/windows/bin/install-node.cmd
Normal file
@@ -0,0 +1,37 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM Check if Node.js is installed in Program Files
|
||||
if exist "C:\Program Files\nodejs\node.exe" (
|
||||
echo Node.js found in Program Files
|
||||
set "NODE_EXE=C:\Program Files\nodejs\node.exe"
|
||||
goto :found
|
||||
)
|
||||
|
||||
REM Check if Node.js is installed in Program Files (x86)
|
||||
if exist "C:\Program Files (x86)\nodejs\node.exe" (
|
||||
echo Node.js found in Program Files (x86)
|
||||
set "NODE_EXE=C:\Program Files (x86)\nodejs\node.exe"
|
||||
goto :found
|
||||
)
|
||||
|
||||
echo Node.js not found in standard locations, installing...
|
||||
|
||||
REM Download Node.js MSI installer
|
||||
powershell -Command "& {[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri '%1' -OutFile '%TEMP%\node-setup.msi'}"
|
||||
|
||||
REM Install Node.js silently
|
||||
msiexec /i "%TEMP%\node-setup.msi" /qn
|
||||
|
||||
REM Wait a bit for installation to complete
|
||||
timeout /t 5 /nobreak
|
||||
|
||||
REM Clean up
|
||||
del "%TEMP%\node-setup.msi"
|
||||
|
||||
REM Set path to installed Node.js
|
||||
set "NODE_EXE=C:\Program Files\nodejs\node.exe"
|
||||
|
||||
:found
|
||||
echo Using Node.js: %NODE_EXE%
|
||||
exit /b 0
|
||||
2
ui/desktop/src/platform/windows/bin/jbang.cmd
Normal file
2
ui/desktop/src/platform/windows/bin/jbang.cmd
Normal file
@@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
"%~dp0\jbang" %*
|
||||
BIN
ui/desktop/src/platform/windows/bin/libgcc_s_seh-1.dll
Executable file
BIN
ui/desktop/src/platform/windows/bin/libgcc_s_seh-1.dll
Executable file
Binary file not shown.
BIN
ui/desktop/src/platform/windows/bin/libstdc++-6.dll
Executable file
BIN
ui/desktop/src/platform/windows/bin/libstdc++-6.dll
Executable file
Binary file not shown.
BIN
ui/desktop/src/platform/windows/bin/libwinpthread-1.dll
Executable file
BIN
ui/desktop/src/platform/windows/bin/libwinpthread-1.dll
Executable file
Binary file not shown.
31
ui/desktop/src/platform/windows/bin/npx.cmd
Normal file
31
ui/desktop/src/platform/windows/bin/npx.cmd
Normal file
@@ -0,0 +1,31 @@
|
||||
@ECHO OFF
|
||||
SETLOCAL EnableDelayedExpansion
|
||||
|
||||
SET "SCRIPT_DIR=%~dp0"
|
||||
|
||||
REM Try to find Node.js in standard locations first
|
||||
if exist "C:\Program Files\nodejs\npx.cmd" (
|
||||
"C:\Program Files\nodejs\npx.cmd" %*
|
||||
exit /b %errorlevel%
|
||||
)
|
||||
|
||||
if exist "C:\Program Files (x86)\nodejs\npx.cmd" (
|
||||
"C:\Program Files (x86)\nodejs\npx.cmd" %*
|
||||
exit /b %errorlevel%
|
||||
)
|
||||
|
||||
REM If Node.js not found, run installer
|
||||
call "%SCRIPT_DIR%install-node.cmd" "https://nodejs.org/dist/v23.10.0/node-v23.10.0-x64.msi"
|
||||
if errorlevel 1 (
|
||||
echo Failed to install Node.js
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Try using the newly installed Node.js
|
||||
if exist "C:\Program Files\nodejs\npx.cmd" (
|
||||
"C:\Program Files\nodejs\npx.cmd" %*
|
||||
exit /b %errorlevel%
|
||||
)
|
||||
|
||||
echo Failed to find npx after Node.js installation
|
||||
exit /b 1
|
||||
@@ -4,18 +4,41 @@ import Electron from 'electron';
|
||||
import log from './logger';
|
||||
|
||||
export const getBinaryPath = (app: Electron.App, binaryName: string): string => {
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
const isPackaged = app.isPackaged;
|
||||
const isWindows = process.platform === 'win32';
|
||||
|
||||
const executableName = isWindows
|
||||
? binaryName === 'npx'
|
||||
? 'npx.cmd'
|
||||
: `${binaryName}.exe`
|
||||
: binaryName;
|
||||
|
||||
const possiblePaths = [];
|
||||
if (isWindows) {
|
||||
addPaths(isWindows, possiblePaths, `${binaryName}.exe`, app);
|
||||
addPaths(isWindows, possiblePaths, `${binaryName}.cmd`, app);
|
||||
} else {
|
||||
addPaths(isWindows, possiblePaths, binaryName, app);
|
||||
}
|
||||
|
||||
for (const binPath of possiblePaths) {
|
||||
try {
|
||||
if (fs.existsSync(binPath)) {
|
||||
return binPath;
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(`Error checking path ${binPath}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Could not find ${binaryName} binary in any of the expected locations: ${possiblePaths.join(
|
||||
', '
|
||||
)}`
|
||||
);
|
||||
};
|
||||
|
||||
const addPaths = (
|
||||
isWindows: boolean,
|
||||
possiblePaths: any[],
|
||||
executableName: string,
|
||||
app: Electron.App
|
||||
): void => {
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
const isPackaged = app.isPackaged;
|
||||
if (isDev && !isPackaged) {
|
||||
possiblePaths.push(
|
||||
path.join(process.cwd(), 'src', 'bin', executableName),
|
||||
@@ -36,18 +59,4 @@ export const getBinaryPath = (app: Electron.App, binaryName: string): string =>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (const binPath of possiblePaths) {
|
||||
try {
|
||||
if (fs.existsSync(binPath)) {
|
||||
return binPath;
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(`Error checking path ${binPath}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Could not find ${binaryName} binary in any of the expected locations: ${possiblePaths.join(', ')}`
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user