@dsh-sup/dsh-core-linux-x64 0.1.6-BETA.4 → 0.1.6-BETA.6
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/core.cjs +498 -306
- package/package.json +1 -1
package/core.cjs
CHANGED
|
@@ -60,11 +60,7 @@ var require_exec = __commonJS({
|
|
|
60
60
|
function runAsync(bin, args, opts) {
|
|
61
61
|
const o = opts || {};
|
|
62
62
|
return new Promise((resolve) => {
|
|
63
|
-
|
|
64
|
-
if (!err) {
|
|
65
|
-
resolve({ ok: true, code: "0", stdout: String(stdout == null ? "" : stdout), stderr: String(stderr == null ? "" : stderr), timedOut: false, error: null });
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
63
|
+
const fail = (err) => {
|
|
68
64
|
if (o.logger && o.logger.warn) {
|
|
69
65
|
try {
|
|
70
66
|
o.logger.warn("[exec] (async) " + bin + " " + (args || []).join(" ").slice(0, 80) + " failed: " + (err && err.message || err));
|
|
@@ -75,12 +71,25 @@ var require_exec = __commonJS({
|
|
|
75
71
|
resolve({
|
|
76
72
|
ok: false,
|
|
77
73
|
code: err.status != null ? String(err.status) : null,
|
|
78
|
-
stdout: String(
|
|
79
|
-
stderr: String(
|
|
74
|
+
stdout: String(err.stdout || ""),
|
|
75
|
+
stderr: String(err.stderr || ""),
|
|
80
76
|
timedOut,
|
|
81
77
|
error: err && err.message ? String(err.message) : String(err)
|
|
82
78
|
});
|
|
83
|
-
}
|
|
79
|
+
};
|
|
80
|
+
try {
|
|
81
|
+
execFile(bin, args, Object.assign({}, options(o), { encoding: "utf8" }), (err, stdout, stderr) => {
|
|
82
|
+
if (!err) {
|
|
83
|
+
resolve({ ok: true, code: "0", stdout: String(stdout == null ? "" : stdout), stderr: String(stderr == null ? "" : stderr), timedOut: false, error: null });
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
err.stdout = stdout;
|
|
87
|
+
err.stderr = stderr;
|
|
88
|
+
fail(err);
|
|
89
|
+
});
|
|
90
|
+
} catch (e) {
|
|
91
|
+
fail(e);
|
|
92
|
+
}
|
|
84
93
|
});
|
|
85
94
|
}
|
|
86
95
|
function runOutAsync(bin, args, opts) {
|
|
@@ -503,15 +512,21 @@ var require_probe = __commonJS({
|
|
|
503
512
|
}
|
|
504
513
|
return null;
|
|
505
514
|
}
|
|
506
|
-
function
|
|
507
|
-
if (!Number.isInteger(pid) || pid <= 0) return
|
|
515
|
+
function probeAlive(pid) {
|
|
516
|
+
if (!Number.isInteger(pid) || pid <= 0) return "dead";
|
|
508
517
|
try {
|
|
509
518
|
process.kill(pid, 0);
|
|
510
|
-
return
|
|
519
|
+
return "alive";
|
|
511
520
|
} catch (e) {
|
|
512
|
-
|
|
521
|
+
const code = e && e.code;
|
|
522
|
+
if (code === "EPERM") return "alive";
|
|
523
|
+
if (code === "ESRCH") return "dead";
|
|
524
|
+
return "unknown";
|
|
513
525
|
}
|
|
514
526
|
}
|
|
527
|
+
function isAlive(pid) {
|
|
528
|
+
return probeAlive(pid) === "alive";
|
|
529
|
+
}
|
|
515
530
|
function isZombie(pid) {
|
|
516
531
|
if (!Number.isInteger(pid) || pid <= 0 || isWindows) return false;
|
|
517
532
|
if (isLinux) {
|
|
@@ -611,6 +626,7 @@ var require_probe = __commonJS({
|
|
|
611
626
|
readCmdline: readCmdline2,
|
|
612
627
|
pgrepList,
|
|
613
628
|
isAlive,
|
|
629
|
+
probeAlive,
|
|
614
630
|
isZombie
|
|
615
631
|
};
|
|
616
632
|
}
|
|
@@ -637,6 +653,7 @@ var require_pidlookup = __commonJS({
|
|
|
637
653
|
readCmdline: readCmdline2,
|
|
638
654
|
pgrepList,
|
|
639
655
|
isAlive,
|
|
656
|
+
probeAlive,
|
|
640
657
|
isZombie
|
|
641
658
|
} = require_probe();
|
|
642
659
|
var isLinux = process.platform === "linux";
|
|
@@ -659,6 +676,7 @@ var require_pidlookup = __commonJS({
|
|
|
659
676
|
module2.exports = {
|
|
660
677
|
findListeningPid,
|
|
661
678
|
isAlive,
|
|
679
|
+
probeAlive,
|
|
662
680
|
isZombie,
|
|
663
681
|
readCmdline: readCmdline2,
|
|
664
682
|
normCmdline,
|
|
@@ -929,7 +947,7 @@ var require_version = __commonJS({
|
|
|
929
947
|
var fs2 = require("node:fs");
|
|
930
948
|
var path2 = require("node:path");
|
|
931
949
|
function guardVersion() {
|
|
932
|
-
if (true) return String("0.1.6-BETA.
|
|
950
|
+
if (true) return String("0.1.6-BETA.6");
|
|
933
951
|
try {
|
|
934
952
|
return JSON.parse(fs2.readFileSync(path2.join(__dirname, "..", "..", "package.json"), "utf8")).version || "unknown";
|
|
935
953
|
} catch {
|
|
@@ -949,6 +967,8 @@ var require_main_record = __commonJS({
|
|
|
949
967
|
const reg = () => typeof g.getManagedObjects === "function" ? g.getManagedObjects() : null;
|
|
950
968
|
const logger = () => typeof g.getLogger === "function" ? g.getLogger() : null;
|
|
951
969
|
let fallback = null;
|
|
970
|
+
const DEFAULTS = { restartCount: 0, backoffLevel: 0, backoffUntil: null, crashWindowStart: null, crashWindowRestarts: 0 };
|
|
971
|
+
const buffered = /* @__PURE__ */ new Map();
|
|
952
972
|
function entryOf() {
|
|
953
973
|
const m = reg();
|
|
954
974
|
if (!m || typeof m.get !== "function") return null;
|
|
@@ -964,8 +984,8 @@ var require_main_record = __commonJS({
|
|
|
964
984
|
kind: "dsh",
|
|
965
985
|
id: "main",
|
|
966
986
|
name: "\u4E3B\u5B9E\u4F8B",
|
|
987
|
+
// 不带 guardian(B2-2/B2-3):目录 entry 形态已无该键,守护开关权威在 dsh-main.json。
|
|
967
988
|
desired: "running",
|
|
968
|
-
guardian: true,
|
|
969
989
|
ownership: { ports: [], rootPath: null, unit: null, daemonScript: null, processMode: "spawn", meta: null },
|
|
970
990
|
phase: "stopped",
|
|
971
991
|
lastObserved: null,
|
|
@@ -994,11 +1014,26 @@ var require_main_record = __commonJS({
|
|
|
994
1014
|
}
|
|
995
1015
|
}
|
|
996
1016
|
function storeOf() {
|
|
997
|
-
|
|
1017
|
+
const e = entryOf();
|
|
1018
|
+
if (!e) return fallbackEntryOf();
|
|
1019
|
+
if (buffered.size) flushBuffered(e);
|
|
1020
|
+
return e;
|
|
1021
|
+
}
|
|
1022
|
+
function flushBuffered(e) {
|
|
1023
|
+
let changed = false;
|
|
1024
|
+
for (const [k, v] of buffered) {
|
|
1025
|
+
if (k in DEFAULTS && e[k] === DEFAULTS[k] && e[k] !== v) {
|
|
1026
|
+
e[k] = v;
|
|
1027
|
+
changed = true;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
buffered.clear();
|
|
1031
|
+
if (changed) persistCrashField();
|
|
998
1032
|
}
|
|
999
1033
|
function fieldOf(name, v, write) {
|
|
1000
1034
|
const e = storeOf();
|
|
1001
1035
|
if (write) {
|
|
1036
|
+
if (e === fallback && name in DEFAULTS) buffered.set(name, v);
|
|
1002
1037
|
if (e[name] !== v) {
|
|
1003
1038
|
e[name] = v;
|
|
1004
1039
|
persistCrashField();
|
|
@@ -1280,8 +1315,8 @@ var require_fields = __commonJS({
|
|
|
1280
1315
|
try {
|
|
1281
1316
|
if (m && typeof m.setPhase === "function" && record.entryOf() === e) {
|
|
1282
1317
|
if (e.phase !== ph) m.setPhase("main", ph);
|
|
1283
|
-
} else
|
|
1284
|
-
|
|
1318
|
+
} else {
|
|
1319
|
+
record.fieldOf("phase", ph, true);
|
|
1285
1320
|
}
|
|
1286
1321
|
} catch (e2) {
|
|
1287
1322
|
const l = logger();
|
|
@@ -1308,8 +1343,8 @@ var require_fields = __commonJS({
|
|
|
1308
1343
|
try {
|
|
1309
1344
|
if (m && typeof m.update === "function" && record.entryOf() === e) {
|
|
1310
1345
|
if (e.desired !== want) m.update("main", { desired: want });
|
|
1311
|
-
} else
|
|
1312
|
-
|
|
1346
|
+
} else {
|
|
1347
|
+
record.fieldOf("desired", want, true);
|
|
1313
1348
|
}
|
|
1314
1349
|
} catch (e2) {
|
|
1315
1350
|
const l = logger();
|
|
@@ -1511,6 +1546,7 @@ var require_desired = __commonJS({
|
|
|
1511
1546
|
const intents = () => typeof g.getIntents === "function" ? g.getIntents() : null;
|
|
1512
1547
|
const events = () => typeof g.getEvents === "function" ? g.getEvents() : null;
|
|
1513
1548
|
const configPath = () => typeof g.getConfigPath === "function" ? g.getConfigPath() : null;
|
|
1549
|
+
const configAliases = () => typeof g.getConfigAliases === "function" ? g.getConfigAliases() || [] : [];
|
|
1514
1550
|
const logger = () => typeof g.getLogger === "function" ? g.getLogger() : null;
|
|
1515
1551
|
const setCrashHalted = typeof g.setCrashHalted === "function" ? g.setCrashHalted : () => {
|
|
1516
1552
|
};
|
|
@@ -1592,7 +1628,9 @@ var require_desired = __commonJS({
|
|
|
1592
1628
|
}
|
|
1593
1629
|
}
|
|
1594
1630
|
Object.assign(cur, patch);
|
|
1595
|
-
|
|
1631
|
+
for (const [from, to] of configAliases()) {
|
|
1632
|
+
if (cur[from] !== void 0 && cur[to] !== void 0) delete cur[from];
|
|
1633
|
+
}
|
|
1596
1634
|
writeAtomic(p, JSON.stringify(cur, null, 2), { mode: 384 });
|
|
1597
1635
|
return true;
|
|
1598
1636
|
} catch (e) {
|
|
@@ -1741,6 +1779,7 @@ var require_collaborator = __commonJS({
|
|
|
1741
1779
|
getIntents: g.getIntents,
|
|
1742
1780
|
getEvents: g.getEvents,
|
|
1743
1781
|
getConfigPath: g.getConfigPath,
|
|
1782
|
+
getConfigAliases: g.getConfigAliases,
|
|
1744
1783
|
getLogger: logger,
|
|
1745
1784
|
setCrashHalted: g.setCrashHalted,
|
|
1746
1785
|
setManualRestart: g.setManualRestart,
|
|
@@ -2022,13 +2061,11 @@ var require_specs = __commonJS({
|
|
|
2022
2061
|
const daemons = () => typeof g.getDaemons === "function" ? g.getDaemons() : null;
|
|
2023
2062
|
const logger = () => typeof g.getLogger === "function" ? g.getLogger() : null;
|
|
2024
2063
|
function mainSpec() {
|
|
2025
|
-
const m = state().readMainMeta();
|
|
2026
2064
|
return {
|
|
2027
2065
|
kind: "dsh",
|
|
2028
2066
|
id: "main",
|
|
2029
2067
|
name: "\u4E3B\u5B9E\u4F8B",
|
|
2030
2068
|
desired: state().desired() === "stopped" ? "stopped" : "running",
|
|
2031
|
-
guardian: m.guardian === true,
|
|
2032
2069
|
ownership: {
|
|
2033
2070
|
ports: [{ role: "dsh-main", port: Number(config().targetPort || 3080) }],
|
|
2034
2071
|
rootPath: path2.join(os2.homedir(), ".dsh"),
|
|
@@ -2048,8 +2085,6 @@ var require_specs = __commonJS({
|
|
|
2048
2085
|
kind: "sandbox-instance",
|
|
2049
2086
|
id: inst.id,
|
|
2050
2087
|
name: String(inst.name || inst.id),
|
|
2051
|
-
desired: inst.state && inst.state.desired === "stopped" ? "stopped" : "running",
|
|
2052
|
-
guardian: inst.guardian === true,
|
|
2053
2088
|
ownership: {
|
|
2054
2089
|
ports: [{ role: "inst", port: Number(inst.port) }],
|
|
2055
2090
|
rootPath,
|
|
@@ -2063,7 +2098,7 @@ var require_specs = __commonJS({
|
|
|
2063
2098
|
if (!m || !spec) return;
|
|
2064
2099
|
try {
|
|
2065
2100
|
const existing = m.get(spec.id);
|
|
2066
|
-
if (existing) m.update(spec.id, { desired: spec.desired,
|
|
2101
|
+
if (existing) m.update(spec.id, { desired: spec.desired, name: spec.name, ownership: spec.ownership });
|
|
2067
2102
|
else m.register(spec);
|
|
2068
2103
|
} catch (e) {
|
|
2069
2104
|
const l = logger();
|
|
@@ -3172,6 +3207,14 @@ var require_store2 = __commonJS({
|
|
|
3172
3207
|
}
|
|
3173
3208
|
return out;
|
|
3174
3209
|
}
|
|
3210
|
+
function fileStamp(file) {
|
|
3211
|
+
try {
|
|
3212
|
+
const st = fs2.statSync(file);
|
|
3213
|
+
return st.mtimeMs + ":" + st.size;
|
|
3214
|
+
} catch {
|
|
3215
|
+
return "0";
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3175
3218
|
function saveRecords(file, records) {
|
|
3176
3219
|
try {
|
|
3177
3220
|
fs2.mkdirSync(path2.dirname(file), { recursive: true });
|
|
@@ -3197,7 +3240,7 @@ var require_store2 = __commonJS({
|
|
|
3197
3240
|
}
|
|
3198
3241
|
return out;
|
|
3199
3242
|
}
|
|
3200
|
-
module2.exports = { loadRecords, saveRecords, extraRecords };
|
|
3243
|
+
module2.exports = { loadRecords, saveRecords, extraRecords, fileStamp };
|
|
3201
3244
|
}
|
|
3202
3245
|
});
|
|
3203
3246
|
|
|
@@ -3440,6 +3483,7 @@ var require_alloc = __commonJS({
|
|
|
3440
3483
|
}
|
|
3441
3484
|
r._allocLock = true;
|
|
3442
3485
|
this._xrel = await this._acquireXLock();
|
|
3486
|
+
r._syncFromDisk();
|
|
3443
3487
|
}
|
|
3444
3488
|
_releaseAlloc() {
|
|
3445
3489
|
this._registry._allocLock = false;
|
|
@@ -3694,6 +3738,14 @@ var require_pool = __commonJS({
|
|
|
3694
3738
|
_load() {
|
|
3695
3739
|
this._records = /* @__PURE__ */ new Map();
|
|
3696
3740
|
for (const r of store.loadRecords(this._file)) this._records.set(r.port, r);
|
|
3741
|
+
this._diskStamp = store.fileStamp(this._file);
|
|
3742
|
+
}
|
|
3743
|
+
/** 跨进程对时(B2-5):ports.json 是多进程(守卫 + lan-daemon)共享事实源,各方全量
|
|
3744
|
+
* read-modify-write,陈旧内存快照会在 _save 时把他人新增整段覆盖丢失、或让分配器抢注
|
|
3745
|
+
* 他进程已登记的端口。指纹(mtime+size)变化即重载——所有写口与冲突判读口的入口。
|
|
3746
|
+
* 不动 _allocLock(复位会击穿本进程在飞分配的互斥)。 */
|
|
3747
|
+
_syncFromDisk() {
|
|
3748
|
+
if (store.fileStamp(this._file) !== this._diskStamp) this._load();
|
|
3697
3749
|
}
|
|
3698
3750
|
/** 重新从文件加载(读路径先 reload,以权威文件为准)。 */
|
|
3699
3751
|
reload() {
|
|
@@ -3703,6 +3755,7 @@ var require_pool = __commonJS({
|
|
|
3703
3755
|
}
|
|
3704
3756
|
_save() {
|
|
3705
3757
|
store.saveRecords(this._file, [...this._records.values()]);
|
|
3758
|
+
this._diskStamp = store.fileStamp(this._file);
|
|
3706
3759
|
}
|
|
3707
3760
|
/** 通用记录迁移:owner 命中任一前缀的记录 oldFile 到 newFile,并从旧文件清除。 */
|
|
3708
3761
|
migrateByOwnerPrefix(oldFile, newFile, prefixes) {
|
|
@@ -3711,6 +3764,7 @@ var require_pool = __commonJS({
|
|
|
3711
3764
|
/* 登记(固定 / 用户 / 动态) */
|
|
3712
3765
|
/** 登记固定端口;同端口已被其它固定角色占用则报错;user/动态记录由固定权威覆盖。 */
|
|
3713
3766
|
register(role, port) {
|
|
3767
|
+
this._syncFromDisk();
|
|
3714
3768
|
const p = Number(port);
|
|
3715
3769
|
if (!Number.isInteger(p) || p <= 0 || p > 65535) throw new Error("ports.register: \u975E\u6CD5\u7AEF\u53E3 " + port);
|
|
3716
3770
|
const existing = this._records.get(p);
|
|
@@ -3723,8 +3777,21 @@ var require_pool = __commonJS({
|
|
|
3723
3777
|
this._save();
|
|
3724
3778
|
return p;
|
|
3725
3779
|
}
|
|
3780
|
+
/** 登记固定端口,并保证该 role 在全表唯一(先清除同 role 的其它端口记录再登记)。
|
|
3781
|
+
* 登记表以端口号为键,避让/重绑后新端口是**追加**记录;只 release 旧端口不足以立住不变式
|
|
3782
|
+
* (该调用在内核侧被 catch{} 包住且忽略返回值),残留两条同 role 记录时任何「按 role 取号」
|
|
3783
|
+
* 的读法(本表 get、桌面壳读 ports.json)都可能拿到一个没人监听的端口。
|
|
3784
|
+
* @returns {number} port */
|
|
3785
|
+
registerSole(role, port) {
|
|
3786
|
+
const p = Number(port);
|
|
3787
|
+
for (const [existing, r] of [...this._records]) {
|
|
3788
|
+
if (r.role === role && existing !== p) this._records.delete(existing);
|
|
3789
|
+
}
|
|
3790
|
+
return this.register(role, p);
|
|
3791
|
+
}
|
|
3726
3792
|
/** 登记用户配置端口(实例内部端口等);冲突(固定/保留池/已占)抛错。 */
|
|
3727
3793
|
registerUser(port, owner) {
|
|
3794
|
+
this._syncFromDisk();
|
|
3728
3795
|
const p = Number(port);
|
|
3729
3796
|
if (!Number.isInteger(p) || p <= 0 || p > 65535) throw new Error("ports.registerUser: \u975E\u6CD5\u7AEF\u53E3 " + port);
|
|
3730
3797
|
if (this._records.has(p)) throw new Error("\u7AEF\u53E3 " + p + " \u5DF2\u88AB [" + this._records.get(p).role + "] \u5360\u7528");
|
|
@@ -3736,6 +3803,7 @@ var require_pool = __commonJS({
|
|
|
3736
3803
|
}
|
|
3737
3804
|
/** 按 owner 释放端口(对象删除/关闭时调用)。 */
|
|
3738
3805
|
unregister(owner) {
|
|
3806
|
+
this._syncFromDisk();
|
|
3739
3807
|
let removed = false;
|
|
3740
3808
|
for (const [p, r] of this._records) {
|
|
3741
3809
|
if (r.owner === owner) {
|
|
@@ -3748,6 +3816,7 @@ var require_pool = __commonJS({
|
|
|
3748
3816
|
/** 释放端口:不传 ownerId 按端口号;传了则仅当登记 owner 匹配才释放。空值检查必须先于 owner 比较。
|
|
3749
3817
|
* @returns {boolean} 是否真的释放了一条记录 */
|
|
3750
3818
|
release(port, ownerId) {
|
|
3819
|
+
this._syncFromDisk();
|
|
3751
3820
|
const p = Number(port);
|
|
3752
3821
|
const rec = this._records.get(p);
|
|
3753
3822
|
if (!rec) return false;
|
|
@@ -3757,18 +3826,27 @@ var require_pool = __commonJS({
|
|
|
3757
3826
|
return true;
|
|
3758
3827
|
}
|
|
3759
3828
|
/* 查询 */
|
|
3760
|
-
/** 按 role
|
|
3829
|
+
/** 按 role 取端口(固定端口)。同 role 有多条(老版本避让留下的残留记录)时取**最新登记**:
|
|
3830
|
+
* 桌面壳读 ports.json 用的是同一判据,两侧不许对「哪个端口是当前的」给出不同答案。 */
|
|
3761
3831
|
get(role) {
|
|
3762
|
-
|
|
3763
|
-
|
|
3832
|
+
this._syncFromDisk();
|
|
3833
|
+
let best = null;
|
|
3834
|
+
for (const r of this._records.values()) {
|
|
3835
|
+
if (r.role !== role) continue;
|
|
3836
|
+
if (!best || (r.createdAt || 0) >= (best.createdAt || 0)) best = r;
|
|
3837
|
+
}
|
|
3838
|
+
return best ? best.port : null;
|
|
3764
3839
|
}
|
|
3765
3840
|
isRegistered(port) {
|
|
3841
|
+
this._syncFromDisk();
|
|
3766
3842
|
return this._records.has(Number(port));
|
|
3767
3843
|
}
|
|
3768
3844
|
recordOf(port) {
|
|
3845
|
+
this._syncFromDisk();
|
|
3769
3846
|
return this._records.get(Number(port)) || null;
|
|
3770
3847
|
}
|
|
3771
3848
|
byOwner(owner) {
|
|
3849
|
+
this._syncFromDisk();
|
|
3772
3850
|
for (const r of this._records.values()) if (r.owner === owner) return r.port;
|
|
3773
3851
|
return null;
|
|
3774
3852
|
}
|
|
@@ -3781,6 +3859,7 @@ var require_pool = __commonJS({
|
|
|
3781
3859
|
}
|
|
3782
3860
|
/** 全部端口清单(按端口升序)。 */
|
|
3783
3861
|
list() {
|
|
3862
|
+
this._syncFromDisk();
|
|
3784
3863
|
return [...this._records.values()].sort((a, b) => a.port - b.port);
|
|
3785
3864
|
}
|
|
3786
3865
|
/** 只读聚合:本注册表 + 同目录下其它注册表文件(去重,本表优先)。
|
|
@@ -3805,6 +3884,7 @@ var require_pool = __commonJS({
|
|
|
3805
3884
|
}
|
|
3806
3885
|
/** 显式登记已分配端口(复用持久化端口时调用)。 */
|
|
3807
3886
|
allocateMark(port, role, owner) {
|
|
3887
|
+
this._syncFromDisk();
|
|
3808
3888
|
const p = Number(port);
|
|
3809
3889
|
if (!this._records.has(p)) {
|
|
3810
3890
|
this._records.set(p, { port: p, role: role || "dynamic", owner: owner || "dynamic", createdAt: Date.now() });
|
|
@@ -3999,6 +4079,7 @@ var require_collaborators = __commonJS({
|
|
|
3999
4079
|
var { createCtl } = require_collaborator3();
|
|
4000
4080
|
var { createOrphanScan } = require_collaborator4();
|
|
4001
4081
|
var { ENTRY_FIELDS, PROC_FIELDS } = require_field_tables();
|
|
4082
|
+
var { aliases: CONFIG_ALIASES } = require_domain_config();
|
|
4002
4083
|
var THIN_SPEC = {
|
|
4003
4084
|
ctl: {
|
|
4004
4085
|
call: "_ctlCall",
|
|
@@ -4088,6 +4169,7 @@ var require_collaborators = __commonJS({
|
|
|
4088
4169
|
const state = createStateStore({
|
|
4089
4170
|
getConfig: () => host2.config,
|
|
4090
4171
|
getConfigPath: () => host2.configPath,
|
|
4172
|
+
getConfigAliases: () => CONFIG_ALIASES,
|
|
4091
4173
|
getLogger: () => host2.logger,
|
|
4092
4174
|
getEvents: () => host2.events,
|
|
4093
4175
|
getManagedObjects: () => host2.managedObjects,
|
|
@@ -4133,7 +4215,6 @@ var require_collaborators = __commonJS({
|
|
|
4133
4215
|
return host2;
|
|
4134
4216
|
};
|
|
4135
4217
|
host2._dshEntry = () => state.dshEntry();
|
|
4136
|
-
host2._mainFallbackEntry = () => state.fallbackEntry();
|
|
4137
4218
|
host2._persistCrashField = () => state.persistCrashField();
|
|
4138
4219
|
host2._mStore = () => state.store();
|
|
4139
4220
|
host2._mField = function(name, v) {
|
|
@@ -6278,7 +6359,7 @@ var require_bootstrap = __commonJS({
|
|
|
6278
6359
|
}
|
|
6279
6360
|
function _registerFixedPorts(host2) {
|
|
6280
6361
|
ports.register("dsh-main", host2.config.targetPort);
|
|
6281
|
-
ports.
|
|
6362
|
+
ports.registerSole("supervisor-api", host2.config.apiPort);
|
|
6282
6363
|
}
|
|
6283
6364
|
function _bindNativeDshCommand(host2) {
|
|
6284
6365
|
try {
|
|
@@ -6362,9 +6443,9 @@ var require_api_rebind = __commonJS({
|
|
|
6362
6443
|
bind._tries = 0;
|
|
6363
6444
|
host2.api = server;
|
|
6364
6445
|
try {
|
|
6365
|
-
portsShared.
|
|
6446
|
+
portsShared.registerSole("supervisor-api", host2.config.apiPort);
|
|
6366
6447
|
} catch (e) {
|
|
6367
|
-
host2.logger.warn("ports.
|
|
6448
|
+
host2.logger.warn("ports.registerSole(supervisor-api) \u5931\u8D25: " + (e && e.message || e));
|
|
6368
6449
|
}
|
|
6369
6450
|
host2.events.append("api_listening", { host: host2.config.apiHost, port: host2.config.apiPort });
|
|
6370
6451
|
host2.logger.info("api listening on " + host2.config.apiHost + ":" + host2.config.apiPort);
|
|
@@ -6392,17 +6473,13 @@ var require_api_rebind = __commonJS({
|
|
|
6392
6473
|
host2.api = server;
|
|
6393
6474
|
const prev = host2.config.apiPort;
|
|
6394
6475
|
if (port !== prev) {
|
|
6395
|
-
try {
|
|
6396
|
-
portsShared.release(prev, "system:supervisor-api");
|
|
6397
|
-
} catch {
|
|
6398
|
-
}
|
|
6399
6476
|
host2.config.apiPort = port;
|
|
6400
6477
|
if (host2.configPath) host2.persistConfigPatch({ apiPort: port });
|
|
6401
6478
|
}
|
|
6402
6479
|
try {
|
|
6403
|
-
portsShared.
|
|
6480
|
+
portsShared.registerSole("supervisor-api", port);
|
|
6404
6481
|
} catch (e) {
|
|
6405
|
-
host2.logger.warn("ports.
|
|
6482
|
+
host2.logger.warn("ports.registerSole(supervisor-api) \u5931\u8D25: " + e.message);
|
|
6406
6483
|
}
|
|
6407
6484
|
host2.events.append("api_listening", { host: host2.config.apiHost, port });
|
|
6408
6485
|
host2.logger.info("api listening on " + host2.config.apiHost + ":" + port);
|
|
@@ -7804,8 +7881,8 @@ var require_instance_adapter = __commonJS({
|
|
|
7804
7881
|
return { ok: running, error: running ? null : "\u6C99\u7BB1\u5B9E\u4F8B\u672A\u8FD0\u884C" };
|
|
7805
7882
|
},
|
|
7806
7883
|
/** 目录项 <- 实例域状态对齐(监督拍后调用):实例已删 -> 注销(防死登记);存在 -> 经
|
|
7807
|
-
* sandboxSpec 同步 name/guardian/ownership + phase
|
|
7808
|
-
*
|
|
7884
|
+
* sandboxSpec 同步 name/guardian/ownership + phase 落目录词表。沙箱不申报 desired
|
|
7885
|
+
* (运行意图无第二落点,B2-1),观测路径因此不可能改写任何意图。 */
|
|
7809
7886
|
_syncSandboxRegistryEntry(entry) {
|
|
7810
7887
|
const d = depsOf(this);
|
|
7811
7888
|
if (!entry || !d.managedObjects() || !d.instances()) return;
|
|
@@ -7838,6 +7915,9 @@ var require_decide = __commonJS({
|
|
|
7838
7915
|
"src/app/main/decide.js"(exports2, module2) {
|
|
7839
7916
|
"use strict";
|
|
7840
7917
|
var pidlook = require_pidlookup();
|
|
7918
|
+
function startDeadlinePassed(deadline, now) {
|
|
7919
|
+
return !!(deadline && now > deadline);
|
|
7920
|
+
}
|
|
7841
7921
|
var DEPS = /* @__PURE__ */ new WeakMap();
|
|
7842
7922
|
function depsOf(host2) {
|
|
7843
7923
|
let d = DEPS.get(host2);
|
|
@@ -7925,7 +8005,7 @@ var require_decide = __commonJS({
|
|
|
7925
8005
|
upgradeHold: d.upgradeHold() === true,
|
|
7926
8006
|
manualRestart: d.manualRestart() === true,
|
|
7927
8007
|
spawnBlocked: !!(d.mSpawnBlockedUntil() && now < d.mSpawnBlockedUntil()),
|
|
7928
|
-
startDeadlinePassed:
|
|
8008
|
+
startDeadlinePassed: startDeadlinePassed(d.mStartDeadline(), now),
|
|
7929
8009
|
restartDue: d.mRestartAt() === null || now >= d.mRestartAt(),
|
|
7930
8010
|
backoffDue: d.mBackoffUntil() === null || now >= d.mBackoffUntil(),
|
|
7931
8011
|
// `_shouldRun()` 有两个否决位,快照必须建模(crashHalted/sessionHalting),否则影子每拍
|
|
@@ -8000,7 +8080,9 @@ var require_decide = __commonJS({
|
|
|
8000
8080
|
_decideCrashRestart(reason) {
|
|
8001
8081
|
return decideCrashRestart(reason);
|
|
8002
8082
|
}
|
|
8003
|
-
}
|
|
8083
|
+
},
|
|
8084
|
+
// 非 host 方法:纯谓词导出,controller 与本文件快照判据共用(facets 只安装 methods)。
|
|
8085
|
+
startDeadlinePassed
|
|
8004
8086
|
};
|
|
8005
8087
|
}
|
|
8006
8088
|
});
|
|
@@ -8051,6 +8133,7 @@ var require_controller = __commonJS({
|
|
|
8051
8133
|
"use strict";
|
|
8052
8134
|
var pidlook = require_pidlookup();
|
|
8053
8135
|
var monitor = require_monitor();
|
|
8136
|
+
var { startDeadlinePassed } = require_decide();
|
|
8054
8137
|
var DEPS = /* @__PURE__ */ new WeakMap();
|
|
8055
8138
|
function depsOf(host2) {
|
|
8056
8139
|
let d = DEPS.get(host2);
|
|
@@ -8155,6 +8238,9 @@ var require_controller = __commonJS({
|
|
|
8155
8238
|
mStartDeadline() {
|
|
8156
8239
|
return host2._mStartDeadline();
|
|
8157
8240
|
},
|
|
8241
|
+
mSetStartDeadline(v) {
|
|
8242
|
+
return host2._mSetStartDeadline(v);
|
|
8243
|
+
},
|
|
8158
8244
|
mRestartAt() {
|
|
8159
8245
|
return host2._mRestartAt();
|
|
8160
8246
|
},
|
|
@@ -8302,7 +8388,9 @@ var require_controller = __commonJS({
|
|
|
8302
8388
|
}
|
|
8303
8389
|
case "STARTING": {
|
|
8304
8390
|
if (portUp && healthOk) d.main().enterRunning();
|
|
8305
|
-
else if (
|
|
8391
|
+
else if (d.mStartDeadline() === null) {
|
|
8392
|
+
d.mSetStartDeadline(Date.now() + d.config().startTimeoutMs);
|
|
8393
|
+
} else if (startDeadlinePassed(d.mStartDeadline(), Date.now())) d.main().beginRestart("start_timeout", { countCrash: true });
|
|
8306
8394
|
break;
|
|
8307
8395
|
}
|
|
8308
8396
|
case "RUNNING": {
|
|
@@ -9556,13 +9644,7 @@ var require_process_wait = __commonJS({
|
|
|
9556
9644
|
async function waitProcessExit(pid, timeoutMs) {
|
|
9557
9645
|
const deadline = Date.now() + timeoutMs;
|
|
9558
9646
|
while (Date.now() < deadline) {
|
|
9559
|
-
|
|
9560
|
-
try {
|
|
9561
|
-
alive = pidlook.isAlive ? pidlook.isAlive(pid) : true;
|
|
9562
|
-
} catch {
|
|
9563
|
-
alive = false;
|
|
9564
|
-
}
|
|
9565
|
-
if (!alive) return true;
|
|
9647
|
+
if (!pidlook.isAlive(pid)) return true;
|
|
9566
9648
|
await new Promise((r) => setTimeout(r, 200));
|
|
9567
9649
|
}
|
|
9568
9650
|
return false;
|
|
@@ -9680,13 +9762,15 @@ var require_process3 = __commonJS({
|
|
|
9680
9762
|
} catch {
|
|
9681
9763
|
}
|
|
9682
9764
|
}
|
|
9765
|
+
/** 判活(platform/pidlookup.probeAlive 单源):unknown 不 fail-open——必须有第二条证据
|
|
9766
|
+
* (ctl 端口属主正是该 pid 且 cmdline 匹配本服务)才认活,否则按死走 reclaim/spawn。
|
|
9767
|
+
* fail-open 会让已死 daemon 被判活,此后既不接管也不拉起,永不自愈。 */
|
|
9683
9768
|
_pidAlive(pid) {
|
|
9684
9769
|
if (!pid) return false;
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
9689
|
-
}
|
|
9770
|
+
const st = pidlook.probeAlive(pid);
|
|
9771
|
+
if (st === "alive") return true;
|
|
9772
|
+
if (st === "dead") return false;
|
|
9773
|
+
return this._ctlOwnerPid() === pid;
|
|
9690
9774
|
}
|
|
9691
9775
|
/** ctl 端口的监听者是否就是本服务进程(cmdline 匹配)。 */
|
|
9692
9776
|
_ctlOwnerPid() {
|
|
@@ -10192,6 +10276,7 @@ var require_identity = __commonJS({
|
|
|
10192
10276
|
"use strict";
|
|
10193
10277
|
var fs2 = require("node:fs");
|
|
10194
10278
|
var path2 = require("node:path");
|
|
10279
|
+
var { isAlive } = require_pidlookup();
|
|
10195
10280
|
function lockPid(p) {
|
|
10196
10281
|
if (!p) return null;
|
|
10197
10282
|
try {
|
|
@@ -10201,14 +10286,8 @@ var require_identity = __commonJS({
|
|
|
10201
10286
|
return null;
|
|
10202
10287
|
}
|
|
10203
10288
|
}
|
|
10204
|
-
function
|
|
10205
|
-
|
|
10206
|
-
try {
|
|
10207
|
-
process.kill(pid, 0);
|
|
10208
|
-
return true;
|
|
10209
|
-
} catch (e) {
|
|
10210
|
-
return !!(e && e.code === "EPERM");
|
|
10211
|
-
}
|
|
10289
|
+
function pidAlive2(pid) {
|
|
10290
|
+
return isAlive(pid);
|
|
10212
10291
|
}
|
|
10213
10292
|
function acquireLock2(p, onErr) {
|
|
10214
10293
|
if (!p) return false;
|
|
@@ -10233,7 +10312,7 @@ var require_identity = __commonJS({
|
|
|
10233
10312
|
if (attempt()) return true;
|
|
10234
10313
|
const holder = lockPid(p);
|
|
10235
10314
|
if (holder === process.pid) return true;
|
|
10236
|
-
if (holder !== null &&
|
|
10315
|
+
if (holder !== null && pidAlive2(holder)) return false;
|
|
10237
10316
|
try {
|
|
10238
10317
|
fs2.unlinkSync(p);
|
|
10239
10318
|
} catch {
|
|
@@ -10271,7 +10350,7 @@ var require_identity = __commonJS({
|
|
|
10271
10350
|
}
|
|
10272
10351
|
module2.exports = {
|
|
10273
10352
|
// 测试缝:锁的取/放/读主是纯 fs + kill(0) 语义,直接导出给回归用。
|
|
10274
|
-
_lockPrimitives: { acquireLock: acquireLock2, releaseLock: releaseLock2, lockPid, pidAlive },
|
|
10353
|
+
_lockPrimitives: { acquireLock: acquireLock2, releaseLock: releaseLock2, lockPid, pidAlive: pidAlive2 },
|
|
10275
10354
|
methods: {
|
|
10276
10355
|
_lanLockPath() {
|
|
10277
10356
|
const d = depsOf(this);
|
|
@@ -10589,7 +10668,7 @@ var require_ports2 = __commonJS({
|
|
|
10589
10668
|
"use strict";
|
|
10590
10669
|
var probe = require_probe2();
|
|
10591
10670
|
var ports = require_ports().shared;
|
|
10592
|
-
var SIBLING_REGISTRIES = ["ports-
|
|
10671
|
+
var SIBLING_REGISTRIES = ["ports-router.json"];
|
|
10593
10672
|
var DEPS = /* @__PURE__ */ new WeakMap();
|
|
10594
10673
|
function depsOf(host2) {
|
|
10595
10674
|
let d = DEPS.get(host2);
|
|
@@ -11185,24 +11264,32 @@ var require_lan2 = __commonJS({
|
|
|
11185
11264
|
}
|
|
11186
11265
|
}
|
|
11187
11266
|
return {
|
|
11188
|
-
/** 远程控制模式唯一写入口(off|lan|wan)。
|
|
11267
|
+
/** 远程控制模式唯一写入口(off|lan|wan)。mode 必须显式给出——缺省归 'off' 会让
|
|
11268
|
+
* 漏字段的请求静默关闭远程控制。wan 前置闸:必须先有合规访问令牌。 */
|
|
11189
11269
|
setRemoteMode(id, mode) {
|
|
11190
|
-
|
|
11270
|
+
if (mode !== "off" && mode !== "lan" && mode !== "wan") {
|
|
11271
|
+
return { ok: false, error: "mode \u5FC5\u987B\u663E\u5F0F\u7ED9\u51FA\uFF08off|lan|wan\uFF09" };
|
|
11272
|
+
}
|
|
11191
11273
|
const target = resolveTarget(id);
|
|
11192
11274
|
if (!target) return { ok: false, error: "\u5B9E\u4F8B\u4E0D\u5B58\u5728" };
|
|
11193
|
-
if (
|
|
11275
|
+
if (mode === "wan") {
|
|
11194
11276
|
const v = validateWanAccess({ remoteToken: target.remoteToken });
|
|
11195
11277
|
if (!v.ok) return { ok: false, error: v.error };
|
|
11196
11278
|
}
|
|
11197
11279
|
if (target.kind === "main") {
|
|
11198
|
-
if (target.mode !==
|
|
11280
|
+
if (target.mode !== mode) applyMainIntent({ remoteMode: mode }, { id: "main", name: "\u539F\u751F DSH", mode });
|
|
11199
11281
|
return { ok: true };
|
|
11200
11282
|
}
|
|
11201
|
-
return g.getInstances().updateInstance(id, { remoteMode:
|
|
11283
|
+
return g.getInstances().updateInstance(id, { remoteMode: mode });
|
|
11202
11284
|
},
|
|
11203
|
-
/**
|
|
11285
|
+
/** 访问令牌唯一写入口。token 必须是字符串:空串=显式清除;缺字段/非字符串=请求方缺陷,
|
|
11286
|
+
* 拒绝而非当作清除(漏 token 字段清掉访问凭据是事故,不是语义)。lan 模式可无令牌,
|
|
11287
|
+
* wan 模式的守门由执行边界闸兜住。 */
|
|
11204
11288
|
setRemoteToken(id, token) {
|
|
11205
|
-
|
|
11289
|
+
if (typeof token !== "string") {
|
|
11290
|
+
return { ok: false, error: "token \u5FC5\u987B\u663E\u5F0F\u7ED9\u51FA\uFF08\u7A7A\u4E32=\u6E05\u9664\uFF09" };
|
|
11291
|
+
}
|
|
11292
|
+
const next = token;
|
|
11206
11293
|
if (next && !remoteTokenStrength(next).ok) {
|
|
11207
11294
|
return { ok: false, error: "\u8FDC\u7A0B\u8BBF\u95EE\u4EE4\u724C\uFF08remoteToken\uFF09\u81F3\u5C11 8 \u4F4D" };
|
|
11208
11295
|
}
|
|
@@ -11286,16 +11373,17 @@ var require_env_catalog = __commonJS({
|
|
|
11286
11373
|
const v = ex2.runOut(bin, (Array.isArray(args) ? args : []).concat(["--version"]), { timeoutMs: 3e3 });
|
|
11287
11374
|
return v ? v.trim() || null : null;
|
|
11288
11375
|
}
|
|
11376
|
+
function whichVersionAsync(bin, args) {
|
|
11377
|
+
return ex2.runOutAsync(bin, (Array.isArray(args) ? args : []).concat(["--version"]), { timeoutMs: 3e3 }).then((v) => v ? v.trim() || null : null);
|
|
11378
|
+
}
|
|
11289
11379
|
var _verCache = /* @__PURE__ */ new Map();
|
|
11290
11380
|
var CACHE_TTL = 1e4;
|
|
11291
|
-
function
|
|
11381
|
+
function cacheKey(bin, args) {
|
|
11292
11382
|
const a = Array.isArray(args) ? args : [];
|
|
11293
|
-
|
|
11294
|
-
|
|
11295
|
-
|
|
11296
|
-
|
|
11297
|
-
const v = whichVersion(bin, a);
|
|
11298
|
-
_verCache.set(key, { at: now, v });
|
|
11383
|
+
return bin + "\0" + a.join("\0");
|
|
11384
|
+
}
|
|
11385
|
+
function cacheSet(key, v) {
|
|
11386
|
+
_verCache.set(key, { at: Date.now(), v });
|
|
11299
11387
|
if (_verCache.size > 16) {
|
|
11300
11388
|
let oldest = null;
|
|
11301
11389
|
for (const [k, e] of _verCache) if (!oldest || e.at < oldest.at) oldest = { k, at: e.at };
|
|
@@ -11303,6 +11391,19 @@ var require_env_catalog = __commonJS({
|
|
|
11303
11391
|
}
|
|
11304
11392
|
return v;
|
|
11305
11393
|
}
|
|
11394
|
+
function cachedWhichVersion(bin, args) {
|
|
11395
|
+
const key = cacheKey(bin, args);
|
|
11396
|
+
const hit = _verCache.get(key);
|
|
11397
|
+
const now = Date.now();
|
|
11398
|
+
if (hit && now - hit.at < CACHE_TTL) return hit.v;
|
|
11399
|
+
return cacheSet(key, whichVersion(bin, args));
|
|
11400
|
+
}
|
|
11401
|
+
function cachedWhichVersionAsync(bin, args) {
|
|
11402
|
+
const key = cacheKey(bin, args);
|
|
11403
|
+
const hit = _verCache.get(key);
|
|
11404
|
+
if (hit && Date.now() - hit.at < CACHE_TTL) return Promise.resolve(hit.v);
|
|
11405
|
+
return whichVersionAsync(bin, args).then((v) => cacheSet(key, v));
|
|
11406
|
+
}
|
|
11306
11407
|
var MIN_NODE_DEFAULT = "v22.12.0";
|
|
11307
11408
|
var _runtimeMetaCache = null;
|
|
11308
11409
|
var _runtimeMetaAt = 0;
|
|
@@ -11329,50 +11430,68 @@ var require_env_catalog = __commonJS({
|
|
|
11329
11430
|
}
|
|
11330
11431
|
return true;
|
|
11331
11432
|
}
|
|
11332
|
-
function
|
|
11333
|
-
const v = cachedWhichVersion("node");
|
|
11433
|
+
function nodeVerdict(v) {
|
|
11334
11434
|
if (!v) return null;
|
|
11335
11435
|
const m = /v?(\d+\.\d+\.\d+)/.exec(String(v));
|
|
11336
11436
|
const ver = m ? m[1] : String(v).trim();
|
|
11337
11437
|
const min = String(runtimeMeta().minNode || MIN_NODE_DEFAULT);
|
|
11338
11438
|
return { version: "v" + ver, min, meets: verAtLeast(ver, min) };
|
|
11339
11439
|
}
|
|
11440
|
+
function probeNode() {
|
|
11441
|
+
return nodeVerdict(cachedWhichVersion("node"));
|
|
11442
|
+
}
|
|
11443
|
+
function probeNodeAsync() {
|
|
11444
|
+
return cachedWhichVersionAsync("node").then(nodeVerdict);
|
|
11445
|
+
}
|
|
11340
11446
|
function probeNpm() {
|
|
11341
11447
|
const l = runtime.npmLauncher();
|
|
11342
11448
|
return cachedWhichVersion(l.program, l.args);
|
|
11343
11449
|
}
|
|
11450
|
+
function probeNpmAsync() {
|
|
11451
|
+
const l = runtime.npmLauncher();
|
|
11452
|
+
return cachedWhichVersionAsync(l.program, l.args);
|
|
11453
|
+
}
|
|
11344
11454
|
var SYSTEM_ENTRIES = {
|
|
11345
|
-
node: { label: "Node.js", required: true, probe: probeNode },
|
|
11346
|
-
npm: { label: "npm", required: true, probe: probeNpm },
|
|
11347
|
-
git: { label: "git", required: false, probe: () => cachedWhichVersion("git") }
|
|
11455
|
+
node: { label: "Node.js", required: true, probe: probeNode, probeAsync: probeNodeAsync },
|
|
11456
|
+
npm: { label: "npm", required: true, probe: probeNpm, probeAsync: probeNpmAsync },
|
|
11457
|
+
git: { label: "git", required: false, probe: () => cachedWhichVersion("git"), probeAsync: () => cachedWhichVersionAsync("git") }
|
|
11348
11458
|
};
|
|
11459
|
+
function entryView(id, e, v) {
|
|
11460
|
+
if (v && typeof v === "object" && typeof v.meets === "boolean") {
|
|
11461
|
+
return {
|
|
11462
|
+
label: e.label,
|
|
11463
|
+
required: e.required,
|
|
11464
|
+
state: v.meets ? "ok" : "outdated",
|
|
11465
|
+
version: v.version,
|
|
11466
|
+
min: v.min,
|
|
11467
|
+
meets: v.meets,
|
|
11468
|
+
detail: v.meets ? v.version : v.version + "\uFF08\u4F4E\u4E8E\u6700\u4F4E\u8981\u6C42 " + v.min + "\uFF09"
|
|
11469
|
+
};
|
|
11470
|
+
}
|
|
11471
|
+
return { label: e.label, required: e.required, state: v ? "ok" : "missing", detail: v };
|
|
11472
|
+
}
|
|
11349
11473
|
var EnvCatalog = class {
|
|
11350
11474
|
constructor(config) {
|
|
11351
11475
|
this.config = config || {};
|
|
11352
11476
|
}
|
|
11353
|
-
/**
|
|
11354
|
-
* ok = 存在且满足门槛(Node 需 >= 壳投放的 minNode);outdated = 存在但低于门槛;missing = 不存在。
|
|
11355
|
-
* 兼容:detail 保持字符串,新增字段(version/min/meets)放 detail 之外,不破坏既有契约。 */
|
|
11477
|
+
/** 系统二进制条目探测(同步口径):{ id: 条目视图 }。仅限启动早期/CLI;HTTP 路径用 probeAsync。 */
|
|
11356
11478
|
probe() {
|
|
11357
11479
|
const out = {};
|
|
11358
11480
|
for (const [id, e] of Object.entries(SYSTEM_ENTRIES)) {
|
|
11359
|
-
|
|
11360
|
-
if (v && typeof v === "object" && typeof v.meets === "boolean") {
|
|
11361
|
-
out[id] = {
|
|
11362
|
-
label: e.label,
|
|
11363
|
-
required: e.required,
|
|
11364
|
-
state: v.meets ? "ok" : "outdated",
|
|
11365
|
-
version: v.version,
|
|
11366
|
-
min: v.min,
|
|
11367
|
-
meets: v.meets,
|
|
11368
|
-
detail: v.meets ? v.version : v.version + "\uFF08\u4F4E\u4E8E\u6700\u4F4E\u8981\u6C42 " + v.min + "\uFF09"
|
|
11369
|
-
};
|
|
11370
|
-
} else {
|
|
11371
|
-
out[id] = { label: e.label, required: e.required, state: v ? "ok" : "missing", detail: v };
|
|
11372
|
-
}
|
|
11481
|
+
out[id] = entryView(id, e, e.probe() || null);
|
|
11373
11482
|
}
|
|
11374
11483
|
return out;
|
|
11375
11484
|
}
|
|
11485
|
+
/** 异步口径:条目并行探测(最坏 3s x N 的串行冻结 -> 全程不阻塞事件循环)。 */
|
|
11486
|
+
async probeAsync() {
|
|
11487
|
+
const entries = Object.entries(SYSTEM_ENTRIES);
|
|
11488
|
+
const vals = await Promise.all(entries.map(([, e]) => e.probeAsync()));
|
|
11489
|
+
const out = {};
|
|
11490
|
+
entries.forEach(([id, e], i) => {
|
|
11491
|
+
out[id] = entryView(id, e, vals[i] || null);
|
|
11492
|
+
});
|
|
11493
|
+
return out;
|
|
11494
|
+
}
|
|
11376
11495
|
/** 内核更新依赖条目(单写入者契约:安装/重启归桌面壳,守卫只读 corePackageName 查版本状态)。
|
|
11377
11496
|
* id 仍为 selfUpdate 以兼容既有 /env/status 消费方。 */
|
|
11378
11497
|
selfUpdateEntry() {
|
|
@@ -11416,20 +11535,22 @@ var require_env = __commonJS({
|
|
|
11416
11535
|
var fs2 = require("node:fs");
|
|
11417
11536
|
var { EnvCatalog } = require_env_catalog();
|
|
11418
11537
|
var runtimeContract = require_runtime();
|
|
11419
|
-
function envCatalogSummary(that) {
|
|
11538
|
+
async function envCatalogSummary(that) {
|
|
11420
11539
|
const cat = new EnvCatalog(that.config);
|
|
11421
11540
|
const extra = {};
|
|
11422
11541
|
const d = that.dshenvStatus();
|
|
11423
11542
|
extra.dsh = cat.dshEntry(d.binOk, d.installed, d.bin);
|
|
11424
11543
|
extra.selfUpdate = cat.selfUpdateEntry();
|
|
11425
|
-
return cat.summary(extra);
|
|
11544
|
+
return cat.summary(extra, await cat.probeAsync());
|
|
11426
11545
|
}
|
|
11427
11546
|
module2.exports = {
|
|
11428
11547
|
methods: {
|
|
11429
|
-
|
|
11548
|
+
// 异步:全部子进程探测(EnvCatalog/契约回读)走异步口径——本方法挂在 /env/status 上,
|
|
11549
|
+
// 同步 execFileSync 会把守卫事件循环冻结在探测超时上(心跳/自愈停摆,B1-6 收口)。
|
|
11550
|
+
async envStatus() {
|
|
11430
11551
|
const c = runtimeContract.read() || {};
|
|
11431
|
-
const cat = new EnvCatalog(this.config).
|
|
11432
|
-
const en = this.nativeManager && typeof this.nativeManager.checkEnvironment === "function" ? this.nativeManager.checkEnvironment() : null;
|
|
11552
|
+
const cat = await new EnvCatalog(this.config).probeAsync();
|
|
11553
|
+
const en = this.nativeManager && typeof this.nativeManager.checkEnvironment === "function" ? await this.nativeManager.checkEnvironment() : null;
|
|
11433
11554
|
return {
|
|
11434
11555
|
node: { detected: cat.node.detail || null, runtime: c.nodeVersion || null, path: c.nodePath || null },
|
|
11435
11556
|
// npm 与 node 同构三段:detected = 本机实跑版本;runtime = 壳实跑后投放的版本
|
|
@@ -11441,7 +11562,7 @@ var require_env = __commonJS({
|
|
|
11441
11562
|
ok: cat.node.state === "ok" && cat.npm.state === "ok",
|
|
11442
11563
|
npmRoot: en ? en.npmRoot : null,
|
|
11443
11564
|
// EnvCatalog 声明式视图(面板环境卡用)
|
|
11444
|
-
catalog: envCatalogSummary(this),
|
|
11565
|
+
catalog: await envCatalogSummary(this),
|
|
11445
11566
|
// 平台能力矩阵:三平台静态档位 x 实际工具探测;前端据此做能力感知呈现与降级提示。
|
|
11446
11567
|
capabilities: (() => {
|
|
11447
11568
|
try {
|
|
@@ -11667,15 +11788,16 @@ var require_versions = __commonJS({
|
|
|
11667
11788
|
return { ok: false, error: e.message };
|
|
11668
11789
|
}
|
|
11669
11790
|
},
|
|
11670
|
-
/** 读磁盘上运行位的自报版本:spawn --version
|
|
11791
|
+
/** 读磁盘上运行位的自报版本:spawn --version,解析版本行(异步:20s 上限的同步 exec
|
|
11792
|
+
* 在 HTTP 路径上会冻结守卫整条事件循环,判据不变)。
|
|
11671
11793
|
* 条件是 updatable(sea-binary 或 launcher):launcher 的 bin 入口同样可执行,
|
|
11672
11794
|
* 若只认 sea-binary 则发布态永远读不到磁盘实况,updatePending 恒 false。
|
|
11673
11795
|
* source-shell 不支持:其 --version 报的是开发目录版本,与 npm 安装无关。 */
|
|
11674
|
-
_readBinarySelfVersion() {
|
|
11796
|
+
async _readBinarySelfVersion() {
|
|
11675
11797
|
const dep = deploy.detect();
|
|
11676
11798
|
if (!dep.updatable || !dep.runningTarget) return null;
|
|
11677
11799
|
try {
|
|
11678
|
-
const out = ex2.
|
|
11800
|
+
const out = await ex2.runOutAsync(dep.runningTarget, ["--version"], { timeoutMs: 2e4 });
|
|
11679
11801
|
const m = /dsh-supervisor v([^\s]+)/.exec(out);
|
|
11680
11802
|
return m ? m[1] : null;
|
|
11681
11803
|
} catch {
|
|
@@ -11697,18 +11819,18 @@ var require_versions = __commonJS({
|
|
|
11697
11819
|
}
|
|
11698
11820
|
return dir;
|
|
11699
11821
|
},
|
|
11700
|
-
/** 本地视角(无网络 I/O
|
|
11701
|
-
|
|
11822
|
+
/** 本地视角(无网络 I/O;git 子进程异步执行——同步 spawn 会冻结事件循环,
|
|
11823
|
+
* 消费方含 HTTP 路径,见 exec.js 同步仅限启动早期/CLI 的纪律)。 */
|
|
11824
|
+
async guardVersionLocal() {
|
|
11702
11825
|
const d = depsOf(this);
|
|
11703
11826
|
const root = d.vcsRoot();
|
|
11704
|
-
|
|
11705
|
-
|
|
11827
|
+
const [rawCommit, rawUp] = await Promise.all([
|
|
11828
|
+
ex2.runOutAsync("git", ["-C", root, "rev-parse", "--short", "HEAD"]),
|
|
11829
|
+
ex2.runOutAsync("git", ["-C", root, "rev-parse", "--abbrev-ref", "@{u}"])
|
|
11830
|
+
]);
|
|
11831
|
+
const commit = (rawCommit || "").trim() || null;
|
|
11706
11832
|
let upstream = "local";
|
|
11707
|
-
|
|
11708
|
-
const up = (ex2.runOut("git", ["-C", root, "rev-parse", "--abbrev-ref", "@{u}"]) || "").trim();
|
|
11709
|
-
if (up) upstream = "git-repo";
|
|
11710
|
-
} catch {
|
|
11711
|
-
}
|
|
11833
|
+
if ((rawUp || "").trim()) upstream = "git-repo";
|
|
11712
11834
|
return { version: d.guardVersion(), runningVersion: d.guardVersion(), commit, updateAvailable: false, upstream, latest: d.guardVersion() };
|
|
11713
11835
|
},
|
|
11714
11836
|
/** 完整版本检查(async):本地 commit + 远端 fetch 比对。
|
|
@@ -11716,20 +11838,17 @@ var require_versions = __commonJS({
|
|
|
11716
11838
|
* fetch 失败/超时只降级为「本地视图」,不抛错。 */
|
|
11717
11839
|
async guardVersionCheck() {
|
|
11718
11840
|
const d = depsOf(this);
|
|
11719
|
-
const base = d.guardVersionLocal();
|
|
11841
|
+
const base = await d.guardVersionLocal();
|
|
11720
11842
|
if (base.upstream !== "git-repo") return base;
|
|
11721
11843
|
const root = d.vcsRoot();
|
|
11722
11844
|
const fetchOk = await ex2.runOutAsync("git", ["-C", root, "fetch", "--quiet"], { timeoutMs: 1e4 }) !== null;
|
|
11723
11845
|
if (!fetchOk) return base;
|
|
11724
11846
|
let updateAvailable = false;
|
|
11725
|
-
|
|
11726
|
-
|
|
11727
|
-
updateAvailable = parseInt(ahead, 10) > 0;
|
|
11728
|
-
} catch {
|
|
11729
|
-
}
|
|
11847
|
+
const ahead = (await ex2.runOutAsync("git", ["-C", root, "rev-list", "--count", "HEAD..@{u}"], { timeoutMs: 1e4 }) || "").trim();
|
|
11848
|
+
updateAvailable = parseInt(ahead, 10) > 0;
|
|
11730
11849
|
const dep = deploy.detect();
|
|
11731
11850
|
let diskVersion = null;
|
|
11732
|
-
if (dep.updatable) diskVersion = d.readBinarySelfVersion();
|
|
11851
|
+
if (dep.updatable) diskVersion = await d.readBinarySelfVersion();
|
|
11733
11852
|
const updatePending = !!(diskVersion && diskVersion !== d.guardVersion());
|
|
11734
11853
|
return { ...base, diskVersion, updatePending };
|
|
11735
11854
|
}
|
|
@@ -11813,7 +11932,9 @@ var require_access = __commonJS({
|
|
|
11813
11932
|
return { ok: false, error: e.message };
|
|
11814
11933
|
}
|
|
11815
11934
|
}
|
|
11816
|
-
}
|
|
11935
|
+
},
|
|
11936
|
+
// settings 门面的写口核验件(B2-4):lan-panel 共用同一「写后读回」口径,不各写各的。
|
|
11937
|
+
verifyPersisted
|
|
11817
11938
|
};
|
|
11818
11939
|
}
|
|
11819
11940
|
});
|
|
@@ -11920,9 +12041,8 @@ var require_netinfo = __commonJS({
|
|
|
11920
12041
|
var require_lan_panel = __commonJS({
|
|
11921
12042
|
"src/app/settings/lan-panel.js"(exports2, module2) {
|
|
11922
12043
|
"use strict";
|
|
11923
|
-
var fs2 = require("node:fs");
|
|
11924
12044
|
var netInfo = require_netinfo();
|
|
11925
|
-
var {
|
|
12045
|
+
var { verifyPersisted } = require_access();
|
|
11926
12046
|
var DEPS = /* @__PURE__ */ new WeakMap();
|
|
11927
12047
|
function depsOf(host2) {
|
|
11928
12048
|
let d = DEPS.get(host2);
|
|
@@ -11932,6 +12052,7 @@ var require_lan_panel = __commonJS({
|
|
|
11932
12052
|
logger: () => host2.logger,
|
|
11933
12053
|
events: () => host2.events,
|
|
11934
12054
|
configPath: () => host2.configPath,
|
|
12055
|
+
state: () => host2.state,
|
|
11935
12056
|
api: () => host2.api,
|
|
11936
12057
|
lanPanelStatus: () => host2.lanPanelStatus(),
|
|
11937
12058
|
apiRebind: () => host2._apiRebind()
|
|
@@ -11973,14 +12094,9 @@ var require_lan_panel = __commonJS({
|
|
|
11973
12094
|
d.config().apiHost = host2;
|
|
11974
12095
|
let persistError = null;
|
|
11975
12096
|
if (d.configPath()) {
|
|
11976
|
-
|
|
11977
|
-
|
|
11978
|
-
|
|
11979
|
-
writeAtomic(d.configPath(), JSON.stringify(doc, null, 2), { mode: 384 });
|
|
11980
|
-
} catch (e) {
|
|
11981
|
-
persistError = "persist apiHost: " + e.message;
|
|
11982
|
-
d.logger().error(persistError);
|
|
11983
|
-
}
|
|
12097
|
+
d.state().persistConfigPatch({ apiHost: host2 });
|
|
12098
|
+
persistError = verifyPersisted(d.configPath(), { apiHost: host2 });
|
|
12099
|
+
if (persistError) d.logger().error(persistError);
|
|
11984
12100
|
}
|
|
11985
12101
|
if (changed && d.api() && typeof d.api().close === "function") d.apiRebind();
|
|
11986
12102
|
if (d.events()) d.events().append("lan_panel_changed", { enabled: on });
|
|
@@ -12598,6 +12714,8 @@ var require_pool2 = __commonJS({
|
|
|
12598
12714
|
this._bus = new FollowBus({ logger: this.logger });
|
|
12599
12715
|
this._schedules = /* @__PURE__ */ new Map();
|
|
12600
12716
|
this._seq = 0;
|
|
12717
|
+
this._attachGen = /* @__PURE__ */ new Map();
|
|
12718
|
+
this._journalFn = o.journal || capture.captureJournal;
|
|
12601
12719
|
this._backfillAt = /* @__PURE__ */ new Map();
|
|
12602
12720
|
this._poolFile = o.poolFile ? path2.resolve(o.poolFile) : null;
|
|
12603
12721
|
this._loaded = false;
|
|
@@ -12622,6 +12740,7 @@ var require_pool2 = __commonJS({
|
|
|
12622
12740
|
const unit = s.unit || prev && prev.unit || null;
|
|
12623
12741
|
const file = s.file || prev && prev.file || null;
|
|
12624
12742
|
this._sources.set(id, { kind, unit, file, lines: prev && prev.lines || [] });
|
|
12743
|
+
this._attachGen.set(id, (this._attachGen.get(id) || 0) + 1);
|
|
12625
12744
|
const rec = this._records.get(id);
|
|
12626
12745
|
if (rec) rec.kind = kind;
|
|
12627
12746
|
return true;
|
|
@@ -12646,9 +12765,16 @@ var require_pool2 = __commonJS({
|
|
|
12646
12765
|
return this._commit(id, hit.token, hit.source);
|
|
12647
12766
|
}
|
|
12648
12767
|
if (src.unit && kinds.isCaptured(src.kind)) {
|
|
12649
|
-
|
|
12768
|
+
const gen = this._attachGen.get(id) || 0;
|
|
12769
|
+
const fresh = () => (this._attachGen.get(id) || 0) === gen ? this._sources.get(id) : null;
|
|
12770
|
+
Promise.resolve().then(() => {
|
|
12771
|
+
const cur = fresh();
|
|
12772
|
+
return cur ? this._journalFn(cur.unit, { logger: this.logger }) : null;
|
|
12773
|
+
}).then((j) => {
|
|
12650
12774
|
if (!j) return;
|
|
12651
|
-
|
|
12775
|
+
const cur = fresh();
|
|
12776
|
+
if (!cur) return;
|
|
12777
|
+
if (cur.file) this._persistLine(id, cur.file, j.line);
|
|
12652
12778
|
this._commit(id, j.token, j.source);
|
|
12653
12779
|
}).catch(() => {
|
|
12654
12780
|
});
|
|
@@ -12716,6 +12842,7 @@ var require_pool2 = __commonJS({
|
|
|
12716
12842
|
this._backfillAt.delete(id);
|
|
12717
12843
|
const src = this._sources.get(id);
|
|
12718
12844
|
if (src && src.lines && src.lines.length) src.lines.length = 0;
|
|
12845
|
+
this._attachGen.set(id, (this._attachGen.get(id) || 0) + 1);
|
|
12719
12846
|
this._records.delete(id);
|
|
12720
12847
|
this._persistPool();
|
|
12721
12848
|
this._bus.emit(id, null, null);
|
|
@@ -13646,7 +13773,6 @@ var require_core5 = __commonJS({
|
|
|
13646
13773
|
host2._routerFacade = null;
|
|
13647
13774
|
host2._lc = null;
|
|
13648
13775
|
host2._dshMainLive = null;
|
|
13649
|
-
host2._fallbackEntry = null;
|
|
13650
13776
|
host2._lastStateBody = null;
|
|
13651
13777
|
host2._shadowSeq = 0;
|
|
13652
13778
|
host2._shadowConsistentBeats = 0;
|
|
@@ -17193,10 +17319,11 @@ var require_oauth = __commonJS({
|
|
|
17193
17319
|
const d = deps || {};
|
|
17194
17320
|
const ports = d.ports;
|
|
17195
17321
|
const openInBrowser = d.openInBrowser;
|
|
17196
|
-
const st = { _ccLogin: null, _ccLoginPromise: null, _ccLoginResolve: null, _ccLoginReject: null };
|
|
17322
|
+
const st = { _ccLogin: null, _ccLoginPromise: null, _ccLoginResolve: null, _ccLoginReject: null, _ccLoginRound: 0 };
|
|
17197
17323
|
async function commandcodeLoginStart() {
|
|
17198
17324
|
const STUDIO_BASE = "https://commandcode.ai";
|
|
17199
17325
|
const state = crypto.randomBytes(32).toString("base64url");
|
|
17326
|
+
const roundId = ++st._ccLoginRound;
|
|
17200
17327
|
if (st._ccLogin && st._ccLogin.server) {
|
|
17201
17328
|
const oldState = st._ccLogin.state;
|
|
17202
17329
|
try {
|
|
@@ -17258,6 +17385,11 @@ var require_oauth = __commonJS({
|
|
|
17258
17385
|
if (b.length > 1e4) req.destroy();
|
|
17259
17386
|
});
|
|
17260
17387
|
req.on("end", () => {
|
|
17388
|
+
if (st._ccLoginRound !== roundId) {
|
|
17389
|
+
res.writeHead(410);
|
|
17390
|
+
res.end(callbackJson({ success: false, error: "Stale login round" }));
|
|
17391
|
+
return;
|
|
17392
|
+
}
|
|
17261
17393
|
try {
|
|
17262
17394
|
const j = JSON.parse(b || "{}");
|
|
17263
17395
|
if (j && typeof j === "object" && "error" in j) {
|
|
@@ -17348,6 +17480,7 @@ var require_oauth = __commonJS({
|
|
|
17348
17480
|
});
|
|
17349
17481
|
st._ccLoginPromise = promise;
|
|
17350
17482
|
const tmpProfile = openInBrowser(authUrl, () => {
|
|
17483
|
+
if (st._ccLoginRound !== roundId) return;
|
|
17351
17484
|
if (st._ccLoginReject) {
|
|
17352
17485
|
const r = st._ccLoginReject;
|
|
17353
17486
|
st._ccLoginReject = null;
|
|
@@ -19234,10 +19367,7 @@ var require_model3 = __commonJS({
|
|
|
19234
19367
|
inst.state.lastError = null;
|
|
19235
19368
|
}
|
|
19236
19369
|
if (inst.state) inst.state.phase = inst.state.phase || "STOPPED";
|
|
19237
|
-
if (inst.state
|
|
19238
|
-
const p = inst.state.phase;
|
|
19239
|
-
inst.state.desired = p === "RUNNING" || p === "STARTING" || p === "INSTALLING" ? "running" : "stopped";
|
|
19240
|
-
}
|
|
19370
|
+
if (inst.state) delete inst.state.desired;
|
|
19241
19371
|
return inst;
|
|
19242
19372
|
}
|
|
19243
19373
|
function createRecord(payload, id) {
|
|
@@ -19262,7 +19392,7 @@ var require_model3 = __commonJS({
|
|
|
19262
19392
|
protectHome: payload.protectHome === void 0 ? false : !!payload.protectHome
|
|
19263
19393
|
// 资源配额不接收户输入:启动时由 governor 按机器预算与活跃实例数推导。
|
|
19264
19394
|
},
|
|
19265
|
-
state: { phase: "STOPPED",
|
|
19395
|
+
state: { phase: "STOPPED", restartCount: 0, backoffLevel: 0, lastProbeOk: null },
|
|
19266
19396
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
19267
19397
|
};
|
|
19268
19398
|
}
|
|
@@ -19502,6 +19632,7 @@ var require_lifecycle = __commonJS({
|
|
|
19502
19632
|
"use strict";
|
|
19503
19633
|
var fs2 = require("node:fs");
|
|
19504
19634
|
var monitor = require_monitor();
|
|
19635
|
+
var ports = require_ports().shared;
|
|
19505
19636
|
var guardian = require_guardian();
|
|
19506
19637
|
var sandbox = require_sandbox();
|
|
19507
19638
|
var governor = require_governor();
|
|
@@ -19544,7 +19675,7 @@ var require_lifecycle = __commonJS({
|
|
|
19544
19675
|
logger.info && logger.info("cleaned stale transient unit: " + unit);
|
|
19545
19676
|
}
|
|
19546
19677
|
}
|
|
19547
|
-
function _systemdStart(inst) {
|
|
19678
|
+
function _systemdStart(inst, opts) {
|
|
19548
19679
|
try {
|
|
19549
19680
|
const cmdArr = sandbox.effectiveCommand(instancesRoot, deps.dshBin, inst);
|
|
19550
19681
|
if (!cmdArr || !cmdArr.length) return { ok: false, error: "\u5B9E\u4F8B\u672A\u914D\u7F6E\u542F\u52A8\u547D\u4EE4" };
|
|
@@ -19560,6 +19691,15 @@ var require_lifecycle = __commonJS({
|
|
|
19560
19691
|
logger.warn && logger.warn("[" + inst.id + "] " + msg);
|
|
19561
19692
|
return { ok: false, error: msg };
|
|
19562
19693
|
}
|
|
19694
|
+
const takenBy = ports.recordOf(inst.port);
|
|
19695
|
+
if (takenBy && takenBy.owner !== "inst:" + inst.id) {
|
|
19696
|
+
const msg = "PORT_TAKEN:" + (takenBy.owner || takenBy.role);
|
|
19697
|
+
inst.state.lastError = msg;
|
|
19698
|
+
store.save();
|
|
19699
|
+
if (events) events.append("inst_start_refused", { id: inst.id, name: inst.name, error: msg });
|
|
19700
|
+
logger.warn && logger.warn("[" + inst.id + "] " + msg);
|
|
19701
|
+
return { ok: false, error: msg };
|
|
19702
|
+
}
|
|
19563
19703
|
if (probe(inst).running) return { ok: false, error: "\u7AEF\u53E3 " + inst.port + " \u5DF2\u88AB\u5360\u7528" };
|
|
19564
19704
|
const alloc = governor.currentAllocation(store.instances, inst.id, machineFactsNow());
|
|
19565
19705
|
inst.state.allocation = alloc;
|
|
@@ -19579,6 +19719,12 @@ var require_lifecycle = __commonJS({
|
|
|
19579
19719
|
inst.state.phase = "STARTING";
|
|
19580
19720
|
inst.state.startAt = Date.now();
|
|
19581
19721
|
inst.state.lastError = null;
|
|
19722
|
+
if (opts && opts.manual) {
|
|
19723
|
+
inst.state.restartCount = 0;
|
|
19724
|
+
inst.state.backoffLevel = 0;
|
|
19725
|
+
inst.state.backoffUntil = null;
|
|
19726
|
+
inst.state.lastFailAt = null;
|
|
19727
|
+
}
|
|
19582
19728
|
store.save();
|
|
19583
19729
|
if (inst.port && hooks.onInstanceStart) hooks.onInstanceStart(inst);
|
|
19584
19730
|
if (events) events.append("inst_started", { id: inst.id, port: inst.port });
|
|
@@ -19604,10 +19750,6 @@ var require_lifecycle = __commonJS({
|
|
|
19604
19750
|
return { ok: false, error: adm.error };
|
|
19605
19751
|
}
|
|
19606
19752
|
}
|
|
19607
|
-
if (inst.state.desired !== "running") {
|
|
19608
|
-
inst.state.desired = "running";
|
|
19609
|
-
store.save();
|
|
19610
|
-
}
|
|
19611
19753
|
store.ensureDirs(inst);
|
|
19612
19754
|
const dshEntry = sandbox.dshEntry(instancesRoot, inst);
|
|
19613
19755
|
if (!fs2.existsSync(dshEntry)) {
|
|
@@ -19616,10 +19758,9 @@ var require_lifecycle = __commonJS({
|
|
|
19616
19758
|
return { ok: true, installing: true };
|
|
19617
19759
|
}
|
|
19618
19760
|
}
|
|
19619
|
-
return _systemdStart(inst);
|
|
19761
|
+
return _systemdStart(inst, opts);
|
|
19620
19762
|
}
|
|
19621
|
-
function stop(id
|
|
19622
|
-
const transient = !!(opts && opts.intent === "transient");
|
|
19763
|
+
function stop(id) {
|
|
19623
19764
|
const inst = store.instances.find((i) => i.id === id);
|
|
19624
19765
|
if (!inst) return { ok: false, error: "\u5B9E\u4F8B\u4E0D\u5B58\u5728" };
|
|
19625
19766
|
if (!isSandboxSupported()) return { ok: false, error: "\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301\u6C99\u7BB1\u5B9E\u4F8B\uFF08\u80FD\u529B\u77E9\u9635\u89C1 GET /env/status \u7684 capabilities.sandboxLaunch\uFF1B\u9650\u989D\u6267\u884C\u6863\u4F4D\u89C1 capabilities.sandboxEnforcement\uFF09" };
|
|
@@ -19641,7 +19782,6 @@ var require_lifecycle = __commonJS({
|
|
|
19641
19782
|
}
|
|
19642
19783
|
inst.state.phase = "STOPPED";
|
|
19643
19784
|
inst.state.usage = null;
|
|
19644
|
-
if (!transient) inst.state.desired = "stopped";
|
|
19645
19785
|
runtime.delete(inst.id);
|
|
19646
19786
|
store.save();
|
|
19647
19787
|
if (inst.port && hooks.onInstanceStop) hooks.onInstanceStop(inst);
|
|
@@ -19697,15 +19837,17 @@ var require_lifecycle = __commonJS({
|
|
|
19697
19837
|
}).catch(() => {
|
|
19698
19838
|
});
|
|
19699
19839
|
}
|
|
19840
|
+
}
|
|
19841
|
+
function governSweep() {
|
|
19700
19842
|
const roster = _sandboxRoster();
|
|
19701
|
-
if (!roster.length) return;
|
|
19843
|
+
if (!roster.length) return { ok: true, entries: 0 };
|
|
19702
19844
|
let plan;
|
|
19703
19845
|
try {
|
|
19704
19846
|
const f = machineFactsNow();
|
|
19705
19847
|
plan = governor.decide({ totalMemBytes: f.totalMemBytes, cpuCount: f.cpuCount, roster });
|
|
19706
19848
|
} catch (e) {
|
|
19707
|
-
logger.warn && logger.warn("
|
|
19708
|
-
return;
|
|
19849
|
+
logger.warn && logger.warn("govern decide \u5931\u8D25: " + (e && e.message));
|
|
19850
|
+
return { ok: false, error: e && e.message || String(e) };
|
|
19709
19851
|
}
|
|
19710
19852
|
const now = Date.now();
|
|
19711
19853
|
for (const entry of plan.entries) {
|
|
@@ -19730,19 +19872,21 @@ var require_lifecycle = __commonJS({
|
|
|
19730
19872
|
}
|
|
19731
19873
|
}
|
|
19732
19874
|
}
|
|
19733
|
-
if (!entry.violation
|
|
19875
|
+
if (!entry.violation) continue;
|
|
19734
19876
|
const v = entry.violation;
|
|
19735
19877
|
const kindLabel = v.kind === "memory" ? "\u5185\u5B58" : "CPU";
|
|
19736
19878
|
const reason = "\u8D44\u6E90\u8FDD\u89C4:" + kindLabel + "\u6301\u7EED\u8D85\u9650(\u5B9E\u9645 " + v.actual + "/\u9650\u989D " + v.target + ")";
|
|
19737
|
-
if (events) events.append("inst_resource_violation", { id:
|
|
19738
|
-
logger.warn && logger.warn("[" +
|
|
19879
|
+
if (events) events.append("inst_resource_violation", { id: target.id, name: target.name, kind: v.kind, actual: v.actual, target: v.target });
|
|
19880
|
+
logger.warn && logger.warn("[" + target.id + "] " + reason);
|
|
19739
19881
|
try {
|
|
19740
|
-
service.stopUnit("dsh-web@" +
|
|
19882
|
+
service.stopUnit("dsh-web@" + target.id, Object.assign({ timeoutMs: 2e4 }, sandbox.launchCtx(instancesRoot, deps.dshBin, target)));
|
|
19741
19883
|
} catch (e) {
|
|
19742
|
-
logger.warn && logger.warn("[" +
|
|
19884
|
+
logger.warn && logger.warn("[" + target.id + "] \u8FDD\u89C4\u505C\u5355\u5143\u5F02\u5E38: " + (e && e.message));
|
|
19743
19885
|
}
|
|
19744
|
-
stateMachine.restart(stateDeps(),
|
|
19886
|
+
stateMachine.restart(stateDeps(), target, reason);
|
|
19745
19887
|
}
|
|
19888
|
+
store.save();
|
|
19889
|
+
return { ok: true, entries: plan.entries.length };
|
|
19746
19890
|
}
|
|
19747
19891
|
function supervise(id) {
|
|
19748
19892
|
const inst = store.instances.find((i) => i.id === id);
|
|
@@ -19836,7 +19980,7 @@ var require_lifecycle = __commonJS({
|
|
|
19836
19980
|
}
|
|
19837
19981
|
return { ok: true };
|
|
19838
19982
|
}
|
|
19839
|
-
return { _prepareSystemd, start, stop, probe, probeInstance, supervise };
|
|
19983
|
+
return { _prepareSystemd, start, stop, probe, probeInstance, supervise, governSweep };
|
|
19840
19984
|
}
|
|
19841
19985
|
module2.exports = { createLifecycle };
|
|
19842
19986
|
}
|
|
@@ -20145,7 +20289,7 @@ var require_upgrade = __commonJS({
|
|
|
20145
20289
|
tasks.stepState(task.id, tasks.get(task.id).steps.indexOf(s), "running");
|
|
20146
20290
|
}
|
|
20147
20291
|
try {
|
|
20148
|
-
await lifecycle.stop(id
|
|
20292
|
+
await lifecycle.stop(id);
|
|
20149
20293
|
} catch {
|
|
20150
20294
|
}
|
|
20151
20295
|
if (task) {
|
|
@@ -20193,7 +20337,7 @@ var require_upgrade = __commonJS({
|
|
|
20193
20337
|
tasks.log(task.id, "\u81EA\u52A8\u56DE\u6EDA\u5230 " + oldVersion + "\u2026");
|
|
20194
20338
|
}
|
|
20195
20339
|
try {
|
|
20196
|
-
const rs = await lifecycle.stop(id
|
|
20340
|
+
const rs = await lifecycle.stop(id);
|
|
20197
20341
|
if (rs && rs.ok === false && task) tasks.log(task.id, "\u56DE\u6EDA\u524D\u505C\u6B62\u5931\u8D25\uFF08\u7EE7\u7EED\u56DE\u88C5\u65E7\u7248\uFF09\uFF1A" + (rs.error || ""));
|
|
20198
20342
|
} catch (e) {
|
|
20199
20343
|
if (task) tasks.log(task.id, "\u56DE\u6EDA\u524D\u505C\u6B62\u5F02\u5E38\uFF08\u7EE7\u7EED\u56DE\u88C5\u65E7\u7248\uFF09\uFF1A" + (e && e.message || e));
|
|
@@ -20480,6 +20624,11 @@ var require_ops2 = __commonJS({
|
|
|
20480
20624
|
} catch {
|
|
20481
20625
|
}
|
|
20482
20626
|
}
|
|
20627
|
+
try {
|
|
20628
|
+
lifecycle.governSweep();
|
|
20629
|
+
} catch (e) {
|
|
20630
|
+
logger.warn && logger.warn("governSweep: " + (e && e.message));
|
|
20631
|
+
}
|
|
20483
20632
|
}, intervalMs || 5e3);
|
|
20484
20633
|
}
|
|
20485
20634
|
return { list, addInstance, removeInstance, updateInstance, startTimer };
|
|
@@ -20772,12 +20921,16 @@ var require_instance = __commonJS({
|
|
|
20772
20921
|
startInstance(id, opts) {
|
|
20773
20922
|
return this._lifecycle.start(id, opts);
|
|
20774
20923
|
}
|
|
20775
|
-
stopInstance(id
|
|
20776
|
-
return this._lifecycle.stop(id
|
|
20924
|
+
stopInstance(id) {
|
|
20925
|
+
return this._lifecycle.stop(id);
|
|
20777
20926
|
}
|
|
20778
20927
|
supervise(id) {
|
|
20779
20928
|
return this._lifecycle.supervise(id);
|
|
20780
20929
|
}
|
|
20930
|
+
/** 治理单拍(B2-6e):心跳拍末由 onBeatDone 调一次,全花名册 decide+下发+违规处置。 */
|
|
20931
|
+
governSweep() {
|
|
20932
|
+
return this._lifecycle.governSweep();
|
|
20933
|
+
}
|
|
20781
20934
|
probeInstance(id) {
|
|
20782
20935
|
return this._lifecycle.probeInstance(id);
|
|
20783
20936
|
}
|
|
@@ -21099,8 +21252,6 @@ var require_market = __commonJS({
|
|
|
21099
21252
|
this._ts = 0;
|
|
21100
21253
|
this._inFlight = null;
|
|
21101
21254
|
this.buildBudgetMs = opts.buildBudgetMs || 24e4;
|
|
21102
|
-
this._deadline = 0;
|
|
21103
|
-
this._truncatedSources = /* @__PURE__ */ new Set();
|
|
21104
21255
|
this.loadFromDisk();
|
|
21105
21256
|
}
|
|
21106
21257
|
loadFromDisk() {
|
|
@@ -21147,19 +21298,18 @@ var require_market = __commonJS({
|
|
|
21147
21298
|
}
|
|
21148
21299
|
async buildIndex() {
|
|
21149
21300
|
const start = Date.now();
|
|
21150
|
-
|
|
21151
|
-
this._truncatedSources = /* @__PURE__ */ new Set();
|
|
21301
|
+
const bctx = { deadline: start + this.buildBudgetMs, truncated: /* @__PURE__ */ new Set() };
|
|
21152
21302
|
try {
|
|
21153
|
-
return await this._buildIndexInner(start);
|
|
21303
|
+
return await this._buildIndexInner(start, bctx);
|
|
21154
21304
|
} finally {
|
|
21155
|
-
|
|
21305
|
+
bctx.deadline = 0;
|
|
21156
21306
|
}
|
|
21157
21307
|
}
|
|
21158
|
-
/**
|
|
21159
|
-
_budgetExhausted() {
|
|
21160
|
-
return
|
|
21308
|
+
/** 预算是否已耗尽(供各源的批次循环调用;无 ctx = 单源直调,不设预算)。 */
|
|
21309
|
+
_budgetExhausted(bctx) {
|
|
21310
|
+
return !!bctx && bctx.deadline > 0 && Date.now() >= bctx.deadline;
|
|
21161
21311
|
}
|
|
21162
|
-
async _buildIndexInner(start) {
|
|
21312
|
+
async _buildIndexInner(start, bctx) {
|
|
21163
21313
|
const plugins = [];
|
|
21164
21314
|
const seen = /* @__PURE__ */ new Set();
|
|
21165
21315
|
const add = (p) => {
|
|
@@ -21167,11 +21317,11 @@ var require_market = __commonJS({
|
|
|
21167
21317
|
seen.add(p.name);
|
|
21168
21318
|
plugins.push(p);
|
|
21169
21319
|
};
|
|
21170
|
-
const npm = await this.indexNpm();
|
|
21320
|
+
const npm = await this.indexNpm(bctx);
|
|
21171
21321
|
npm.forEach(add);
|
|
21172
|
-
const gh = await this.indexGithub();
|
|
21322
|
+
const gh = await this.indexGithub(bctx);
|
|
21173
21323
|
gh.forEach(add);
|
|
21174
|
-
const community = await this.indexCommunity();
|
|
21324
|
+
const community = await this.indexCommunity(bctx);
|
|
21175
21325
|
community.forEach(add);
|
|
21176
21326
|
for (const p of plugins) {
|
|
21177
21327
|
p.category = p.category || classify(p);
|
|
@@ -21179,7 +21329,7 @@ var require_market = __commonJS({
|
|
|
21179
21329
|
}
|
|
21180
21330
|
plugins.sort((a, b) => (b.stars || 0) - (a.stars || 0));
|
|
21181
21331
|
const prev = this._cache;
|
|
21182
|
-
const truncated =
|
|
21332
|
+
const truncated = bctx.truncated;
|
|
21183
21333
|
if (prev && prev.plugins && prev.plugins.length > 0 && truncated.size > 0) {
|
|
21184
21334
|
const freshNames = new Set(plugins.map((pp) => pp.name));
|
|
21185
21335
|
const kept = prev.plugins.filter((pp) => truncated.has(pp.source) && !freshNames.has(pp.name));
|
|
@@ -21214,8 +21364,8 @@ var require_market = __commonJS({
|
|
|
21214
21364
|
this.logger.info && this.logger.info("market index built in " + (Date.now() - start) + "ms: " + plugins.length + " plugins (npm=" + npm.length + ", gh=" + gh.length + ", community=" + community.length + ")");
|
|
21215
21365
|
return this._cache;
|
|
21216
21366
|
}
|
|
21217
|
-
/** npm 源:搜 deepseek-harness 受限 dsh,逐个检测 dsh.bundle。 */
|
|
21218
|
-
async indexNpm() {
|
|
21367
|
+
/** npm 源:搜 deepseek-harness 受限 dsh,逐个检测 dsh.bundle。bctx 为本次构建的预算上下文(见 buildIndex)。 */
|
|
21368
|
+
async indexNpm(bctx) {
|
|
21219
21369
|
const out = [];
|
|
21220
21370
|
const queries = ["keywords:deepseek-harness", "keywords:dsh-bundle", "keywords:dsh-plugin"];
|
|
21221
21371
|
const allNames = /* @__PURE__ */ new Set();
|
|
@@ -21242,8 +21392,8 @@ var require_market = __commonJS({
|
|
|
21242
21392
|
this.logger.info && this.logger.info("npm candidates: " + names.length);
|
|
21243
21393
|
const batch = 8;
|
|
21244
21394
|
for (let i = 0; i < names.length; i += batch) {
|
|
21245
|
-
if (this._budgetExhausted()) {
|
|
21246
|
-
|
|
21395
|
+
if (this._budgetExhausted(bctx)) {
|
|
21396
|
+
bctx.truncated.add("npm");
|
|
21247
21397
|
this.logger.warn && this.logger.warn("market: npm \u6E90\u9884\u7B97\u8017\u5C3D\uFF0C\u5DF2\u5904\u7406 " + i + "/" + names.length + " \u4E2A\u5019\u9009");
|
|
21248
21398
|
break;
|
|
21249
21399
|
}
|
|
@@ -21273,7 +21423,7 @@ var require_market = __commonJS({
|
|
|
21273
21423
|
return fetchLatest(await this._npmOrigin(), name);
|
|
21274
21424
|
}
|
|
21275
21425
|
/** GitHub 源:搜 topic:dsh-plugin + deepseek-harness,逐个验证 dsh.bundle。 */
|
|
21276
|
-
async indexGithub() {
|
|
21426
|
+
async indexGithub(bctx) {
|
|
21277
21427
|
const out = [];
|
|
21278
21428
|
const topics = ["dsh-plugin", "deepseek-harness"];
|
|
21279
21429
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -21303,7 +21453,7 @@ var require_market = __commonJS({
|
|
|
21303
21453
|
return repoPkg(fullName);
|
|
21304
21454
|
}
|
|
21305
21455
|
/** 社区列表:抓 awesome-dsh-plugin README 白名单(官方社区维护的精选)。 */
|
|
21306
|
-
async indexCommunity() {
|
|
21456
|
+
async indexCommunity(bctx) {
|
|
21307
21457
|
const out = [];
|
|
21308
21458
|
try {
|
|
21309
21459
|
const md = await rawGet("awesome-dsh-plugin/awesome-dsh-plugin/main/README.md", false, 3e4);
|
|
@@ -21315,8 +21465,8 @@ var require_market = __commonJS({
|
|
|
21315
21465
|
}
|
|
21316
21466
|
const seenName = /* @__PURE__ */ new Set();
|
|
21317
21467
|
for (let i = 0; i < links.length; i += 8) {
|
|
21318
|
-
if (this._budgetExhausted()) {
|
|
21319
|
-
|
|
21468
|
+
if (this._budgetExhausted(bctx)) {
|
|
21469
|
+
bctx.truncated.add("community");
|
|
21320
21470
|
this.logger.warn && this.logger.warn("market: community \u6E90\u9884\u7B97\u8017\u5C3D\uFF0C\u5DF2\u5904\u7406 " + i + "/" + links.length + " \u4E2A\u5019\u9009");
|
|
21321
21471
|
break;
|
|
21322
21472
|
}
|
|
@@ -21838,7 +21988,7 @@ var require_restart3 = __commonJS({
|
|
|
21838
21988
|
log("\u91CD\u542F\u5B9E\u4F8B\u300C" + (target.name || target.id) + "\u300D\u4F7F\u63D2\u4EF6\u53D8\u66F4\u751F\u6548\u2026");
|
|
21839
21989
|
if (ctx.events) ctx.events.append("plugin_restart_started", { name: target.name || target.id, target: target.id, kind });
|
|
21840
21990
|
try {
|
|
21841
|
-
ctx.instances.stopInstance(target.id
|
|
21991
|
+
ctx.instances.stopInstance(target.id);
|
|
21842
21992
|
} catch (e) {
|
|
21843
21993
|
log("\u505C\u6B62\u5B9E\u4F8B\u5931\u8D25: " + e.message);
|
|
21844
21994
|
}
|
|
@@ -22549,10 +22699,6 @@ var require_managed_object = __commonJS({
|
|
|
22549
22699
|
function registerKind(kind, meta) {
|
|
22550
22700
|
_customKinds[kind] = Object.assign({ label: kind, startable: false, guardable: false }, meta || {});
|
|
22551
22701
|
}
|
|
22552
|
-
var DOMAIN_A_KINDS = /* @__PURE__ */ new Set(["dsh", "sandbox-instance"]);
|
|
22553
|
-
function isDomainA(kind) {
|
|
22554
|
-
return DOMAIN_A_KINDS.has(kind);
|
|
22555
|
-
}
|
|
22556
22702
|
function createEntry(o) {
|
|
22557
22703
|
const meta = kindMeta(o.kind);
|
|
22558
22704
|
if (!meta) throw new Error("\u672A\u77E5\u53D7\u7BA1\u5BF9\u8C61\u7C7B\u578B: " + o.kind + "\uFF08\u5148 registerKind \u58F0\u660E\uFF09");
|
|
@@ -22563,8 +22709,9 @@ var require_managed_object = __commonJS({
|
|
|
22563
22709
|
name: String(o.name || o.id),
|
|
22564
22710
|
// desired 两域共用字段名但语义不同:域 A=用户意图;域 B=「当前业务是否需要它」的条件
|
|
22565
22711
|
desired: o.desired === "stopped" ? "stopped" : "running",
|
|
22566
|
-
// guardian
|
|
22567
|
-
|
|
22712
|
+
// guardian 开关的权威在域记录本身(dsh-main.json / inst.guardian),消费者全部直读源;
|
|
22713
|
+
// 目录曾在域 A entry 上物化该字段但零读者(B2-2 收口)。createEntry 永不物化 guardian 键
|
|
22714
|
+
// = 老库残留的天然一次性清理口(load 经本函数重建即消失),无需迁移脚本。
|
|
22568
22715
|
ownership: normalizeOwnership(o.ownership),
|
|
22569
22716
|
// 初始 stopped;业务不得直接改,由 heartbeat 调谐循环写入
|
|
22570
22717
|
phase: "stopped",
|
|
@@ -22599,7 +22746,7 @@ var require_managed_object = __commonJS({
|
|
|
22599
22746
|
// 域备注(只读参考)
|
|
22600
22747
|
};
|
|
22601
22748
|
}
|
|
22602
|
-
module2.exports = { DESIRED, MANAGED_KINDS, kindMeta, registerKind,
|
|
22749
|
+
module2.exports = { DESIRED, MANAGED_KINDS, kindMeta, registerKind, createEntry, normalizeOwnership };
|
|
22603
22750
|
}
|
|
22604
22751
|
});
|
|
22605
22752
|
|
|
@@ -22666,6 +22813,13 @@ var require_heartbeat = __commonJS({
|
|
|
22666
22813
|
registry._log("warn", "heartbeat " + (ad.supervise ? "supervise" : "observe") + "(" + e.kind + ":" + e.id + "): " + (err && err.message || err));
|
|
22667
22814
|
}
|
|
22668
22815
|
}
|
|
22816
|
+
if (typeof registry.onBeatDone === "function") {
|
|
22817
|
+
try {
|
|
22818
|
+
await registry.onBeatDone({ observed, errors });
|
|
22819
|
+
} catch (err) {
|
|
22820
|
+
registry._log("warn", "heartbeat onBeatDone: " + (err && err.message || err));
|
|
22821
|
+
}
|
|
22822
|
+
}
|
|
22669
22823
|
return { observed, errors };
|
|
22670
22824
|
}
|
|
22671
22825
|
module2.exports = { runHeartbeat, withTimeout, ADAPTER_TIMEOUT_TICKS };
|
|
@@ -22679,7 +22833,7 @@ var require_registry3 = __commonJS({
|
|
|
22679
22833
|
var fs2 = require("node:fs");
|
|
22680
22834
|
var path2 = require("node:path");
|
|
22681
22835
|
var { writeAtomic } = require_fs();
|
|
22682
|
-
var { DESIRED, MANAGED_KINDS, kindMeta, registerKind: registerManagedKind,
|
|
22836
|
+
var { DESIRED, MANAGED_KINDS, kindMeta, registerKind: registerManagedKind, createEntry, normalizeOwnership } = require_managed_object();
|
|
22683
22837
|
var PHASES = ["stopped", "installing", "starting", "running", "draining", "backoff", "failed", "restarting"];
|
|
22684
22838
|
var { runHeartbeat } = require_heartbeat();
|
|
22685
22839
|
var ManagedRegistry = class {
|
|
@@ -22730,7 +22884,7 @@ var require_registry3 = __commonJS({
|
|
|
22730
22884
|
for (const o of arr) {
|
|
22731
22885
|
try {
|
|
22732
22886
|
if (!o || !kindMeta(o.kind)) continue;
|
|
22733
|
-
const e = createEntry({ kind: o.kind, id: o.id, name: o.name, desired: o.desired,
|
|
22887
|
+
const e = createEntry({ kind: o.kind, id: o.id, name: o.name, desired: o.desired, ownership: o.ownership });
|
|
22734
22888
|
if (PHASES.includes(o.phase)) e.phase = o.phase;
|
|
22735
22889
|
if (Number.isInteger(o.backoffLevel)) e.backoffLevel = o.backoffLevel;
|
|
22736
22890
|
if (typeof o.backoffUntil === "number" && o.backoffUntil > Date.now()) e.backoffUntil = o.backoffUntil;
|
|
@@ -22757,7 +22911,7 @@ var require_registry3 = __commonJS({
|
|
|
22757
22911
|
kind: o.kind,
|
|
22758
22912
|
id: o.id,
|
|
22759
22913
|
name: o.name,
|
|
22760
|
-
// desired 两域共用(语义不同,见 createEntry);guardian
|
|
22914
|
+
// desired 两域共用(语义不同,见 createEntry);guardian 不落盘(B2-2,权威在域记录)。
|
|
22761
22915
|
desired: o.desired,
|
|
22762
22916
|
ownership: o.ownership,
|
|
22763
22917
|
phase: o.phase,
|
|
@@ -22769,7 +22923,7 @@ var require_registry3 = __commonJS({
|
|
|
22769
22923
|
startedAt: o.startedAt,
|
|
22770
22924
|
createdAt: o.createdAt,
|
|
22771
22925
|
updatedAt: o.updatedAt
|
|
22772
|
-
}
|
|
22926
|
+
}))
|
|
22773
22927
|
}, null, 2);
|
|
22774
22928
|
writeAtomic(this.file, body, { mode: 384 });
|
|
22775
22929
|
} catch (e) {
|
|
@@ -22831,8 +22985,8 @@ var require_registry3 = __commonJS({
|
|
|
22831
22985
|
this._event("managed_object_registered", { kind: e.kind, id: e.id, name: e.name });
|
|
22832
22986
|
return e;
|
|
22833
22987
|
}
|
|
22834
|
-
/** 对象变更申报(desired/
|
|
22835
|
-
*
|
|
22988
|
+
/** 对象变更申报(desired/ownership/name)。guardian 不接受申报(B2-2):createEntry 永不
|
|
22989
|
+
* 物化该键,patch 里带 guardian 一律忽略,老库残留由 load 重建时清理。 */
|
|
22836
22990
|
update(id, patch) {
|
|
22837
22991
|
const e = this.get(id);
|
|
22838
22992
|
if (!e) return { ok: false, error: "\u672A\u6CE8\u518C: " + id };
|
|
@@ -22841,11 +22995,6 @@ var require_registry3 = __commonJS({
|
|
|
22841
22995
|
if (!DESIRED.includes(p.desired)) return { ok: false, error: "\u975E\u6CD5 desired: " + p.desired };
|
|
22842
22996
|
e.desired = p.desired;
|
|
22843
22997
|
}
|
|
22844
|
-
if (isDomainA(e.kind)) {
|
|
22845
|
-
if (p.guardian !== void 0) e.guardian = p.guardian === true;
|
|
22846
|
-
} else if ("guardian" in e) {
|
|
22847
|
-
delete e.guardian;
|
|
22848
|
-
}
|
|
22849
22998
|
if (p.name !== void 0) e.name = String(p.name || e.id);
|
|
22850
22999
|
if (p.ownership !== void 0) {
|
|
22851
23000
|
const old = e.ownership.ports;
|
|
@@ -23263,20 +23412,23 @@ var require_npm = __commonJS({
|
|
|
23263
23412
|
const l = runtimeContract.npmLauncher();
|
|
23264
23413
|
return { program: l.program, args: l.args };
|
|
23265
23414
|
}
|
|
23266
|
-
function resolveNpmRoot(host2) {
|
|
23415
|
+
async function resolveNpmRoot(host2) {
|
|
23267
23416
|
if (host2.npmRoot) return host2.npmRoot;
|
|
23268
23417
|
const l = npmLaunch(host2);
|
|
23269
|
-
const r = ex2.
|
|
23418
|
+
const r = await ex2.runOutAsync(l.program, l.args.concat(["root", "-g"]));
|
|
23270
23419
|
return r ? r.trim() : null;
|
|
23271
23420
|
}
|
|
23272
|
-
function checkEnvironment(host2) {
|
|
23421
|
+
async function checkEnvironment(host2) {
|
|
23273
23422
|
const errors = [];
|
|
23274
|
-
const nv = ex2.runOut("node", ["--version"]);
|
|
23275
|
-
if (!nv || !nv.trim()) errors.push("node \u672A\u5B89\u88C5\u6216\u4E0D\u53EF\u6267\u884C");
|
|
23276
23423
|
const l = npmLaunch(host2);
|
|
23277
|
-
const npmv =
|
|
23424
|
+
const [nv, npmv, npmRoot] = await Promise.all([
|
|
23425
|
+
ex2.runOutAsync("node", ["--version"]),
|
|
23426
|
+
ex2.runOutAsync(l.program, l.args.concat(["--version"])),
|
|
23427
|
+
resolveNpmRoot(host2)
|
|
23428
|
+
]);
|
|
23429
|
+
if (!nv || !nv.trim()) errors.push("node \u672A\u5B89\u88C5\u6216\u4E0D\u53EF\u6267\u884C");
|
|
23278
23430
|
if (!npmv || !npmv.trim()) errors.push("npm \u672A\u5B89\u88C5\u6216\u4E0D\u53EF\u6267\u884C");
|
|
23279
|
-
return { ok: errors.length === 0, errors, npmRoot
|
|
23431
|
+
return { ok: errors.length === 0, errors, npmRoot };
|
|
23280
23432
|
}
|
|
23281
23433
|
async function latestVersion(host2) {
|
|
23282
23434
|
if (!host2.dist || !host2.config.packageName) throw new Error("\u5206\u53D1\u670D\u52A1\u672A\u521D\u59CB\u5316\uFF0C\u65E0\u6CD5\u67E5\u8BE2\u6700\u65B0\u7248\u672C");
|
|
@@ -23375,13 +23527,14 @@ var require_ops4 = __commonJS({
|
|
|
23375
23527
|
}
|
|
23376
23528
|
async function install(host2, version) {
|
|
23377
23529
|
if (!policies.isValidVersion(version)) return { ok: false, error: "\u975E\u6CD5\u7248\u672C\u53F7: " + version };
|
|
23378
|
-
const env = host2.checkEnvironment();
|
|
23379
|
-
if (!env.ok) return { ok: false, error: "\u73AF\u5883\u68C0\u67E5\u5931\u8D25: " + env.errors.join("; ") };
|
|
23380
23530
|
host2.installing = true;
|
|
23381
23531
|
host2.installLog = [];
|
|
23382
|
-
|
|
23383
|
-
let target = version;
|
|
23532
|
+
let task = null;
|
|
23384
23533
|
try {
|
|
23534
|
+
const env = await host2.checkEnvironment();
|
|
23535
|
+
if (!env.ok) return { ok: false, error: "\u73AF\u5883\u68C0\u67E5\u5931\u8D25: " + env.errors.join("; ") };
|
|
23536
|
+
task = beginTask(host2, "install", { to: version || null, createdBy: "user" });
|
|
23537
|
+
let target = version;
|
|
23385
23538
|
if (!target) {
|
|
23386
23539
|
target = await host2._latestVersion().catch(() => null);
|
|
23387
23540
|
if (!target) {
|
|
@@ -23404,7 +23557,7 @@ var require_ops4 = __commonJS({
|
|
|
23404
23557
|
return { ok: false, error: res.error, output: res.output };
|
|
23405
23558
|
}
|
|
23406
23559
|
const isFirstInstall = !host2._manifest();
|
|
23407
|
-
host2._recordManifest(target, isFirstInstall ? host2._claimDataPaths() : void 0);
|
|
23560
|
+
await host2._recordManifest(target, isFirstInstall ? host2._claimDataPaths() : void 0);
|
|
23408
23561
|
try {
|
|
23409
23562
|
if (typeof host2._bindNativeDshCommand === "function") host2._bindNativeDshCommand();
|
|
23410
23563
|
} catch (e) {
|
|
@@ -23429,8 +23582,6 @@ var require_ops4 = __commonJS({
|
|
|
23429
23582
|
if (host2.uninstalling) return { ok: false, error: "\u5378\u8F7D\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7A0D\u540E\u518D\u88C5" };
|
|
23430
23583
|
if (policies.busy(host2)) return { ok: false, error: "\u5347\u7EA7\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7A0D\u540E\u518D\u88C5\uFF08state=" + host2.upgradeState + "\uFF09" };
|
|
23431
23584
|
if (!policies.isValidVersion(version)) return { ok: false, error: "\u975E\u6CD5\u7248\u672C\u53F7: " + version };
|
|
23432
|
-
const env = host2.checkEnvironment();
|
|
23433
|
-
if (!env.ok) return { ok: false, error: "\u73AF\u5883\u68C0\u67E5\u5931\u8D25: " + env.errors.join("; ") };
|
|
23434
23585
|
install(host2, version).then(() => {
|
|
23435
23586
|
}).catch((e) => {
|
|
23436
23587
|
host2.installing = null;
|
|
@@ -23623,7 +23774,7 @@ var require_upgrade2 = __commonJS({
|
|
|
23623
23774
|
if (!res.ok) throw new Error(res.error || "install failed");
|
|
23624
23775
|
const newV = host2.installedVersion();
|
|
23625
23776
|
if (newV !== target) throw new Error("\u5B89\u88C5\u540E\u7248\u672C\u6821\u9A8C\u5931\u8D25\uFF1A\u671F\u671B " + target + "\uFF0C\u5B9E\u9645 " + newV);
|
|
23626
|
-
host2._recordManifest(newV || target);
|
|
23777
|
+
await host2._recordManifest(newV || target);
|
|
23627
23778
|
if (host2.events) host2.events.append("upgrade_installed", { from: oldV, to: target });
|
|
23628
23779
|
log(host2, "\u5B89\u88C5\u5B8C\u6210\uFF0C\u78C1\u76D8\u7248\u672C " + newV);
|
|
23629
23780
|
if (task) {
|
|
@@ -23693,9 +23844,9 @@ var require_upgrade2 = __commonJS({
|
|
|
23693
23844
|
async function rollbackAfterFailedVerify(host2, oldV, task, healthy) {
|
|
23694
23845
|
log(host2, "\u5065\u5EB7\u9A8C\u8BC1\u5931\u8D25\uFF08" + healthy.reason + "\uFF09");
|
|
23695
23846
|
if (task) host2.tasks.log(task.id, "\u5065\u5EB7\u9A8C\u8BC1\u5931\u8D25\uFF08" + healthy.reason + "\uFF09");
|
|
23696
|
-
host2.rolledBack = true;
|
|
23697
23847
|
host2.upgradeState = "rolling_back";
|
|
23698
23848
|
const rb = await rollbackNative(host2, oldV, task);
|
|
23849
|
+
host2.rolledBack = rb.ok === true;
|
|
23699
23850
|
host2.upgradeError = rb.ok ? "\u5347\u7EA7\u5931\u8D25\uFF0C\u5DF2\u56DE\u6EDA\u5230 " + oldV : "\u5347\u7EA7\u5931\u8D25\u4E14\u56DE\u6EDA\u5931\u8D25\uFF1A" + (rb.error || "");
|
|
23700
23851
|
host2.upgradeState = "failed";
|
|
23701
23852
|
host2.upgradeFinishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -23727,7 +23878,7 @@ var require_upgrade2 = __commonJS({
|
|
|
23727
23878
|
}
|
|
23728
23879
|
tlog("\u56DE\u6EDA\u5B8C\u6210\uFF0C\u78C1\u76D8\u7248\u672C " + oldVersion);
|
|
23729
23880
|
try {
|
|
23730
|
-
host2._recordManifest(oldVersion);
|
|
23881
|
+
await host2._recordManifest(oldVersion);
|
|
23731
23882
|
} catch (e2) {
|
|
23732
23883
|
tlog("manifest \u66F4\u65B0\u5931\u8D25: " + e2.message);
|
|
23733
23884
|
}
|
|
@@ -23742,7 +23893,6 @@ var require_upgrade2 = __commonJS({
|
|
|
23742
23893
|
}
|
|
23743
23894
|
async function rollbackAfterFailure(host2) {
|
|
23744
23895
|
host2.upgradeState = "rolling_back";
|
|
23745
|
-
host2.rolledBack = true;
|
|
23746
23896
|
if (host2.events) host2.events.append("upgrade_rollback_started", { to: host2.oldVersion });
|
|
23747
23897
|
log(host2, "\u56DE\u6EDA\u5230 " + host2.oldVersion + "\u2026");
|
|
23748
23898
|
const registry = await host2._selectRegistry();
|
|
@@ -23763,8 +23913,9 @@ var require_upgrade2 = __commonJS({
|
|
|
23763
23913
|
return { ok: false };
|
|
23764
23914
|
}
|
|
23765
23915
|
log(host2, "\u56DE\u6EDA\u5B8C\u6210\u3002");
|
|
23916
|
+
host2.rolledBack = true;
|
|
23766
23917
|
try {
|
|
23767
|
-
host2._recordManifest(host2.oldVersion);
|
|
23918
|
+
await host2._recordManifest(host2.oldVersion);
|
|
23768
23919
|
} catch (e2) {
|
|
23769
23920
|
log(host2, "manifest \u66F4\u65B0\u5931\u8D25: " + e2.message);
|
|
23770
23921
|
}
|
|
@@ -23914,8 +24065,8 @@ var require_installer = __commonJS({
|
|
|
23914
24065
|
_saveManifest(m) {
|
|
23915
24066
|
return manifest.save(this, m);
|
|
23916
24067
|
}
|
|
23917
|
-
_recordManifest(version, dataPaths) {
|
|
23918
|
-
return manifest.record(this, version, dataPaths, this.npmRoot || npm.resolveNpmRoot(this));
|
|
24068
|
+
async _recordManifest(version, dataPaths) {
|
|
24069
|
+
return manifest.record(this, version, dataPaths, this.npmRoot || await npm.resolveNpmRoot(this));
|
|
23919
24070
|
}
|
|
23920
24071
|
_claimDataPaths() {
|
|
23921
24072
|
return manifest.claimDataPaths(this);
|
|
@@ -24297,6 +24448,7 @@ var require_domains = __commonJS({
|
|
|
24297
24448
|
host2.managedObjects.registerAdapter("dsh", { supervise: () => host2._dshSuperviseOnce(), tickEvery: 1 });
|
|
24298
24449
|
host2.managedObjects.registerAdapter("sandbox-instance", { supervise: (entry) => host2._sandboxSuperviseOnce(entry), tickEvery: 1 });
|
|
24299
24450
|
}
|
|
24451
|
+
if (host2.managedObjects) host2.managedObjects.onBeatDone = () => host2.instances.governSweep();
|
|
24300
24452
|
} catch (e) {
|
|
24301
24453
|
host2.logger && host2.logger.warn && host2.logger.warn("managed registry init: " + (e && e.message));
|
|
24302
24454
|
}
|
|
@@ -24891,7 +25043,7 @@ var require_guard = __commonJS({
|
|
|
24891
25043
|
}
|
|
24892
25044
|
}
|
|
24893
25045
|
if (req.method === "GET" && pathname === "/guard/version") {
|
|
24894
|
-
return send(200,
|
|
25046
|
+
return Promise.resolve(sup.guardVersionLocal()).then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
24895
25047
|
}
|
|
24896
25048
|
if (req.method === "POST" && pathname === "/guard/version/check") {
|
|
24897
25049
|
req.resume();
|
|
@@ -25036,7 +25188,7 @@ var require_guard = __commonJS({
|
|
|
25036
25188
|
req.resume();
|
|
25037
25189
|
return send(403, {});
|
|
25038
25190
|
}
|
|
25039
|
-
return send(200,
|
|
25191
|
+
return Promise.resolve(sup.envStatus()).then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
25040
25192
|
}
|
|
25041
25193
|
if (req.method === "GET" && pathname === "/env/node-lts") {
|
|
25042
25194
|
return sup.nodeLtsStatus().then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
@@ -25691,7 +25843,7 @@ var require_instances = __commonJS({
|
|
|
25691
25843
|
const r = sup.instances.updateInstance(j.id, j);
|
|
25692
25844
|
return send(r && r.ok ? 200 : 400, r);
|
|
25693
25845
|
}
|
|
25694
|
-
if (act === "start" && j.id) return Promise.resolve(sup.instances.startInstance(j.id)).then((r) => send(r && r.ok ? 200 : 400, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
25846
|
+
if (act === "start" && j.id) return Promise.resolve(sup.instances.startInstance(j.id, { manual: true })).then((r) => send(r && r.ok ? 200 : 400, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
25695
25847
|
if (act === "stop" && j.id) {
|
|
25696
25848
|
const r = sup.instances.stopInstance(j.id);
|
|
25697
25849
|
return send(r && r.ok ? 200 : 400, r);
|
|
@@ -25995,7 +26147,8 @@ var require_static = __commonJS({
|
|
|
25995
26147
|
".png": "image/png",
|
|
25996
26148
|
".ico": "image/x-icon"
|
|
25997
26149
|
};
|
|
25998
|
-
var
|
|
26150
|
+
var FRAME_ANCESTORS = "tauri://localhost http://tauri.localhost https://tauri.localhost";
|
|
26151
|
+
var CSP = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; frame-ancestors " + FRAME_ANCESTORS;
|
|
25999
26152
|
function serveStatic(res, file, corsOrigin) {
|
|
26000
26153
|
if (!UI_DIR) {
|
|
26001
26154
|
res.writeHead(503, { "Content-Type": "text/plain; charset=utf-8" });
|
|
@@ -27904,28 +28057,45 @@ function printSelfVersion() {
|
|
|
27904
28057
|
const { guardVersion } = require_version();
|
|
27905
28058
|
console.log("dsh-supervisor v" + guardVersion());
|
|
27906
28059
|
}
|
|
27907
|
-
function
|
|
28060
|
+
function apiRaw(method, apiPath, body) {
|
|
27908
28061
|
return new Promise((resolve) => {
|
|
27909
28062
|
const addr = readApiAddress();
|
|
27910
28063
|
const req = http.request(
|
|
27911
|
-
{
|
|
28064
|
+
{
|
|
28065
|
+
hostname: addr.host,
|
|
28066
|
+
port: addr.port,
|
|
28067
|
+
path: apiPath,
|
|
28068
|
+
method,
|
|
28069
|
+
timeout: 5e3,
|
|
28070
|
+
headers: body ? { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) } : {}
|
|
28071
|
+
},
|
|
27912
28072
|
(res) => {
|
|
27913
|
-
let
|
|
27914
|
-
res.
|
|
27915
|
-
res.on("
|
|
27916
|
-
|
|
27917
|
-
|
|
27918
|
-
} catch {
|
|
27919
|
-
resolve({ error: "parse error", raw: body });
|
|
27920
|
-
}
|
|
27921
|
-
});
|
|
27922
|
-
res.on("error", () => resolve({ error: "response error" }));
|
|
28073
|
+
let text = "";
|
|
28074
|
+
res.setEncoding("utf8");
|
|
28075
|
+
res.on("data", (d) => text += d);
|
|
28076
|
+
res.on("end", () => resolve({ status: res.statusCode, text }));
|
|
28077
|
+
res.on("error", (e) => resolve({ status: 0, text: "", error: e.message }));
|
|
27923
28078
|
}
|
|
27924
28079
|
);
|
|
27925
|
-
req.on("
|
|
28080
|
+
req.on("timeout", () => req.destroy(new Error("api-timeout")));
|
|
28081
|
+
req.on(
|
|
28082
|
+
"error",
|
|
28083
|
+
(e) => resolve({ status: 0, text: "", error: e && e.message === "api-timeout" ? "daemon \u54CD\u5E94\u8D85\u65F6\uFF085s\uFF09" : "daemon \u672A\u8FD0\u884C\u6216\u8FDE\u63A5\u5931\u8D25" })
|
|
28084
|
+
);
|
|
28085
|
+
if (body) req.write(body);
|
|
27926
28086
|
req.end();
|
|
27927
28087
|
});
|
|
27928
28088
|
}
|
|
28089
|
+
function apiRequest(method, apiPath) {
|
|
28090
|
+
return apiRaw(method, apiPath).then(({ status, text, error }) => {
|
|
28091
|
+
if (error) return { error };
|
|
28092
|
+
try {
|
|
28093
|
+
return JSON.parse(text);
|
|
28094
|
+
} catch {
|
|
28095
|
+
return { error: "parse error", raw: text };
|
|
28096
|
+
}
|
|
28097
|
+
});
|
|
28098
|
+
}
|
|
27929
28099
|
var LOCK_FILE = process.env.DSH_SUPERVISOR_LOCK_FILE || path.join(SUPERVISOR_DIR, "guard.lock");
|
|
27930
28100
|
var LOCK_OWNER = { pid: process.pid, started: Date.now(), entry: process.argv[1] || "" };
|
|
27931
28101
|
function readLock() {
|
|
@@ -27946,6 +28116,41 @@ function readLock() {
|
|
|
27946
28116
|
function isOwnGuardEntry(cmdline) {
|
|
27947
28117
|
return typeof cmdline === "string" && cmdline.includes("dsh-supervisor");
|
|
27948
28118
|
}
|
|
28119
|
+
var LOCK_HEARTBEAT_MS = 2e3;
|
|
28120
|
+
var LOCK_STALE_MS = LOCK_HEARTBEAT_MS * 15;
|
|
28121
|
+
function lockSilentMs() {
|
|
28122
|
+
try {
|
|
28123
|
+
return Math.max(0, Date.now() - fs.statSync(LOCK_FILE).mtimeMs);
|
|
28124
|
+
} catch {
|
|
28125
|
+
return null;
|
|
28126
|
+
}
|
|
28127
|
+
}
|
|
28128
|
+
function pidAlive(pid) {
|
|
28129
|
+
try {
|
|
28130
|
+
process.kill(pid, 0);
|
|
28131
|
+
return true;
|
|
28132
|
+
} catch (e) {
|
|
28133
|
+
return e.code === "EPERM";
|
|
28134
|
+
}
|
|
28135
|
+
}
|
|
28136
|
+
var LOCK_TAKE_RETRY_MS = 8e3;
|
|
28137
|
+
var LOCK_TAKE_NAP_MS = 250;
|
|
28138
|
+
function napSync(ms) {
|
|
28139
|
+
try {
|
|
28140
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
28141
|
+
} catch {
|
|
28142
|
+
}
|
|
28143
|
+
}
|
|
28144
|
+
function startLockHeartbeat() {
|
|
28145
|
+
const t = setInterval(() => {
|
|
28146
|
+
try {
|
|
28147
|
+
const d = /* @__PURE__ */ new Date();
|
|
28148
|
+
fs.utimesSync(LOCK_FILE, d, d);
|
|
28149
|
+
} catch {
|
|
28150
|
+
}
|
|
28151
|
+
}, LOCK_HEARTBEAT_MS);
|
|
28152
|
+
if (t.unref) t.unref();
|
|
28153
|
+
}
|
|
27949
28154
|
function acquireLock() {
|
|
27950
28155
|
fs.mkdirSync(SUPERVISOR_DIR, { recursive: true });
|
|
27951
28156
|
const tryCreate = () => {
|
|
@@ -27960,26 +28165,47 @@ function acquireLock() {
|
|
|
27960
28165
|
process.exit(1);
|
|
27961
28166
|
}
|
|
27962
28167
|
};
|
|
27963
|
-
|
|
28168
|
+
const take = () => {
|
|
28169
|
+
if (!tryCreate()) return null;
|
|
28170
|
+
startLockHeartbeat();
|
|
28171
|
+
return true;
|
|
28172
|
+
};
|
|
28173
|
+
const first = take();
|
|
28174
|
+
if (first) return true;
|
|
27964
28175
|
const held = readLock();
|
|
27965
28176
|
if (held) {
|
|
27966
|
-
|
|
27967
|
-
|
|
27968
|
-
|
|
27969
|
-
|
|
27970
|
-
|
|
27971
|
-
|
|
28177
|
+
if (!pidAlive(held.pid)) {
|
|
28178
|
+
console.log("[supervisor] \u6E05\u7406\u9648\u65E7\u5B88\u536B\u9501\uFF08\u6301\u6709 pid " + held.pid + " \u5DF2\u9000\u51FA\uFF09");
|
|
28179
|
+
} else {
|
|
28180
|
+
const cmdline = readCmdline(held.pid);
|
|
28181
|
+
if (cmdline && isOwnGuardEntry(cmdline)) {
|
|
28182
|
+
const deadline = Date.now() + LOCK_TAKE_RETRY_MS;
|
|
28183
|
+
while (pidAlive(held.pid)) {
|
|
28184
|
+
if (Date.now() >= deadline) {
|
|
28185
|
+
return "\u6301\u6709 pid " + held.pid + " \u5B58\u6D3B\u3001\u547D\u4EE4\u884C\u662F\u672C\u4EA7\u54C1\u7684\u5B88\u536B\u5165\u53E3\uFF0C\u6709\u754C\u7B49\u5F85 " + Math.round(LOCK_TAKE_RETRY_MS / 1e3) + "s \u540E\u4ECD\u672A\u8BA9\u51FA";
|
|
28186
|
+
}
|
|
28187
|
+
napSync(LOCK_TAKE_NAP_MS);
|
|
28188
|
+
}
|
|
28189
|
+
console.log("[supervisor] \u524D\u4EFB\u5B88\u536B pid " + held.pid + " \u5728\u7B49\u5F85\u4E2D\u9000\u51FA -> \u63A5\u7BA1\u5B88\u536B\u9501");
|
|
28190
|
+
} else if (cmdline) {
|
|
28191
|
+
console.log("[supervisor] \u6E05\u7406\u9648\u65E7\u5B88\u536B\u9501\uFF08\u6301\u6709 pid " + held.pid + " \u5B58\u6D3B\u4F46\u547D\u4EE4\u884C\u4E0D\u662F\u672C\u4EA7\u54C1\u7684\u5B88\u536B\u5165\u53E3\uFF1A" + cmdline + "\uFF09");
|
|
28192
|
+
} else {
|
|
28193
|
+
const silent = lockSilentMs();
|
|
28194
|
+
if (silent !== null && silent >= LOCK_STALE_MS) {
|
|
28195
|
+
console.log("[supervisor] \u6E05\u7406\u9648\u65E7\u5B88\u536B\u9501\uFF08\u6301\u6709 pid " + held.pid + " \u5B58\u6D3B\u4F46\u547D\u4EE4\u884C\u8BFB\u4E0D\u5230\uFF0C\u4E14\u9501\u5DF2 " + Math.round(silent / 1e3) + "s \u672A\u7EED\u7EA6 -> \u5224\u5B9A\u539F\u6301\u6709\u8005\u5DF2\u6B7B\uFF09");
|
|
28196
|
+
} else {
|
|
28197
|
+
return "\u6301\u6709 pid " + held.pid + " \u5B58\u6D3B\u3001\u547D\u4EE4\u884C\u8BFB\u4E0D\u5230\uFF0C" + (silent === null ? "\u9501\u72B6\u6001\u4E0D\u53EF\u7EDF\u8BA1\uFF08\u4FDD\u5B88\u8BA9\u4F4D\uFF09" : "\u9501 " + Math.round(silent / 1e3) + "s \u524D\u4ECD\u5728\u7EED\u7EA6\uFF08\u4FDD\u5B88\u8BA9\u4F4D\uFF09");
|
|
28198
|
+
}
|
|
28199
|
+
}
|
|
27972
28200
|
}
|
|
27973
|
-
const cmdline = alive ? readCmdline(held.pid) : null;
|
|
27974
|
-
if (alive && !cmdline) return false;
|
|
27975
|
-
if (alive && isOwnGuardEntry(cmdline)) return false;
|
|
27976
|
-
console.log("[supervisor] \u6E05\u7406\u9648\u65E7\u5B88\u536B\u9501\uFF08\u6301\u6709 pid " + held.pid + (alive ? " \u5B58\u6D3B\u4F46\u547D\u4EE4\u884C\u4E0D\u662F\u672C\u4EA7\u54C1\u7684\u5B88\u536B\u5165\u53E3\uFF1A" + cmdline : " \u5DF2\u9000\u51FA") + "\uFF09");
|
|
27977
28201
|
}
|
|
27978
28202
|
try {
|
|
27979
28203
|
fs.unlinkSync(LOCK_FILE);
|
|
27980
28204
|
} catch {
|
|
27981
28205
|
}
|
|
27982
|
-
|
|
28206
|
+
const again = take();
|
|
28207
|
+
if (again) return true;
|
|
28208
|
+
return "\u6E05\u7406\u9648\u65E7\u9501\u540E\u4ECD\u521B\u5EFA\u4E0D\u4E86\uFF08" + LOCK_FILE + " \u4E0D\u53EF\u5199\uFF1F\uFF09";
|
|
27983
28209
|
}
|
|
27984
28210
|
function releaseLock() {
|
|
27985
28211
|
try {
|
|
@@ -27991,8 +28217,9 @@ function releaseLock() {
|
|
|
27991
28217
|
function cmdDaemon() {
|
|
27992
28218
|
const moved = stateRoot.migrateLegacy();
|
|
27993
28219
|
for (const m of moved) console.log("[migrate] \u72B6\u6001\u76EE\u5F55\u8FC1\u79FB: " + m);
|
|
27994
|
-
|
|
27995
|
-
|
|
28220
|
+
const lock = acquireLock();
|
|
28221
|
+
if (lock !== true) {
|
|
28222
|
+
console.error("[supervisor] \u672C\u8FDB\u7A0B\u9000\u51FA\uFF1A\u672A\u53D6\u5F97\u5B88\u536B\u9501\uFF08\u9501 " + LOCK_FILE + "\uFF09\u2014\u2014 " + lock);
|
|
27996
28223
|
process.exit(1);
|
|
27997
28224
|
}
|
|
27998
28225
|
process.on("exit", releaseLock);
|
|
@@ -28187,26 +28414,9 @@ function cmdVersion() {
|
|
|
28187
28414
|
});
|
|
28188
28415
|
}
|
|
28189
28416
|
function cmdSelfUpdate(action) {
|
|
28190
|
-
const addr = readApiAddress();
|
|
28191
|
-
const apiOne = (method, p, body) => new Promise((resolve) => {
|
|
28192
|
-
const req = http.request({ hostname: addr.host, port: addr.port, path: p, method, timeout: 5e3, headers: body ? { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) } : {} }, (res) => {
|
|
28193
|
-
let b = "";
|
|
28194
|
-
res.on("data", (d) => b += d);
|
|
28195
|
-
res.on("end", () => {
|
|
28196
|
-
try {
|
|
28197
|
-
resolve(JSON.parse(b));
|
|
28198
|
-
} catch {
|
|
28199
|
-
resolve({ error: "parse error", raw: b });
|
|
28200
|
-
}
|
|
28201
|
-
});
|
|
28202
|
-
});
|
|
28203
|
-
req.on("error", () => resolve({ error: "daemon \u672A\u8FD0\u884C\u6216\u8FDE\u63A5\u5931\u8D25" }));
|
|
28204
|
-
if (body) req.write(body);
|
|
28205
|
-
req.end();
|
|
28206
|
-
});
|
|
28207
28417
|
(async () => {
|
|
28208
28418
|
if (action === "check" || !action) {
|
|
28209
|
-
const s = await
|
|
28419
|
+
const s = await apiRequest("GET", "/self-update/status");
|
|
28210
28420
|
if (s.error) return console.log("\u68C0\u67E5\u5931\u8D25: " + s.error);
|
|
28211
28421
|
if (s.ok) {
|
|
28212
28422
|
console.log("\u5B88\u536B\u5F53\u524D\u7248\u672C: " + s.installed);
|
|
@@ -28224,31 +28434,13 @@ function cmdSelfUpdate(action) {
|
|
|
28224
28434
|
})();
|
|
28225
28435
|
}
|
|
28226
28436
|
function cmdUpgrade(requested) {
|
|
28227
|
-
const
|
|
28228
|
-
|
|
28229
|
-
|
|
28230
|
-
const
|
|
28231
|
-
|
|
28232
|
-
hostname: addr.host,
|
|
28233
|
-
port: addr.port,
|
|
28234
|
-
path: "/native/upgrade",
|
|
28235
|
-
method: "POST",
|
|
28236
|
-
timeout: 5e3,
|
|
28237
|
-
headers: body ? { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) } : {}
|
|
28238
|
-
},
|
|
28239
|
-
(res) => {
|
|
28240
|
-
let b = "";
|
|
28241
|
-
res.on("data", (d) => b += d);
|
|
28242
|
-
res.on("end", () => resolve({ code: res.statusCode, body: b }));
|
|
28243
|
-
}
|
|
28244
|
-
);
|
|
28245
|
-
req.on("error", () => resolve({ code: 0, body: "" }));
|
|
28246
|
-
if (body) req.write(body);
|
|
28247
|
-
req.end();
|
|
28248
|
-
});
|
|
28249
|
-
post().then(({ code, body }) => {
|
|
28437
|
+
const body = requested ? JSON.stringify({ version: requested }) : void 0;
|
|
28438
|
+
const post = () => apiRaw("POST", "/native/upgrade", body);
|
|
28439
|
+
post().then(({ status, text, error }) => {
|
|
28440
|
+
const code = error ? 0 : status;
|
|
28441
|
+
const outText = error ? "" : text;
|
|
28250
28442
|
if (code !== 202) {
|
|
28251
|
-
console.log("\u5347\u7EA7\u672A\u88AB\u63A5\u53D7:",
|
|
28443
|
+
console.log("\u5347\u7EA7\u672A\u88AB\u63A5\u53D7:", outText || "HTTP " + code);
|
|
28252
28444
|
process.exit(1);
|
|
28253
28445
|
}
|
|
28254
28446
|
console.log("\u5347\u7EA7\u5DF2\u5F00\u59CB\uFF0C\u8DDF\u8E2A\u8FDB\u5EA6\uFF08\u5148\u505C DSH \u2192 \u5B89\u88C5 \u2192 \u81EA\u52A8\u62C9\u8D77\uFF0C\u9700\u6570\u5206\u949F\uFF09\u2026");
|