chore: initialize qiming workspace repository
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* 从 node_modules 复制 agent-gui-server 到 resources/
|
||||
*
|
||||
* 前提:
|
||||
* 1. pnpm install 已执行(workspace 链接生效)
|
||||
* 2. agent-gui-server 已构建(npm run build)
|
||||
*
|
||||
* 产物:
|
||||
* resources/agent-gui-server/
|
||||
* ├── dist/index.js — esbuild CLI bundle(ESM,原生依赖标记为 external)
|
||||
* ├── dist/lib.bundle.cjs — esbuild SDK bundle(CJS,供 Electron runtime require)
|
||||
* ├── node_modules/ — external 原生依赖(sharp, @nut-tree-fork/*, clipboardy)
|
||||
* └── package.json — 精简版(name/version/main/bin)
|
||||
*
|
||||
* 打包时 electron-builder extraResources 会打包到
|
||||
* .app/Contents/Resources/agent-gui-server/
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const { execSync } = require('child_process');
|
||||
const { getProjectRoot } = require('../utils/project-paths');
|
||||
|
||||
const projectRoot = getProjectRoot();
|
||||
const srcDir = path.join(projectRoot, 'node_modules', 'agent-gui-server');
|
||||
const destDir = path.join(projectRoot, 'resources', 'agent-gui-server');
|
||||
|
||||
// esbuild 中标记为 external 的原生依赖(需要在运行时可用)
|
||||
const NATIVE_EXTERNALS = ['sharp', '@nut-tree-fork/nut-js', 'clipboardy'];
|
||||
|
||||
function main() {
|
||||
// 1. 验证 node_modules 中存在 agent-gui-server
|
||||
if (!fs.existsSync(path.join(srcDir, 'package.json'))) {
|
||||
console.error('[prepare-gui-server] node_modules 中未找到 agent-gui-server');
|
||||
console.error('[prepare-gui-server] 请先执行 pnpm install');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const srcPkg = JSON.parse(fs.readFileSync(path.join(srcDir, 'package.json'), 'utf8'));
|
||||
console.log(`[prepare-gui-server] 源码版本: ${srcPkg.name}@${srcPkg.version}`);
|
||||
|
||||
// 2. 验证必要文件存在
|
||||
const srcIndexJs = path.join(srcDir, 'dist', 'index.js');
|
||||
if (!fs.existsSync(srcIndexJs)) {
|
||||
console.error(`[prepare-gui-server] CLI 入口不存在: ${srcIndexJs}`);
|
||||
console.error('[prepare-gui-server] 请先在 crates/agent-gui-server 中执行 npm run build');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// 3. 检查目标是否已是最新版本
|
||||
const destPkgPath = path.join(destDir, 'package.json');
|
||||
const destLibBundle = path.join(destDir, 'dist', 'lib.bundle.cjs');
|
||||
if (fs.existsSync(destPkgPath) && fs.existsSync(destLibBundle)) {
|
||||
try {
|
||||
const destPkg = JSON.parse(fs.readFileSync(destPkgPath, 'utf8'));
|
||||
if (destPkg.version === srcPkg.version) {
|
||||
const destIndexJs = path.join(destDir, 'dist', 'index.js');
|
||||
if (fs.existsSync(destIndexJs)) {
|
||||
const srcSize = fs.statSync(srcIndexJs).size;
|
||||
const destSize = fs.statSync(destIndexJs).size;
|
||||
if (srcSize === destSize) {
|
||||
console.log(`[prepare-gui-server] ${srcPkg.version} 已是最新,跳过`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// 目标损坏,重新复制
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 清理并创建目标目录
|
||||
console.log('[prepare-gui-server] 复制到 resources/agent-gui-server/...');
|
||||
if (fs.existsSync(destDir)) {
|
||||
fs.rmSync(destDir, { recursive: true });
|
||||
}
|
||||
fs.mkdirSync(path.join(destDir, 'dist'), { recursive: true });
|
||||
|
||||
// 5. 复制 dist/index.js (esbuild CLI bundle)
|
||||
const destIndexJs = path.join(destDir, 'dist', 'index.js');
|
||||
fs.copyFileSync(srcIndexJs, destIndexJs);
|
||||
fs.chmodSync(destIndexJs, 0o755);
|
||||
console.log(` dist/index.js (${(fs.statSync(destIndexJs).size / 1024).toFixed(0)} KB)`);
|
||||
|
||||
// 5b. 复制 dist/lib.bundle.cjs (esbuild CJS SDK bundle, for Electron runtime require)
|
||||
const srcLibBundle = path.join(srcDir, 'dist', 'lib.bundle.cjs');
|
||||
if (fs.existsSync(srcLibBundle)) {
|
||||
fs.copyFileSync(srcLibBundle, destLibBundle);
|
||||
console.log(` dist/lib.bundle.cjs (${(fs.statSync(destLibBundle).size / 1024).toFixed(0)} KB)`);
|
||||
} else {
|
||||
console.warn('[prepare-gui-server] dist/lib.bundle.cjs not found — CJS SDK bundle will be unavailable');
|
||||
}
|
||||
|
||||
// 6. 安装 external 原生依赖到 resources/agent-gui-server/node_modules/
|
||||
// 使用 npm install 确保原生模块为当前平台编译
|
||||
const depsToInstall = [];
|
||||
for (const dep of NATIVE_EXTERNALS) {
|
||||
const ver = srcPkg.dependencies?.[dep];
|
||||
if (ver) {
|
||||
depsToInstall.push(`${dep}@${ver.replace(/^[\^~]/, '')}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (depsToInstall.length > 0) {
|
||||
// 先写一个临时 package.json 让 npm install 工作
|
||||
const tmpPkg = { name: 'agent-gui-server-runtime', version: '0.0.0', private: true };
|
||||
fs.writeFileSync(destPkgPath, JSON.stringify(tmpPkg, null, 2) + '\n');
|
||||
|
||||
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
||||
|
||||
// CI 交叉编译支持:TARGET_ARCH 环境变量指定目标架构(如 macOS arm64 runner 构建 x64 包)
|
||||
// npm install 通过 --cpu 标志安装目标架构的原生模块
|
||||
const targetArch = process.env.TARGET_ARCH;
|
||||
const archFlag = targetArch ? ` --cpu=${targetArch}` : '';
|
||||
const archLabel = targetArch ? ` (target: ${targetArch})` : '';
|
||||
|
||||
console.log(` 安装原生依赖${archLabel}: ${depsToInstall.join(', ')}...`);
|
||||
try {
|
||||
execSync(`${npmCmd} install --no-save${archFlag} ${depsToInstall.join(' ')}`, {
|
||||
cwd: destDir,
|
||||
stdio: 'pipe',
|
||||
});
|
||||
console.log(' node_modules/ (原生依赖安装完成)');
|
||||
} catch (e) {
|
||||
console.error('[prepare-gui-server] 原生依赖安装失败:', e.stderr?.toString() || e.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 7. 生成最终精简版 package.json
|
||||
const slimPkg = {
|
||||
name: srcPkg.name,
|
||||
version: srcPkg.version,
|
||||
type: 'module',
|
||||
main: './dist/lib.bundle.cjs',
|
||||
bin: { 'agent-gui-server': './dist/index.js' },
|
||||
};
|
||||
fs.writeFileSync(destPkgPath, JSON.stringify(slimPkg, null, 2) + '\n');
|
||||
console.log(' package.json (slim)');
|
||||
|
||||
console.log(`[prepare-gui-server] ✓ resources/agent-gui-server/ (${srcPkg.version})`);
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user