@sciagent/cli 1.0.53 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sciagent/cli",
3
- "version": "1.0.53",
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.53",
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.53",
22
+ "@sciagent/cli-win32-x64": "1.0.54",
23
23
  "@sciagent/cli-win32-arm64": "1.0.39"
24
24
  },
25
25
  "keywords": [
@@ -27,7 +27,7 @@ const ARCH_MAP = {
27
27
  };
28
28
 
29
29
  // 当前版本号 - 每次发布时同步更新
30
- const CURRENT_VERSION = '1.0.53';
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,19 +79,34 @@ 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';
85
-
86
- // 检查 ~/.sciagent/bin/ 或 %LOCALAPPDATA%\sciagent\bin(postinstall下载位置)
87
- const homeBinDir = platform === 'win32'
88
- ? path.join(process.env.LOCALAPPDATA || os.homedir(), 'sciagent', 'bin')
89
- : path.join(os.homedir(), '.sciagent', 'bin');
91
+ const homeBinDir = getHomeBinDir();
90
92
  const homeBinPath = path.join(homeBinDir, binName);
93
+
94
+ // 检查 ~/.sciagent/bin/ 或 %LOCALAPPDATA%\sciagent\bin
91
95
  if (fs.existsSync(homeBinPath)) {
92
96
  const stats = fs.statSync(homeBinPath);
93
97
  if (stats.size > 10 * 1024 * 1024) {
94
- return { installed: true, path: homeBinPath };
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
+ }
95
110
  }
96
111
  }
97
112
 
@@ -285,42 +300,34 @@ async function installCodebuddySdk() {
285
300
  const platformKey = `${platform}-${arch}`;
286
301
  const platformTag = PYPI_PLATFORM_MAP[platformKey];
287
302
 
288
- if (!platformTag) {
289
- console.log(`⚠️ 不支持的平台: ${platformKey},跳过 CodeBuddy SDK 安装`);
290
- return false;
291
- }
292
-
293
303
  console.log('');
294
304
  console.log('📦 正在安装 CodeBuddy SDK...');
295
305
 
296
- try {
297
- // 获取版本信息和下载URL
298
- console.log(' 正在获取版本信息...');
299
- const sdkInfo = await getSdkDownloadInfo(platformTag);
300
- console.log(` 版本: ${sdkInfo.version}`);
301
- console.log(` 平台: ${platformTag}`);
302
- console.log(` 文件大小: ${(sdkInfo.size / (1024 * 1024)).toFixed(1)} MB`);
303
-
304
- // 创建临时目录
305
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'sciagent-sdk-'));
306
- const wheelFilename = `codebuddy_agent_sdk-${sdkInfo.version}-py3-none-${platformTag}.whl`;
307
- const wheelPath = path.join(tmpDir, wheelFilename);
308
-
309
- // 使用从JSON API获取的正确URL下载
310
- const binaryName = BINARY_NAMES[platform] || 'codebuddy-headless';
311
- const binDir = getCodebuddyBinDir();
312
- const targetPath = path.join(binDir, binaryName);
313
-
314
- console.log(' 正在下载...');
315
- await downloadFile(sdkInfo.url, wheelPath);
316
- console.log(' ✅ 下载成功');
317
-
318
- // 提取二进制文件
319
- console.log(' 正在提取二进制文件...');
320
- fs.mkdirSync(binDir, { recursive: true });
321
-
322
- // 使用 Python 解压 wheel 文件
323
- 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 = `
324
331
  import zipfile, sys, os
325
332
  wheel_path = sys.argv[1]
326
333
  target_dir = sys.argv[2]
@@ -340,49 +347,106 @@ with zipfile.ZipFile(wheel_path, 'r') as zf:
340
347
  print(f'Error: {binary_name} not found in wheel')
341
348
  sys.exit(1)
342
349
  `;
343
-
344
- const scriptPath = path.join(tmpDir, 'extract.py');
345
- fs.writeFileSync(scriptPath, extractScript);
346
-
347
- try {
348
- execSync(`python3 "${scriptPath}" "${wheelPath}" "${binDir}" "${binaryName}"`, {
349
- stdio: 'inherit',
350
- timeout: 120000
351
- });
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
+ }
352
375
  } catch (e) {
353
- // 如果python3失败,尝试python
354
- execSync(`python "${scriptPath}" "${wheelPath}" "${binDir}" "${binaryName}"`, {
355
- stdio: 'inherit',
356
- timeout: 120000
357
- });
376
+ console.log(` ⚠️ PyPI 下载失败: ${e.message}`);
358
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
+ });
359
387
 
360
- // 验证安装
361
- if (fs.existsSync(targetPath)) {
362
- const stats = fs.statSync(targetPath);
363
- const sizeMb = (stats.size / (1024 * 1024)).toFixed(1);
364
- console.log(`✅ CodeBuddy SDK 安装成功!`);
365
- console.log(` 路径: ${targetPath}`);
366
- console.log(` 大小: ${sizeMb} MB`);
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);
367
398
 
368
- // 清理临时文件
369
- try {
370
- fs.unlinkSync(wheelPath);
371
- fs.unlinkSync(scriptPath);
372
- fs.rmdirSync(tmpDir);
373
- } catch (e) {}
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
+ }
374
409
 
410
+ console.log(`✅ CodeBuddy SDK 安装成功!(npm @tencent-ai/codebuddy-code)`);
411
+ console.log(` 路径: ${wrapperPath}`);
412
+ console.log(` headless.js: ${headlessJsPath}`);
375
413
  return true;
376
414
  } else {
377
- console.error('❌ 安装验证失败');
378
- return false;
415
+ console.log(` ⚠️ npm 安装成功但未找到 codebuddy-headless.js`);
379
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`;
429
+
430
+ await downloadFile(downloadUrl, targetPath, 600000);
380
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
+ }
381
443
  } catch (e) {
382
- console.error(`❌ CodeBuddy SDK 安装失败: ${e.message}`);
383
- console.error(' 你可以稍后运行 "sciagent install-sdk" 手动安装');
384
- return false;
444
+ console.log(` ⚠️ Releases 服务器下载失败: ${e.message}`);
385
445
  }
446
+
447
+ console.log('⚠️ CodeBuddy SDK 安装失败,CLI 仍可启动(AI 对话功能将在 SDK 安装后可用)');
448
+ console.log(' 手动安装: npm install -g @tencent-ai/codebuddy-code');
449
+ return false;
386
450
  }
387
451
 
388
452
  // GitHub Releases 配置
@@ -396,7 +460,7 @@ async function downloadFromGitHub(platform, arch, version) {
396
460
  console.log(`\n 📥 尝试从 GitHub Releases 下载...`);
397
461
 
398
462
  // 确定安装目录
399
- const installDir = path.join(os.homedir(), '.sciagent', 'bin');
463
+ const installDir = getHomeBinDir();
400
464
  fs.mkdirSync(installDir, { recursive: true });
401
465
  const targetPath = path.join(installDir, binName);
402
466
 
@@ -500,6 +564,8 @@ async function downloadFromGitHub(platform, arch, version) {
500
564
  if (platform !== 'win32') {
501
565
  fs.chmodSync(targetPath, 0o755);
502
566
  }
567
+ // 写入版本文件
568
+ fs.writeFileSync(path.join(installDir, '.version'), version);
503
569
  return true;
504
570
  }
505
571
  }
@@ -519,7 +585,7 @@ async function downloadFromServer(platform, arch, version) {
519
585
  console.log(`\n 📥 从 Releases 服务器下载: ${downloadUrl}`);
520
586
 
521
587
  // 确定安装目录
522
- const installDir = path.join(os.homedir(), '.sciagent', 'bin');
588
+ const installDir = getHomeBinDir();
523
589
  fs.mkdirSync(installDir, { recursive: true });
524
590
 
525
591
  const targetPath = path.join(installDir, binName);
@@ -538,6 +604,9 @@ async function downloadFromServer(platform, arch, version) {
538
604
  fs.chmodSync(targetPath, 0o755);
539
605
  }
540
606
 
607
+ // 写入版本文件
608
+ fs.writeFileSync(path.join(installDir, '.version'), version);
609
+
541
610
  return true;
542
611
  }
543
612
  }