diff --git a/package.json b/package.json index afd9cbc6f7..25ed3d5ca9 100644 --- a/package.json +++ b/package.json @@ -483,6 +483,25 @@ ] }, "optionalDependencies": { - "@strongtz/win32-arm64-msvc": "^0.4.7" + "@img/sharp-darwin-arm64": "0.34.3", + "@img/sharp-darwin-x64": "0.34.3", + "@img/sharp-libvips-darwin-arm64": "1.2.0", + "@img/sharp-libvips-darwin-x64": "1.2.0", + "@img/sharp-libvips-linux-arm64": "1.2.0", + "@img/sharp-libvips-linux-x64": "1.2.0", + "@img/sharp-linux-arm64": "0.34.3", + "@img/sharp-linux-x64": "0.34.3", + "@img/sharp-win32-arm64": "0.34.3", + "@img/sharp-win32-x64": "0.34.3", + "@libsql/darwin-arm64": "0.4.7", + "@libsql/darwin-x64": "0.4.7", + "@libsql/linux-arm64-gnu": "0.4.7", + "@libsql/linux-x64-gnu": "0.4.7", + "@libsql/win32-x64-msvc": "0.4.7", + "@napi-rs/system-ocr-darwin-arm64": "1.0.2", + "@napi-rs/system-ocr-darwin-x64": "1.0.2", + "@napi-rs/system-ocr-win32-arm64-msvc": "1.0.2", + "@napi-rs/system-ocr-win32-x64-msvc": "1.0.2", + "@strongtz/win32-arm64-msvc": "0.4.7" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2f0a16951c..08bba96fef 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1118,8 +1118,65 @@ importers: specifier: ^4.1.5 version: 4.3.4 optionalDependencies: + '@img/sharp-darwin-arm64': + specifier: 0.34.3 + version: 0.34.3 + '@img/sharp-darwin-x64': + specifier: 0.34.3 + version: 0.34.3 + '@img/sharp-libvips-darwin-arm64': + specifier: 1.2.0 + version: 1.2.0 + '@img/sharp-libvips-darwin-x64': + specifier: 1.2.0 + version: 1.2.0 + '@img/sharp-libvips-linux-arm64': + specifier: 1.2.0 + version: 1.2.0 + '@img/sharp-libvips-linux-x64': + specifier: 1.2.0 + version: 1.2.0 + '@img/sharp-linux-arm64': + specifier: 0.34.3 + version: 0.34.3 + '@img/sharp-linux-x64': + specifier: 0.34.3 + version: 0.34.3 + '@img/sharp-win32-arm64': + specifier: 0.34.3 + version: 0.34.3 + '@img/sharp-win32-x64': + specifier: 0.34.3 + version: 0.34.3 + '@libsql/darwin-arm64': + specifier: 0.4.7 + version: 0.4.7 + '@libsql/darwin-x64': + specifier: 0.4.7 + version: 0.4.7 + '@libsql/linux-arm64-gnu': + specifier: 0.4.7 + version: 0.4.7 + '@libsql/linux-x64-gnu': + specifier: 0.4.7 + version: 0.4.7 + '@libsql/win32-x64-msvc': + specifier: 0.4.7 + version: 0.4.7 + '@napi-rs/system-ocr-darwin-arm64': + specifier: 1.0.2 + version: 1.0.2 + '@napi-rs/system-ocr-darwin-x64': + specifier: 1.0.2 + version: 1.0.2 + '@napi-rs/system-ocr-win32-arm64-msvc': + specifier: 1.0.2 + version: 1.0.2 + '@napi-rs/system-ocr-win32-x64-msvc': + specifier: 1.0.2 + version: 1.0.2 '@strongtz/win32-arm64-msvc': - specifier: ^0.4.7 + specifier: 0.4.7 version: 0.4.7 packages/ai-sdk-provider: @@ -17668,11 +17725,11 @@ snapshots: - utf-8-validate - vite - '@vitest/browser@3.2.4(msw@2.12.7(@types/node@24.10.4)(typescript@5.8.3))(playwright@1.57.0)(rolldown-vite@7.3.0(@types/node@22.17.2)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@3.2.4)': + '@vitest/browser@3.2.4(msw@2.12.7(@types/node@24.10.4)(typescript@5.8.3))(playwright@1.57.0)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@3.2.4)': dependencies: '@testing-library/dom': 10.4.1 '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) - '@vitest/mocker': 3.2.4(msw@2.12.7(@types/node@24.10.4)(typescript@5.8.3))(rolldown-vite@7.3.0(@types/node@22.17.2)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/mocker': 3.2.4(msw@2.12.7(@types/node@24.10.4)(typescript@5.8.3))(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/utils': 3.2.4 magic-string: 0.30.21 sirv: 3.0.2 @@ -17726,14 +17783,14 @@ snapshots: msw: 2.12.7(@types/node@22.17.2)(typescript@5.8.3) vite: rolldown-vite@7.3.0(@types/node@22.17.2)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2) - '@vitest/mocker@3.2.4(msw@2.12.7(@types/node@24.10.4)(typescript@5.8.3))(rolldown-vite@7.3.0(@types/node@22.17.2)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/mocker@3.2.4(msw@2.12.7(@types/node@24.10.4)(typescript@5.8.3))(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.12.7(@types/node@24.10.4)(typescript@5.8.3) - vite: rolldown-vite@7.3.0(@types/node@22.17.2)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2) + vite: rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2) '@vitest/pretty-format@3.2.4': dependencies: @@ -17764,7 +17821,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.15 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.17.2)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(esbuild@0.25.12)(jiti@2.6.1)(jsdom@26.1.0)(msw@2.12.7(@types/node@22.17.2)(typescript@5.8.3))(tsx@4.21.0)(yaml@2.8.2) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(esbuild@0.25.12)(jiti@2.6.1)(jsdom@26.1.0)(msw@2.12.7(@types/node@24.10.4)(typescript@5.8.3))(tsx@4.21.0)(yaml@2.8.2) '@vitest/utils@3.2.4': dependencies: @@ -25219,7 +25276,7 @@ snapshots: dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(msw@2.12.7(@types/node@24.10.4)(typescript@5.8.3))(rolldown-vite@7.3.0(@types/node@22.17.2)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/mocker': 3.2.4(msw@2.12.7(@types/node@24.10.4)(typescript@5.8.3))(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -25243,7 +25300,7 @@ snapshots: optionalDependencies: '@types/debug': 4.1.12 '@types/node': 24.10.4 - '@vitest/browser': 3.2.4(msw@2.12.7(@types/node@24.10.4)(typescript@5.8.3))(playwright@1.57.0)(rolldown-vite@7.3.0(@types/node@22.17.2)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@3.2.4) + '@vitest/browser': 3.2.4(msw@2.12.7(@types/node@24.10.4)(typescript@5.8.3))(playwright@1.57.0)(rolldown-vite@7.3.0(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@3.2.4) '@vitest/ui': 3.2.4(vitest@3.2.4) jsdom: 26.1.0 transitivePeerDependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 18ec407efc..486c912434 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,8 @@ packages: - 'packages/*' + +supportedArchitectures: + os: + - current + cpu: + - current diff --git a/scripts/before-pack.js b/scripts/before-pack.js index eae16a09b3..9a5abf743f 100644 --- a/scripts/before-pack.js +++ b/scripts/before-pack.js @@ -1,42 +1,35 @@ const { Arch } = require('electron-builder') -const { downloadNpmPackage } = require('./utils') +const { execSync } = require('child_process') +const fs = require('fs') +const path = require('path') +const yaml = require('js-yaml') + +const workspaceConfigPath = path.join(__dirname, '..', 'pnpm-workspace.yaml') // if you want to add new prebuild binaries packages with different architectures, you can add them here // please add to allX64 and allArm64 from pnpm-lock.yaml -const allArm64 = { - '@img/sharp-darwin-arm64': '0.34.3', - '@img/sharp-win32-arm64': '0.34.3', - '@img/sharp-linux-arm64': '0.34.3', - - '@img/sharp-libvips-darwin-arm64': '1.2.4', - '@img/sharp-libvips-linux-arm64': '1.2.4', - - '@libsql/darwin-arm64': '0.4.7', - '@libsql/linux-arm64-gnu': '0.4.7', - '@strongtz/win32-arm64-msvc': '0.4.7', - - '@napi-rs/system-ocr-darwin-arm64': '1.0.2', - '@napi-rs/system-ocr-win32-arm64-msvc': '1.0.2' -} - -const allX64 = { - '@img/sharp-darwin-x64': '0.34.3', - '@img/sharp-linux-x64': '0.34.3', - '@img/sharp-win32-x64': '0.34.3', - - '@img/sharp-libvips-darwin-x64': '1.2.4', - '@img/sharp-libvips-linux-x64': '1.2.4', - - '@libsql/darwin-x64': '0.4.7', - '@libsql/linux-x64-gnu': '0.4.7', - '@libsql/win32-x64-msvc': '0.4.7', - - '@napi-rs/system-ocr-darwin-x64': '1.0.2', - '@napi-rs/system-ocr-win32-x64-msvc': '1.0.2' -} - -const claudeCodeVenderPath = '@anthropic-ai/claude-agent-sdk/vendor' -const claudeCodeVenders = ['arm64-darwin', 'arm64-linux', 'x64-darwin', 'x64-linux', 'x64-win32'] +const packages = [ + '@img/sharp-darwin-arm64', + '@img/sharp-darwin-x64', + '@img/sharp-linux-arm64', + '@img/sharp-linux-x64', + '@img/sharp-win32-arm64', + '@img/sharp-win32-x64', + '@img/sharp-libvips-darwin-arm64', + '@img/sharp-libvips-darwin-x64', + '@img/sharp-libvips-linux-arm64', + '@img/sharp-libvips-linux-x64', + '@libsql/darwin-arm64', + '@libsql/darwin-x64', + '@libsql/linux-arm64-gnu', + '@libsql/linux-x64-gnu', + '@libsql/win32-x64-msvc', + '@napi-rs/system-ocr-darwin-arm64', + '@napi-rs/system-ocr-darwin-x64', + '@napi-rs/system-ocr-win32-arm64-msvc', + '@napi-rs/system-ocr-win32-x64-msvc', + '@strongtz/win32-arm64-msvc' +] const platformToArch = { mac: 'darwin', @@ -45,68 +38,82 @@ const platformToArch = { } exports.default = async function (context) { - const arch = context.arch - const archType = arch === Arch.arm64 ? 'arm64' : 'x64' - const platform = context.packager.platform.name + const arch = context.arch === Arch.arm64 ? 'arm64' : 'x64' + const platformName = context.packager.platform.name + const platform = platformToArch[platformName] - const downloadPackages = async (packages) => { - console.log('downloading packages ......') - const downloadPromises = [] - - for (const name of Object.keys(packages)) { - if (name.includes(`${platformToArch[platform]}`) && name.includes(`-${archType}`)) { - downloadPromises.push( - downloadNpmPackage( - name, - `https://registry.npmjs.org/${name}/-/${name.split('/').pop()}-${packages[name]}.tgz` - ) - ) - } + const downloadPackages = async () => { + // Skip if target platform and architecture match current system + if (platform === process.platform && arch === process.arch) { + console.log(`Skipping install: target (${platform}/${arch}) matches current system`) + return } - await Promise.all(downloadPromises) + console.log(`Installing packages for target platform=${platform} arch=${arch}...`) + + // Backup and modify pnpm-workspace.yaml to add target platform support + const originalWorkspaceConfig = fs.readFileSync(workspaceConfigPath, 'utf-8') + const workspaceConfig = yaml.load(originalWorkspaceConfig) + + // Add target platform to supportedArchitectures.os + if (!workspaceConfig.supportedArchitectures.os.includes(platform)) { + workspaceConfig.supportedArchitectures.os.push(platform) + } + + // Add target architecture to supportedArchitectures.cpu + if (!workspaceConfig.supportedArchitectures.cpu.includes(arch)) { + workspaceConfig.supportedArchitectures.cpu.push(arch) + } + + const modifiedWorkspaceConfig = yaml.dump(workspaceConfig) + console.log('Modified workspace config:', modifiedWorkspaceConfig) + fs.writeFileSync(workspaceConfigPath, modifiedWorkspaceConfig) + + try { + execSync(`pnpm install`, { stdio: 'inherit' }) + } finally { + // Restore original pnpm-workspace.yaml + fs.writeFileSync(workspaceConfigPath, originalWorkspaceConfig) + } } - const changeFilters = async (filtersToExclude, filtersToInclude) => { - // remove filters for the target architecture (allow inclusion) - let filters = context.packager.config.files[0].filter - filters = filters.filter((filter) => !filtersToInclude.includes(filter)) + await downloadPackages() + + const excludePackages = async (packagesToExclude) => { + // 从项目根目录的 electron-builder.yml 读取 files 配置,避免多次覆盖配置导致出错 + const electronBuilderConfigPath = path.join(__dirname, '..', 'electron-builder.yml') + const electronBuilderConfig = yaml.load(fs.readFileSync(electronBuilderConfigPath, 'utf-8')) + let filters = electronBuilderConfig.files // add filters for other architectures (exclude them) - filters.push(...filtersToExclude) + filters.push(...packagesToExclude) context.packager.config.files[0].filter = filters } - await downloadPackages(arch === Arch.arm64 ? allArm64 : allX64) + const arm64KeepPackages = packages.filter((p) => p.includes('arm64') && p.includes(platform)) + const arm64ExcludePackages = packages + .filter((p) => !arm64KeepPackages.includes(p)) + .map((p) => '!node_modules/' + p + '/**') - const arm64Filters = Object.keys(allArm64).map((f) => '!node_modules/' + f + '/**') - const x64Filters = Object.keys(allX64).map((f) => '!node_modules/' + f + '/*') + const x64KeepPackages = packages.filter((p) => p.includes('x64') && p.includes(platform)) + const x64ExcludePackages = packages + .filter((p) => !x64KeepPackages.includes(p)) + .map((p) => '!node_modules/' + p + '/**') - // Determine which claudeCodeVenders to include - // For Windows ARM64, also include x64-win32 for compatibility - const includedClaudeCodeVenders = [`${archType}-${platformToArch[platform]}`] - if (platform === 'windows' && arch === Arch.arm64) { - includedClaudeCodeVenders.push('x64-win32') - } + const excludeRipgrepFilters = ['arm64-darwin', 'arm64-linux', 'x64-darwin', 'x64-linux', 'x64-win32'] + .filter((f) => { + // On Windows ARM64, also keep x64-win32 for emulation compatibility + if (platform === 'win32' && context.arch === Arch.arm64 && f === 'x64-win32') { + return false + } + return f !== `${arch}-${platform}` + }) + .map((f) => '!node_modules/@anthropic-ai/claude-agent-sdk/vendor/ripgrep/' + f + '/**') - const excludeClaudeCodeRipgrepFilters = claudeCodeVenders - .filter((f) => !includedClaudeCodeVenders.includes(f)) - .map((f) => '!node_modules/' + claudeCodeVenderPath + '/ripgrep/' + f + '/**') - - const includeClaudeCodeFilters = includedClaudeCodeVenders.map( - (f) => '!node_modules/' + claudeCodeVenderPath + '/ripgrep/' + f + '/**' - ) - - if (arch === Arch.arm64) { - await changeFilters( - [...x64Filters, ...excludeClaudeCodeRipgrepFilters], - [...arm64Filters, ...includeClaudeCodeFilters] - ) + if (context.arch === Arch.arm64) { + await excludePackages([...arm64ExcludePackages, ...excludeRipgrepFilters]) } else { - await changeFilters( - [...arm64Filters, ...excludeClaudeCodeRipgrepFilters], - [...x64Filters, ...includeClaudeCodeFilters] - ) + await excludePackages([...x64ExcludePackages, ...excludeRipgrepFilters]) } } diff --git a/scripts/utils.js b/scripts/utils.js deleted file mode 100644 index cafa07b681..0000000000 --- a/scripts/utils.js +++ /dev/null @@ -1,64 +0,0 @@ -const fs = require('fs') -const path = require('path') -const os = require('os') -const zlib = require('zlib') -const tar = require('tar') -const { pipeline } = require('stream/promises') - -async function downloadNpmPackage(packageName, url) { - const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'npm-download-')) - const targetDir = path.join('./node_modules/', packageName) - const filename = path.join(tempDir, packageName.replace('/', '-') + '.tgz') - const extractDir = path.join(tempDir, 'extract') - - // Skip if directory already exists - if (fs.existsSync(targetDir)) { - console.log(`${targetDir} already exists, skipping download...`) - return - } - - try { - console.log(`Downloading ${packageName}...`, url) - - // Download file using fetch API - const response = await fetch(url) - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`) - } - - const fileStream = fs.createWriteStream(filename) - await pipeline(response.body, fileStream) - - console.log(`Extracting ${filename}...`) - - // Create extraction directory - fs.mkdirSync(extractDir, { recursive: true }) - - // Extract tar.gz file using Node.js streams - await pipeline(fs.createReadStream(filename), zlib.createGunzip(), tar.extract({ cwd: extractDir })) - - // Remove the downloaded file - fs.rmSync(filename, { force: true }) - - // Create target directory - fs.mkdirSync(targetDir, { recursive: true }) - - // Move extracted package contents to target directory - const packageDir = path.join(extractDir, 'package') - if (fs.existsSync(packageDir)) { - fs.cpSync(packageDir, targetDir, { recursive: true }) - } - } catch (error) { - console.error(`Error processing ${packageName}: ${error.message}`) - throw error - } finally { - // Clean up temp directory - if (fs.existsSync(tempDir)) { - fs.rmSync(tempDir, { recursive: true, force: true }) - } - } -} - -module.exports = { - downloadNpmPackage -}