@sciagent/cli 1.0.71 → 1.0.73
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 +31 -10
- package/package.json +3 -3
- package/scripts/postinstall.js +30 -110
package/bin/sciagent.js
CHANGED
|
@@ -11,7 +11,7 @@ const fs = require('fs');
|
|
|
11
11
|
const os = require('os');
|
|
12
12
|
|
|
13
13
|
// 当前版本号 - 与 postinstall.js 和 package.json 保持同步
|
|
14
|
-
const CURRENT_VERSION = '1.0.
|
|
14
|
+
const CURRENT_VERSION = '1.0.73';
|
|
15
15
|
|
|
16
16
|
// 平台和架构映射
|
|
17
17
|
const PLATFORM_MAP = {
|
|
@@ -26,6 +26,22 @@ const ARCH_MAP = {
|
|
|
26
26
|
amd64: 'x64'
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* 比较语义化版本号
|
|
31
|
+
* 返回: -1 (a<b), 0 (a==b), 1 (a>b)
|
|
32
|
+
*/
|
|
33
|
+
function compareVersions(a, b) {
|
|
34
|
+
const pa = a.split('.').map(Number);
|
|
35
|
+
const pb = b.split('.').map(Number);
|
|
36
|
+
for (let i = 0; i < 3; i++) {
|
|
37
|
+
const na = pa[i] || 0;
|
|
38
|
+
const nb = pb[i] || 0;
|
|
39
|
+
if (na < nb) return -1;
|
|
40
|
+
if (na > nb) return 1;
|
|
41
|
+
}
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
29
45
|
/**
|
|
30
46
|
* 获取当前平台的二进制文件路径
|
|
31
47
|
*/
|
|
@@ -63,31 +79,36 @@ function getBinaryPath() {
|
|
|
63
79
|
const versionFile = path.join(homeBinDir, '.version');
|
|
64
80
|
if (fs.existsSync(versionFile)) {
|
|
65
81
|
const installedVersion = fs.readFileSync(versionFile, 'utf8').trim();
|
|
66
|
-
|
|
67
|
-
|
|
82
|
+
const cmp = compareVersions(installedVersion, CURRENT_VERSION);
|
|
83
|
+
if (cmp < 0) {
|
|
84
|
+
// 安装版本低于预期版本 → 旧版有bug,删除
|
|
85
|
+
console.error(`[ERROR] Binary version outdated: installed=${installedVersion}, expected=${CURRENT_VERSION}`);
|
|
68
86
|
console.error(` The cached binary is outdated and may have critical bugs (e.g., 405 error on login).`);
|
|
69
87
|
console.error(` Deleting cached binary and exiting. Please run 'npm install -g @sciagent/cli' again.`);
|
|
70
|
-
// 自动删除旧版二进制,下次安装时 postinstall 会重新下载
|
|
71
88
|
try {
|
|
72
89
|
fs.unlinkSync(homeBinPath);
|
|
73
90
|
fs.unlinkSync(versionFile);
|
|
74
|
-
console.error(`
|
|
75
|
-
console.error(`
|
|
91
|
+
console.error(` [OK] Deleted: ${homeBinPath}`);
|
|
92
|
+
console.error(` [OK] Deleted: ${versionFile}`);
|
|
76
93
|
} catch (e) {
|
|
77
|
-
console.error(`
|
|
94
|
+
console.error(` [WARN] Failed to delete: ${e.message}`);
|
|
78
95
|
console.error(` Please manually delete: ${homeBinDir}`);
|
|
79
96
|
}
|
|
80
97
|
process.exit(1);
|
|
98
|
+
} else if (cmp > 0) {
|
|
99
|
+
// 安装版本高于预期 → 用户手动装了新版,允许运行
|
|
100
|
+
console.log(`[INFO] Binary version ${installedVersion} is newer than npm package version ${CURRENT_VERSION}, using it.`);
|
|
81
101
|
}
|
|
102
|
+
// cmp === 0 → 版本匹配,正常使用
|
|
82
103
|
} else {
|
|
83
104
|
// 没有 .version 文件,说明是极旧版本(v1.0.64之前),可能有405 bug
|
|
84
|
-
console.error(
|
|
105
|
+
console.error(`[ERROR] Binary version unknown (no .version file). This binary may be outdated.`);
|
|
85
106
|
console.error(` Deleting cached binary and exiting. Please run 'npm install -g @sciagent/cli' again.`);
|
|
86
107
|
try {
|
|
87
108
|
fs.unlinkSync(homeBinPath);
|
|
88
|
-
console.error(`
|
|
109
|
+
console.error(` [OK] Deleted: ${homeBinPath}`);
|
|
89
110
|
} catch (e) {
|
|
90
|
-
console.error(`
|
|
111
|
+
console.error(` [WARN] Failed to delete: ${e.message}`);
|
|
91
112
|
}
|
|
92
113
|
process.exit(1);
|
|
93
114
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sciagent/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.73",
|
|
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.73",
|
|
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.73",
|
|
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.73';
|
|
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'];
|
|
@@ -494,15 +494,25 @@ sys.exit(1)
|
|
|
494
494
|
return false;
|
|
495
495
|
}
|
|
496
496
|
|
|
497
|
-
//
|
|
498
|
-
const
|
|
499
|
-
const
|
|
497
|
+
// 极狐GitLab Package Registry 配置
|
|
498
|
+
const JIHULAB_URL = 'https://jihulab.com';
|
|
499
|
+
const JIHULAB_PROJECT_ID = 351778;
|
|
500
|
+
const JIHULAB_PACKAGE_NAME = 'sciagent';
|
|
501
|
+
// Deploy token with read_package_registry permission (for downloading)
|
|
502
|
+
const JIHULAB_DOWNLOAD_TOKEN = '2qxfs606HfwESUYJxtRlgm86MQp1OjVnazAK.01.101vzs2qo';
|
|
500
503
|
|
|
501
|
-
async function
|
|
504
|
+
async function downloadFromJiHuLab(platform, arch, version) {
|
|
502
505
|
const binName = platform === 'win32' ? 'sciagent.exe' : 'sciagent';
|
|
503
|
-
const
|
|
506
|
+
const ext = platform === 'win32' ? '.exe' : '';
|
|
507
|
+
const filename = `sciagent-${platform}-${arch}${ext}`;
|
|
504
508
|
|
|
505
|
-
|
|
509
|
+
const downloadUrl = (
|
|
510
|
+
`${JIHULAB_URL}/api/v4/projects/${JIHULAB_PROJECT_ID}` +
|
|
511
|
+
`/packages/generic/${JIHULAB_PACKAGE_NAME}/${version}/${filename}` +
|
|
512
|
+
`?access_token=${JIHULAB_DOWNLOAD_TOKEN}`
|
|
513
|
+
);
|
|
514
|
+
|
|
515
|
+
console.log(`\n [JiHuLab] Downloading ${filename} v${version}...`);
|
|
506
516
|
|
|
507
517
|
// 确定安装目录
|
|
508
518
|
const installDir = getHomeBinDir();
|
|
@@ -510,102 +520,13 @@ async function downloadFromGitHub(platform, arch, version) {
|
|
|
510
520
|
const targetPath = path.join(installDir, binName);
|
|
511
521
|
|
|
512
522
|
try {
|
|
513
|
-
//
|
|
514
|
-
const releaseUrl = `${GITHUB_API}/tags/v${version}`;
|
|
515
|
-
console.log(` 查找 release: v${version}`);
|
|
516
|
-
|
|
517
|
-
const releaseInfo = await new Promise((resolve, reject) => {
|
|
518
|
-
https.get(releaseUrl, {
|
|
519
|
-
headers: {
|
|
520
|
-
'User-Agent': 'sciagent-cli/1.0',
|
|
521
|
-
'Accept': 'application/vnd.github.v3+json'
|
|
522
|
-
},
|
|
523
|
-
timeout: 15000
|
|
524
|
-
}, (response) => {
|
|
525
|
-
let data = '';
|
|
526
|
-
if (response.statusCode === 301 || response.statusCode === 302) {
|
|
527
|
-
// Follow redirect
|
|
528
|
-
https.get(response.headers.location, {
|
|
529
|
-
headers: { 'User-Agent': 'sciagent-cli/1.0' },
|
|
530
|
-
timeout: 15000
|
|
531
|
-
}, (res2) => {
|
|
532
|
-
let data2 = '';
|
|
533
|
-
res2.on('data', (chunk) => { data2 += chunk; });
|
|
534
|
-
res2.on('end', () => {
|
|
535
|
-
try { resolve(JSON.parse(data2)); } catch (e) { reject(e); }
|
|
536
|
-
});
|
|
537
|
-
}).on('error', reject);
|
|
538
|
-
return;
|
|
539
|
-
}
|
|
540
|
-
response.on('data', (chunk) => { data += chunk; });
|
|
541
|
-
response.on('end', () => {
|
|
542
|
-
if (response.statusCode === 404) {
|
|
543
|
-
reject(new Error(`Release v${version} not found`));
|
|
544
|
-
return;
|
|
545
|
-
}
|
|
546
|
-
try { resolve(JSON.parse(data)); } catch (e) { reject(e); }
|
|
547
|
-
});
|
|
548
|
-
}).on('error', reject);
|
|
549
|
-
});
|
|
550
|
-
|
|
551
|
-
// 查找匹配的 asset
|
|
552
|
-
const assets = releaseInfo.assets || [];
|
|
553
|
-
const asset = assets.find(a => a.name === assetName || a.name.includes(`${platform}-${arch}`));
|
|
554
|
-
|
|
555
|
-
if (!asset) {
|
|
556
|
-
console.log(` ⚠️ 未找到匹配的 asset: ${assetName}`);
|
|
557
|
-
console.log(` 可用 assets: ${assets.map(a => a.name).join(', ') || 'none'}`);
|
|
558
|
-
return false;
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
console.log(` 找到: ${asset.name} (${(asset.size / (1024 * 1024)).toFixed(1)} MB)`);
|
|
562
|
-
console.log(` 下载中...`);
|
|
563
|
-
|
|
564
|
-
// 下载 asset(带 redirect 支持)
|
|
565
|
-
await new Promise((resolve, reject) => {
|
|
566
|
-
const downloadUrl = asset.browser_download_url;
|
|
567
|
-
const protocol = downloadUrl.startsWith('https') ? https : http;
|
|
568
|
-
|
|
569
|
-
const doDownload = (url) => {
|
|
570
|
-
protocol.get(url, {
|
|
571
|
-
headers: { 'User-Agent': 'sciagent-cli/1.0' },
|
|
572
|
-
timeout: 30000
|
|
573
|
-
}, (response) => {
|
|
574
|
-
if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
|
|
575
|
-
doDownload(response.headers.location);
|
|
576
|
-
return;
|
|
577
|
-
}
|
|
578
|
-
if (response.statusCode !== 200) {
|
|
579
|
-
reject(new Error(`HTTP ${response.statusCode}`));
|
|
580
|
-
return;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
const totalSize = parseInt(response.headers['content-length'], 10);
|
|
584
|
-
let downloadedSize = 0;
|
|
585
|
-
const file = fs.createWriteStream(targetPath);
|
|
586
|
-
|
|
587
|
-
response.on('data', (chunk) => {
|
|
588
|
-
downloadedSize += chunk.length;
|
|
589
|
-
if (totalSize) {
|
|
590
|
-
const percent = Math.floor((downloadedSize / totalSize) * 100);
|
|
591
|
-
process.stdout.write(`\r 下载进度: ${percent}% (${(downloadedSize / (1024*1024)).toFixed(1)}/${(totalSize / (1024*1024)).toFixed(1)} MB)`);
|
|
592
|
-
}
|
|
593
|
-
});
|
|
594
|
-
|
|
595
|
-
response.pipe(file);
|
|
596
|
-
file.on('finish', () => { file.close(); console.log(); resolve(); });
|
|
597
|
-
file.on('error', (err) => { file.close(); try { fs.unlinkSync(targetPath); } catch(e){} reject(err); });
|
|
598
|
-
}).on('error', reject);
|
|
599
|
-
};
|
|
600
|
-
|
|
601
|
-
doDownload(downloadUrl);
|
|
602
|
-
});
|
|
523
|
+
await downloadFile(downloadUrl, targetPath, 600000); // 10 分钟超时
|
|
603
524
|
|
|
604
525
|
// 验证下载
|
|
605
526
|
if (fs.existsSync(targetPath)) {
|
|
606
527
|
const stats = fs.statSync(targetPath);
|
|
607
528
|
if (stats.size > 10 * 1024 * 1024) {
|
|
608
|
-
console.log(`
|
|
529
|
+
console.log(` [OK] JiHuLab download success: ${targetPath} (${(stats.size / (1024 * 1024)).toFixed(1)} MB)`);
|
|
609
530
|
if (platform !== 'win32') {
|
|
610
531
|
fs.chmodSync(targetPath, 0o755);
|
|
611
532
|
}
|
|
@@ -615,10 +536,10 @@ async function downloadFromGitHub(platform, arch, version) {
|
|
|
615
536
|
}
|
|
616
537
|
}
|
|
617
538
|
|
|
618
|
-
console.log(`
|
|
539
|
+
console.log(` [WARN] Downloaded file validation failed`);
|
|
619
540
|
return false;
|
|
620
541
|
} catch (e) {
|
|
621
|
-
console.log(`
|
|
542
|
+
console.log(` [WARN] JiHuLab download failed: ${e.message}`);
|
|
622
543
|
return false;
|
|
623
544
|
}
|
|
624
545
|
}
|
|
@@ -754,31 +675,30 @@ async function main() {
|
|
|
754
675
|
} else {
|
|
755
676
|
console.log(`⚠️ Platform binary not found: ${packageName}`);
|
|
756
677
|
|
|
757
|
-
// 下载策略: 1) Releases服务器 2)
|
|
678
|
+
// 下载策略: 1) Releases服务器 2) 极狐GitLab 3) npm包
|
|
758
679
|
console.log('');
|
|
759
680
|
console.log(' 尝试从 Releases 服务器下载...');
|
|
760
681
|
const serverSuccess = await downloadFromServer(platform, arch, CURRENT_VERSION);
|
|
761
682
|
|
|
762
683
|
if (!serverSuccess) {
|
|
763
|
-
// Releases
|
|
684
|
+
// Releases 服务器失败,尝试极狐GitLab
|
|
764
685
|
console.log('');
|
|
765
|
-
console.log('
|
|
686
|
+
console.log(' 尝试从极狐GitLab下载...');
|
|
766
687
|
|
|
767
|
-
|
|
768
|
-
let githubSuccess = await downloadFromGitHub(platform, arch, CURRENT_VERSION);
|
|
688
|
+
let jihuSuccess = await downloadFromJiHuLab(platform, arch, CURRENT_VERSION);
|
|
769
689
|
|
|
770
690
|
// 如果当前版本失败,尝试回退版本
|
|
771
|
-
if (!
|
|
691
|
+
if (!jihuSuccess) {
|
|
772
692
|
for (const fallbackVersion of GITHUB_FALLBACK_VERSIONS) {
|
|
773
693
|
if (fallbackVersion === CURRENT_VERSION) continue;
|
|
774
694
|
console.log(` 尝试回退版本 v${fallbackVersion}...`);
|
|
775
|
-
|
|
776
|
-
if (
|
|
695
|
+
jihuSuccess = await downloadFromJiHuLab(platform, arch, fallbackVersion);
|
|
696
|
+
if (jihuSuccess) break;
|
|
777
697
|
}
|
|
778
698
|
}
|
|
779
699
|
|
|
780
|
-
if (!
|
|
781
|
-
//
|
|
700
|
+
if (!jihuSuccess) {
|
|
701
|
+
// 极狐GitLab 也失败,回退到 npm 包安装
|
|
782
702
|
console.log('');
|
|
783
703
|
console.log(' 回退到 npm 包安装...');
|
|
784
704
|
const npmSuccess = installBinaryPackage(platform, arch);
|