fix: harden agent prompt handling

This commit is contained in:
Codex
2026-05-30 13:52:18 +08:00
parent 9eb44acd18
commit 5a858f89b5
12 changed files with 212 additions and 69 deletions

View File

@@ -35,9 +35,30 @@ function exec(cmd, opts = {}) {
execSync(cmd, { stdio: 'inherit', ...opts });
}
function getLocalSourceDir() {
const candidates = [
process.env.CLAUDE_CODE_ACP_TS_SOURCE_DIR,
path.resolve(electronClientRoot, '..', '..', '..', 'claude-code-acp-ts'),
].filter(Boolean);
for (const candidate of candidates) {
if (fs.existsSync(path.join(candidate, 'package.json'))) {
return candidate;
}
}
return null;
}
function main() {
const localSourceDir = getLocalSourceDir();
let sourceDir = SOURCE_DIR;
// 1. 克隆或更新源码
if (!fs.existsSync(path.join(SOURCE_DIR, '.git'))) {
if (localSourceDir) {
sourceDir = localSourceDir;
console.log(`[prepare-claude-code-acp-ts] 使用本地源码: ${sourceDir}`);
} else if (!fs.existsSync(path.join(SOURCE_DIR, '.git'))) {
console.log('[prepare-claude-code-acp-ts] 克隆源码...');
exec(`git clone --branch ${GIT_BRANCH} ${GIT_REPO} "${SOURCE_DIR}"`);
} else {
@@ -46,31 +67,32 @@ function main() {
}
// 2. 检查构建产物是否存在
const hasBuild = fs.existsSync(path.join(SOURCE_DIR, 'dist'));
const hasNodeModules = fs.existsSync(path.join(SOURCE_DIR, 'node_modules'));
const hasBuild = fs.existsSync(path.join(sourceDir, 'dist'));
const hasNodeModules = fs.existsSync(path.join(sourceDir, 'node_modules'));
if (!hasBuild || !hasNodeModules) {
// 清理旧的 node_modules若有
if (fs.existsSync(path.join(SOURCE_DIR, 'node_modules'))) {
const nodeModulesDir = path.join(sourceDir, 'node_modules');
if (fs.existsSync(nodeModulesDir)) {
console.log('[prepare-claude-code-acp-ts] 清理旧的 node_modules...');
exec(`rm -rf "${path.join(SOURCE_DIR, 'node_modules')}"`);
fs.rmSync(nodeModulesDir, { recursive: true, force: true });
}
// 3. 安装依赖
console.log('[prepare-claude-code-acp-ts] 安装依赖...');
exec(`cd "${SOURCE_DIR}" && npm install --ignore-scripts`);
exec('npm install --ignore-scripts', { cwd: sourceDir });
// 4. 构建
// 注意:不用 npm run build因为其 build 脚本可能是 ./node_modules/.bin/tscUnix 风格Windows 不认识
//改用 npx tsc 替代,可跨平台
console.log('[prepare-claude-code-acp-ts] 构建项目...');
exec(`cd "${SOURCE_DIR}" && npx tsc`);
exec('npx tsc', { cwd: sourceDir });
} else {
console.log('[prepare-claude-code-acp-ts] 构建产物已就绪,跳过构建');
}
// 5. 读取版本
const srcPkg = JSON.parse(fs.readFileSync(path.join(SOURCE_DIR, 'package.json'), 'utf8'));
const srcPkg = JSON.parse(fs.readFileSync(path.join(sourceDir, 'package.json'), 'utf8'));
console.log(`[prepare-claude-code-acp-ts] 源码版本: ${srcPkg.name}@${srcPkg.version}`);
// 6. 清理并创建目标目录
@@ -81,20 +103,20 @@ function main() {
// 7. 复制 dist/
console.log('[prepare-claude-code-acp-ts] 复制 dist/...');
exec(`cp -R "${path.join(SOURCE_DIR, 'dist')}" "${destDir}/"`);
fs.cpSync(path.join(sourceDir, 'dist'), path.join(destDir, 'dist'), { recursive: true });
// 8. 复制 package.json
fs.copyFileSync(
path.join(SOURCE_DIR, 'package.json'),
path.join(sourceDir, 'package.json'),
path.join(destDir, 'package.json')
);
// 9. 复制 node_modules/
console.log('[prepare-claude-code-acp-ts] 复制 node_modules/...');
exec(`cp -R "${path.join(SOURCE_DIR, 'node_modules')}" "${destDir}/"`);
fs.cpSync(path.join(sourceDir, 'node_modules'), path.join(destDir, 'node_modules'), { recursive: true });
// 10. 复制 LICENSE
const licenseSrc = path.join(SOURCE_DIR, 'LICENSE');
const licenseSrc = path.join(sourceDir, 'LICENSE');
if (fs.existsSync(licenseSrc)) {
fs.copyFileSync(licenseSrc, path.join(destDir, 'LICENSE'));
}

View File

@@ -35,9 +35,30 @@ function exec(cmd, opts = {}) {
execSync(cmd, { stdio: 'inherit', ...opts });
}
function getLocalSourceDir() {
const candidates = [
process.env.QIMING_FILE_SERVER_SOURCE_DIR,
path.resolve(electronClientRoot, '..', '..', '..', 'qiming-file-server'),
].filter(Boolean);
for (const candidate of candidates) {
if (fs.existsSync(path.join(candidate, 'package.json'))) {
return candidate;
}
}
return null;
}
function main() {
const localSourceDir = getLocalSourceDir();
let sourceDir = SOURCE_DIR;
// 1. 克隆或更新源码
if (!fs.existsSync(path.join(SOURCE_DIR, '.git'))) {
if (localSourceDir) {
sourceDir = localSourceDir;
console.log(`[prepare-qiming-file-server] 使用本地源码: ${sourceDir}`);
} else if (!fs.existsSync(path.join(SOURCE_DIR, '.git'))) {
console.log('[prepare-qiming-file-server] 克隆源码...');
exec(`git clone --branch ${GIT_BRANCH} ${GIT_REPO} "${SOURCE_DIR}"`);
} else {
@@ -46,29 +67,30 @@ function main() {
}
// 2. 检查构建产物是否存在
const hasBuild = fs.existsSync(path.join(SOURCE_DIR, 'dist'));
const hasNodeModules = fs.existsSync(path.join(SOURCE_DIR, 'node_modules'));
const hasBuild = fs.existsSync(path.join(sourceDir, 'dist'));
const hasNodeModules = fs.existsSync(path.join(sourceDir, 'node_modules'));
if (!hasBuild || !hasNodeModules) {
// 清理旧的 node_modules若有
if (fs.existsSync(path.join(SOURCE_DIR, 'node_modules'))) {
const nodeModulesDir = path.join(sourceDir, 'node_modules');
if (fs.existsSync(nodeModulesDir)) {
console.log('[prepare-qiming-file-server] 清理旧的 node_modules...');
exec(`rm -rf "${path.join(SOURCE_DIR, 'node_modules')}"`);
fs.rmSync(nodeModulesDir, { recursive: true, force: true });
}
// 3. 安装依赖
console.log('[prepare-qiming-file-server] 安装依赖...');
exec(`cd "${SOURCE_DIR}" && npm install --ignore-scripts`);
exec('npm install --ignore-scripts', { cwd: sourceDir });
// 4. 构建
console.log('[prepare-qiming-file-server] 构建项目...');
exec(`cd "${SOURCE_DIR}" && npm run build`);
exec('npm run build', { cwd: sourceDir });
} else {
console.log('[prepare-qiming-file-server] 构建产物已就绪,跳过构建');
}
// 5. 读取版本
const srcPkg = JSON.parse(fs.readFileSync(path.join(SOURCE_DIR, 'package.json'), 'utf8'));
const srcPkg = JSON.parse(fs.readFileSync(path.join(sourceDir, 'package.json'), 'utf8'));
console.log(`[prepare-qiming-file-server] 源码版本: ${srcPkg.name}@${srcPkg.version}`);
// 6. 清理并创建目标目录
@@ -79,20 +101,20 @@ function main() {
// 7. 复制 dist/
console.log('[prepare-qiming-file-server] 复制 dist/...');
exec(`cp -R "${path.join(SOURCE_DIR, 'dist')}" "${destDir}/"`);
fs.cpSync(path.join(sourceDir, 'dist'), path.join(destDir, 'dist'), { recursive: true });
// 8. 复制 package.json
fs.copyFileSync(
path.join(SOURCE_DIR, 'package.json'),
path.join(sourceDir, 'package.json'),
path.join(destDir, 'package.json')
);
// 9. 复制 node_modules/
console.log('[prepare-qiming-file-server] 复制 node_modules/...');
exec(`cp -R "${path.join(SOURCE_DIR, 'node_modules')}" "${destDir}/"`);
fs.cpSync(path.join(sourceDir, 'node_modules'), path.join(destDir, 'node_modules'), { recursive: true });
// 10. 复制 LICENSE
const licenseSrc = path.join(SOURCE_DIR, 'LICENSE');
const licenseSrc = path.join(sourceDir, 'LICENSE');
if (fs.existsSync(licenseSrc)) {
fs.copyFileSync(licenseSrc, path.join(destDir, 'LICENSE'));
}

View File

@@ -28,7 +28,7 @@ const { URL } = require('url');
const { execSync, execFileSync } = require('child_process');
const { getProjectRoot } = require('../utils/project-paths');
const QIMINGCODE_VERSION = '1.1.97';
const QIMINGCODE_VERSION = '1.2.1';
const QIMINGCODE_REPO = process.env.QIMINGCODE_REPO || 'qiming-ai/qimingcode';
const projectRoot = getProjectRoot();
@@ -140,10 +140,7 @@ const FORCE_REFRESH_ON_MATCH = true;
// ==================== 模式 1: 本地 dist 复制 ====================
function copyFromDist(key) {
const qimingcodeDist = process.env.QIMINGCODE_DIST_DIR || path.join(
process.env.HOME || '/root',
'workspace/qimingcode/packages/opencode/dist',
);
const qimingcodeDist = getLocalDistDir();
const distName = PLATFORM_MAP[key];
if (!distName) {
console.error(`[prepare-qimingcode] 不支持的平台: ${key}`);
@@ -152,12 +149,19 @@ function copyFromDist(key) {
const resourceKey = getResourcePlatformKey(key);
const binary = getBinaryName(key);
const srcPath = path.join(qimingcodeDist, distName, 'bin', binary);
const destDir = path.join(resDir, resourceKey, 'bin');
const destPath = path.join(destDir, binary);
const srcBinDir = path.join(qimingcodeDist, distName, 'bin');
const srcBinary = getBinaryCandidates(key)
.map((candidate) => path.join(srcBinDir, candidate))
.find((candidatePath) => fs.existsSync(candidatePath));
if (!fs.existsSync(srcPath)) {
console.warn(`[prepare-qimingcode] ${key}: 构建产物不存在 ${srcPath}`);
if (!srcBinary) {
console.warn(
`[prepare-qimingcode] ${key}: 构建产物不存在,已检查 ${getBinaryCandidates(key)
.map((candidate) => path.join(srcBinDir, candidate))
.join(', ')}`,
);
return false;
}
@@ -195,8 +199,11 @@ function copyFromDist(key) {
resetDestBinDir(destDir);
// 复制整个 bin 目录(包含二进制 + assets 等)
const srcBinDir = path.join(qimingcodeDist, distName, 'bin');
fs.cpSync(srcBinDir, destDir, { recursive: true });
const copiedBinaryPath = path.join(destDir, path.basename(srcBinary));
if (copiedBinaryPath !== destPath) {
fs.renameSync(copiedBinaryPath, destPath);
}
ensureModelJson(destDir, QIMINGCODE_VERSION);
fs.chmodSync(destPath, 0o755);
@@ -218,6 +225,16 @@ function copyFromDist(key) {
return true;
}
function getLocalDistDir() {
const candidates = [
process.env.QIMINGCODE_DIST_DIR,
path.resolve(projectRoot, '..', '..', '..', 'qimingcode', 'packages', 'opencode', 'dist'),
path.join(process.env.HOME || '/root', 'workspace/qimingcode/packages/opencode/dist'),
].filter(Boolean);
return candidates.find((candidate) => fs.existsSync(candidate)) || candidates[0];
}
// ==================== 模式 2: GitHub Release 下载 ====================
/**
@@ -577,7 +594,7 @@ function codesign(binaryPath, key) {
async function main() {
const allPlatforms = process.argv.includes('--all') || process.argv.includes('--all-platforms');
const useLocalDist = !!process.env.QIMINGCODE_DIST_DIR;
const useLocalDist = !!process.env.QIMINGCODE_DIST_DIR || fs.existsSync(getLocalDistDir());
const mode = useLocalDist ? '本地 dist 复制' : 'GitHub Release 下载';
fs.mkdirSync(resDir, { recursive: true });