@morndream/mihomo-tui 0.5.0-rc.0
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/CHANGELOG.md +93 -0
- package/LICENSE +21 -0
- package/README.md +462 -0
- package/bin/mihomo-tui +34 -0
- package/dist/App.js +161 -0
- package/dist/App.js.map +1 -0
- package/dist/api/client.js +239 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/status.js +43 -0
- package/dist/api/status.js.map +1 -0
- package/dist/api/stream.js +139 -0
- package/dist/api/stream.js.map +1 -0
- package/dist/api/types.js +6 -0
- package/dist/api/types.js.map +1 -0
- package/dist/cli.js +221 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/conn.js +122 -0
- package/dist/commands/conn.js.map +1 -0
- package/dist/commands/logs.js +99 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/output.js +177 -0
- package/dist/commands/output.js.map +1 -0
- package/dist/commands/provider.js +140 -0
- package/dist/commands/provider.js.map +1 -0
- package/dist/commands/proxy.js +161 -0
- package/dist/commands/proxy.js.map +1 -0
- package/dist/commands/proxyEnv.js +193 -0
- package/dist/commands/proxyEnv.js.map +1 -0
- package/dist/commands/rules.js +87 -0
- package/dist/commands/rules.js.map +1 -0
- package/dist/commands/status.js +75 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/components/ConfirmDialog.js +31 -0
- package/dist/components/ConfirmDialog.js.map +1 -0
- package/dist/components/DelayBadge.js +27 -0
- package/dist/components/DelayBadge.js.map +1 -0
- package/dist/components/InputDialog.js +325 -0
- package/dist/components/InputDialog.js.map +1 -0
- package/dist/components/ListDialog.js +86 -0
- package/dist/components/ListDialog.js.map +1 -0
- package/dist/components/ProgressDialog.js +34 -0
- package/dist/components/ProgressDialog.js.map +1 -0
- package/dist/components/ScrollList.js +26 -0
- package/dist/components/ScrollList.js.map +1 -0
- package/dist/components/StatusBar.js +58 -0
- package/dist/components/StatusBar.js.map +1 -0
- package/dist/components/TextEditor.js +112 -0
- package/dist/components/TextEditor.js.map +1 -0
- package/dist/components/textEditorModel.js +154 -0
- package/dist/components/textEditorModel.js.map +1 -0
- package/dist/config/manager.js +296 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/preserveGroups.js +9 -0
- package/dist/config/preserveGroups.js.map +1 -0
- package/dist/config/ruleDocument.js +88 -0
- package/dist/config/ruleDocument.js.map +1 -0
- package/dist/config/ruleService.js +256 -0
- package/dist/config/ruleService.js.map +1 -0
- package/dist/config/ruleValidation.js +98 -0
- package/dist/config/ruleValidation.js.map +1 -0
- package/dist/config/service.js +63 -0
- package/dist/config/service.js.map +1 -0
- package/dist/config/settingsService.js +162 -0
- package/dist/config/settingsService.js.map +1 -0
- package/dist/config/skeleton.js +324 -0
- package/dist/config/skeleton.js.map +1 -0
- package/dist/config/subscriptionService.js +284 -0
- package/dist/config/subscriptionService.js.map +1 -0
- package/dist/config/subscriptions.js +200 -0
- package/dist/config/subscriptions.js.map +1 -0
- package/dist/config/types.js +5 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config.js +101 -0
- package/dist/config.js.map +1 -0
- package/dist/hooks/useProviders.js +138 -0
- package/dist/hooks/useProviders.js.map +1 -0
- package/dist/hooks/useProxies.js +298 -0
- package/dist/hooks/useProxies.js.map +1 -0
- package/dist/hooks/useStream.js +127 -0
- package/dist/hooks/useStream.js.map +1 -0
- package/dist/kernel/installer.js +317 -0
- package/dist/kernel/installer.js.map +1 -0
- package/dist/kernel/releases.js +111 -0
- package/dist/kernel/releases.js.map +1 -0
- package/dist/kernel/sources.js +98 -0
- package/dist/kernel/sources.js.map +1 -0
- package/dist/rules/editor.js +181 -0
- package/dist/rules/editor.js.map +1 -0
- package/dist/rules/matcher.js +83 -0
- package/dist/rules/matcher.js.map +1 -0
- package/dist/rules/model.js +25 -0
- package/dist/rules/model.js.map +1 -0
- package/dist/rules/runtime.js +46 -0
- package/dist/rules/runtime.js.map +1 -0
- package/dist/rules/types.js +10 -0
- package/dist/rules/types.js.map +1 -0
- package/dist/ui/FooterLine.js +62 -0
- package/dist/ui/FooterLine.js.map +1 -0
- package/dist/ui/Panel.js +47 -0
- package/dist/ui/Panel.js.map +1 -0
- package/dist/ui/RowIndicator.js +25 -0
- package/dist/ui/RowIndicator.js.map +1 -0
- package/dist/ui/SectionHeader.js +14 -0
- package/dist/ui/SectionHeader.js.map +1 -0
- package/dist/ui/StatusDot.js +15 -0
- package/dist/ui/StatusDot.js.map +1 -0
- package/dist/ui/TopBar.js +81 -0
- package/dist/ui/TopBar.js.map +1 -0
- package/dist/ui/exitGuard.js +20 -0
- package/dist/ui/exitGuard.js.map +1 -0
- package/dist/ui/keyCapture.js +28 -0
- package/dist/ui/keyCapture.js.map +1 -0
- package/dist/ui/layout.js +32 -0
- package/dist/ui/layout.js.map +1 -0
- package/dist/ui/rowIndicator.js +42 -0
- package/dist/ui/rowIndicator.js.map +1 -0
- package/dist/ui/tableHeader.js +33 -0
- package/dist/ui/tableHeader.js.map +1 -0
- package/dist/ui/theme.js +47 -0
- package/dist/ui/theme.js.map +1 -0
- package/dist/ui/tone.js +131 -0
- package/dist/ui/tone.js.map +1 -0
- package/dist/version.js +27 -0
- package/dist/version.js.map +1 -0
- package/dist/views/Conns.js +107 -0
- package/dist/views/Conns.js.map +1 -0
- package/dist/views/Logs.js +89 -0
- package/dist/views/Logs.js.map +1 -0
- package/dist/views/Providers.js +392 -0
- package/dist/views/Providers.js.map +1 -0
- package/dist/views/Proxies.js +233 -0
- package/dist/views/Proxies.js.map +1 -0
- package/dist/views/RuleEditor.js +356 -0
- package/dist/views/RuleEditor.js.map +1 -0
- package/dist/views/Rules.js +286 -0
- package/dist/views/Rules.js.map +1 -0
- package/dist/views/Settings.js +734 -0
- package/dist/views/Settings.js.map +1 -0
- package/dist/views/groupDisplay.js +53 -0
- package/dist/views/groupDisplay.js.map +1 -0
- package/dist/views/subscriptionFields.js +59 -0
- package/dist/views/subscriptionFields.js.map +1 -0
- package/dist/views/yamlFile.js +32 -0
- package/dist/views/yamlFile.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 内核安装四段式(spec 2026-09-13 settings-kernel §3.4,范式照搬 mihari):
|
|
3
|
+
* staging 下载(流式 gunzip + sha256)→ 验证(-v 输出比对)→ 原子替换
|
|
4
|
+
* (备份旧二进制 + 同目录 tmp+rename)→ 重启服务并轮询 /version 确认。
|
|
5
|
+
*
|
|
6
|
+
* 任何一步失败都保证目标二进制可用:验证阶段失败只留 staging 残留(finally
|
|
7
|
+
* 清理);替换后失败从备份恢复并再次重启。已下载过的版本归档在
|
|
8
|
+
* kernelsDir/<tag>/mihomo,切回时离线直换(跳过下载)。
|
|
9
|
+
*/
|
|
10
|
+
import { execFile } from 'node:child_process';
|
|
11
|
+
import { createHash } from 'node:crypto';
|
|
12
|
+
import { chmodSync, copyFileSync, createWriteStream, existsSync, mkdirSync, mkdtempSync, readdirSync, renameSync, rmSync, } from 'node:fs';
|
|
13
|
+
import { basename, dirname, join } from 'node:path';
|
|
14
|
+
import { homedir } from 'node:os';
|
|
15
|
+
import { Readable, Transform } from 'node:stream';
|
|
16
|
+
import { pipeline } from 'node:stream/promises';
|
|
17
|
+
import { createGunzip } from 'node:zlib';
|
|
18
|
+
import { promisify } from 'node:util';
|
|
19
|
+
import { MIHOMO_BIN_DEFAULT } from '../config/manager.js';
|
|
20
|
+
import { alphaShaFromAssetName, assetNamesFor } from './releases.js';
|
|
21
|
+
import { MAX_ASSET_BYTES, assetDownloadUrl, resolveSources } from './sources.js';
|
|
22
|
+
export const KERNELS_DIR_DEFAULT = join(homedir(), '.local', 'share', 'mihomo-tui', 'kernels');
|
|
23
|
+
const execFileAsync = promisify(execFile);
|
|
24
|
+
const DOWNLOAD_TIMEOUT_MS = 15 * 60 * 1000;
|
|
25
|
+
const PROBE_INTERVAL_MS = 500;
|
|
26
|
+
const PROBE_ATTEMPTS = 20;
|
|
27
|
+
const BACKUP_KEEP = 2;
|
|
28
|
+
export class InstallError extends Error {
|
|
29
|
+
phase;
|
|
30
|
+
detail;
|
|
31
|
+
constructor(message, phase, detail) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.phase = phase;
|
|
34
|
+
this.detail = detail;
|
|
35
|
+
this.name = 'InstallError';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function msg(err) {
|
|
39
|
+
return err instanceof Error ? err.message : String(err);
|
|
40
|
+
}
|
|
41
|
+
const defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
42
|
+
/** 归档键:稳定版用 tag;alpha 滚动 tag 每次构建的 sha 都不同,按 sha 键控避免换上陈旧 alpha */
|
|
43
|
+
export function archiveKeyFor(tag, alpha, asset) {
|
|
44
|
+
if (!alpha)
|
|
45
|
+
return tag;
|
|
46
|
+
const sha = asset ? alphaShaFromAssetName(asset.name) : undefined;
|
|
47
|
+
return sha ? `Prerelease-Alpha-${sha}` : `${tag}-${Date.now()}`;
|
|
48
|
+
}
|
|
49
|
+
/** 归档路径:kernelsDir/<key>/mihomo */
|
|
50
|
+
export function archivedBinPath(kernelsDir, key) {
|
|
51
|
+
return join(kernelsDir, key, 'mihomo');
|
|
52
|
+
}
|
|
53
|
+
/** 本机已归档的版本键列表(目录名即键,仅保留含 mihomo 的目录;staging-* 是崩溃残留不是归档) */
|
|
54
|
+
export function listArchivedTags(kernelsDir) {
|
|
55
|
+
let entries;
|
|
56
|
+
try {
|
|
57
|
+
entries = readdirSync(kernelsDir);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
return entries
|
|
63
|
+
.filter((entry) => !entry.startsWith('staging-') && existsSync(join(kernelsDir, entry, 'mihomo')))
|
|
64
|
+
.sort();
|
|
65
|
+
}
|
|
66
|
+
/** 同盘原子替换:先拷到目标同目录临时名再 rename;跨盘(EXDEV)退化为直接拷贝 */
|
|
67
|
+
function replaceFile(src, dst) {
|
|
68
|
+
try {
|
|
69
|
+
const tmp = `${dst}.next`;
|
|
70
|
+
copyFileSync(src, tmp);
|
|
71
|
+
renameSync(tmp, dst);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
if (err.code !== 'EXDEV')
|
|
75
|
+
throw err;
|
|
76
|
+
copyFileSync(src, dst);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** 保留最近 keep 份 <bin>.bak.* 备份(含刚创建的那份),其余清理 */
|
|
80
|
+
function pruneBackups(binPath, keep) {
|
|
81
|
+
const prefix = `${basename(binPath)}.bak.`;
|
|
82
|
+
let entries;
|
|
83
|
+
try {
|
|
84
|
+
entries = readdirSync(dirname(binPath));
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const backups = entries
|
|
90
|
+
.filter((entry) => entry.startsWith(prefix))
|
|
91
|
+
.map((entry) => join(dirname(binPath), entry))
|
|
92
|
+
.sort()
|
|
93
|
+
.reverse();
|
|
94
|
+
for (const stale of backups.slice(keep)) {
|
|
95
|
+
rmSync(stale, { force: true });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** 流式下载 .gz:边下边算 sha256,gunzip 落盘到 binFile;字节进度按 ≥512KB 节流上报 */
|
|
99
|
+
async function downloadAndGunzip(url, binFile, total, deps) {
|
|
100
|
+
const { fetchImpl = fetch } = deps;
|
|
101
|
+
const response = await fetchImpl(url, {
|
|
102
|
+
headers: { 'User-Agent': 'mihomo-tui' },
|
|
103
|
+
signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS),
|
|
104
|
+
});
|
|
105
|
+
if (!response.ok || !response.body) {
|
|
106
|
+
throw new InstallError(`下载失败:HTTP ${response.status}`, 'download');
|
|
107
|
+
}
|
|
108
|
+
const declared = Number(response.headers.get('content-length'));
|
|
109
|
+
const totalBytes = total ?? (Number.isFinite(declared) && declared > 0 ? declared : undefined);
|
|
110
|
+
const hash = createHash('sha256');
|
|
111
|
+
let received = 0;
|
|
112
|
+
let lastEmit = 0;
|
|
113
|
+
const counter = new Transform({
|
|
114
|
+
transform(chunk, _enc, callback) {
|
|
115
|
+
received += chunk.length;
|
|
116
|
+
hash.update(chunk);
|
|
117
|
+
if (received - lastEmit >= 512 * 1024) {
|
|
118
|
+
lastEmit = received;
|
|
119
|
+
deps.onProgress?.({
|
|
120
|
+
phase: 'download',
|
|
121
|
+
message: '下载内核',
|
|
122
|
+
received,
|
|
123
|
+
...(totalBytes !== undefined ? { total: totalBytes } : {}),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
callback(null, chunk);
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
await pipeline(Readable.fromWeb(response.body), counter, createGunzip(), createWriteStream(binFile, { mode: 0o700 }));
|
|
130
|
+
return { sha256: hash.digest('hex'), received };
|
|
131
|
+
}
|
|
132
|
+
/** 候选二进制验证:chmod 0700 → `-v` 输出必须含验证标记(稳定版 tag / alpha sha) */
|
|
133
|
+
async function verifyBinary(binFile, marker) {
|
|
134
|
+
chmodSync(binFile, 0o700);
|
|
135
|
+
let output;
|
|
136
|
+
try {
|
|
137
|
+
const { stdout, stderr } = await execFileAsync(binFile, ['-v'], { timeout: 15_000 });
|
|
138
|
+
output = `${stdout}${stderr}`;
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
const e = err;
|
|
142
|
+
throw new InstallError('内核二进制无法执行', 'verify', `${e.stdout ?? ''}${e.stderr ?? ''}`.trim() || msg(err));
|
|
143
|
+
}
|
|
144
|
+
if (!output.includes(marker)) {
|
|
145
|
+
throw new InstallError(`-v 输出不含目标版本标记 ${marker}`, 'verify', output.trim());
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* 从备份恢复目标二进制并尽力恢复服务;返回回滚过程中的问题清单
|
|
150
|
+
* (空数组 = 干净回滚)。恢复失败也仍尝试重启:与其留下一个可能损坏的
|
|
151
|
+
* 目标二进制 + 停摆的服务,不如让服务拉起盘上现存的二进制。
|
|
152
|
+
*/
|
|
153
|
+
async function restoreBackup(binPath, backupPath, restart) {
|
|
154
|
+
const problems = [];
|
|
155
|
+
if (backupPath && existsSync(backupPath)) {
|
|
156
|
+
try {
|
|
157
|
+
replaceFile(backupPath, binPath);
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
problems.push(`恢复备份失败:${msg(err)}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (restart) {
|
|
164
|
+
try {
|
|
165
|
+
await restart();
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
problems.push(`恢复性重启失败:${msg(err)}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return problems;
|
|
172
|
+
}
|
|
173
|
+
/** 把回滚问题并进错误文案:干净回滚注明「已回滚」,失败则如实陈述(绝不静默撒谎) */
|
|
174
|
+
function rollbackSuffix(problems) {
|
|
175
|
+
return problems.length > 0 ? `;回滚失败:${problems.join(';')}` : '(已回滚旧内核)';
|
|
176
|
+
}
|
|
177
|
+
/** 安装/切换内核:四段式 + 失败回滚。成功返回 { tag, fromArchive }。 */
|
|
178
|
+
export async function installKernel(input, deps = {}) {
|
|
179
|
+
const binPath = deps.mihomoBin ?? MIHOMO_BIN_DEFAULT;
|
|
180
|
+
const kernelsDir = deps.kernelsDir ?? KERNELS_DIR_DEFAULT;
|
|
181
|
+
const sleep = deps.sleep ?? defaultSleep;
|
|
182
|
+
const emit = (progress) => deps.onProgress?.(progress);
|
|
183
|
+
const { tag } = input;
|
|
184
|
+
if (input.alpha && !input.asset) {
|
|
185
|
+
throw new InstallError('Alpha 版需要资产信息才能确定验证标记', 'download');
|
|
186
|
+
}
|
|
187
|
+
// -v 输出验证标记:稳定版为 tag(如 v1.19.30);alpha 为资产名中的短 sha
|
|
188
|
+
const marker = input.alpha
|
|
189
|
+
? (input.asset ? alphaShaFromAssetName(input.asset.name) : undefined) ?? tag
|
|
190
|
+
: tag;
|
|
191
|
+
mkdirSync(kernelsDir, { recursive: true });
|
|
192
|
+
const archiveKey = archiveKeyFor(tag, Boolean(input.alpha), input.asset);
|
|
193
|
+
const archivedBin = archivedBinPath(kernelsDir, archiveKey);
|
|
194
|
+
const fromArchive = existsSync(archivedBin);
|
|
195
|
+
if (!fromArchive) {
|
|
196
|
+
const staging = mkdtempSync(join(kernelsDir, 'staging-'));
|
|
197
|
+
try {
|
|
198
|
+
const names = input.asset ? [input.asset.name] : assetNamesFor(tag);
|
|
199
|
+
const binFile = join(staging, 'mihomo');
|
|
200
|
+
emit({
|
|
201
|
+
phase: 'download',
|
|
202
|
+
message: '下载内核',
|
|
203
|
+
received: 0,
|
|
204
|
+
...(input.asset?.size ? { total: input.asset.size } : {}),
|
|
205
|
+
});
|
|
206
|
+
// 源 × 资产名组合逐个尝试:镜像不可达或 404(如无 compatible 变体)都落到下一组合
|
|
207
|
+
let sha256;
|
|
208
|
+
let lastError;
|
|
209
|
+
outer: for (const source of resolveSources(deps.sourceConfig, 'dl')) {
|
|
210
|
+
for (const name of names) {
|
|
211
|
+
const url = `${source.prefix}${assetDownloadUrl(tag, name)}`;
|
|
212
|
+
try {
|
|
213
|
+
const result = await downloadAndGunzip(url, binFile, input.asset?.size, deps);
|
|
214
|
+
if (result.received > MAX_ASSET_BYTES) {
|
|
215
|
+
throw new InstallError(`下载体积超过 ${MAX_ASSET_BYTES} 字节上限`, 'download');
|
|
216
|
+
}
|
|
217
|
+
sha256 = result.sha256;
|
|
218
|
+
break outer;
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
lastError = err;
|
|
222
|
+
rmSync(binFile, { force: true });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (sha256 === undefined) {
|
|
227
|
+
throw lastError instanceof InstallError
|
|
228
|
+
? lastError
|
|
229
|
+
: new InstallError(`下载失败:${msg(lastError)}`, 'download', msg(lastError));
|
|
230
|
+
}
|
|
231
|
+
// digest 校验放在执行候选二进制之前(不可信内容不执行)
|
|
232
|
+
const expectedDigest = input.asset?.digest;
|
|
233
|
+
if (expectedDigest && expectedDigest.replace(/^sha256:/, '') !== sha256) {
|
|
234
|
+
throw new InstallError('sha256 校验失败:下载内容与 release 摘要不符', 'verify');
|
|
235
|
+
}
|
|
236
|
+
emit({ phase: 'verify', message: '校验二进制' });
|
|
237
|
+
await verifyBinary(binFile, marker);
|
|
238
|
+
emit({ phase: 'replace', message: '替换二进制' });
|
|
239
|
+
mkdirSync(dirname(archivedBin), { recursive: true });
|
|
240
|
+
renameSync(binFile, archivedBin);
|
|
241
|
+
}
|
|
242
|
+
finally {
|
|
243
|
+
rmSync(staging, { recursive: true, force: true });
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// 备份 + 原子替换(tmpNext 与目标同目录,rename 原子生效)
|
|
247
|
+
let backupPath;
|
|
248
|
+
if (existsSync(binPath)) {
|
|
249
|
+
backupPath = `${binPath}.bak.${Date.now()}`;
|
|
250
|
+
copyFileSync(binPath, backupPath);
|
|
251
|
+
}
|
|
252
|
+
emit({ phase: 'replace', message: '替换二进制' });
|
|
253
|
+
try {
|
|
254
|
+
replaceFile(archivedBin, binPath);
|
|
255
|
+
chmodSync(binPath, 0o700);
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
const problems = await restoreBackup(binPath, backupPath, deps.restart);
|
|
259
|
+
throw new InstallError(`替换二进制失败${rollbackSuffix(problems)}:${msg(err)}`, 'replace', msg(err));
|
|
260
|
+
}
|
|
261
|
+
// 重启 + 轮询 /version 直到出现目标标记;失败恢复备份
|
|
262
|
+
if (deps.restart) {
|
|
263
|
+
emit({ phase: 'restart', message: '重启服务' });
|
|
264
|
+
try {
|
|
265
|
+
await deps.restart();
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
const problems = await restoreBackup(binPath, backupPath, deps.restart);
|
|
269
|
+
throw new InstallError(`重启服务失败${rollbackSuffix(problems)}:${msg(err)}`, 'restart', msg(err));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
emit({ phase: 'confirm', message: '确认内核状态' });
|
|
273
|
+
const hasProbe = Boolean(deps.probeVersion ?? deps.isActive);
|
|
274
|
+
if (hasProbe) {
|
|
275
|
+
let probeDetail;
|
|
276
|
+
let confirmed = false;
|
|
277
|
+
for (let attempt = 0; attempt < PROBE_ATTEMPTS && !confirmed; attempt += 1) {
|
|
278
|
+
await sleep(PROBE_INTERVAL_MS);
|
|
279
|
+
if (deps.isActive) {
|
|
280
|
+
try {
|
|
281
|
+
if (!(await deps.isActive())) {
|
|
282
|
+
probeDetail = '服务未处于 active 状态';
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
probeDetail = msg(err);
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (deps.probeVersion) {
|
|
292
|
+
try {
|
|
293
|
+
const version = await deps.probeVersion();
|
|
294
|
+
if (version && version.includes(marker)) {
|
|
295
|
+
confirmed = true;
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
probeDetail = version ? `运行版本 ${version} 与目标 ${marker} 不符` : '版本探针无响应';
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
catch (err) {
|
|
302
|
+
probeDetail = msg(err);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
confirmed = true;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
if (!confirmed) {
|
|
310
|
+
const problems = await restoreBackup(binPath, backupPath, deps.restart);
|
|
311
|
+
throw new InstallError(`切换后未确认到内核 ${marker}${rollbackSuffix(problems)}`, 'confirm', probeDetail);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
pruneBackups(binPath, BACKUP_KEEP);
|
|
315
|
+
return { tag, fromArchive };
|
|
316
|
+
}
|
|
317
|
+
//# sourceMappingURL=installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/kernel/installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mihomo release 数据(spec 2026-09-13 settings-kernel §3.4):
|
|
3
|
+
* 稳定版列表 + Alpha 滚动 tag(Prerelease-Alpha);资产按
|
|
4
|
+
* mihomo-<goos>-<goarch>-<tag>.gz 规则选择(amd64 命中 404 时回退 -compatible)。
|
|
5
|
+
*/
|
|
6
|
+
import { fetchJsonThrough } from './sources.js';
|
|
7
|
+
function isRecord(value) {
|
|
8
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
9
|
+
}
|
|
10
|
+
function toRelease(raw) {
|
|
11
|
+
if (!isRecord(raw) || typeof raw.tag_name !== 'string')
|
|
12
|
+
return undefined;
|
|
13
|
+
const assets = Array.isArray(raw.assets)
|
|
14
|
+
? raw.assets
|
|
15
|
+
.map((item) => {
|
|
16
|
+
if (!isRecord(item) || typeof item.name !== 'string')
|
|
17
|
+
return undefined;
|
|
18
|
+
const digest = typeof item.digest === 'string' ? item.digest : undefined;
|
|
19
|
+
return {
|
|
20
|
+
name: item.name,
|
|
21
|
+
size: typeof item.size === 'number' ? item.size : 0,
|
|
22
|
+
...(digest ? { digest } : {}),
|
|
23
|
+
};
|
|
24
|
+
})
|
|
25
|
+
.filter((item) => item !== undefined)
|
|
26
|
+
: [];
|
|
27
|
+
return {
|
|
28
|
+
tag: raw.tag_name,
|
|
29
|
+
...(typeof raw.published_at === 'string' ? { publishedAt: raw.published_at } : {}),
|
|
30
|
+
assets,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** 稳定版列表(过滤 prerelease/draft,按 API 返回顺序即新到旧;per_page=12 供过滤后取前 10) */
|
|
34
|
+
export async function listStableReleases(options = {}) {
|
|
35
|
+
const { data } = await fetchJsonThrough('/releases?per_page=12', options);
|
|
36
|
+
if (!Array.isArray(data))
|
|
37
|
+
return [];
|
|
38
|
+
return data
|
|
39
|
+
.filter((raw) => isRecord(raw) && raw.prerelease !== true && raw.draft !== true && typeof raw.tag_name === 'string')
|
|
40
|
+
.map(toRelease)
|
|
41
|
+
.filter((release) => release !== undefined);
|
|
42
|
+
}
|
|
43
|
+
/** Alpha 滚动 tag 的最新 release(不存在或请求失败由调用方处理) */
|
|
44
|
+
export async function fetchAlphaRelease(options = {}) {
|
|
45
|
+
const { data } = await fetchJsonThrough('/releases/tags/Prerelease-Alpha', options);
|
|
46
|
+
const release = toRelease(data);
|
|
47
|
+
if (!release) {
|
|
48
|
+
throw new Error('Prerelease-Alpha 响应缺少 tag_name');
|
|
49
|
+
}
|
|
50
|
+
return release;
|
|
51
|
+
}
|
|
52
|
+
function goArch(arch) {
|
|
53
|
+
switch (arch) {
|
|
54
|
+
case 'x64':
|
|
55
|
+
return 'amd64';
|
|
56
|
+
case 'arm':
|
|
57
|
+
return 'armv7';
|
|
58
|
+
default:
|
|
59
|
+
return arch; // arm64 / armv6 / armv7 / riscv64 / loong64 等直接沿用
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** 资产命名规则:mihomo-<goos>-<goarch>-<tag>.gz(Windows .zip 不支持,本项目 Linux/macOS only) */
|
|
63
|
+
export function assetNamesFor(tag, platform = process.platform, arch = process.arch) {
|
|
64
|
+
const goarch = goArch(arch);
|
|
65
|
+
const names = [`mihomo-${platform}-${goarch}-${tag}.gz`];
|
|
66
|
+
// amd64 直连性能版对 CPU 指令集有要求,老 CPU 用 compatible 通用版
|
|
67
|
+
if (goarch === 'amd64') {
|
|
68
|
+
names.push(`mihomo-${platform}-amd64-compatible-${tag}.gz`);
|
|
69
|
+
}
|
|
70
|
+
return names;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 从 release 资产里选出目标平台的 .gz:按 assetNamesFor 顺序精确匹配。
|
|
74
|
+
* alpha 版资产名形如 mihomo-linux-amd64-alpha-<hexsha>.gz——tag 不是
|
|
75
|
+
* Prerelease-Alpha 时才按 tag 匹配;alpha 走 alphaAssetName。
|
|
76
|
+
*/
|
|
77
|
+
export function selectAsset(release, tag, platform = process.platform, arch = process.arch) {
|
|
78
|
+
for (const name of assetNamesFor(tag, platform, arch)) {
|
|
79
|
+
const found = release.assets.find((asset) => asset.name === name);
|
|
80
|
+
if (found)
|
|
81
|
+
return found;
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
/** alpha 资产名:mihomo-<goos>-<goarch>-alpha-<sha>.gz(取 release 资产里第一个匹配 goos/goarch 的) */
|
|
86
|
+
export function selectAlphaAsset(release, platform = process.platform, arch = process.arch) {
|
|
87
|
+
const goarch = goArch(arch);
|
|
88
|
+
return release.assets.find((asset) => asset.name.startsWith(`mihomo-${platform}-${goarch}-alpha-`) && asset.name.endsWith('.gz'));
|
|
89
|
+
}
|
|
90
|
+
/** 从 alpha 资产名解析短 sha(-v 输出验证用) */
|
|
91
|
+
export function alphaShaFromAssetName(name) {
|
|
92
|
+
const match = /-alpha-([0-9a-f]+)\.gz$/.exec(name);
|
|
93
|
+
return match?.[1];
|
|
94
|
+
}
|
|
95
|
+
/** 语义化版本比较:v1.19.30 > v1.19.9;无法解析时按字符串不等判定 */
|
|
96
|
+
export function isNewerVersion(candidate, current) {
|
|
97
|
+
const parse = (tag) => {
|
|
98
|
+
const match = /^v?(\d+)\.(\d+)\.(\d+)/.exec(tag);
|
|
99
|
+
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : undefined;
|
|
100
|
+
};
|
|
101
|
+
const a = parse(candidate);
|
|
102
|
+
const b = parse(current);
|
|
103
|
+
if (!a || !b)
|
|
104
|
+
return candidate !== current;
|
|
105
|
+
for (let i = 0; i < 3; i += 1) {
|
|
106
|
+
if ((a[i] ?? 0) !== (b[i] ?? 0))
|
|
107
|
+
return (a[i] ?? 0) > (b[i] ?? 0);
|
|
108
|
+
}
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=releases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"releases.js","sourceRoot":"","sources":["../../src/kernel/releases.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
export const SOURCES = [
|
|
2
|
+
{ id: 'direct', label: '直连 GitHub', api: true, dl: true, prefix: '' },
|
|
3
|
+
{
|
|
4
|
+
id: 'gh-proxy.com',
|
|
5
|
+
label: 'gh-proxy.com',
|
|
6
|
+
api: true,
|
|
7
|
+
dl: true,
|
|
8
|
+
prefix: 'https://gh-proxy.com/',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
id: 'ghfast.top',
|
|
12
|
+
label: 'ghfast.top',
|
|
13
|
+
api: false,
|
|
14
|
+
dl: true,
|
|
15
|
+
prefix: 'https://ghfast.top/',
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
export const REPO_API = 'https://api.github.com/repos/MetaCubeX/mihomo';
|
|
19
|
+
export const REPO_DOWNLOAD = 'https://github.com/MetaCubeX/mihomo/releases/download';
|
|
20
|
+
/** JSON 响应上限:releases 列表带巨大 changelog(实测单 release ~156KB),4MB 封顶 */
|
|
21
|
+
export const MAX_JSON_BYTES = 4 * 1024 * 1024;
|
|
22
|
+
/** 资产下载上限 */
|
|
23
|
+
export const MAX_ASSET_BYTES = 128 * 1024 * 1024;
|
|
24
|
+
export class SourceError extends Error {
|
|
25
|
+
attempts;
|
|
26
|
+
constructor(message, attempts) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.attempts = attempts;
|
|
29
|
+
this.name = 'SourceError';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 按配置解析请求源列表(顺序即回退顺序):
|
|
34
|
+
* auto → 全部具备该角色能力的源,直连优先;
|
|
35
|
+
* direct / 具名源 → 锁定单一源,失败不静默回退(用户意图优先);
|
|
36
|
+
* custom → 仅用户自定义前缀(同时用于 API 与下载)。
|
|
37
|
+
*/
|
|
38
|
+
export function resolveSources(config, role) {
|
|
39
|
+
const mode = config?.mode ?? 'auto';
|
|
40
|
+
if (mode === 'auto') {
|
|
41
|
+
return SOURCES.filter((source) => (role === 'api' ? source.api : source.dl));
|
|
42
|
+
}
|
|
43
|
+
if (mode === 'direct') {
|
|
44
|
+
return SOURCES.filter((source) => source.id === 'direct');
|
|
45
|
+
}
|
|
46
|
+
if (mode === 'custom') {
|
|
47
|
+
const prefix = config?.customPrefix;
|
|
48
|
+
if (!prefix) {
|
|
49
|
+
throw new SourceError('自定义下载源前缀未配置', []);
|
|
50
|
+
}
|
|
51
|
+
return [{ id: 'custom', label: '自定义', api: true, dl: true, prefix }];
|
|
52
|
+
}
|
|
53
|
+
const locked = SOURCES.filter((source) => source.id === mode && (role === 'api' ? source.api : source.dl));
|
|
54
|
+
if (locked.length === 0) {
|
|
55
|
+
throw new SourceError(`下载源 ${mode} 不支持${role === 'api' ? 'API 请求' : '资产下载'}`, []);
|
|
56
|
+
}
|
|
57
|
+
return locked;
|
|
58
|
+
}
|
|
59
|
+
/** GitHub API 要求显式 UA;Accept 固定到 vnd.github+json */
|
|
60
|
+
function githubHeaders() {
|
|
61
|
+
return { 'User-Agent': 'mihomo-tui', Accept: 'application/vnd.github+json' };
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 经镜像回退请求 GitHub API:按 resolveSources 顺序尝试,全部失败抛
|
|
65
|
+
* SourceError(attempts 记录每个源的失败原因)。响应超过 MAX_JSON_BYTES 视为该源失败。
|
|
66
|
+
*/
|
|
67
|
+
export async function fetchJsonThrough(path, options = {}) {
|
|
68
|
+
const { fetchImpl = fetch, sourceConfig, timeoutMs = 8000 } = options;
|
|
69
|
+
const sources = resolveSources(sourceConfig, 'api');
|
|
70
|
+
const attempts = [];
|
|
71
|
+
for (const source of sources) {
|
|
72
|
+
try {
|
|
73
|
+
const response = await fetchImpl(`${source.prefix}${REPO_API}${path}`, {
|
|
74
|
+
headers: githubHeaders(),
|
|
75
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
76
|
+
});
|
|
77
|
+
if (!response.ok) {
|
|
78
|
+
attempts.push(`${source.id}: HTTP ${response.status}`);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const buffer = await response.arrayBuffer();
|
|
82
|
+
if (buffer.byteLength > MAX_JSON_BYTES) {
|
|
83
|
+
attempts.push(`${source.id}: 响应超过 ${MAX_JSON_BYTES} 字节上限`);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
return { data: JSON.parse(new TextDecoder().decode(buffer)), source: source.id };
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
attempts.push(`${source.id}: ${err instanceof Error ? err.message : String(err)}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
throw new SourceError(`获取 GitHub 数据失败(已尝试 ${sources.length} 个源)`, attempts);
|
|
93
|
+
}
|
|
94
|
+
/** release 资产下载 URL:tag + 资产名(浏览器下载地址可从 API 响应取,这里按规则拼装) */
|
|
95
|
+
export function assetDownloadUrl(tag, assetName) {
|
|
96
|
+
return `${REPO_DOWNLOAD}/${tag}/${assetName}`;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=sources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sources.js","sourceRoot":"","sources":["../../src/kernel/sources.ts"],"names":[],"mappings":"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"}
|