@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 +3 -3
- package/scripts/postinstall.js +174 -20
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sciagent/cli",
|
|
3
|
-
"version": "1.0.
|
|
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.
|
|
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.
|
|
22
|
+
"@sciagent/cli-win32-x64": "1.0.50",
|
|
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.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 📥
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
632
|
+
// Releases 服务器失败,尝试 GitHub Releases
|
|
486
633
|
console.log('');
|
|
487
|
-
console.log('
|
|
488
|
-
const
|
|
634
|
+
console.log(' 尝试从 GitHub Releases 下载...');
|
|
635
|
+
const githubSuccess = await downloadFromGitHub(platform, arch, CURRENT_VERSION);
|
|
489
636
|
|
|
490
|
-
if (!
|
|
491
|
-
|
|
492
|
-
console.
|
|
493
|
-
console.
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
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
|
|