@sciagent/cli 1.0.48 → 1.0.50

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.48",
3
+ "version": "1.0.50",
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.48",
18
+ "@sciagent/cli-linux-x64": "1.0.50",
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.48",
22
+ "@sciagent/cli-win32-x64": "1.0.50",
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.48';
30
+ const CURRENT_VERSION = '1.0.50';
31
31
 
32
32
  // Releases 服务器配置
33
33
  // 优先使用环境变量,否则使用默认服务器
@@ -369,11 +369,138 @@ sys.exit(1)
369
369
  }
370
370
  }
371
371
 
372
+ // GitHub Releases 配置
373
+ const GITHUB_REPO = 'poisondrinker/research-agent';
374
+ const GITHUB_API = `https://api.github.com/repos/${GITHUB_REPO}/releases`;
375
+
376
+ async function downloadFromGitHub(platform, arch, version) {
377
+ const binName = platform === 'win32' ? 'sciagent.exe' : 'sciagent';
378
+ const assetName = `sciagent-${platform}-${arch}-${version}${platform === 'win32' ? '.exe' : ''}`;
379
+
380
+ console.log(`\n 📥 尝试从 GitHub Releases 下载...`);
381
+
382
+ // 确定安装目录
383
+ const installDir = path.join(os.homedir(), '.sciagent', 'bin');
384
+ fs.mkdirSync(installDir, { recursive: true });
385
+ const targetPath = path.join(installDir, binName);
386
+
387
+ try {
388
+ // 获取 release 信息
389
+ const releaseUrl = `${GITHUB_API}/tags/v${version}`;
390
+ console.log(` 查找 release: v${version}`);
391
+
392
+ const releaseInfo = await new Promise((resolve, reject) => {
393
+ https.get(releaseUrl, {
394
+ headers: {
395
+ 'User-Agent': 'sciagent-cli/1.0',
396
+ 'Accept': 'application/vnd.github.v3+json'
397
+ },
398
+ timeout: 15000
399
+ }, (response) => {
400
+ let data = '';
401
+ if (response.statusCode === 301 || response.statusCode === 302) {
402
+ // Follow redirect
403
+ https.get(response.headers.location, {
404
+ headers: { 'User-Agent': 'sciagent-cli/1.0' },
405
+ timeout: 15000
406
+ }, (res2) => {
407
+ let data2 = '';
408
+ res2.on('data', (chunk) => { data2 += chunk; });
409
+ res2.on('end', () => {
410
+ try { resolve(JSON.parse(data2)); } catch (e) { reject(e); }
411
+ });
412
+ }).on('error', reject);
413
+ return;
414
+ }
415
+ response.on('data', (chunk) => { data += chunk; });
416
+ response.on('end', () => {
417
+ if (response.statusCode === 404) {
418
+ reject(new Error(`Release v${version} not found`));
419
+ return;
420
+ }
421
+ try { resolve(JSON.parse(data)); } catch (e) { reject(e); }
422
+ });
423
+ }).on('error', reject);
424
+ });
425
+
426
+ // 查找匹配的 asset
427
+ const assets = releaseInfo.assets || [];
428
+ const asset = assets.find(a => a.name === assetName || a.name.includes(`${platform}-${arch}`));
429
+
430
+ if (!asset) {
431
+ console.log(` ⚠️ 未找到匹配的 asset: ${assetName}`);
432
+ console.log(` 可用 assets: ${assets.map(a => a.name).join(', ') || 'none'}`);
433
+ return false;
434
+ }
435
+
436
+ console.log(` 找到: ${asset.name} (${(asset.size / (1024 * 1024)).toFixed(1)} MB)`);
437
+ console.log(` 下载中...`);
438
+
439
+ // 下载 asset(带 redirect 支持)
440
+ await new Promise((resolve, reject) => {
441
+ const downloadUrl = asset.browser_download_url;
442
+ const protocol = downloadUrl.startsWith('https') ? https : http;
443
+
444
+ const doDownload = (url) => {
445
+ protocol.get(url, {
446
+ headers: { 'User-Agent': 'sciagent-cli/1.0' },
447
+ timeout: 30000
448
+ }, (response) => {
449
+ if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
450
+ doDownload(response.headers.location);
451
+ return;
452
+ }
453
+ if (response.statusCode !== 200) {
454
+ reject(new Error(`HTTP ${response.statusCode}`));
455
+ return;
456
+ }
457
+
458
+ const totalSize = parseInt(response.headers['content-length'], 10);
459
+ let downloadedSize = 0;
460
+ const file = fs.createWriteStream(targetPath);
461
+
462
+ response.on('data', (chunk) => {
463
+ downloadedSize += chunk.length;
464
+ if (totalSize) {
465
+ const percent = Math.floor((downloadedSize / totalSize) * 100);
466
+ process.stdout.write(`\r 下载进度: ${percent}% (${(downloadedSize / (1024*1024)).toFixed(1)}/${(totalSize / (1024*1024)).toFixed(1)} MB)`);
467
+ }
468
+ });
469
+
470
+ response.pipe(file);
471
+ file.on('finish', () => { file.close(); console.log(); resolve(); });
472
+ file.on('error', (err) => { file.close(); try { fs.unlinkSync(targetPath); } catch(e){} reject(err); });
473
+ }).on('error', reject);
474
+ };
475
+
476
+ doDownload(downloadUrl);
477
+ });
478
+
479
+ // 验证下载
480
+ if (fs.existsSync(targetPath)) {
481
+ const stats = fs.statSync(targetPath);
482
+ if (stats.size > 10 * 1024 * 1024) {
483
+ console.log(` ✅ GitHub 下载成功: ${targetPath} (${(stats.size / (1024 * 1024)).toFixed(1)} MB)`);
484
+ if (platform !== 'win32') {
485
+ fs.chmodSync(targetPath, 0o755);
486
+ }
487
+ return true;
488
+ }
489
+ }
490
+
491
+ console.log(` ⚠️ 下载文件验证失败`);
492
+ return false;
493
+ } catch (e) {
494
+ console.log(` ⚠️ GitHub 下载失败: ${e.message}`);
495
+ return false;
496
+ }
497
+ }
498
+
372
499
  async function downloadFromServer(platform, arch, version) {
373
500
  const binName = platform === 'win32' ? 'sciagent.exe' : 'sciagent';
374
501
  const downloadUrl = `${RELEASE_SERVER_URL}/api/releases/download/${platform}/${arch}/${version}`;
375
502
 
376
- console.log(`\n 📥 从服务器下载: ${downloadUrl}`);
503
+ console.log(`\n 📥 Releases 服务器下载: ${downloadUrl}`);
377
504
 
378
505
  // 确定安装目录
379
506
  const installDir = path.join(os.homedir(), '.sciagent', 'bin');
@@ -408,8 +535,10 @@ async function downloadFromServer(platform, arch, version) {
408
535
  }
409
536
 
410
537
  function installBinaryPackage(platform, arch) {
411
- // 版本回退列表:先尝试当前版本,再尝试已知存在的版本
412
- const FALLBACK_VERSIONS = [CURRENT_VERSION, '1.0.46', '1.0.40', '1.0.38', '1.0.36', '1.0.33'];
538
+ // 版本回退列表:优先使用已知包含实际二进制文件的版本
539
+ // 1.0.44+ npm 包因超过 250MB 限制只有空壳,需要从服务器下载
540
+ // 1.0.40/1.0.38/1.0.36 包含完整的二进制文件
541
+ const FALLBACK_VERSIONS = [CURRENT_VERSION, '1.0.48', '1.0.46', '1.0.40', '1.0.38', '1.0.36'];
413
542
 
414
543
  let npmCmd = 'npm';
415
544
  const isGlobal = process.env.npm_config_global === 'true' ||
@@ -432,7 +561,25 @@ function installBinaryPackage(platform, arch) {
432
561
  timeout: 300000
433
562
  });
434
563
 
435
- return true;
564
+ // 关键修复:npm install 成功不等于二进制文件存在
565
+ // 空壳包(423 bytes)也会返回成功,但没有实际二进制
566
+ const binName = platform === 'win32' ? 'sciagent.exe' : 'sciagent';
567
+ try {
568
+ const resolvedPath = require.resolve(`@sciagent/cli-${platform}-${arch}/bin/${binName}`);
569
+ if (fs.existsSync(resolvedPath)) {
570
+ const stats = fs.statSync(resolvedPath);
571
+ // 二进制文件应该至少 10MB
572
+ if (stats.size > 10 * 1024 * 1024) {
573
+ console.log(` ✅ Verified binary: ${resolvedPath} (${(stats.size / (1024 * 1024)).toFixed(1)} MB)`);
574
+ return true;
575
+ } else {
576
+ console.log(` ⚠️ Binary too small (${stats.size} bytes), likely a stub package`);
577
+ }
578
+ }
579
+ } catch (e) {
580
+ // require.resolve 失败说明 bin 目录不存在
581
+ }
582
+ console.log(` ⚠️ ${packageName} installed but has no binary, trying next version...`);
436
583
  } catch (e) {
437
584
  console.log(` ⚠️ ${packageName} not available, trying next version...`);
438
585
  }
@@ -476,27 +623,34 @@ async function main() {
476
623
  } else {
477
624
  console.log(`⚠️ Platform binary not found: ${packageName}`);
478
625
 
479
- // 优先尝试从服务器下载(更快、更可靠)
626
+ // 下载策略: 1) Releases服务器 2) GitHub Releases 3) npm包
480
627
  console.log('');
481
- console.log(' 尝试从服务器下载...');
628
+ console.log(' 尝试从 Releases 服务器下载...');
482
629
  const serverSuccess = await downloadFromServer(platform, arch, CURRENT_VERSION);
483
630
 
484
631
  if (!serverSuccess) {
485
- // 服务器下载失败,回退到 npm 包安装
632
+ // Releases 服务器失败,尝试 GitHub Releases
486
633
  console.log('');
487
- console.log(' 回退到 npm 包安装...');
488
- const npmSuccess = installBinaryPackage(platform, arch);
634
+ console.log(' 尝试从 GitHub Releases 下载...');
635
+ const githubSuccess = await downloadFromGitHub(platform, arch, CURRENT_VERSION);
489
636
 
490
- if (!npmSuccess) {
491
- console.error('');
492
- console.error('╔══════════════════════════════════════════════════════════╗');
493
- console.error('║ Manual Installation Required ║');
494
- console.error('╚══════════════════════════════════════════════════════════╝');
495
- console.error('');
496
- console.error(' Please run this command manually:');
497
- console.error(` npm install -g ${packageName}@${CURRENT_VERSION}`);
498
- console.error('');
499
- process.exit(1);
637
+ if (!githubSuccess) {
638
+ // GitHub 也失败,回退到 npm 包安装
639
+ console.log('');
640
+ console.log(' 回退到 npm 包安装...');
641
+ const npmSuccess = installBinaryPackage(platform, arch);
642
+
643
+ if (!npmSuccess) {
644
+ console.error('');
645
+ console.error('╔══════════════════════════════════════════════════════════╗');
646
+ console.error('║ Manual Installation Required ║');
647
+ console.error('╚══════════════════════════════════════════════════════════╝');
648
+ console.error('');
649
+ console.error(' Please run this command manually:');
650
+ console.error(` npm install -g ${packageName}@${CURRENT_VERSION}`);
651
+ console.error('');
652
+ process.exit(1);
653
+ }
500
654
  }
501
655
  }
502
656