@sciagent/cli 1.0.52 → 1.0.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/sciagent.js +15 -5
- package/package.json +3 -3
- package/scripts/postinstall.js +150 -68
package/bin/sciagent.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
const { spawn } = require('child_process');
|
|
9
9
|
const path = require('path');
|
|
10
10
|
const fs = require('fs');
|
|
11
|
+
const os = require('os');
|
|
11
12
|
|
|
12
13
|
// 平台和架构映射
|
|
13
14
|
const PLATFORM_MAP = {
|
|
@@ -47,6 +48,15 @@ function getBinaryPath() {
|
|
|
47
48
|
// 尝试从node_modules中查找
|
|
48
49
|
const binName = platform === 'win32' ? 'sciagent.exe' : 'sciagent';
|
|
49
50
|
|
|
51
|
+
// 方法0: 从 ~/.sciagent/bin/ 或 %LOCALAPPDATA%\sciagent\bin 查找(postinstall下载位置)
|
|
52
|
+
const homeBinDir = platform === 'win32'
|
|
53
|
+
? path.join(process.env.LOCALAPPDATA || os.homedir(), 'sciagent', 'bin')
|
|
54
|
+
: path.join(os.homedir(), '.sciagent', 'bin');
|
|
55
|
+
const homeBinPath = path.join(homeBinDir, binName);
|
|
56
|
+
if (fs.existsSync(homeBinPath)) {
|
|
57
|
+
return homeBinPath;
|
|
58
|
+
}
|
|
59
|
+
|
|
50
60
|
// 方法1: 从optionalDependencies安装的包中查找
|
|
51
61
|
try {
|
|
52
62
|
const packagePath = require.resolve(`${packageName}/bin/${binName}`);
|
|
@@ -69,12 +79,12 @@ function getBinaryPath() {
|
|
|
69
79
|
|
|
70
80
|
// 未找到二进制文件
|
|
71
81
|
console.error(`Error: Could not find SciAgent binary for ${platform}-${arch}`);
|
|
72
|
-
console.error(`Tried
|
|
73
|
-
console.error(
|
|
74
|
-
console.error(
|
|
75
|
-
console.error(`
|
|
82
|
+
console.error(`Tried locations:`);
|
|
83
|
+
console.error(` ${homeBinPath}`);
|
|
84
|
+
console.error(` ${packageName}/bin/${binName} (npm package)`);
|
|
85
|
+
console.error(` ${localPath} (dev mode)`);
|
|
76
86
|
console.error('');
|
|
77
|
-
console.error('
|
|
87
|
+
console.error('Please reinstall:');
|
|
78
88
|
console.error(' npm install -g @sciagent/cli');
|
|
79
89
|
process.exit(1);
|
|
80
90
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sciagent/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.54",
|
|
4
4
|
"description": "SciAgent CLI - AI Research Assistant",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
"postinstall": "node scripts/postinstall.js"
|
|
16
16
|
},
|
|
17
17
|
"optionalDependencies": {
|
|
18
|
-
"@sciagent/cli-linux-x64": "1.0.
|
|
18
|
+
"@sciagent/cli-linux-x64": "1.0.54",
|
|
19
19
|
"@sciagent/cli-linux-arm64": "1.0.39",
|
|
20
20
|
"@sciagent/cli-darwin-x64": "1.0.39",
|
|
21
21
|
"@sciagent/cli-darwin-arm64": "1.0.39",
|
|
22
|
-
"@sciagent/cli-win32-x64": "1.0.
|
|
22
|
+
"@sciagent/cli-win32-x64": "1.0.54",
|
|
23
23
|
"@sciagent/cli-win32-arm64": "1.0.39"
|
|
24
24
|
},
|
|
25
25
|
"keywords": [
|
package/scripts/postinstall.js
CHANGED
|
@@ -27,7 +27,7 @@ const ARCH_MAP = {
|
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
// 当前版本号 - 每次发布时同步更新
|
|
30
|
-
const CURRENT_VERSION = '1.0.
|
|
30
|
+
const CURRENT_VERSION = '1.0.54';
|
|
31
31
|
|
|
32
32
|
// GitHub Releases 回退版本列表(当当前版本的 release 不存在时尝试)
|
|
33
33
|
const GITHUB_FALLBACK_VERSIONS = ['1.0.50', '1.0.48', '1.0.46', '1.0.40', '1.0.38', '1.0.36'];
|
|
@@ -79,10 +79,38 @@ function getCodebuddyBinDir() {
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
function getHomeBinDir() {
|
|
83
|
+
return process.platform === 'win32'
|
|
84
|
+
? path.join(process.env.LOCALAPPDATA || os.homedir(), 'sciagent', 'bin')
|
|
85
|
+
: path.join(os.homedir(), '.sciagent', 'bin');
|
|
86
|
+
}
|
|
87
|
+
|
|
82
88
|
function checkBinaryInstalled(platform, arch) {
|
|
83
89
|
const packageName = `@sciagent/cli-${platform}-${arch}`;
|
|
84
90
|
const binName = platform === 'win32' ? 'sciagent.exe' : 'sciagent';
|
|
91
|
+
const homeBinDir = getHomeBinDir();
|
|
92
|
+
const homeBinPath = path.join(homeBinDir, binName);
|
|
93
|
+
|
|
94
|
+
// 检查 ~/.sciagent/bin/ 或 %LOCALAPPDATA%\sciagent\bin
|
|
95
|
+
if (fs.existsSync(homeBinPath)) {
|
|
96
|
+
const stats = fs.statSync(homeBinPath);
|
|
97
|
+
if (stats.size > 10 * 1024 * 1024) {
|
|
98
|
+
// 检查版本文件,版本不匹配则视为未安装(需要重新下载)
|
|
99
|
+
const versionFile = path.join(homeBinDir, '.version');
|
|
100
|
+
if (fs.existsSync(versionFile)) {
|
|
101
|
+
const installedVersion = fs.readFileSync(versionFile, 'utf8').trim();
|
|
102
|
+
if (installedVersion === CURRENT_VERSION) {
|
|
103
|
+
return { installed: true, path: homeBinPath };
|
|
104
|
+
} else {
|
|
105
|
+
console.log(` ℹ️ 已安装版本 ${installedVersion} != 目标版本 ${CURRENT_VERSION},需要更新`);
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
console.log(` ℹ️ 二进制版本未知,需要重新下载`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
85
112
|
|
|
113
|
+
// 检查 npm 包路径
|
|
86
114
|
try {
|
|
87
115
|
const packagePath = require.resolve(`${packageName}/bin/${binName}`);
|
|
88
116
|
return { installed: true, path: packagePath };
|
|
@@ -272,42 +300,34 @@ async function installCodebuddySdk() {
|
|
|
272
300
|
const platformKey = `${platform}-${arch}`;
|
|
273
301
|
const platformTag = PYPI_PLATFORM_MAP[platformKey];
|
|
274
302
|
|
|
275
|
-
if (!platformTag) {
|
|
276
|
-
console.log(`⚠️ 不支持的平台: ${platformKey},跳过 CodeBuddy SDK 安装`);
|
|
277
|
-
return false;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
303
|
console.log('');
|
|
281
304
|
console.log('📦 正在安装 CodeBuddy SDK...');
|
|
282
305
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
// 使用 Python 解压 wheel 文件
|
|
310
|
-
const extractScript = `
|
|
306
|
+
// 策略1: 从 PyPI 下载 wheel(Linux/macOS 有wheel,Windows 没有)
|
|
307
|
+
if (platformTag) {
|
|
308
|
+
try {
|
|
309
|
+
console.log(' 正在获取版本信息...');
|
|
310
|
+
const sdkInfo = await getSdkDownloadInfo(platformTag);
|
|
311
|
+
console.log(` 版本: ${sdkInfo.version}`);
|
|
312
|
+
console.log(` 平台: ${platformTag}`);
|
|
313
|
+
console.log(` 文件大小: ${(sdkInfo.size / (1024 * 1024)).toFixed(1)} MB`);
|
|
314
|
+
|
|
315
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'sciagent-sdk-'));
|
|
316
|
+
const wheelFilename = `codebuddy_agent_sdk-${sdkInfo.version}-py3-none-${platformTag}.whl`;
|
|
317
|
+
const wheelPath = path.join(tmpDir, wheelFilename);
|
|
318
|
+
|
|
319
|
+
const binaryName = BINARY_NAMES[platform] || 'codebuddy-headless';
|
|
320
|
+
const binDir = getCodebuddyBinDir();
|
|
321
|
+
const targetPath = path.join(binDir, binaryName);
|
|
322
|
+
|
|
323
|
+
console.log(' 正在下载...');
|
|
324
|
+
await downloadFile(sdkInfo.url, wheelPath);
|
|
325
|
+
console.log(' ✅ 下载成功');
|
|
326
|
+
|
|
327
|
+
console.log(' 正在提取二进制文件...');
|
|
328
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
329
|
+
|
|
330
|
+
const extractScript = `
|
|
311
331
|
import zipfile, sys, os
|
|
312
332
|
wheel_path = sys.argv[1]
|
|
313
333
|
target_dir = sys.argv[2]
|
|
@@ -327,49 +347,106 @@ with zipfile.ZipFile(wheel_path, 'r') as zf:
|
|
|
327
347
|
print(f'Error: {binary_name} not found in wheel')
|
|
328
348
|
sys.exit(1)
|
|
329
349
|
`;
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
350
|
+
|
|
351
|
+
const scriptPath = path.join(tmpDir, 'extract.py');
|
|
352
|
+
fs.writeFileSync(scriptPath, extractScript);
|
|
353
|
+
|
|
354
|
+
try {
|
|
355
|
+
execSync(`python3 "${scriptPath}" "${wheelPath}" "${binDir}" "${binaryName}"`, {
|
|
356
|
+
stdio: 'inherit',
|
|
357
|
+
timeout: 120000
|
|
358
|
+
});
|
|
359
|
+
} catch (e) {
|
|
360
|
+
execSync(`python "${scriptPath}" "${wheelPath}" "${binDir}" "${binaryName}"`, {
|
|
361
|
+
stdio: 'inherit',
|
|
362
|
+
timeout: 120000
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (fs.existsSync(targetPath)) {
|
|
367
|
+
const stats = fs.statSync(targetPath);
|
|
368
|
+
console.log(`✅ CodeBuddy SDK 安装成功!(PyPI wheel)`);
|
|
369
|
+
console.log(` 路径: ${targetPath}`);
|
|
370
|
+
console.log(` 大小: ${(stats.size / (1024 * 1024)).toFixed(1)} MB`);
|
|
371
|
+
|
|
372
|
+
try { fs.unlinkSync(wheelPath); fs.unlinkSync(scriptPath); fs.rmdirSync(tmpDir); } catch (e) {}
|
|
373
|
+
return true;
|
|
374
|
+
}
|
|
339
375
|
} catch (e) {
|
|
340
|
-
|
|
341
|
-
execSync(`python "${scriptPath}" "${wheelPath}" "${binDir}" "${binaryName}"`, {
|
|
342
|
-
stdio: 'inherit',
|
|
343
|
-
timeout: 120000
|
|
344
|
-
});
|
|
376
|
+
console.log(` ⚠️ PyPI 下载失败: ${e.message}`);
|
|
345
377
|
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// 策略2: 从 npm 安装 @tencent-ai/codebuddy-code(全平台支持,国内可访问)
|
|
381
|
+
console.log(' 尝试从 npm 安装 @tencent-ai/codebuddy-code...');
|
|
382
|
+
try {
|
|
383
|
+
execSync('npm install -g @tencent-ai/codebuddy-code', {
|
|
384
|
+
stdio: 'inherit',
|
|
385
|
+
timeout: 300000
|
|
386
|
+
});
|
|
346
387
|
|
|
347
|
-
//
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
388
|
+
// 查找 npm 安装的 codebuddy-headless.js
|
|
389
|
+
const npmRootResult = execSync('npm root -g', { encoding: 'utf8', timeout: 10000 }).trim();
|
|
390
|
+
const headlessJsPath = path.join(npmRootResult, '@tencent-ai', 'codebuddy-code', 'dist', 'codebuddy-headless.js');
|
|
391
|
+
|
|
392
|
+
if (fs.existsSync(headlessJsPath)) {
|
|
393
|
+
// 创建 wrapper 脚本,让 codebuddy-headless 可以被直接调用
|
|
394
|
+
const binDir = getCodebuddyBinDir();
|
|
395
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
396
|
+
const binaryName = BINARY_NAMES[platform] || 'codebuddy-headless';
|
|
397
|
+
const wrapperPath = path.join(binDir, binaryName);
|
|
354
398
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
fs.
|
|
359
|
-
|
|
360
|
-
|
|
399
|
+
if (platform === 'win32') {
|
|
400
|
+
// Windows: 创建 .cmd wrapper
|
|
401
|
+
const cmdPath = wrapperPath.replace(/\.(exe)?$/, '.cmd');
|
|
402
|
+
fs.writeFileSync(cmdPath, `@echo off\r\nnode "${headlessJsPath}" %*\r\n`);
|
|
403
|
+
// 也创建 .exe placeholder(实际用 .cmd)
|
|
404
|
+
fs.writeFileSync(wrapperPath, `#!/usr/bin/env node\r\nrequire("${headlessJsPath}");`);
|
|
405
|
+
} else {
|
|
406
|
+
fs.writeFileSync(wrapperPath, `#!/usr/bin/env node\nrequire("${headlessJsPath}");`);
|
|
407
|
+
fs.chmodSync(wrapperPath, 0o755);
|
|
408
|
+
}
|
|
361
409
|
|
|
410
|
+
console.log(`✅ CodeBuddy SDK 安装成功!(npm @tencent-ai/codebuddy-code)`);
|
|
411
|
+
console.log(` 路径: ${wrapperPath}`);
|
|
412
|
+
console.log(` headless.js: ${headlessJsPath}`);
|
|
362
413
|
return true;
|
|
363
414
|
} else {
|
|
364
|
-
console.
|
|
365
|
-
return false;
|
|
415
|
+
console.log(` ⚠️ npm 安装成功但未找到 codebuddy-headless.js`);
|
|
366
416
|
}
|
|
417
|
+
} catch (e) {
|
|
418
|
+
console.log(` ⚠️ npm 安装失败: ${e.message}`);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// 策略3: 从 releases 服务器下载
|
|
422
|
+
console.log(' 尝试从 Releases 服务器下载 CodeBuddy SDK...');
|
|
423
|
+
try {
|
|
424
|
+
const binDir = getCodebuddyBinDir();
|
|
425
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
426
|
+
const binaryName = BINARY_NAMES[platform] || 'codebuddy-headless';
|
|
427
|
+
const targetPath = path.join(binDir, binaryName);
|
|
428
|
+
const downloadUrl = `${RELEASE_SERVER_URL}/api/releases/download/codebuddy/${platform}/${arch}/latest`;
|
|
367
429
|
|
|
430
|
+
await downloadFile(downloadUrl, targetPath, 600000);
|
|
431
|
+
|
|
432
|
+
if (fs.existsSync(targetPath)) {
|
|
433
|
+
const stats = fs.statSync(targetPath);
|
|
434
|
+
if (stats.size > 10 * 1024 * 1024) {
|
|
435
|
+
if (platform !== 'win32') {
|
|
436
|
+
fs.chmodSync(targetPath, 0o755);
|
|
437
|
+
}
|
|
438
|
+
console.log(`✅ CodeBuddy SDK 安装成功!(Releases 服务器)`);
|
|
439
|
+
console.log(` 路径: ${targetPath}`);
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
368
443
|
} catch (e) {
|
|
369
|
-
console.
|
|
370
|
-
console.error(' 你可以稍后运行 "sciagent install-sdk" 手动安装');
|
|
371
|
-
return false;
|
|
444
|
+
console.log(` ⚠️ Releases 服务器下载失败: ${e.message}`);
|
|
372
445
|
}
|
|
446
|
+
|
|
447
|
+
console.log('⚠️ CodeBuddy SDK 安装失败,CLI 仍可启动(AI 对话功能将在 SDK 安装后可用)');
|
|
448
|
+
console.log(' 手动安装: npm install -g @tencent-ai/codebuddy-code');
|
|
449
|
+
return false;
|
|
373
450
|
}
|
|
374
451
|
|
|
375
452
|
// GitHub Releases 配置
|
|
@@ -383,7 +460,7 @@ async function downloadFromGitHub(platform, arch, version) {
|
|
|
383
460
|
console.log(`\n 📥 尝试从 GitHub Releases 下载...`);
|
|
384
461
|
|
|
385
462
|
// 确定安装目录
|
|
386
|
-
const installDir =
|
|
463
|
+
const installDir = getHomeBinDir();
|
|
387
464
|
fs.mkdirSync(installDir, { recursive: true });
|
|
388
465
|
const targetPath = path.join(installDir, binName);
|
|
389
466
|
|
|
@@ -487,6 +564,8 @@ async function downloadFromGitHub(platform, arch, version) {
|
|
|
487
564
|
if (platform !== 'win32') {
|
|
488
565
|
fs.chmodSync(targetPath, 0o755);
|
|
489
566
|
}
|
|
567
|
+
// 写入版本文件
|
|
568
|
+
fs.writeFileSync(path.join(installDir, '.version'), version);
|
|
490
569
|
return true;
|
|
491
570
|
}
|
|
492
571
|
}
|
|
@@ -506,7 +585,7 @@ async function downloadFromServer(platform, arch, version) {
|
|
|
506
585
|
console.log(`\n 📥 从 Releases 服务器下载: ${downloadUrl}`);
|
|
507
586
|
|
|
508
587
|
// 确定安装目录
|
|
509
|
-
const installDir =
|
|
588
|
+
const installDir = getHomeBinDir();
|
|
510
589
|
fs.mkdirSync(installDir, { recursive: true });
|
|
511
590
|
|
|
512
591
|
const targetPath = path.join(installDir, binName);
|
|
@@ -525,6 +604,9 @@ async function downloadFromServer(platform, arch, version) {
|
|
|
525
604
|
fs.chmodSync(targetPath, 0o755);
|
|
526
605
|
}
|
|
527
606
|
|
|
607
|
+
// 写入版本文件
|
|
608
|
+
fs.writeFileSync(path.join(installDir, '.version'), version);
|
|
609
|
+
|
|
528
610
|
return true;
|
|
529
611
|
}
|
|
530
612
|
}
|