chore: initialize qiming workspace repository

This commit is contained in:
Codex
2026-05-29 14:22:48 +08:00
commit bfd67a0f2c
10750 changed files with 1885711 additions and 0 deletions

View File

@@ -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 bundleESM原生依赖标记为 external
* ├── dist/lib.bundle.cjs — esbuild SDK bundleCJS供 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();