@lob-ox/core-darwin-x64 0.0.7 → 0.0.10
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/README.md +1 -5
- package/bin/lobox +0 -2
- package/core.cjs +901 -985
- package/package.json +1 -1
- package/ui-react/assets/{InstancesPage-BhQi8uZH.js → InstancesPage-BfUNgbrz.js} +1 -1
- package/ui-react/assets/{LanPage-B7rIbPDQ.js → LanPage-C_v98nOL.js} +1 -1
- package/ui-react/assets/{OverviewPage-DmUsmQzj.js → OverviewPage-BVNv_we9.js} +1 -1
- package/ui-react/assets/{PluginsPage-L4vpNgAF.js → PluginsPage-CB9vP3Zw.js} +1 -1
- package/ui-react/assets/{RouterPage-Ca_UoOpv.js → RouterPage-DhiSp8tn.js} +1 -1
- package/ui-react/assets/{SettingsPage-C2pK_HKz.js → SettingsPage-CFxjRGSS.js} +1 -1
- package/ui-react/assets/{TasksPage-DgQrSNwD.js → TasksPage-C4MaW5ZN.js} +1 -1
- package/ui-react/assets/{openExternal-Ds20EFp9.js → openExternal-BL2ow_UN.js} +1 -1
- package/ui-react/assets/{refresh-cw-CFZGPyP6.js → refresh-cw-CHZo8X7a.js} +1 -1
- package/ui-react/assets/{rocket-Dit4Xpeq.js → rocket-OqsLWeGD.js} +1 -1
- package/ui-react/assets/{shield-check-D2xvjEfM.js → shield-check-DdG3gN1L.js} +1 -1
- package/ui-react/assets/{supervisor-yMki50vd.js → supervisor-BASdnb70.js} +3 -3
- package/ui-react/assets/{supervisor-Dfq_YAmt.js → supervisor-Blfqgw-f.js} +1 -1
- package/ui-react/assets/{useSupervisorAction-DZSdzPif.js → useSupervisorAction-DUxfx47b.js} +1 -1
- package/ui-react/assets/{widgets-M2h3F-43.js → widgets-C9CEOdGF.js} +1 -1
- package/ui-react/supervisor.html +2 -2
package/core.cjs
CHANGED
|
@@ -306,6 +306,78 @@ var require_exec_path = __commonJS({
|
|
|
306
306
|
function dshJsIn(prefix) {
|
|
307
307
|
return path2.join(prefix, "node_modules", ...DSH_PKG, "lib", "bin.js");
|
|
308
308
|
}
|
|
309
|
+
function shimJsTarget(hit) {
|
|
310
|
+
if (!/\.(cmd|bat)$/i.test(hit)) return null;
|
|
311
|
+
let txt = null;
|
|
312
|
+
try {
|
|
313
|
+
txt = fs2.readFileSync(hit, "utf8");
|
|
314
|
+
} catch {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
const re = /"([^"]+\.(?:js|cjs|mjs))"|(\S+\.(?:js|cjs|mjs))(?=\s|$)/gi;
|
|
318
|
+
let m;
|
|
319
|
+
while (m = re.exec(txt)) {
|
|
320
|
+
const cand = m[1] || m[2];
|
|
321
|
+
try {
|
|
322
|
+
const rp = fs2.realpathSync(cand);
|
|
323
|
+
if (fs2.statSync(rp).isFile()) return rp;
|
|
324
|
+
} catch {
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
function harnessHome(env) {
|
|
330
|
+
const e = env || process.env;
|
|
331
|
+
const h = e.HOME || e.USERPROFILE || os2.homedir();
|
|
332
|
+
return path2.join(h, ".dsh-app");
|
|
333
|
+
}
|
|
334
|
+
function dshJsFromLive(pl, env) {
|
|
335
|
+
const pidlookup = require_pidlookup();
|
|
336
|
+
const isFile = (p) => {
|
|
337
|
+
try {
|
|
338
|
+
return fs2.statSync(p).isFile();
|
|
339
|
+
} catch {
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
let port = null;
|
|
344
|
+
try {
|
|
345
|
+
const cfg = env && env.DSH_CONFIG && typeof env.DSH_CONFIG === "object" ? env.DSH_CONFIG : null;
|
|
346
|
+
if (cfg && Number.isInteger(cfg.targetPort) && cfg.targetPort > 0) port = cfg.targetPort;
|
|
347
|
+
else if (cfg && cfg.healthUrl) {
|
|
348
|
+
const u = new URL(cfg.healthUrl);
|
|
349
|
+
if (u.port) port = Number(u.port);
|
|
350
|
+
}
|
|
351
|
+
} catch {
|
|
352
|
+
}
|
|
353
|
+
if (!port) return null;
|
|
354
|
+
let pid = null;
|
|
355
|
+
try {
|
|
356
|
+
pid = pidlookup.findListeningPid(port);
|
|
357
|
+
} catch {
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
if (!pid) return null;
|
|
361
|
+
let cmd2 = null;
|
|
362
|
+
try {
|
|
363
|
+
cmd2 = pidlookup.readCmdline(pid);
|
|
364
|
+
} catch {
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
if (!cmd2) return null;
|
|
368
|
+
for (const part of cmd2.split(/\s+/).filter(Boolean)) {
|
|
369
|
+
try {
|
|
370
|
+
const rp = fs2.realpathSync(part);
|
|
371
|
+
if (isFile(rp) && /\.(js|cjs|mjs)$/i.test(rp)) {
|
|
372
|
+
const js = dshJsIn(path2.dirname(rp));
|
|
373
|
+
if (isFile(js)) return asJs(js, rp);
|
|
374
|
+
if (isFile(rp)) return asJs(rp, rp);
|
|
375
|
+
}
|
|
376
|
+
} catch {
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
309
381
|
function resolveDsh(opts) {
|
|
310
382
|
const o = opts || {};
|
|
311
383
|
const pl = o.platform || process.platform;
|
|
@@ -317,35 +389,43 @@ var require_exec_path = __commonJS({
|
|
|
317
389
|
return false;
|
|
318
390
|
}
|
|
319
391
|
};
|
|
320
|
-
const
|
|
392
|
+
const asJs2 = (bin, launcher) => ({ runtime: process.execPath, bin, isJs: true, launcher: launcher || null });
|
|
321
393
|
if (env.DSH_BIN) {
|
|
322
394
|
try {
|
|
323
395
|
const r = fs2.realpathSync(env.DSH_BIN);
|
|
324
|
-
if (isFile(r)) return
|
|
396
|
+
if (isFile(r)) return asJs2(r, env.DSH_BIN);
|
|
325
397
|
} catch {
|
|
326
398
|
}
|
|
327
399
|
}
|
|
328
400
|
const hit = resolveExecutable("dsh", { platform: pl, env });
|
|
329
401
|
if (hit) {
|
|
402
|
+
const shim = shimJsTarget(hit);
|
|
403
|
+
if (shim) return asJs2(shim, hit);
|
|
330
404
|
try {
|
|
331
405
|
const real = fs2.realpathSync(hit);
|
|
332
|
-
if (isFile(real) && /\.(js|cjs|mjs)$/i.test(real)) return
|
|
406
|
+
if (isFile(real) && /\.(js|cjs|mjs)$/i.test(real)) return asJs2(real, hit);
|
|
333
407
|
} catch {
|
|
334
408
|
}
|
|
335
409
|
const js = dshJsIn(path2.dirname(hit));
|
|
336
|
-
if (isFile(js)) return
|
|
337
|
-
if (isFile(hit) && !/\.(cmd|bat|exe)$/i.test(hit)) return
|
|
410
|
+
if (isFile(js)) return asJs2(js, hit);
|
|
411
|
+
if (isFile(hit) && !/\.(cmd|bat|exe)$/i.test(hit)) return asJs2(hit, hit);
|
|
338
412
|
return { runtime: null, bin: hit, isJs: false, launcher: hit };
|
|
339
413
|
}
|
|
340
414
|
if (o.npmRoot) {
|
|
341
415
|
const js = dshJsIn(o.npmRoot);
|
|
342
|
-
if (isFile(js)) return
|
|
416
|
+
if (isFile(js)) return asJs2(js, null);
|
|
343
417
|
}
|
|
344
418
|
const gRoot = globalInstallRoot(pl, void 0, env);
|
|
345
419
|
{
|
|
346
420
|
const js = dshJsIn(gRoot);
|
|
347
|
-
if (isFile(js)) return
|
|
421
|
+
if (isFile(js)) return asJs2(js, null);
|
|
422
|
+
}
|
|
423
|
+
{
|
|
424
|
+
const js = dshJsIn(harnessHome(env));
|
|
425
|
+
if (isFile(js)) return asJs2(js, null);
|
|
348
426
|
}
|
|
427
|
+
const live = dshJsFromLive(pl, env);
|
|
428
|
+
if (live) return live;
|
|
349
429
|
return null;
|
|
350
430
|
}
|
|
351
431
|
function knownDshEntries(opts) {
|
|
@@ -918,8 +998,6 @@ var require_brand = __commonJS({
|
|
|
918
998
|
var CLI_SHIM_NAMES = ["lobox", "lobox.cmd", "lobox.ps1"];
|
|
919
999
|
var GUI_BIN_NAMES = ["lobox-shell", "lobox-shell.exe"];
|
|
920
1000
|
var PROC_MATCH_GUARD = SHARED.proc.matchGuard;
|
|
921
|
-
var PROC_MATCH_GUI = "lobox-shell";
|
|
922
|
-
var PROC_MATCH_GUI_RE = "lobox-shell(\\.exe)?";
|
|
923
1001
|
var BRIDGE_MSG_KERNEL_UPDATE_REQUEST = SHARED.bridge.msgKernelUpdateRequest;
|
|
924
1002
|
var BRIDGE_MSG_KERNEL_UPDATE_RESULT = SHARED.bridge.msgKernelUpdateResult;
|
|
925
1003
|
var BRIDGE_MSG_KERNEL_UPDATE_PROGRESS = SHARED.bridge.msgKernelUpdateProgress;
|
|
@@ -936,9 +1014,7 @@ var require_brand = __commonJS({
|
|
|
936
1014
|
var EVENT_HARNESS_REMOTE_TOKEN_CHANGED = "harness_remote_token_changed";
|
|
937
1015
|
var EVENT_LAN_HARNESS_TOKEN_UPDATED = "lan_harness_token_updated";
|
|
938
1016
|
var EVENT_UPGRADE_STOPPING_HARNESS = "upgrade_stopping_harness";
|
|
939
|
-
var EVENT_SHELL_UPDATE_PENDING = "shell_update_pending";
|
|
940
1017
|
var EVENT_SHELL_UPDATE_CHECKED = "shell_update_checked";
|
|
941
|
-
var EVENT_SHELL_RESTART_REQUESTED = "shell_restart_requested";
|
|
942
1018
|
var SYSTEMD_TEMPLATE_ASIDE_SUFFIX = ".disabled-by-lobox-";
|
|
943
1019
|
function corePackageName(tag) {
|
|
944
1020
|
return NPM_SCOPE + "/" + CORE_PKG_PREFIX + tag;
|
|
@@ -1040,8 +1116,6 @@ var require_brand = __commonJS({
|
|
|
1040
1116
|
CLI_SHIM_NAMES,
|
|
1041
1117
|
GUI_BIN_NAMES,
|
|
1042
1118
|
PROC_MATCH_GUARD,
|
|
1043
|
-
PROC_MATCH_GUI,
|
|
1044
|
-
PROC_MATCH_GUI_RE,
|
|
1045
1119
|
BRIDGE_MSG_KERNEL_UPDATE_REQUEST,
|
|
1046
1120
|
BRIDGE_MSG_KERNEL_UPDATE_RESULT,
|
|
1047
1121
|
BRIDGE_MSG_KERNEL_UPDATE_PROGRESS,
|
|
@@ -1058,9 +1132,7 @@ var require_brand = __commonJS({
|
|
|
1058
1132
|
EVENT_HARNESS_REMOTE_TOKEN_CHANGED,
|
|
1059
1133
|
EVENT_LAN_HARNESS_TOKEN_UPDATED,
|
|
1060
1134
|
EVENT_UPGRADE_STOPPING_HARNESS,
|
|
1061
|
-
EVENT_SHELL_UPDATE_PENDING,
|
|
1062
1135
|
EVENT_SHELL_UPDATE_CHECKED,
|
|
1063
|
-
EVENT_SHELL_RESTART_REQUESTED,
|
|
1064
1136
|
SYSTEMD_TEMPLATE_ASIDE_SUFFIX,
|
|
1065
1137
|
corePackageName,
|
|
1066
1138
|
stateRoot: stateRoot2,
|
|
@@ -1232,14 +1304,11 @@ var require_config = __commonJS({
|
|
|
1232
1304
|
};
|
|
1233
1305
|
}
|
|
1234
1306
|
var BASE_DEFAULTS = {
|
|
1235
|
-
// 守卫监控节拍(进程存活只由 child 的 exit/close 事件与平台 pidlookup 判定,见 app/main/*)。
|
|
1236
1307
|
tickIntervalMs: 5e3,
|
|
1237
|
-
// 启动窗口(秒):spawn 后 startsecs 内退出 ⇒ 记一次「启动失败」;活过 startsecs 后退出 ⇒ 正常重启,不计失败。
|
|
1238
1308
|
startsecs: 10,
|
|
1239
|
-
// 唯一一条限流:startupFailWindowMs 内「启动失败」达 startupFailBurst 次 ⇒ phase=FAILED,停止自动重启,等人工重试。
|
|
1240
|
-
// 不变量:startupFailWindowMs > startupFailBurst × startsecs×1000(60s > 5×10s);同一规则按域参数化,实例域见 domains/instance/state-machine.js。
|
|
1241
1309
|
startupFailWindowMs: 6e4,
|
|
1242
1310
|
startupFailBurst: 5,
|
|
1311
|
+
restart: { windowMs: 6e4, burst: 5, baseDelayMs: 2e3, maxDelayMs: 6e4 },
|
|
1243
1312
|
stopGraceMs: 1e4,
|
|
1244
1313
|
portReleaseWaitMs: 1e4,
|
|
1245
1314
|
apiHost: "127.0.0.1",
|
|
@@ -1267,7 +1336,6 @@ var require_config = __commonJS({
|
|
|
1267
1336
|
initialCheckDelayMs: 2e4,
|
|
1268
1337
|
upgradeTimeoutMs: 6e5,
|
|
1269
1338
|
installCommandTemplate: ["npm", "install", "-g", "{pkg}@{version}"],
|
|
1270
|
-
// apiAccessKey:非回环须带 Authorization: Bearer <key> 或 ?access_key=<key>,回环豁免;不配置则 LAN 受 RFC1918 约束、FRP 仍强制 remoteToken。
|
|
1271
1339
|
apiAccessKey: null,
|
|
1272
1340
|
closeAction: "hide",
|
|
1273
1341
|
externalBrowser: null
|
|
@@ -1403,7 +1471,7 @@ var require_version = __commonJS({
|
|
|
1403
1471
|
var fs2 = require("node:fs");
|
|
1404
1472
|
var path2 = require("node:path");
|
|
1405
1473
|
function guardVersion() {
|
|
1406
|
-
if (true) return String("0.0.
|
|
1474
|
+
if (true) return String("0.0.10");
|
|
1407
1475
|
try {
|
|
1408
1476
|
return JSON.parse(fs2.readFileSync(path2.join(__dirname, "..", "..", "package.json"), "utf8")).version || "unknown";
|
|
1409
1477
|
} catch {
|
|
@@ -1742,28 +1810,38 @@ var require_field_tables = __commonJS({
|
|
|
1742
1810
|
var require_phase = __commonJS({
|
|
1743
1811
|
"src/app/state/phase.js"(exports2, module2) {
|
|
1744
1812
|
"use strict";
|
|
1813
|
+
var ENTRY_TO_LEGACY = {
|
|
1814
|
+
stopped: "STOPPED",
|
|
1815
|
+
installing: "INSTALLING",
|
|
1816
|
+
starting: "STARTING",
|
|
1817
|
+
running: "RUNNING",
|
|
1818
|
+
draining: "STOPPING",
|
|
1819
|
+
failed: "FAILED"
|
|
1820
|
+
};
|
|
1821
|
+
var LEGACY_TO_ENTRY = {
|
|
1822
|
+
STOPPED: "stopped",
|
|
1823
|
+
INSTALLING: "installing",
|
|
1824
|
+
STARTING: "starting",
|
|
1825
|
+
RUNNING: "running",
|
|
1826
|
+
STOPPING: "draining",
|
|
1827
|
+
FAILED: "failed",
|
|
1828
|
+
OBSERVED: "stopped",
|
|
1829
|
+
RESTARTING: "starting",
|
|
1830
|
+
BACKOFF: "failed"
|
|
1831
|
+
};
|
|
1832
|
+
function entryToLegacyPhase(ph) {
|
|
1833
|
+
return ENTRY_TO_LEGACY[ph] || "STOPPED";
|
|
1834
|
+
}
|
|
1745
1835
|
function legacyToEntryPhase(ph) {
|
|
1746
|
-
return
|
|
1747
|
-
STOPPED: "stopped",
|
|
1748
|
-
STARTING: "starting",
|
|
1749
|
-
RUNNING: "running",
|
|
1750
|
-
FAILED: "failed",
|
|
1751
|
-
OBSERVED: "stopped",
|
|
1752
|
-
RESTARTING: "starting",
|
|
1753
|
-
BACKOFF: "failed"
|
|
1754
|
-
}[ph] || "stopped";
|
|
1836
|
+
return LEGACY_TO_ENTRY[ph] || "stopped";
|
|
1755
1837
|
}
|
|
1756
|
-
function
|
|
1757
|
-
return
|
|
1758
|
-
stopped: "STOPPED",
|
|
1759
|
-
starting: "STARTING",
|
|
1760
|
-
running: "RUNNING",
|
|
1761
|
-
failed: "FAILED",
|
|
1762
|
-
restarting: "STARTING",
|
|
1763
|
-
backoff: "FAILED"
|
|
1764
|
-
}[ph] || "STOPPED";
|
|
1838
|
+
function isKnownEntry(ph) {
|
|
1839
|
+
return Object.prototype.hasOwnProperty.call(ENTRY_TO_LEGACY, ph);
|
|
1765
1840
|
}
|
|
1766
|
-
|
|
1841
|
+
function isKnownLegacy(ph) {
|
|
1842
|
+
return Object.prototype.hasOwnProperty.call(LEGACY_TO_ENTRY, ph);
|
|
1843
|
+
}
|
|
1844
|
+
module2.exports = { entryToLegacyPhase, legacyToEntryPhase, isKnownEntry, isKnownLegacy };
|
|
1767
1845
|
}
|
|
1768
1846
|
});
|
|
1769
1847
|
|
|
@@ -2210,7 +2288,6 @@ var require_decide = __commonJS({
|
|
|
2210
2288
|
return {
|
|
2211
2289
|
phase,
|
|
2212
2290
|
desired: d.state().desired(),
|
|
2213
|
-
// 端口视角(不是存活判据):只喂孤儿接管/占用分支。
|
|
2214
2291
|
portUp: d.portUp() === true,
|
|
2215
2292
|
childAlive: childAlive(d.mChild()),
|
|
2216
2293
|
adoptedAlive: adoptedAlive(d.mAdoptPid()),
|
|
@@ -2222,7 +2299,6 @@ var require_decide = __commonJS({
|
|
|
2222
2299
|
manualRestart: d.manualRestart() === true,
|
|
2223
2300
|
spawnBlocked: !!(d.mSpawnBlockedUntil() && now < d.mSpawnBlockedUntil()),
|
|
2224
2301
|
startDeadlinePassed: startDeadlinePassed(startDeadline, now),
|
|
2225
|
-
// STARTING 且没有存活进程/没记启动窗口 = 已判定重启,等端口释放落点。
|
|
2226
2302
|
restartInFlight: phase === "STARTING" && startDeadline === null,
|
|
2227
2303
|
restartDue: d.mRestartAt() === null || now >= d.mRestartAt(),
|
|
2228
2304
|
crashHalted: d.crashHalted() === true,
|
|
@@ -4058,13 +4134,6 @@ var require_alloc = __commonJS({
|
|
|
4058
4134
|
this._releaseAlloc();
|
|
4059
4135
|
}
|
|
4060
4136
|
}
|
|
4061
|
-
/**
|
|
4062
|
-
* Lease I1:把"检查"与"置位"放在**同一个同步块**内。
|
|
4063
|
-
*
|
|
4064
|
-
* 修前:`while (r._allocLock) { await sleep(10); } r._allocLock = true;`
|
|
4065
|
-
* —— 检查与置位之间隔着 await,两个并发 claimSlot 可同时观察到 false 并都置 true(真 TOCTOU)。
|
|
4066
|
-
* 现在用 Lease.acquireSync 做同步 test-and-set;未取得则由调用方退避重试。
|
|
4067
|
-
*/
|
|
4068
4137
|
async _acquireAlloc() {
|
|
4069
4138
|
const r = this._registry;
|
|
4070
4139
|
let waited = 0;
|
|
@@ -4091,7 +4160,6 @@ var require_alloc = __commonJS({
|
|
|
4091
4160
|
}
|
|
4092
4161
|
}
|
|
4093
4162
|
}
|
|
4094
|
-
// 跨进程分配锁 best-effort:获取超时返回 null 并继续(fail-open 有界,登记后复检是第二道防线)。
|
|
4095
4163
|
async _acquireXLock() {
|
|
4096
4164
|
const f = String(this._registry._file || "") + ".alloc.lock";
|
|
4097
4165
|
const deadline = Date.now() + XLOCK_TIMEOUT_MS;
|
|
@@ -4967,320 +5035,138 @@ var require_policies = __commonJS({
|
|
|
4967
5035
|
}
|
|
4968
5036
|
});
|
|
4969
5037
|
|
|
4970
|
-
// src/
|
|
4971
|
-
var
|
|
4972
|
-
"src/
|
|
4973
|
-
"use strict";
|
|
4974
|
-
var BRAND2 = require_brand();
|
|
4975
|
-
var DEFAULTS = {
|
|
4976
|
-
enabled: true,
|
|
4977
|
-
intervalMs: 2e4,
|
|
4978
|
-
graceMs: 9e4,
|
|
4979
|
-
updateGraceMs: 3e5,
|
|
4980
|
-
maxRestarts: 5,
|
|
4981
|
-
windowMs: 18e5,
|
|
4982
|
-
phaseMaxAgeMs: 6e5,
|
|
4983
|
-
// 壳进程判据的**唯一来源**是跨语言单源(brand.js#PROC_MATCH_GUI,与 brand.rs 同名同值):
|
|
4984
|
-
// 此处再写一份字面量 = 改名漏一处 ⇒ pgrep 找不到壳(watchdog 反复拉起/双实例),或杀错进程。
|
|
4985
|
-
procPattern: BRAND2.PROC_MATCH_GUI
|
|
4986
|
-
};
|
|
4987
|
-
var HEADLESS_FLAGS = Object.freeze([
|
|
4988
|
-
"--shell-update-plan",
|
|
4989
|
-
"--core-plan",
|
|
4990
|
-
"--node-plan",
|
|
4991
|
-
"--mirror-plan",
|
|
4992
|
-
"--env-plan",
|
|
4993
|
-
"--service-plan",
|
|
4994
|
-
"--platform-matrix",
|
|
4995
|
-
"--run-guard",
|
|
4996
|
-
"--watchdog"
|
|
4997
|
-
]);
|
|
4998
|
-
var HEADLESS_RE = new RegExp(HEADLESS_FLAGS.join("|"));
|
|
4999
|
-
var SHELL_PROC_RE = new RegExp(BRAND2.PROC_MATCH_GUI_RE);
|
|
5000
|
-
function isShellProcess(proc) {
|
|
5001
|
-
const c = String(proc && proc.cmdline || "");
|
|
5002
|
-
if (HEADLESS_RE.test(c)) return false;
|
|
5003
|
-
return SHELL_PROC_RE.test(c);
|
|
5004
|
-
}
|
|
5005
|
-
function decide(i) {
|
|
5006
|
-
const c = i.config || {};
|
|
5007
|
-
if (i.alive > 0) return { action: "alive", reason: "\u58F3\u5728\u8FD0\u884C" };
|
|
5008
|
-
if (i.absentForMs === null || i.absentForMs === void 0) {
|
|
5009
|
-
return { action: "record", reason: "\u9996\u6B21\u89C2\u5BDF\u5230\u58F3\u7F3A\u5931\uFF0C\u5F00\u59CB\u8BA1\u65F6" };
|
|
5010
|
-
}
|
|
5011
|
-
const needMs = i.expectedAbsence ? c.updateGraceMs || DEFAULTS.updateGraceMs : c.graceMs || DEFAULTS.graceMs;
|
|
5012
|
-
if (i.absentForMs < needMs) {
|
|
5013
|
-
return { action: "wait", reason: i.expectedAbsence ? "\u58F3\u5904\u4E8E\u9884\u671F\u7F3A\u5E2D\uFF08\u66F4\u65B0/\u91CD\u542F\uFF09" : "\u672A\u8FBE\u5BBD\u9650\u671F", needMs };
|
|
5014
|
-
}
|
|
5015
|
-
if (!i.sessionAvailable) {
|
|
5016
|
-
return { action: "skip", reason: "\u65E0\u56FE\u5F62\u4F1A\u8BDD\uFF08\u6CE8\u9500/\u7EAF\u7EC8\u7AEF\uFF09\uFF0C\u62C9\u8D77 GUI \u5FC5\u5931\u8D25" };
|
|
5017
|
-
}
|
|
5018
|
-
if ((i.restartsInWindow || 0) >= (c.maxRestarts || DEFAULTS.maxRestarts)) {
|
|
5019
|
-
return { action: "skip", reason: "\u7A97\u53E3\u5185\u62C9\u8D77\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650\uFF0C\u505C\u6B62\u91CD\u8BD5\uFF08\u9632\u98CE\u66B4\uFF09" };
|
|
5020
|
-
}
|
|
5021
|
-
if (!i.hasExe) {
|
|
5022
|
-
return { action: "skip", reason: "\u65E0\u6CD5\u5B9A\u4F4D\u58F3\u53EF\u6267\u884C\u6587\u4EF6\uFF08identity.json \u672A\u8BB0\u5F55 exe\uFF09" };
|
|
5023
|
-
}
|
|
5024
|
-
return { action: "restart", reason: "\u58F3\u7F3A\u5931\u4E14\u5DF2\u8FC7\u5BBD\u9650\u671F", needMs };
|
|
5025
|
-
}
|
|
5026
|
-
function isUpdatePhase(phase) {
|
|
5027
|
-
const p = String(phase || "");
|
|
5028
|
-
return p === "restarting" || p.indexOf("shell-update") === 0;
|
|
5029
|
-
}
|
|
5030
|
-
function exeFromCmdline(cmdline) {
|
|
5031
|
-
const s = String(cmdline || "").trim();
|
|
5032
|
-
if (!s) return null;
|
|
5033
|
-
if (s.startsWith('"')) {
|
|
5034
|
-
const end = s.indexOf('"', 1);
|
|
5035
|
-
return end > 1 ? s.slice(1, end) : null;
|
|
5036
|
-
}
|
|
5037
|
-
return s.split(/\s+/)[0] || null;
|
|
5038
|
-
}
|
|
5039
|
-
function deriveState(id, journal) {
|
|
5040
|
-
const j = journal || {};
|
|
5041
|
-
if (!j.to) return { state: "idle", reason: "\u65E0\u8FDB\u884C\u4E2D\u7684\u66F4\u65B0", journal: j, identity: id };
|
|
5042
|
-
const cur = id && id.version ? String(id.version) : null;
|
|
5043
|
-
if (cur && cur === j.to && id && id.phase === "ready") {
|
|
5044
|
-
const next = j.confirmed === true ? j : Object.assign({}, j, { confirmed: true });
|
|
5045
|
-
return { state: "confirmed", version: cur, reason: "\u58F3\u5DF2\u5065\u5EB7\u8FD0\u884C\u65B0\u7248\u672C", journal: next, identity: id };
|
|
5046
|
-
}
|
|
5047
|
-
return {
|
|
5048
|
-
state: "pending",
|
|
5049
|
-
target: j.to,
|
|
5050
|
-
current: cur,
|
|
5051
|
-
reason: cur === j.to ? "\u7B49\u5F85\u58F3\u4E0A\u62A5\u5C31\u7EEA" : "\u7B49\u5F85\u58F3\u91CD\u542F\u5230\u65B0\u7248\u672C",
|
|
5052
|
-
journal: j,
|
|
5053
|
-
identity: id
|
|
5054
|
-
};
|
|
5055
|
-
}
|
|
5056
|
-
module2.exports = { DEFAULTS, isShellProcess, decide, isUpdatePhase, exeFromCmdline, deriveState, HEADLESS_FLAGS };
|
|
5057
|
-
}
|
|
5058
|
-
});
|
|
5059
|
-
|
|
5060
|
-
// src/domains/shell/watchdog.js
|
|
5061
|
-
var require_watchdog = __commonJS({
|
|
5062
|
-
"src/domains/shell/watchdog.js"(exports2, module2) {
|
|
5038
|
+
// src/app/control/synchrony.js
|
|
5039
|
+
var require_synchrony = __commonJS({
|
|
5040
|
+
"src/app/control/synchrony.js"(exports2, module2) {
|
|
5063
5041
|
"use strict";
|
|
5064
|
-
var
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
let missingSince = null;
|
|
5076
|
-
let restarts = [];
|
|
5077
|
-
let busy = false;
|
|
5078
|
-
let lastSkipReason = null;
|
|
5079
|
-
let everSawAlive = false;
|
|
5080
|
-
let expectedSince = null;
|
|
5081
|
-
let phaseStale = false;
|
|
5082
|
-
let phaseStaleWarned = false;
|
|
5083
|
-
let journalStale = false;
|
|
5084
|
-
let journalStaleWarned = false;
|
|
5085
|
-
const log = (m) => {
|
|
5086
|
-
try {
|
|
5087
|
-
logger.info && logger.info("[shell-watchdog] " + m);
|
|
5088
|
-
} catch {
|
|
5089
|
-
}
|
|
5090
|
-
};
|
|
5091
|
-
const warn = (m) => {
|
|
5092
|
-
try {
|
|
5093
|
-
logger.warn && logger.warn("[shell-watchdog] " + m);
|
|
5094
|
-
} catch {
|
|
5095
|
-
}
|
|
5096
|
-
};
|
|
5097
|
-
function shellProcs() {
|
|
5098
|
-
let procs = [];
|
|
5099
|
-
try {
|
|
5100
|
-
procs = pidlookup.pgrepList(procPattern) || [];
|
|
5101
|
-
} catch {
|
|
5102
|
-
procs = [];
|
|
5103
|
-
}
|
|
5104
|
-
return procs.filter(isShellProcess);
|
|
5042
|
+
var BeatScheduler = class {
|
|
5043
|
+
constructor(opts) {
|
|
5044
|
+
opts = opts || {};
|
|
5045
|
+
this.logger = opts.logger || null;
|
|
5046
|
+
this._beats = /* @__PURE__ */ new Map();
|
|
5047
|
+
this._timer = null;
|
|
5048
|
+
this._intervalMs = opts.intervalMs || 5e3;
|
|
5049
|
+
this._seq = 0;
|
|
5050
|
+
this._ticking = false;
|
|
5051
|
+
this._stopping = false;
|
|
5052
|
+
this.onBeatDone = null;
|
|
5105
5053
|
}
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
phaseStale = t - expectedSince >= maxAge;
|
|
5123
|
-
if (phaseStale && !phaseStaleWarned) {
|
|
5124
|
-
phaseStaleWarned = true;
|
|
5125
|
-
warn("identity.phase \u505C\u7559\u8FC7\u4E45\uFF08" + Math.round((t - expectedSince) / 1e3) + "s > " + Math.round(maxAge / 1e3) + "s\uFF09\uFF0C\u5224\u5B9A\u4E3A\u9648\u65E7\uFF1B\u4E0D\u518D\u5EF6\u957F\u5BBD\u9650");
|
|
5126
|
-
}
|
|
5054
|
+
register(name, fn, opts) {
|
|
5055
|
+
if (typeof fn !== "function") throw new Error("beat " + name + " \u9700\u8981 fn");
|
|
5056
|
+
opts = opts || {};
|
|
5057
|
+
const every = opts.every === Infinity ? Infinity : Math.max(1, Number(opts.every) || 1);
|
|
5058
|
+
const firstDelayMs = typeof opts.firstDelayMs === "number" && opts.firstDelayMs >= 0 ? opts.firstDelayMs : null;
|
|
5059
|
+
const firstTicks = firstDelayMs !== null ? Math.max(0, Math.ceil(firstDelayMs / this._intervalMs)) : 0;
|
|
5060
|
+
this._beats.set(name, {
|
|
5061
|
+
fn,
|
|
5062
|
+
every,
|
|
5063
|
+
firstTicks,
|
|
5064
|
+
timeoutMs: typeof opts.timeoutMs === "number" && opts.timeoutMs > 0 ? opts.timeoutMs : 0,
|
|
5065
|
+
_seqSeen: 0,
|
|
5066
|
+
_lastSeq: null,
|
|
5067
|
+
_fired: false
|
|
5068
|
+
});
|
|
5069
|
+
return this;
|
|
5127
5070
|
}
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
j = shell.readJournal && shell.readJournal();
|
|
5132
|
-
} catch {
|
|
5133
|
-
}
|
|
5134
|
-
if (!j || !j.to || j.confirmed) {
|
|
5135
|
-
journalStale = false;
|
|
5136
|
-
journalStaleWarned = false;
|
|
5137
|
-
return;
|
|
5138
|
-
}
|
|
5139
|
-
const t0 = Date.parse(String(j.startedAt || ""));
|
|
5140
|
-
if (!Number.isFinite(t0)) {
|
|
5141
|
-
journalStale = false;
|
|
5142
|
-
return;
|
|
5143
|
-
}
|
|
5144
|
-
const maxAge = config.shellWatchdogPhaseMaxAgeMs || DEFAULTS.phaseMaxAgeMs;
|
|
5145
|
-
journalStale = t - t0 >= maxAge;
|
|
5146
|
-
if (journalStale && !journalStaleWarned) {
|
|
5147
|
-
journalStaleWarned = true;
|
|
5148
|
-
warn("\u66F4\u65B0\u8D26\u672C\u672A\u786E\u8BA4\u5DF2\u8D85 " + Math.round((t - t0) / 1e3) + "s\uFF08> " + Math.round(maxAge / 1e3) + "s\uFF09\uFF0C\u5224\u5B9A\u4E3A\u9648\u65E7\uFF1B\u4E0D\u518D\u636E\u6B64\u5EF6\u957F\u5BBD\u9650");
|
|
5149
|
-
}
|
|
5071
|
+
unregister(name) {
|
|
5072
|
+
this._beats.delete(name);
|
|
5073
|
+
return this;
|
|
5150
5074
|
}
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
try {
|
|
5154
|
-
const id = shell.identity();
|
|
5155
|
-
phase = String(id && id.phase || "");
|
|
5156
|
-
} catch {
|
|
5157
|
-
}
|
|
5158
|
-
const inUpdate = isUpdatePhase(phase);
|
|
5159
|
-
if (inUpdate && !phaseStale) return true;
|
|
5160
|
-
try {
|
|
5161
|
-
const j = shell.readJournal && shell.readJournal();
|
|
5162
|
-
if (j && j.to && !j.confirmed) return !journalStale;
|
|
5163
|
-
} catch {
|
|
5164
|
-
}
|
|
5165
|
-
return false;
|
|
5075
|
+
has(name) {
|
|
5076
|
+
return this._beats.has(name);
|
|
5166
5077
|
}
|
|
5167
|
-
|
|
5168
|
-
if (
|
|
5078
|
+
async withLock(fn) {
|
|
5079
|
+
if (this._ticking || this._stopping) return { __skipped: "busy" };
|
|
5080
|
+
this._ticking = true;
|
|
5169
5081
|
try {
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
return null;
|
|
5082
|
+
return await fn();
|
|
5083
|
+
} finally {
|
|
5084
|
+
this._ticking = false;
|
|
5174
5085
|
}
|
|
5175
5086
|
}
|
|
5176
|
-
async
|
|
5177
|
-
if (
|
|
5178
|
-
|
|
5179
|
-
|
|
5087
|
+
async tick() {
|
|
5088
|
+
if (this._ticking || this._stopping) return { skipped: true, done: [], errors: [] };
|
|
5089
|
+
this._ticking = true;
|
|
5090
|
+
const done = [];
|
|
5091
|
+
const errors = [];
|
|
5092
|
+
const iv = this._intervalMs;
|
|
5180
5093
|
try {
|
|
5181
|
-
|
|
5182
|
-
const
|
|
5183
|
-
|
|
5184
|
-
|
|
5094
|
+
this._seq++;
|
|
5095
|
+
for (const [name, b] of this._beats) {
|
|
5096
|
+
b._seqSeen++;
|
|
5097
|
+
if (b.every === Infinity) {
|
|
5098
|
+
if (b._fired || b._seqSeen <= b.firstTicks) continue;
|
|
5099
|
+
b._fired = true;
|
|
5100
|
+
} else {
|
|
5101
|
+
if (b._seqSeen <= b.firstTicks) continue;
|
|
5102
|
+
if (b._lastSeq !== null && this._seq - b._lastSeq < b.every) continue;
|
|
5103
|
+
b._lastSeq = this._seq;
|
|
5104
|
+
}
|
|
5105
|
+
let p;
|
|
5185
5106
|
try {
|
|
5186
|
-
|
|
5187
|
-
} catch {
|
|
5107
|
+
p = Promise.resolve(b.fn());
|
|
5108
|
+
} catch (e) {
|
|
5109
|
+
errors.push(name + ":" + (e && e.message));
|
|
5110
|
+
continue;
|
|
5188
5111
|
}
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
if (alive > 0 && !everSawAlive) {
|
|
5195
|
-
everSawAlive = true;
|
|
5196
|
-
log("\u5DF2\u89C2\u6D4B\u5230\u684C\u9762\u58F3\u5728\u8FD0\u884C\uFF08pid=" + procs[0].pid + "\uFF09");
|
|
5197
|
-
}
|
|
5198
|
-
const absentForMs = alive > 0 ? null : missingSince === null ? null : t - missingSince;
|
|
5199
|
-
updatePhaseTracking(t);
|
|
5200
|
-
updateJournalTracking(t);
|
|
5201
|
-
const expected = absentForMs === null ? false : expectedAbsence();
|
|
5202
|
-
const exe = exePath();
|
|
5203
|
-
restarts = restarts.filter((x) => t - x < (config.shellWatchdogWindowMs || DEFAULTS.windowMs));
|
|
5204
|
-
const d = decide({
|
|
5205
|
-
alive,
|
|
5206
|
-
absentForMs,
|
|
5207
|
-
expectedAbsence: expected,
|
|
5208
|
-
sessionAvailable: desktop.sessionAvailable(),
|
|
5209
|
-
restartsInWindow: restarts.length,
|
|
5210
|
-
hasExe: !!exe,
|
|
5211
|
-
config: {
|
|
5212
|
-
graceMs: config.shellWatchdogGraceMs || DEFAULTS.graceMs,
|
|
5213
|
-
updateGraceMs: config.shellWatchdogUpdateGraceMs || DEFAULTS.updateGraceMs,
|
|
5214
|
-
maxRestarts: config.shellWatchdogMaxRestarts || DEFAULTS.maxRestarts
|
|
5112
|
+
if (b.timeoutMs && b.timeoutMs > 0) {
|
|
5113
|
+
p = Promise.race([p, new Promise((res) => {
|
|
5114
|
+
const t = setTimeout(() => res({ __beatTimeout: true }), b.timeoutMs);
|
|
5115
|
+
if (t.unref) t.unref();
|
|
5116
|
+
})]);
|
|
5215
5117
|
}
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
if (d.action === "wait") {
|
|
5228
|
-
lastSkipReason = d.reason + "\uFF08" + Math.round(absentForMs / 1e3) + "s/" + Math.round(d.needMs / 1e3) + "s\uFF09";
|
|
5229
|
-
return { waiting: d.reason };
|
|
5230
|
-
}
|
|
5231
|
-
if (d.action === "skip") {
|
|
5232
|
-
if (lastSkipReason !== d.reason) {
|
|
5233
|
-
lastSkipReason = d.reason;
|
|
5234
|
-
warn("\u4E0D\u62C9\u8D77\u684C\u9762\u58F3\uFF1A" + d.reason);
|
|
5118
|
+
try {
|
|
5119
|
+
const r = await p;
|
|
5120
|
+
if (r && r.__beatTimeout) {
|
|
5121
|
+
errors.push(name + ":timeout");
|
|
5122
|
+
if (this.logger && this.logger.warn) this.logger.warn("[beat] " + name + " \u8D85\u8FC7 " + b.timeoutMs + "ms\uFF0C\u5DF2\u8DF3\u8FC7\u672C\u62CD\uFF08\u9632\u505C\u6446\uFF09");
|
|
5123
|
+
} else {
|
|
5124
|
+
done.push(name);
|
|
5125
|
+
}
|
|
5126
|
+
} catch (e) {
|
|
5127
|
+
errors.push(name + ":" + (e && e.message));
|
|
5128
|
+
if (this.logger && this.logger.warn) this.logger.warn("[beat] " + name + ": " + (e && e.message));
|
|
5235
5129
|
}
|
|
5236
|
-
return { skipped: d.reason };
|
|
5237
|
-
}
|
|
5238
|
-
restarts.push(t);
|
|
5239
|
-
const r = await shell.restartShell({
|
|
5240
|
-
exePath: exe,
|
|
5241
|
-
procPattern,
|
|
5242
|
-
shouldAbort: typeof o.halted === "function" ? () => o.halted() : void 0
|
|
5243
|
-
});
|
|
5244
|
-
if (r && r.ok) {
|
|
5245
|
-
if (events) events.append("shell_watchdog_restart", { pid: r.pid, exe: r.exe, absentMs: absentForMs });
|
|
5246
|
-
log("\u684C\u9762\u58F3\u7F3A\u5931 " + Math.round(absentForMs / 1e3) + "s\uFF0C\u5DF2\u62C9\u8D77 pid=" + r.pid + " exe=" + r.exe);
|
|
5247
|
-
missingSince = null;
|
|
5248
|
-
} else {
|
|
5249
|
-
if (events) events.append("shell_watchdog_restart_failed", { error: r && r.error || "\u672A\u77E5", absentMs: absentForMs });
|
|
5250
|
-
warn("\u62C9\u8D77\u684C\u9762\u58F3\u5931\u8D25\uFF1A" + (r && r.error || "\u672A\u77E5"));
|
|
5251
5130
|
}
|
|
5252
|
-
return { restarted: !!(r && r.ok), error: r && r.error || null };
|
|
5253
|
-
} catch (e) {
|
|
5254
|
-
warn("\u76D1\u63A7\u5F02\u5E38\uFF1A" + (e && e.message || e));
|
|
5255
|
-
return { error: e && e.message || String(e) };
|
|
5256
5131
|
} finally {
|
|
5257
|
-
|
|
5132
|
+
this._ticking = false;
|
|
5133
|
+
}
|
|
5134
|
+
if (this.onBeatDone) {
|
|
5135
|
+
try {
|
|
5136
|
+
await this.onBeatDone({ done, errors });
|
|
5137
|
+
} catch (e) {
|
|
5138
|
+
if (this.logger && this.logger.warn) this.logger.warn("[beat] onBeatDone: " + (e && e.message));
|
|
5139
|
+
}
|
|
5258
5140
|
}
|
|
5141
|
+
return { done, errors };
|
|
5259
5142
|
}
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5143
|
+
start(intervalMs) {
|
|
5144
|
+
this._intervalMs = intervalMs || this._intervalMs;
|
|
5145
|
+
this._stopping = false;
|
|
5146
|
+
if (this._timer) clearInterval(this._timer);
|
|
5147
|
+
const self = this;
|
|
5148
|
+
this._timer = setInterval(() => {
|
|
5149
|
+
self.tick();
|
|
5150
|
+
}, this._intervalMs);
|
|
5151
|
+
if (this._timer && typeof this._timer.unref === "function") this._timer.unref();
|
|
5152
|
+
return this;
|
|
5153
|
+
}
|
|
5154
|
+
stop() {
|
|
5155
|
+
this._stopping = true;
|
|
5156
|
+
if (this._timer) {
|
|
5157
|
+
clearInterval(this._timer);
|
|
5158
|
+
this._timer = null;
|
|
5266
5159
|
}
|
|
5267
|
-
return {
|
|
5268
|
-
enabled: config.shellWatchdog !== false,
|
|
5269
|
-
intervalMs: config.shellWatchdogIntervalMs || DEFAULTS.intervalMs,
|
|
5270
|
-
graceMs: config.shellWatchdogGraceMs || DEFAULTS.graceMs,
|
|
5271
|
-
updateGraceMs: config.shellWatchdogUpdateGraceMs || DEFAULTS.updateGraceMs,
|
|
5272
|
-
maxRestarts: config.shellWatchdogMaxRestarts || DEFAULTS.maxRestarts,
|
|
5273
|
-
absentForMs: missingSince === null ? null : t - missingSince,
|
|
5274
|
-
restartsInWindow: restarts.filter((x) => t - x < (config.shellWatchdogWindowMs || DEFAULTS.windowMs)).length,
|
|
5275
|
-
everSawAlive,
|
|
5276
|
-
lastSkipReason,
|
|
5277
|
-
session,
|
|
5278
|
-
expectedAbsence: expectedAbsence()
|
|
5279
|
-
};
|
|
5280
5160
|
}
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5161
|
+
resume() {
|
|
5162
|
+
this._stopping = false;
|
|
5163
|
+
}
|
|
5164
|
+
clear() {
|
|
5165
|
+
this._beats.clear();
|
|
5166
|
+
this.stop();
|
|
5167
|
+
}
|
|
5168
|
+
};
|
|
5169
|
+
module2.exports = { BeatScheduler };
|
|
5284
5170
|
}
|
|
5285
5171
|
});
|
|
5286
5172
|
|
|
@@ -5385,7 +5271,6 @@ var require_capability_profile = __commonJS({
|
|
|
5385
5271
|
"use strict";
|
|
5386
5272
|
var linux = {
|
|
5387
5273
|
sandboxLaunch: true,
|
|
5388
|
-
// 服务管理器一律走产品自身的进程管理(不借 systemd)⇒ 无 cgroup 强制,如实为 supervise。
|
|
5389
5274
|
sandboxEnforcement: "supervise",
|
|
5390
5275
|
pidAdoption: true,
|
|
5391
5276
|
processTreeKill: true,
|
|
@@ -7012,7 +6897,7 @@ var require_portable = __commonJS({
|
|
|
7012
6897
|
if (!pid || !Array.isArray(anchors) || !anchors.length) return false;
|
|
7013
6898
|
const cmd2 = pidlookup.readCmdline(pid);
|
|
7014
6899
|
if (!cmd2) return false;
|
|
7015
|
-
return anchors.
|
|
6900
|
+
return anchors.every((a) => a && cmd2.indexOf(String(a)) !== -1);
|
|
7016
6901
|
}
|
|
7017
6902
|
var portOf = (o) => {
|
|
7018
6903
|
const p = Number(o && o.port);
|
|
@@ -7055,15 +6940,6 @@ var require_portable = __commonJS({
|
|
|
7055
6940
|
kind: "portable",
|
|
7056
6941
|
supportsUnits: false,
|
|
7057
6942
|
supportsTransient: true,
|
|
7058
|
-
/**
|
|
7059
|
-
* 能力协商(根因 B 修法;与 router 域 `supports(cap)` 同一范式,下沉到平台层)。
|
|
7060
|
-
*
|
|
7061
|
-
* 判据来源:capability-profile.js 的 sandboxEnforcement —— 三平台均为 'supervise'
|
|
7062
|
-
* (= 产品自身监控,**无 cgroup 级强制**)。此前该字段全仓 0 处查询,
|
|
7063
|
-
* 于是 governor 在"限额根本无法生效"的前提下仍判违规并重启 ⇒ 永动机(P0)。
|
|
7064
|
-
*
|
|
7065
|
-
* 调用方(governor)必须先问后处置:不支持限额 ⇒ 只观测,绝不重启。
|
|
7066
|
-
*/
|
|
7067
6943
|
supports(cap) {
|
|
7068
6944
|
if (cap === "treeKill") return true;
|
|
7069
6945
|
if (cap === "limits") return false;
|
|
@@ -7105,11 +6981,6 @@ var require_portable = __commonJS({
|
|
|
7105
6981
|
}
|
|
7106
6982
|
return true;
|
|
7107
6983
|
},
|
|
7108
|
-
// 审计 P0-I5:原实现在 Windows 上用 Atomics.wait(nap)**同步冻结事件循环**做轮询、且 SIGKILL 兜底分支
|
|
7109
|
-
// 调用的 taskkill 完全异步不 await ⇒ 停止"无法确认"(常返回 false),进而实例仍被标 RUNNING、
|
|
7110
|
-
// upgrade.js 在上个进程仍占端口时继续重装 ⇒ 与端口预检撞车回滚(正是 upgrade.js 想防的故障)。
|
|
7111
|
-
// 修复:改为 async,用 real-timer 轮询(不阻塞事件循环),并等待 taskkill 真正结束(有界 10s,与 process.js killTree 同),
|
|
7112
|
-
// 给足停止窗口再判定;仍超时再报 false(如实,不再假成功)。timeoutMs 仍被 STOP_WAIT_CAP_MS 截断(与调用方意图无关)。
|
|
7113
6984
|
async stopUnit(unit, o) {
|
|
7114
6985
|
const opts = o || {};
|
|
7115
6986
|
const ours = findOurs(opts);
|
|
@@ -7216,19 +7087,6 @@ var require_portable = __commonJS({
|
|
|
7216
7087
|
}
|
|
7217
7088
|
return false;
|
|
7218
7089
|
},
|
|
7219
|
-
/**
|
|
7220
|
-
* 单元是否活跃 —— 返回 Outcome 三态(根因 A 修法)。
|
|
7221
|
-
*
|
|
7222
|
-
* 此前返回 null 表示"未知",而调用方 instance/ops.js:67 用 `active !== false` 判,
|
|
7223
|
-
* 于是 null(未知)被当成"仍活跃" ⇒ removeInstance 把未知报成删除成功(P0)。
|
|
7224
|
-
*
|
|
7225
|
-
* 关键修正:**无 anchors 时不得把"有人在监听"当成"我们的实例在跑"**。
|
|
7226
|
-
* 端口是共享事实、不是身份(与 monitor.js#matchesAnchors 同一条判据);
|
|
7227
|
-
* 缺锚点即无从验证身份 ⇒ 如实返回 unknown,由调用方决定(升级校验须失败并回滚)。
|
|
7228
|
-
*
|
|
7229
|
-
* 兼容:既有调用方若直接判真假,Outcome 对象恒为真值,行为同"true",不会静默反转;
|
|
7230
|
-
* 但显式判据(isOk/isFail/isUnknown)才能区分三态——见 shared/outcome.js。
|
|
7231
|
-
*/
|
|
7232
7090
|
isUnitActive(unit, o) {
|
|
7233
7091
|
const opts = o || {};
|
|
7234
7092
|
if (findOurs(opts)) return OUTCOME.OK;
|
|
@@ -7252,7 +7110,6 @@ var require_portable = __commonJS({
|
|
|
7252
7110
|
transientUnitFile() {
|
|
7253
7111
|
return null;
|
|
7254
7112
|
},
|
|
7255
|
-
// 审计 P0-I5:随 stopUnit 改为 async,cleanTransient 也须 await(不得再用 === false 同步判)。
|
|
7256
7113
|
async cleanTransient(unit, o) {
|
|
7257
7114
|
const opts = o || {};
|
|
7258
7115
|
const errors = [];
|
|
@@ -7291,7 +7148,6 @@ var require_service = __commonJS({
|
|
|
7291
7148
|
kind: UNSUPPORTED_KIND,
|
|
7292
7149
|
supportsUnits: false,
|
|
7293
7150
|
supportsTransient: false,
|
|
7294
|
-
// 能力协商:与 portable 同类,未知平台一律不支持(保持方法集一致)。
|
|
7295
7151
|
supports() {
|
|
7296
7152
|
return false;
|
|
7297
7153
|
},
|
|
@@ -8215,6 +8071,122 @@ var require_os = __commonJS({
|
|
|
8215
8071
|
}
|
|
8216
8072
|
});
|
|
8217
8073
|
|
|
8074
|
+
// src/platform/contract/pm-client.js
|
|
8075
|
+
var require_pm_client = __commonJS({
|
|
8076
|
+
"src/platform/contract/pm-client.js"(exports2, module2) {
|
|
8077
|
+
"use strict";
|
|
8078
|
+
var fs2 = require("node:fs");
|
|
8079
|
+
var path2 = require("node:path");
|
|
8080
|
+
var http2 = require("node:http");
|
|
8081
|
+
var stateRoot2 = require_state_root();
|
|
8082
|
+
var pidlookup = require_pidlookup();
|
|
8083
|
+
var FILE_NAME = "guard-mgmt.json";
|
|
8084
|
+
var SUPPORTED_SCHEMA = 1;
|
|
8085
|
+
var HOST = "127.0.0.1";
|
|
8086
|
+
var TIMEOUT_MS = 1500;
|
|
8087
|
+
var unavailableHook = null;
|
|
8088
|
+
function setUnavailableHook(fn) {
|
|
8089
|
+
unavailableHook = typeof fn === "function" ? fn : null;
|
|
8090
|
+
}
|
|
8091
|
+
function file() {
|
|
8092
|
+
return path2.join(stateRoot2.supervisorDir(), FILE_NAME);
|
|
8093
|
+
}
|
|
8094
|
+
function pidAlive2(pid) {
|
|
8095
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
8096
|
+
return pidlookup.probeAlive(pid) === "alive";
|
|
8097
|
+
}
|
|
8098
|
+
function endpoint() {
|
|
8099
|
+
let text;
|
|
8100
|
+
try {
|
|
8101
|
+
text = fs2.readFileSync(file(), "utf8");
|
|
8102
|
+
} catch {
|
|
8103
|
+
return null;
|
|
8104
|
+
}
|
|
8105
|
+
let j;
|
|
8106
|
+
try {
|
|
8107
|
+
j = JSON.parse(text);
|
|
8108
|
+
} catch {
|
|
8109
|
+
return null;
|
|
8110
|
+
}
|
|
8111
|
+
if (!j || typeof j !== "object" || j.schema !== SUPPORTED_SCHEMA) return null;
|
|
8112
|
+
const port = Number(j.port);
|
|
8113
|
+
if (!Number.isInteger(port) || port <= 0 || port > 65535) return null;
|
|
8114
|
+
if (!pidAlive2(Number(j.pid))) return null;
|
|
8115
|
+
return { port, host: typeof j.host === "string" && j.host ? j.host : HOST };
|
|
8116
|
+
}
|
|
8117
|
+
function post(route, payload) {
|
|
8118
|
+
const ep = endpoint();
|
|
8119
|
+
if (!ep) {
|
|
8120
|
+
if (unavailableHook) {
|
|
8121
|
+
try {
|
|
8122
|
+
unavailableHook(route);
|
|
8123
|
+
} catch {
|
|
8124
|
+
}
|
|
8125
|
+
}
|
|
8126
|
+
return false;
|
|
8127
|
+
}
|
|
8128
|
+
let body;
|
|
8129
|
+
try {
|
|
8130
|
+
body = JSON.stringify(payload || {});
|
|
8131
|
+
} catch {
|
|
8132
|
+
return false;
|
|
8133
|
+
}
|
|
8134
|
+
const req = http2.request(
|
|
8135
|
+
{
|
|
8136
|
+
host: ep.host,
|
|
8137
|
+
port: ep.port,
|
|
8138
|
+
path: route,
|
|
8139
|
+
method: "POST",
|
|
8140
|
+
headers: { "content-type": "application/json", "content-length": Buffer.byteLength(body) },
|
|
8141
|
+
timeout: TIMEOUT_MS
|
|
8142
|
+
},
|
|
8143
|
+
(res) => {
|
|
8144
|
+
res.resume();
|
|
8145
|
+
}
|
|
8146
|
+
);
|
|
8147
|
+
req.on("timeout", () => {
|
|
8148
|
+
try {
|
|
8149
|
+
req.destroy();
|
|
8150
|
+
} catch {
|
|
8151
|
+
}
|
|
8152
|
+
});
|
|
8153
|
+
req.on("error", () => {
|
|
8154
|
+
});
|
|
8155
|
+
try {
|
|
8156
|
+
req.end(body);
|
|
8157
|
+
return true;
|
|
8158
|
+
} catch {
|
|
8159
|
+
return false;
|
|
8160
|
+
}
|
|
8161
|
+
}
|
|
8162
|
+
module2.exports = {
|
|
8163
|
+
FILE_NAME,
|
|
8164
|
+
SUPPORTED_SCHEMA,
|
|
8165
|
+
file,
|
|
8166
|
+
endpoint,
|
|
8167
|
+
setUnavailableHook,
|
|
8168
|
+
register(desc) {
|
|
8169
|
+
return post("/pm/register", desc);
|
|
8170
|
+
},
|
|
8171
|
+
setDesired(id, desired) {
|
|
8172
|
+
return post("/pm/set-desired", { id, desired });
|
|
8173
|
+
},
|
|
8174
|
+
onPhase(id, phase) {
|
|
8175
|
+
return post("/pm/on-phase", { id, phase });
|
|
8176
|
+
},
|
|
8177
|
+
recordExit(id, code, signal, startupFailure) {
|
|
8178
|
+
return post("/pm/record-exit", { id, code, signal, startup_failure: startupFailure === true });
|
|
8179
|
+
},
|
|
8180
|
+
requestRestart(id) {
|
|
8181
|
+
return post("/pm/request-restart", { id });
|
|
8182
|
+
},
|
|
8183
|
+
resetBackoff(id) {
|
|
8184
|
+
return post("/pm/reset-backoff", { id });
|
|
8185
|
+
}
|
|
8186
|
+
};
|
|
8187
|
+
}
|
|
8188
|
+
});
|
|
8189
|
+
|
|
8218
8190
|
// src/app/assembly/bootstrap.js
|
|
8219
8191
|
var require_bootstrap = __commonJS({
|
|
8220
8192
|
"src/app/assembly/bootstrap.js"(exports2, module2) {
|
|
@@ -8225,11 +8197,20 @@ var require_bootstrap = __commonJS({
|
|
|
8225
8197
|
var path2 = require("node:path");
|
|
8226
8198
|
var fs2 = require("node:fs");
|
|
8227
8199
|
var ports = require_ports().shared;
|
|
8228
|
-
var { createShellWatchdog } = require_watchdog();
|
|
8229
8200
|
var pidlook = require_pidlookup();
|
|
8201
|
+
var { BeatScheduler } = require_synchrony();
|
|
8230
8202
|
var platform = require_os();
|
|
8231
8203
|
var ENV_FORM_STARTUP_DELAY_MS = 3e3;
|
|
8232
8204
|
function _bootstrap(host) {
|
|
8205
|
+
try {
|
|
8206
|
+
require_pm_client().setUnavailableHook((route) => {
|
|
8207
|
+
try {
|
|
8208
|
+
host.events.append("pm_endpoint_unavailable", { route });
|
|
8209
|
+
} catch {
|
|
8210
|
+
}
|
|
8211
|
+
});
|
|
8212
|
+
} catch {
|
|
8213
|
+
}
|
|
8233
8214
|
try {
|
|
8234
8215
|
host.events.append("guard_started", {
|
|
8235
8216
|
pid: process.pid,
|
|
@@ -8250,40 +8231,56 @@ var require_bootstrap = __commonJS({
|
|
|
8250
8231
|
routerAutostart: host.config.routerAutostart === true,
|
|
8251
8232
|
routerMode: null,
|
|
8252
8233
|
updateCheck: null,
|
|
8253
|
-
shellWatchdog: null,
|
|
8254
8234
|
lastRefresh: null
|
|
8255
8235
|
};
|
|
8256
|
-
host.
|
|
8257
|
-
host.
|
|
8258
|
-
host.
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
|
|
8264
|
-
|
|
8265
|
-
|
|
8266
|
-
|
|
8267
|
-
host.
|
|
8268
|
-
|
|
8269
|
-
|
|
8270
|
-
|
|
8271
|
-
|
|
8272
|
-
|
|
8273
|
-
|
|
8274
|
-
if (
|
|
8275
|
-
|
|
8276
|
-
}
|
|
8236
|
+
host._startupFacts.bootAt = Date.now();
|
|
8237
|
+
host._startupFacts.updateCheck = host._startupFacts.updateCheck || null;
|
|
8238
|
+
if (!host._beatScheduler) host._beatScheduler = new BeatScheduler({ logger: host.logger, intervalMs: host.config.tickIntervalMs || 5e3 });
|
|
8239
|
+
const beat = host._beatScheduler;
|
|
8240
|
+
const tickMs = host.config.tickIntervalMs || 5e3;
|
|
8241
|
+
beat.unregister("main");
|
|
8242
|
+
beat.unregister("heartbeat");
|
|
8243
|
+
beat.unregister("instance-supervise");
|
|
8244
|
+
beat.unregister("upgrade-check");
|
|
8245
|
+
beat.register("main", () => host.tick(), { every: 1 });
|
|
8246
|
+
beat.register("heartbeat", () => {
|
|
8247
|
+
if (host.managedObjects) return host.managedObjects.heartbeat(tickMs);
|
|
8248
|
+
return host.tick();
|
|
8249
|
+
}, { every: 1, timeoutMs: Math.max(3e4, tickMs * 12) });
|
|
8250
|
+
beat.register("instance-supervise", async () => {
|
|
8251
|
+
if (!host.instances) return;
|
|
8252
|
+
try {
|
|
8253
|
+
for (const inst of host.instances.all()) {
|
|
8254
|
+
if (inst.domain === "native") continue;
|
|
8255
|
+
host.instances.supervise && host.instances.supervise(inst.id);
|
|
8277
8256
|
}
|
|
8278
|
-
}
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8257
|
+
} catch (e) {
|
|
8258
|
+
}
|
|
8259
|
+
try {
|
|
8260
|
+
host.instances.governSweep && host.instances.governSweep();
|
|
8261
|
+
} catch (e) {
|
|
8262
|
+
}
|
|
8263
|
+
}, { every: 1 });
|
|
8264
|
+
if (host.config.updateCheckEnabled !== false) {
|
|
8265
|
+
const checkDelayMs2 = host.config.initialCheckDelayMs || 2e4;
|
|
8266
|
+
const checkIntervalMs2 = Math.max(1, Math.round((host.config.updateCheckIntervalMs || 36e5) / tickMs));
|
|
8267
|
+
beat.register("upgrade-check", () => {
|
|
8268
|
+
try {
|
|
8269
|
+
host.nativeManager.checkUpdate();
|
|
8270
|
+
} catch (e) {
|
|
8271
|
+
}
|
|
8272
|
+
}, { every: checkIntervalMs2, firstDelayMs: checkDelayMs2 });
|
|
8273
|
+
}
|
|
8274
|
+
beat.tick();
|
|
8275
|
+
beat.start(tickMs);
|
|
8276
|
+
host._timer = null;
|
|
8277
|
+
host._heartbeatTimer = null;
|
|
8278
|
+
host._upgradeTimer = null;
|
|
8279
|
+
host._initialCheckTimer = null;
|
|
8280
|
+
host._lastHeartbeatAt = Date.now();
|
|
8281
|
+
host._heartbeatStalls = 0;
|
|
8282
|
+
host._heartbeatBeat = host._heartbeatBeat || 0;
|
|
8283
|
+
if (host.lanDaemonEnabled()) {
|
|
8287
8284
|
host._syncLanState();
|
|
8288
8285
|
const lrt = host._ensureLanRuntime(true);
|
|
8289
8286
|
if (host.logger && host.logger.info) host.logger.info("[lan] L3b \u6A21\u5F0F\uFF1Alan-daemon " + (lrt.mode === "daemon" ? "\u5DF2\u5C31\u7EEA pid=" + (lrt.spawned || "(\u65E2\u6709)") : "\u672A\u5C31\u7EEA mode=" + lrt.mode));
|
|
@@ -8292,7 +8289,6 @@ var require_bootstrap = __commonJS({
|
|
|
8292
8289
|
});
|
|
8293
8290
|
host.lan.syncFrpc();
|
|
8294
8291
|
}
|
|
8295
|
-
if (!host.managedObjects) host.instances.startTimer(host.config.tickIntervalMs || 5e3);
|
|
8296
8292
|
if (!host.lanDaemonEnabled()) {
|
|
8297
8293
|
for (const inst of host.instances.all()) {
|
|
8298
8294
|
if (inst.remoteMode === "lan" || inst.remoteMode === "wan") host.lan.syncProxy(inst).catch(() => {
|
|
@@ -8356,22 +8352,6 @@ var require_bootstrap = __commonJS({
|
|
|
8356
8352
|
initialDelayMs: checkDelayMs,
|
|
8357
8353
|
intervalMs: checkIntervalMs
|
|
8358
8354
|
};
|
|
8359
|
-
if (host.config.updateCheckEnabled !== false) {
|
|
8360
|
-
host._initialCheckTimer = setTimeout(() => {
|
|
8361
|
-
host.nativeManager.checkUpdate();
|
|
8362
|
-
}, checkDelayMs);
|
|
8363
|
-
host._upgradeTimer = setInterval(() => {
|
|
8364
|
-
host.nativeManager.checkUpdate();
|
|
8365
|
-
}, checkIntervalMs);
|
|
8366
|
-
}
|
|
8367
|
-
try {
|
|
8368
|
-
host._startShellWatchdog();
|
|
8369
|
-
} catch (e) {
|
|
8370
|
-
if (host.logger && host.logger.warn) {
|
|
8371
|
-
host.logger.warn("[shell-watchdog] \u542F\u52A8\u5F02\u5E38\uFF08\u4E0D\u5F71\u54CD\u5B88\u536B\u4E3B\u5FAA\u73AF\uFF09: " + (e && e.message || e));
|
|
8372
|
-
}
|
|
8373
|
-
}
|
|
8374
|
-
host._startupFacts.shellWatchdog = !!host.shellWatchdog;
|
|
8375
8355
|
const envTimer = setTimeout(() => {
|
|
8376
8356
|
try {
|
|
8377
8357
|
host._refreshEnvironmentForm();
|
|
@@ -8416,41 +8396,6 @@ var require_bootstrap = __commonJS({
|
|
|
8416
8396
|
return null;
|
|
8417
8397
|
});
|
|
8418
8398
|
}
|
|
8419
|
-
function _startShellWatchdog(host) {
|
|
8420
|
-
if (host.config.shellWatchdog === false) {
|
|
8421
|
-
host.logger.info && host.logger.info("[shell-watchdog] \u5DF2\u6309\u914D\u7F6E\u7981\u7528");
|
|
8422
|
-
return;
|
|
8423
|
-
}
|
|
8424
|
-
try {
|
|
8425
|
-
host.shellWatchdog = createShellWatchdog({
|
|
8426
|
-
shell: host.shellDomain,
|
|
8427
|
-
pidlookup: pidlook,
|
|
8428
|
-
desktop: platform.desktop,
|
|
8429
|
-
logger: host.logger,
|
|
8430
|
-
events: host.events,
|
|
8431
|
-
config: host.config,
|
|
8432
|
-
halted: () => host._shellExitIntended(),
|
|
8433
|
-
onShellAlive: () => {
|
|
8434
|
-
if (!host._shellHalted) return;
|
|
8435
|
-
if (host._stopping) return;
|
|
8436
|
-
if (host._sessionHalting && host._sessionHalting()) return;
|
|
8437
|
-
host._shellHalted = false;
|
|
8438
|
-
try {
|
|
8439
|
-
host.writeState(true);
|
|
8440
|
-
} catch {
|
|
8441
|
-
}
|
|
8442
|
-
}
|
|
8443
|
-
});
|
|
8444
|
-
host._shellWatchdogTimer = setInterval(() => {
|
|
8445
|
-
Promise.resolve(host.shellWatchdog.tick()).catch(() => {
|
|
8446
|
-
});
|
|
8447
|
-
}, host.shellWatchdog.intervalMs);
|
|
8448
|
-
if (host._shellWatchdogTimer.unref) host._shellWatchdogTimer.unref();
|
|
8449
|
-
host.logger.info && host.logger.info("[shell-watchdog] \u5DF2\u542F\u7528\uFF08\u5468\u671F " + Math.round(host.shellWatchdog.intervalMs / 1e3) + "s\uFF09");
|
|
8450
|
-
} catch (e) {
|
|
8451
|
-
host.logger.warn && host.logger.warn("[shell-watchdog] \u521D\u59CB\u5316\u5931\u8D25\uFF08\u4E0D\u5F71\u54CD\u5B88\u536B\uFF09: " + (e && e.message || e));
|
|
8452
|
-
}
|
|
8453
|
-
}
|
|
8454
8399
|
function _registerFixedPorts(host) {
|
|
8455
8400
|
ports.register("dsh-main", host.config.targetPort);
|
|
8456
8401
|
ports.registerSole("supervisor-api", host.config.apiPort);
|
|
@@ -8479,7 +8424,7 @@ var require_bootstrap = __commonJS({
|
|
|
8479
8424
|
}
|
|
8480
8425
|
}
|
|
8481
8426
|
}
|
|
8482
|
-
module2.exports = { _bootstrap,
|
|
8427
|
+
module2.exports = { _bootstrap, _registerFixedPorts, _bindNativeDshCommand, _refreshEnvironmentForm };
|
|
8483
8428
|
}
|
|
8484
8429
|
});
|
|
8485
8430
|
|
|
@@ -8535,14 +8480,17 @@ var require_api_rebind = __commonJS({
|
|
|
8535
8480
|
});
|
|
8536
8481
|
server.listen(host.config.apiPort, host.config.apiHost, () => {
|
|
8537
8482
|
bind._tries = 0;
|
|
8483
|
+
const bound = server.address();
|
|
8484
|
+
const realPort = bound && Number.isInteger(bound.port) ? bound.port : host.config.apiPort;
|
|
8538
8485
|
host.api = server;
|
|
8486
|
+
if (realPort !== host.config.apiPort) host.config.apiPort = realPort;
|
|
8539
8487
|
try {
|
|
8540
|
-
portsShared.registerSole("supervisor-api",
|
|
8488
|
+
portsShared.registerSole("supervisor-api", realPort);
|
|
8541
8489
|
} catch (e) {
|
|
8542
8490
|
host.logger.warn("ports.registerSole(supervisor-api) \u5931\u8D25: " + (e && e.message || e));
|
|
8543
8491
|
}
|
|
8544
|
-
host.events.append("api_listening", { host: host.config.apiHost, port:
|
|
8545
|
-
host.logger.info("api listening on " + host.config.apiHost + ":" +
|
|
8492
|
+
host.events.append("api_listening", { host: host.config.apiHost, port: realPort });
|
|
8493
|
+
host.logger.info("api listening on " + host.config.apiHost + ":" + realPort);
|
|
8546
8494
|
});
|
|
8547
8495
|
};
|
|
8548
8496
|
bind._tries = 0;
|
|
@@ -8564,19 +8512,21 @@ var require_api_rebind = __commonJS({
|
|
|
8564
8512
|
host.logger.error("api error: " + (err ? err.message : String(err)));
|
|
8565
8513
|
});
|
|
8566
8514
|
server.listen(port, host.config.apiHost, () => {
|
|
8515
|
+
const bound = server.address();
|
|
8516
|
+
const realPort = bound && Number.isInteger(bound.port) ? bound.port : port;
|
|
8567
8517
|
host.api = server;
|
|
8568
8518
|
const prev = host.config.apiPort;
|
|
8569
|
-
if (
|
|
8570
|
-
host.config.apiPort =
|
|
8571
|
-
if (host.configPath) host.persistConfigPatch({ apiPort:
|
|
8519
|
+
if (realPort !== prev) {
|
|
8520
|
+
host.config.apiPort = realPort;
|
|
8521
|
+
if (host.configPath) host.persistConfigPatch({ apiPort: realPort });
|
|
8572
8522
|
}
|
|
8573
8523
|
try {
|
|
8574
|
-
portsShared.registerSole("supervisor-api",
|
|
8524
|
+
portsShared.registerSole("supervisor-api", realPort);
|
|
8575
8525
|
} catch (e) {
|
|
8576
8526
|
host.logger.warn("ports.registerSole(supervisor-api) \u5931\u8D25: " + e.message);
|
|
8577
8527
|
}
|
|
8578
|
-
host.events.append("api_listening", { host: host.config.apiHost, port });
|
|
8579
|
-
host.logger.info("api listening on " + host.config.apiHost + ":" +
|
|
8528
|
+
host.events.append("api_listening", { host: host.config.apiHost, port: realPort });
|
|
8529
|
+
host.logger.info("api listening on " + host.config.apiHost + ":" + realPort);
|
|
8580
8530
|
});
|
|
8581
8531
|
return server;
|
|
8582
8532
|
};
|
|
@@ -10019,14 +9969,10 @@ var require_shutdown = __commonJS({
|
|
|
10019
9969
|
host.events.append("guard_exit", {});
|
|
10020
9970
|
host.logger.info("guard shutting down");
|
|
10021
9971
|
host.writeState(true);
|
|
10022
|
-
if (host.
|
|
10023
|
-
if (host._heartbeatTimer) clearInterval(host._heartbeatTimer);
|
|
9972
|
+
if (host._beatScheduler) host._beatScheduler.stop();
|
|
10024
9973
|
if (host._killTimer) clearTimeout(host._killTimer);
|
|
10025
9974
|
if (host._adoptKillTimer) clearTimeout(host._adoptKillTimer);
|
|
10026
9975
|
abortInflightNpm(host, "guard-shutdown");
|
|
10027
|
-
if (host._initialCheckTimer) clearTimeout(host._initialCheckTimer);
|
|
10028
|
-
if (host._upgradeTimer) clearInterval(host._upgradeTimer);
|
|
10029
|
-
if (host._shellWatchdogTimer) clearInterval(host._shellWatchdogTimer);
|
|
10030
9976
|
if (host.api) {
|
|
10031
9977
|
try {
|
|
10032
9978
|
host.api.close();
|
|
@@ -10071,37 +10017,10 @@ var require_shutdown = __commonJS({
|
|
|
10071
10017
|
} catch (e) {
|
|
10072
10018
|
host.logger.warn && host.logger.warn("shutdownAll persist shellHalted: " + e.message);
|
|
10073
10019
|
}
|
|
10074
|
-
if (host._shellWatchdogTimer) {
|
|
10075
|
-
clearInterval(host._shellWatchdogTimer);
|
|
10076
|
-
host._shellWatchdogTimer = null;
|
|
10077
|
-
}
|
|
10078
|
-
if (host._heartbeatTimer) {
|
|
10079
|
-
clearInterval(host._heartbeatTimer);
|
|
10080
|
-
host._heartbeatTimer = null;
|
|
10081
|
-
}
|
|
10082
|
-
if (host._timer) {
|
|
10083
|
-
clearInterval(host._timer);
|
|
10084
|
-
host._timer = null;
|
|
10085
|
-
}
|
|
10086
|
-
if (host._initialCheckTimer) {
|
|
10087
|
-
clearTimeout(host._initialCheckTimer);
|
|
10088
|
-
host._initialCheckTimer = null;
|
|
10089
|
-
}
|
|
10090
|
-
if (host._upgradeTimer) {
|
|
10091
|
-
clearInterval(host._upgradeTimer);
|
|
10092
|
-
host._upgradeTimer = null;
|
|
10093
|
-
}
|
|
10094
|
-
if (host._killTimer) {
|
|
10095
|
-
clearTimeout(host._killTimer);
|
|
10096
|
-
host._killTimer = null;
|
|
10097
|
-
}
|
|
10098
|
-
if (host._adoptKillTimer) {
|
|
10099
|
-
clearTimeout(host._adoptKillTimer);
|
|
10100
|
-
host._adoptKillTimer = null;
|
|
10101
|
-
}
|
|
10102
10020
|
host.logger.info("[session] \u9000\u51FA\u6D41\u7A0B\u5F00\u59CB\uFF1A\u505C\u6B62\u5168\u90E8\u88AB\u7BA1\u5BF9\u8C61\u2026");
|
|
10103
10021
|
host.events && host.events.append("shutdown_all", {});
|
|
10104
10022
|
abortInflightNpm(host, "session-exit");
|
|
10023
|
+
if (host._beatScheduler) host._beatScheduler.stop();
|
|
10105
10024
|
host._stopMainDsh();
|
|
10106
10025
|
await host._stopAllSandboxes();
|
|
10107
10026
|
const stopDaemon = async (kind) => {
|
|
@@ -10337,6 +10256,12 @@ var require_instance_adapter = __commonJS({
|
|
|
10337
10256
|
} catch (e) {
|
|
10338
10257
|
d.logger() && d.logger().warn && d.logger().warn("sandbox setPhase: " + (e && e.message || e));
|
|
10339
10258
|
}
|
|
10259
|
+
try {
|
|
10260
|
+
const rc = Number(inst.state && inst.state.restartCount) || 0;
|
|
10261
|
+
if (entry.restartCount !== rc) d.managedObjects().setRestartCount(entry.id, rc);
|
|
10262
|
+
} catch (e) {
|
|
10263
|
+
d.logger() && d.logger().warn && d.logger().warn("sandbox setRestartCount: " + (e && e.message || e));
|
|
10264
|
+
}
|
|
10340
10265
|
}
|
|
10341
10266
|
}
|
|
10342
10267
|
};
|
|
@@ -10954,6 +10879,7 @@ var require_process2 = __commonJS({
|
|
|
10954
10879
|
var native = require_command();
|
|
10955
10880
|
var BRAND2 = require_brand();
|
|
10956
10881
|
var { findManagedDshPort, applyMainPort } = require_port_rederive();
|
|
10882
|
+
var pmClient = require_pm_client();
|
|
10957
10883
|
var DEPS = /* @__PURE__ */ new WeakMap();
|
|
10958
10884
|
var HELPERS = [
|
|
10959
10885
|
"MissingNotified",
|
|
@@ -11009,7 +10935,6 @@ var require_process2 = __commonJS({
|
|
|
11009
10935
|
const d = depsOf(this);
|
|
11010
10936
|
return native.nativeCommand(d.config(), d.pluginManager());
|
|
11011
10937
|
},
|
|
11012
|
-
// 启动窗口(毫秒):唯一的时间常量,spawn 时落成 startDeadline,窗口内退出即「启动失败」。
|
|
11013
10938
|
startWindowMs() {
|
|
11014
10939
|
const d = depsOf(this);
|
|
11015
10940
|
const secs = Number(d.config().startsecs);
|
|
@@ -11089,6 +11014,7 @@ var require_process2 = __commonJS({
|
|
|
11089
11014
|
errBuf.flush();
|
|
11090
11015
|
if (d.mChild() !== child) return;
|
|
11091
11016
|
d.events().append(BRAND2.EVENT_HARNESS_EXITED, { code, signal, phase: d.state().phase() });
|
|
11017
|
+
pmClient.recordExit("main", code, signal, d.state().phase() === "STARTING");
|
|
11092
11018
|
d.mSetChild(null);
|
|
11093
11019
|
if (d.stopping()) return;
|
|
11094
11020
|
if (d.state().desired() !== "running") return;
|
|
@@ -11098,6 +11024,7 @@ var require_process2 = __commonJS({
|
|
|
11098
11024
|
const why = code !== null ? String(code) : "sig" + signal;
|
|
11099
11025
|
const inStartup = phase === "STARTING";
|
|
11100
11026
|
if (inStartup || d.state().guardian()) {
|
|
11027
|
+
pmClient.requestRestart("main");
|
|
11101
11028
|
d.beginRestart("exit:" + why, { startupFailure: inStartup });
|
|
11102
11029
|
} else {
|
|
11103
11030
|
d.writeCrashHalted(true);
|
|
@@ -11174,8 +11101,6 @@ var require_process2 = __commonJS({
|
|
|
11174
11101
|
d.tokenService().scheduleCapture("main");
|
|
11175
11102
|
d.state().write();
|
|
11176
11103
|
},
|
|
11177
|
-
// 重启:活过 startsecs 后退出(或人工重启)⇒ 正常重启,不记启动失败;窗口内退出 ⇒ 记一次启动失败并由限流裁决。
|
|
11178
|
-
// 相位只有 STARTING / RUNNING / FAILED:重启=回到 STARTING(下一次 spawn 会开新的 startsecs 窗口)。
|
|
11179
11104
|
_beginRestart(reason, opts) {
|
|
11180
11105
|
const d = depsOf(this);
|
|
11181
11106
|
const manual = !!(opts && opts.manual);
|
|
@@ -11316,7 +11241,6 @@ var require_signals = __commonJS({
|
|
|
11316
11241
|
return null;
|
|
11317
11242
|
}
|
|
11318
11243
|
},
|
|
11319
|
-
// 归属凭据:spawn 与 adopt 两条取得所有权的路线都要写;落盘走 writeAtomic + 0600。
|
|
11320
11244
|
_writeMainOwner(dshPid, port) {
|
|
11321
11245
|
const d = depsOf(this);
|
|
11322
11246
|
try {
|
|
@@ -11372,7 +11296,6 @@ var require_signals = __commonJS({
|
|
|
11372
11296
|
}
|
|
11373
11297
|
}, d.config().stopGraceMs));
|
|
11374
11298
|
},
|
|
11375
|
-
// 代际 gen 保护共享的 _adoptKillTimer 槽位:定时器只在「本代仍是当前代」时置空。
|
|
11376
11299
|
_killAdopted(pid) {
|
|
11377
11300
|
const d = depsOf(this);
|
|
11378
11301
|
const gen = (d.readAdoptKillGen() || 0) + 1;
|
|
@@ -11437,7 +11360,35 @@ var require_guardian = __commonJS({
|
|
|
11437
11360
|
}
|
|
11438
11361
|
return { start, count, tripped: count >= burst };
|
|
11439
11362
|
}
|
|
11440
|
-
|
|
11363
|
+
function makeBudget(cfg) {
|
|
11364
|
+
const windowMs = cfg && Number(cfg.windowMs) > 0 ? Number(cfg.windowMs) : 6e4;
|
|
11365
|
+
const burst = cfg && Number(cfg.burst) >= 1 ? Number(cfg.burst) : 5;
|
|
11366
|
+
let state = { start: null, count: 0 };
|
|
11367
|
+
const self = {
|
|
11368
|
+
windowMs,
|
|
11369
|
+
burst,
|
|
11370
|
+
get count() {
|
|
11371
|
+
return state.count;
|
|
11372
|
+
},
|
|
11373
|
+
get tripped() {
|
|
11374
|
+
return state.count >= burst;
|
|
11375
|
+
},
|
|
11376
|
+
note(startupFailure) {
|
|
11377
|
+
if (startupFailure === false || startupFailure == null) {
|
|
11378
|
+
return { tripped: false, count: state.count, halted: false };
|
|
11379
|
+
}
|
|
11380
|
+
const dec = bumpStartupFailure(state, Date.now(), { windowMs, burst });
|
|
11381
|
+
state.start = dec.start;
|
|
11382
|
+
state.count = dec.count;
|
|
11383
|
+
return { tripped: dec.tripped, count: state.count, halted: dec.tripped };
|
|
11384
|
+
},
|
|
11385
|
+
reset() {
|
|
11386
|
+
state = { start: null, count: 0 };
|
|
11387
|
+
}
|
|
11388
|
+
};
|
|
11389
|
+
return self;
|
|
11390
|
+
}
|
|
11391
|
+
module2.exports = { shouldGuard, bumpStartupFailure, makeBudget };
|
|
11441
11392
|
}
|
|
11442
11393
|
});
|
|
11443
11394
|
|
|
@@ -11446,6 +11397,7 @@ var require_startup_throttle = __commonJS({
|
|
|
11446
11397
|
"src/app/main/startup-throttle.js"(exports2, module2) {
|
|
11447
11398
|
"use strict";
|
|
11448
11399
|
var guardian = require_guardian();
|
|
11400
|
+
var pmClient = require_pm_client();
|
|
11449
11401
|
var DEPS = /* @__PURE__ */ new WeakMap();
|
|
11450
11402
|
function depsOf(host) {
|
|
11451
11403
|
let d = DEPS.get(host);
|
|
@@ -11485,8 +11437,6 @@ var require_startup_throttle = __commonJS({
|
|
|
11485
11437
|
}
|
|
11486
11438
|
module2.exports = {
|
|
11487
11439
|
methods: {
|
|
11488
|
-
// 唯一一条限流:startupFailWindowMs 内「启动窗口内退出」达 startupFailBurst 次 ⇒ phase=FAILED。
|
|
11489
|
-
// 到点即停自动重启:不排队、不退避、不指数等待;恢复的唯一入口是人工重试(_retryStartupFailure)。
|
|
11490
11440
|
_noteStartupFailure() {
|
|
11491
11441
|
const d = depsOf(this);
|
|
11492
11442
|
const windowMs = d.config().startupFailWindowMs || 6e4;
|
|
@@ -11511,11 +11461,11 @@ var require_startup_throttle = __commonJS({
|
|
|
11511
11461
|
);
|
|
11512
11462
|
return { failed: true, count: dec.count };
|
|
11513
11463
|
},
|
|
11514
|
-
// 手动重试入口:清计数后回到 STARTING(随后由 STARTING 分支重新 spawn,新的 startsecs 窗口)。
|
|
11515
11464
|
_retryStartupFailure() {
|
|
11516
11465
|
const d = depsOf(this);
|
|
11517
11466
|
d.mSetStartupFailWindowStart(null);
|
|
11518
11467
|
d.mSetStartupFailCount(0);
|
|
11468
|
+
pmClient.resetBackoff("main");
|
|
11519
11469
|
d.events().append("startup_retry", {});
|
|
11520
11470
|
d.logger().warn("\u542F\u52A8\u5931\u8D25\u8BA1\u6570\u5DF2\u6E05\u96F6\uFF1A\u4EBA\u5DE5\u91CD\u8BD5\uFF0C\u56DE\u5230 STARTING");
|
|
11521
11471
|
return { ok: true };
|
|
@@ -12065,8 +12015,6 @@ var require_runtime2 = __commonJS({
|
|
|
12065
12015
|
spawnEnv: () => ({ DSH_SUPERVISOR_CONFIG: cfgPath }),
|
|
12066
12016
|
logger: d.logger(),
|
|
12067
12017
|
events: d.events(),
|
|
12068
|
-
// `this` 是宿主(本方法经 host._daemonLifecycle(kind) 调用);箭头函数捕获它。
|
|
12069
|
-
// 此前写作 host._exitIntended(),而 host 只存在于 depsOf(host) 形参作用域 ⇒ 延迟回调求值时 ReferenceError。
|
|
12070
12018
|
exitIntended: () => this._exitIntended()
|
|
12071
12019
|
});
|
|
12072
12020
|
return lc[kind];
|
|
@@ -12934,7 +12882,7 @@ var require_credential = __commonJS({
|
|
|
12934
12882
|
});
|
|
12935
12883
|
|
|
12936
12884
|
// src/domains/relay/core.js
|
|
12937
|
-
var
|
|
12885
|
+
var require_core3 = __commonJS({
|
|
12938
12886
|
"src/domains/relay/core.js"(exports2, module2) {
|
|
12939
12887
|
"use strict";
|
|
12940
12888
|
var crypto = require("node:crypto");
|
|
@@ -12962,14 +12910,52 @@ var require_core4 = __commonJS({
|
|
|
12962
12910
|
}
|
|
12963
12911
|
return null;
|
|
12964
12912
|
}
|
|
12965
|
-
function
|
|
12966
|
-
|
|
12967
|
-
|
|
12968
|
-
|
|
12969
|
-
|
|
12970
|
-
|
|
12971
|
-
|
|
12913
|
+
function stripGateTokenAndPreserve(rawUrl) {
|
|
12914
|
+
if (!rawUrl) return "/";
|
|
12915
|
+
let url = rawUrl;
|
|
12916
|
+
const hashIdx = url.indexOf("#");
|
|
12917
|
+
if (hashIdx >= 0) url = url.slice(0, hashIdx);
|
|
12918
|
+
const qIdx = url.indexOf("?");
|
|
12919
|
+
const path2 = qIdx >= 0 ? url.slice(0, qIdx) : url;
|
|
12920
|
+
if (qIdx < 0) return path2 || "/";
|
|
12921
|
+
const query = url.slice(qIdx + 1);
|
|
12922
|
+
if (!query) return path2 || "/";
|
|
12923
|
+
const kept = [];
|
|
12924
|
+
for (const pair of query.split("&")) {
|
|
12925
|
+
if (!pair) {
|
|
12926
|
+
kept.push(pair);
|
|
12927
|
+
continue;
|
|
12928
|
+
}
|
|
12929
|
+
const eq = pair.indexOf("=");
|
|
12930
|
+
const rawKey = eq >= 0 ? pair.slice(0, eq) : pair;
|
|
12931
|
+
let key = rawKey;
|
|
12932
|
+
try {
|
|
12933
|
+
key = decodeURIComponent(rawKey);
|
|
12934
|
+
} catch {
|
|
12935
|
+
}
|
|
12936
|
+
if (key === "token") continue;
|
|
12937
|
+
kept.push(pair);
|
|
12972
12938
|
}
|
|
12939
|
+
const out = path2 || "/";
|
|
12940
|
+
return kept.length ? out + "?" + kept.join("&") : out;
|
|
12941
|
+
}
|
|
12942
|
+
function upstreamPath(rawUrl) {
|
|
12943
|
+
return stripGateTokenAndPreserve(rawUrl);
|
|
12944
|
+
}
|
|
12945
|
+
var POLYFILL_SCRIPT = `<script>
|
|
12946
|
+
if (typeof crypto.randomUUID !== 'function') {
|
|
12947
|
+
crypto.randomUUID = function () {
|
|
12948
|
+
var b = crypto.getRandomValues(new Uint8Array(16));
|
|
12949
|
+
b[6] = (b[6] & 0x0f) | 0x40;
|
|
12950
|
+
b[8] = (b[8] & 0x3f) | 0x80;
|
|
12951
|
+
var h = '';
|
|
12952
|
+
for (var i = 0; i < 16; i++) h += (i === 4 || i === 6 || i === 8 || i === 12 ? '-' : '') + ('0' + b[i].toString(16)).slice(-2);
|
|
12953
|
+
return h;
|
|
12954
|
+
};
|
|
12955
|
+
}
|
|
12956
|
+
</script>`;
|
|
12957
|
+
function redactLogPath(rawUrl) {
|
|
12958
|
+
return rawUrl ? stripGateTokenAndPreserve(rawUrl) : "";
|
|
12973
12959
|
}
|
|
12974
12960
|
function lanGateCookieValue(token, salt) {
|
|
12975
12961
|
const t = String(token == null ? "" : token);
|
|
@@ -12977,23 +12963,6 @@ var require_core4 = __commonJS({
|
|
|
12977
12963
|
if (!t || !s) return "";
|
|
12978
12964
|
return crypto.createHash("sha256").update(s + "\n" + t).digest("hex");
|
|
12979
12965
|
}
|
|
12980
|
-
function hasValidToken(req, token, salt, mode) {
|
|
12981
|
-
if (!token) return normalizeRemoteMode(mode) === "lan";
|
|
12982
|
-
const url = new URL(req.url, "http://localhost");
|
|
12983
|
-
const queryToken = url.searchParams.get("token");
|
|
12984
|
-
if (queryToken && safeEqual(queryToken, token)) return true;
|
|
12985
|
-
const cookies = req.headers.cookie || "";
|
|
12986
|
-
const m = LAN_COOKIE_RE.exec(cookies);
|
|
12987
|
-
if (m) {
|
|
12988
|
-
try {
|
|
12989
|
-
const want = lanGateCookieValue(token, salt);
|
|
12990
|
-
return !!want && safeEqual(decodeURIComponent(m[1]), want);
|
|
12991
|
-
} catch {
|
|
12992
|
-
return false;
|
|
12993
|
-
}
|
|
12994
|
-
}
|
|
12995
|
-
return false;
|
|
12996
|
-
}
|
|
12997
12966
|
function tokenGateDecision(req, token, salt, mode) {
|
|
12998
12967
|
if (!token) return normalizeRemoteMode(mode) === "lan" ? { ok: true } : { ok: false, unauthorized: true };
|
|
12999
12968
|
const url = new URL(req.url, "http://localhost");
|
|
@@ -13016,27 +12985,22 @@ var require_core4 = __commonJS({
|
|
|
13016
12985
|
}
|
|
13017
12986
|
return { ok: false, unauthorized: true };
|
|
13018
12987
|
}
|
|
13019
|
-
|
|
13020
|
-
if (
|
|
13021
|
-
|
|
13022
|
-
|
|
13023
|
-
|
|
13024
|
-
|
|
13025
|
-
|
|
13026
|
-
|
|
13027
|
-
|
|
13028
|
-
|
|
13029
|
-
|
|
13030
|
-
|
|
13031
|
-
|
|
13032
|
-
|
|
13033
|
-
try {
|
|
13034
|
-
const u = new URL(rawUrl, "http://127.0.0.1");
|
|
13035
|
-
if (u.searchParams.has("token")) u.searchParams.delete("token");
|
|
13036
|
-
return u.pathname + (u.searchParams.toString() ? "?" + u.searchParams.toString() : "");
|
|
13037
|
-
} catch {
|
|
13038
|
-
return String(rawUrl || "").replace(/[?&]token=[^&]*/, "");
|
|
12988
|
+
function hasValidToken(req, token, salt, mode) {
|
|
12989
|
+
if (!token) return normalizeRemoteMode(mode) === "lan";
|
|
12990
|
+
const url = new URL(req.url, "http://localhost");
|
|
12991
|
+
const queryToken = url.searchParams.get("token");
|
|
12992
|
+
if (queryToken && safeEqual(queryToken, token)) return true;
|
|
12993
|
+
const cookies = req.headers.cookie || "";
|
|
12994
|
+
const m = LAN_COOKIE_RE.exec(cookies);
|
|
12995
|
+
if (m) {
|
|
12996
|
+
try {
|
|
12997
|
+
const want = lanGateCookieValue(token, salt);
|
|
12998
|
+
return !!want && safeEqual(decodeURIComponent(m[1]), want);
|
|
12999
|
+
} catch {
|
|
13000
|
+
return false;
|
|
13001
|
+
}
|
|
13039
13002
|
}
|
|
13003
|
+
return false;
|
|
13040
13004
|
}
|
|
13041
13005
|
function buildFrpcToml(settings, instances) {
|
|
13042
13006
|
const s = settings || {};
|
|
@@ -13067,8 +13031,6 @@ if (typeof crypto.randomUUID !== 'function') {
|
|
|
13067
13031
|
return {
|
|
13068
13032
|
serverAddr: String(j.serverAddr !== void 0 ? j.serverAddr : cur.serverAddr).trim(),
|
|
13069
13033
|
serverPort: Number(j.serverPort) || cur.serverPort,
|
|
13070
|
-
// authToken:null/undefined 归一为空串(frpc 遇空串不写 auth.token,避免 String(null)==="null" 被当成共享密钥);
|
|
13071
|
-
// 非空串统一 trim,与 serverAddr 同口径。
|
|
13072
13034
|
authToken: j.authToken === void 0 ? cur.authToken : j.authToken == null ? "" : String(j.authToken).trim(),
|
|
13073
13035
|
user: String(j.user || cur.user || "dsh")
|
|
13074
13036
|
};
|
|
@@ -13151,7 +13113,7 @@ if (typeof crypto.randomUUID !== 'function') {
|
|
|
13151
13113
|
var require_lan2 = __commonJS({
|
|
13152
13114
|
"src/app/domain-actions/lan.js"(exports2, module2) {
|
|
13153
13115
|
"use strict";
|
|
13154
|
-
var { validateWanAccess, generateRemoteToken } =
|
|
13116
|
+
var { validateWanAccess, generateRemoteToken } = require_core3();
|
|
13155
13117
|
var { remoteTokenStrength } = require_credential();
|
|
13156
13118
|
var BRAND2 = require_brand();
|
|
13157
13119
|
function lanModule(deps) {
|
|
@@ -13518,13 +13480,6 @@ var require_env = __commonJS({
|
|
|
13518
13480
|
} catch {
|
|
13519
13481
|
return null;
|
|
13520
13482
|
}
|
|
13521
|
-
})(),
|
|
13522
|
-
shellWatchdog: (() => {
|
|
13523
|
-
try {
|
|
13524
|
-
return this.shellWatchdog && typeof this.shellWatchdog.status === "function" ? this.shellWatchdog.status() : null;
|
|
13525
|
-
} catch {
|
|
13526
|
-
return null;
|
|
13527
|
-
}
|
|
13528
13483
|
})()
|
|
13529
13484
|
};
|
|
13530
13485
|
},
|
|
@@ -13739,7 +13694,6 @@ var require_versions = __commonJS({
|
|
|
13739
13694
|
}
|
|
13740
13695
|
return dir;
|
|
13741
13696
|
},
|
|
13742
|
-
// 同步 spawn 会冻结事件循环,消费方含 HTTP 路径,故 git 子进程异步执行。
|
|
13743
13697
|
async guardVersionLocal() {
|
|
13744
13698
|
const d = depsOf(this);
|
|
13745
13699
|
const root = d.vcsRoot();
|
|
@@ -13796,7 +13750,6 @@ var require_access = __commonJS({
|
|
|
13796
13750
|
const cfg = this.config || {};
|
|
13797
13751
|
return { configured: !!cfg.apiAccessKey, host: cfg.apiHost || void 0 };
|
|
13798
13752
|
},
|
|
13799
|
-
// 清空密钥必须同时回关 LAN(apiHost→127.0.0.1):只清 key 不动 apiHost 会留下「绑定 0.0.0.0 且零认证」的暴露窗口。
|
|
13800
13753
|
setAccessKey(key) {
|
|
13801
13754
|
try {
|
|
13802
13755
|
const cfg = this.config || {};
|
|
@@ -14707,7 +14660,6 @@ var require_pool2 = __commonJS({
|
|
|
14707
14660
|
this._backfillAt.delete(id);
|
|
14708
14661
|
this.clear(id);
|
|
14709
14662
|
}
|
|
14710
|
-
// journalctl 同步查询会冻结生命周期 tick 的事件循环,故 journal 档非阻塞发射(见 capture.js)。
|
|
14711
14663
|
capture(id) {
|
|
14712
14664
|
const src = this._sources.get(id);
|
|
14713
14665
|
if (!src) return null;
|
|
@@ -15024,6 +14976,35 @@ var require_npm = __commonJS({
|
|
|
15024
14976
|
}
|
|
15025
14977
|
});
|
|
15026
14978
|
|
|
14979
|
+
// src/domains/shell/core.js
|
|
14980
|
+
var require_core4 = __commonJS({
|
|
14981
|
+
"src/domains/shell/core.js"(exports2, module2) {
|
|
14982
|
+
"use strict";
|
|
14983
|
+
function isUpdatePhase(phase) {
|
|
14984
|
+
const p = String(phase || "");
|
|
14985
|
+
return p === "restarting" || p.indexOf("shell-update") === 0;
|
|
14986
|
+
}
|
|
14987
|
+
function deriveState(id, journal) {
|
|
14988
|
+
const j = journal || {};
|
|
14989
|
+
if (!j.to) return { state: "idle", reason: "\u65E0\u8FDB\u884C\u4E2D\u7684\u66F4\u65B0", journal: j, identity: id };
|
|
14990
|
+
const cur = id && id.version ? String(id.version) : null;
|
|
14991
|
+
if (cur && cur === j.to && id && id.phase === "ready") {
|
|
14992
|
+
const next = j.confirmed === true ? j : Object.assign({}, j, { confirmed: true });
|
|
14993
|
+
return { state: "confirmed", version: cur, reason: "\u58F3\u5DF2\u5065\u5EB7\u8FD0\u884C\u65B0\u7248\u672C", journal: next, identity: id };
|
|
14994
|
+
}
|
|
14995
|
+
return {
|
|
14996
|
+
state: "pending",
|
|
14997
|
+
target: j.to,
|
|
14998
|
+
current: cur,
|
|
14999
|
+
reason: cur === j.to ? "\u7B49\u5F85\u58F3\u4E0A\u62A5\u5C31\u7EEA" : "\u7B49\u5F85\u58F3\u91CD\u542F\u5230\u65B0\u7248\u672C",
|
|
15000
|
+
journal: j,
|
|
15001
|
+
identity: id
|
|
15002
|
+
};
|
|
15003
|
+
}
|
|
15004
|
+
module2.exports = { isUpdatePhase, deriveState };
|
|
15005
|
+
}
|
|
15006
|
+
});
|
|
15007
|
+
|
|
15027
15008
|
// src/domains/shell/journal.js
|
|
15028
15009
|
var require_journal = __commonJS({
|
|
15029
15010
|
"src/domains/shell/journal.js"(exports2, module2) {
|
|
@@ -15032,7 +15013,7 @@ var require_journal = __commonJS({
|
|
|
15032
15013
|
var fs2 = require("node:fs");
|
|
15033
15014
|
var path2 = require("node:path");
|
|
15034
15015
|
var { writeAtomic } = require_fs();
|
|
15035
|
-
var { deriveState } =
|
|
15016
|
+
var { deriveState } = require_core4();
|
|
15036
15017
|
function shellDir() {
|
|
15037
15018
|
return stateRoot2.shellDir();
|
|
15038
15019
|
}
|
|
@@ -15111,116 +15092,6 @@ var require_journal = __commonJS({
|
|
|
15111
15092
|
}
|
|
15112
15093
|
});
|
|
15113
15094
|
|
|
15114
|
-
// src/domains/shell/restart.js
|
|
15115
|
-
var require_restart = __commonJS({
|
|
15116
|
-
"src/domains/shell/restart.js"(exports2, module2) {
|
|
15117
|
-
"use strict";
|
|
15118
|
-
var spawnOS = require_spawn();
|
|
15119
|
-
var pidlook = require_pidlookup();
|
|
15120
|
-
var BRAND2 = require_brand();
|
|
15121
|
-
var { identity } = require_journal();
|
|
15122
|
-
var { exeFromCmdline, isShellProcess } = require_core3();
|
|
15123
|
-
var { semverCompare } = require_version2();
|
|
15124
|
-
var SHELL_RELEASE_PKG = "@lob-ox/shell-release";
|
|
15125
|
-
async function checkUpdate(dist, opts) {
|
|
15126
|
-
const id = identity();
|
|
15127
|
-
const installed = id && id.version ? String(id.version) : null;
|
|
15128
|
-
if (!dist || typeof dist.fetchLatestVersion !== "function") {
|
|
15129
|
-
return { ok: false, installed, latest: null, updateAvailable: false, error: "\u5206\u53D1\u670D\u52A1\u672A\u521D\u59CB\u5316" };
|
|
15130
|
-
}
|
|
15131
|
-
try {
|
|
15132
|
-
const latest = await dist.fetchLatestVersion(SHELL_RELEASE_PKG, "npm", { authoritative: (opts && opts.authoritative) === true });
|
|
15133
|
-
if (!latest) {
|
|
15134
|
-
return { ok: false, installed, latest: null, updateAvailable: false, error: "\u672A\u67E5\u8BE2\u5230\u58F3\u53D1\u5E03\u7248\u672C\uFF08\u53EF\u80FD\u5C1A\u672A\u53D1\u5E03\uFF09" };
|
|
15135
|
-
}
|
|
15136
|
-
const updateAvailable = Boolean(installed && semverCompare(latest, installed) > 0);
|
|
15137
|
-
return { ok: true, installed, latest, updateAvailable };
|
|
15138
|
-
} catch (e) {
|
|
15139
|
-
return { ok: false, installed, latest: null, updateAvailable: false, error: e && e.message || String(e) };
|
|
15140
|
-
}
|
|
15141
|
-
}
|
|
15142
|
-
async function restartShell(opts) {
|
|
15143
|
-
const o = opts || {};
|
|
15144
|
-
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
15145
|
-
const pattern = o.procPattern || BRAND2.PROC_MATCH_GUI;
|
|
15146
|
-
let procs = [];
|
|
15147
|
-
try {
|
|
15148
|
-
procs = pidlook.pgrepList(pattern) || [];
|
|
15149
|
-
} catch {
|
|
15150
|
-
procs = [];
|
|
15151
|
-
}
|
|
15152
|
-
procs = procs.filter((p) => isShellProcess(p));
|
|
15153
|
-
const exe = procs.length ? exeFromCmdline(procs[0].cmdline) : o.exePath || null;
|
|
15154
|
-
if (!exe) return { ok: false, error: "\u65E0\u6CD5\u5B9A\u4F4D\u684C\u9762\u58F3\u53EF\u6267\u884C\u6587\u4EF6\uFF08\u58F3\u672A\u8FD0\u884C\u4E14\u672A\u63D0\u4F9B exePath\uFF09" };
|
|
15155
|
-
const killed = [];
|
|
15156
|
-
for (const p of procs) {
|
|
15157
|
-
try {
|
|
15158
|
-
process.kill(p.pid, "SIGTERM");
|
|
15159
|
-
killed.push(p.pid);
|
|
15160
|
-
} catch {
|
|
15161
|
-
}
|
|
15162
|
-
}
|
|
15163
|
-
const waitGone = async (ms) => {
|
|
15164
|
-
const deadline = Date.now() + ms;
|
|
15165
|
-
while (Date.now() < deadline) {
|
|
15166
|
-
const alive = procs.some((p) => {
|
|
15167
|
-
try {
|
|
15168
|
-
return pidlook.isAlive(p.pid);
|
|
15169
|
-
} catch {
|
|
15170
|
-
return false;
|
|
15171
|
-
}
|
|
15172
|
-
});
|
|
15173
|
-
if (!alive) return true;
|
|
15174
|
-
await sleep(200);
|
|
15175
|
-
}
|
|
15176
|
-
return !procs.some((p) => {
|
|
15177
|
-
try {
|
|
15178
|
-
return pidlook.isAlive(p.pid);
|
|
15179
|
-
} catch {
|
|
15180
|
-
return false;
|
|
15181
|
-
}
|
|
15182
|
-
});
|
|
15183
|
-
};
|
|
15184
|
-
let gone = await waitGone(o.graceMs || 6e3);
|
|
15185
|
-
if (!gone) {
|
|
15186
|
-
for (const p of procs) {
|
|
15187
|
-
try {
|
|
15188
|
-
process.kill(p.pid, "SIGKILL");
|
|
15189
|
-
} catch {
|
|
15190
|
-
}
|
|
15191
|
-
}
|
|
15192
|
-
gone = await waitGone(2e3);
|
|
15193
|
-
}
|
|
15194
|
-
if (!gone) {
|
|
15195
|
-
return { ok: false, error: "\u65E7\u58F3\u8FDB\u7A0B\u672A\u80FD\u5728\u8D85\u65F6\u5185\u9000\u51FA\uFF0C\u5DF2\u653E\u5F03\u91CD\u542F\uFF08\u907F\u514D\u53CC\u5B9E\u4F8B\uFF09", killed };
|
|
15196
|
-
}
|
|
15197
|
-
if (typeof o.shouldAbort === "function") {
|
|
15198
|
-
try {
|
|
15199
|
-
if (o.shouldAbort()) return { ok: false, aborted: true, error: "\u4F1A\u8BDD\u5DF2\u9000\u51FA/\u9000\u51FA\u4E2D\uFF0C\u5DF2\u653E\u5F03\u62C9\u8D77\u684C\u9762\u58F3", killed };
|
|
15200
|
-
} catch {
|
|
15201
|
-
}
|
|
15202
|
-
}
|
|
15203
|
-
try {
|
|
15204
|
-
const child = spawnOS.detachedIgnored(exe, [], { env: process.env });
|
|
15205
|
-
child.on("error", (e) => {
|
|
15206
|
-
try {
|
|
15207
|
-
if (o.events && o.events.append) o.events.append("shell_restart_spawn_error", { exe, error: e && e.message || String(e) });
|
|
15208
|
-
} catch {
|
|
15209
|
-
}
|
|
15210
|
-
});
|
|
15211
|
-
child.unref();
|
|
15212
|
-
if (!child.pid) {
|
|
15213
|
-
return { ok: false, error: "\u62C9\u8D77\u65B0\u58F3\u5931\u8D25\uFF1A\u5B50\u8FDB\u7A0B\u672A\u542F\u52A8\uFF08" + exe + " \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u6267\u884C\uFF09", killed };
|
|
15214
|
-
}
|
|
15215
|
-
return { ok: true, restarted: true, killed, pid: child.pid, exe };
|
|
15216
|
-
} catch (e) {
|
|
15217
|
-
return { ok: false, error: "\u62C9\u8D77\u65B0\u58F3\u5931\u8D25: " + (e && e.message || e), killed };
|
|
15218
|
-
}
|
|
15219
|
-
}
|
|
15220
|
-
module2.exports = { SHELL_RELEASE_PKG, checkUpdate, restartShell };
|
|
15221
|
-
}
|
|
15222
|
-
});
|
|
15223
|
-
|
|
15224
15095
|
// src/domains/shell/index.js
|
|
15225
15096
|
var require_shell = __commonJS({
|
|
15226
15097
|
"src/domains/shell/index.js"(exports2, module2) {
|
|
@@ -15234,8 +15105,7 @@ var require_shell = __commonJS({
|
|
|
15234
15105
|
health,
|
|
15235
15106
|
status
|
|
15236
15107
|
} = require_journal();
|
|
15237
|
-
|
|
15238
|
-
module2.exports = { status, evaluate, health, markPending, identity, readJournal, shellDir, checkUpdate, restartShell, SHELL_RELEASE_PKG };
|
|
15108
|
+
module2.exports = { status, evaluate, health, markPending, identity, readJournal, shellDir };
|
|
15239
15109
|
}
|
|
15240
15110
|
});
|
|
15241
15111
|
|
|
@@ -15538,8 +15408,6 @@ var require_intents = __commonJS({
|
|
|
15538
15408
|
if (this._pending.has(intent)) this._pending.delete(intent);
|
|
15539
15409
|
return p;
|
|
15540
15410
|
}
|
|
15541
|
-
// W5:生产零调用,仅 session-lifecycle-test.js 用于「模拟重启后内存态为空」的夹具。
|
|
15542
|
-
// 保留(它是一个合理的测试缝),不视为待删死代码。
|
|
15543
15411
|
clear() {
|
|
15544
15412
|
this._pending.clear();
|
|
15545
15413
|
}
|
|
@@ -15726,7 +15594,6 @@ var require_core5 = __commonJS({
|
|
|
15726
15594
|
routerAutostart: s.routerAutostart,
|
|
15727
15595
|
routerMode: s.routerMode,
|
|
15728
15596
|
updateCheck: s.updateCheck,
|
|
15729
|
-
shellWatchdog: s.shellWatchdog,
|
|
15730
15597
|
lastRefresh: s.lastRefresh
|
|
15731
15598
|
};
|
|
15732
15599
|
}
|
|
@@ -15784,12 +15651,10 @@ var require_core5 = __commonJS({
|
|
|
15784
15651
|
host._upgradeHold = false;
|
|
15785
15652
|
host._upgradeHoldSince = null;
|
|
15786
15653
|
host._timer = null;
|
|
15654
|
+
host._beatScheduler = null;
|
|
15787
15655
|
host._heartbeatBusy = false;
|
|
15788
15656
|
host._killTimer = null;
|
|
15789
15657
|
host._adoptKillTimer = null;
|
|
15790
|
-
host._initialCheckTimer = null;
|
|
15791
|
-
host._upgradeTimer = null;
|
|
15792
|
-
host._shellWatchdogTimer = null;
|
|
15793
15658
|
host._lastOccupiedWarn = 0;
|
|
15794
15659
|
host._lastMainPortRederive = 0;
|
|
15795
15660
|
host._lastPortUp = false;
|
|
@@ -17047,11 +16912,21 @@ var require_instance_lifecycle = __commonJS({
|
|
|
17047
16912
|
});
|
|
17048
16913
|
|
|
17049
16914
|
// src/domains/router/providers/restart.js
|
|
17050
|
-
var
|
|
16915
|
+
var require_restart = __commonJS({
|
|
17051
16916
|
"src/domains/router/providers/restart.js"(exports2, module2) {
|
|
17052
16917
|
"use strict";
|
|
17053
16918
|
var { INSTANCE_STATES } = require_model2();
|
|
17054
16919
|
var ports = require_ports().shared;
|
|
16920
|
+
var { makeBudget } = require_guardian();
|
|
16921
|
+
var PROXY_INSTANCE_THROTTLE = { windowMs: 10 * 60 * 1e3, burst: 5 };
|
|
16922
|
+
function budgetFor(inst) {
|
|
16923
|
+
if (!inst) return makeBudget(PROXY_INSTANCE_THROTTLE);
|
|
16924
|
+
if (!inst._restartBudget) inst._restartBudget = makeBudget(PROXY_INSTANCE_THROTTLE);
|
|
16925
|
+
return inst._restartBudget;
|
|
16926
|
+
}
|
|
16927
|
+
function resetBudget(inst) {
|
|
16928
|
+
if (inst) inst._restartBudget = makeBudget(PROXY_INSTANCE_THROTTLE);
|
|
16929
|
+
}
|
|
17055
16930
|
function createRestartOrchestrator(deps) {
|
|
17056
16931
|
const d = deps || {};
|
|
17057
16932
|
const { startInstance, waitHealthy, isAlive, logger } = d;
|
|
@@ -17085,8 +16960,8 @@ var require_restart2 = __commonJS({
|
|
|
17085
16960
|
}
|
|
17086
16961
|
return { respawn };
|
|
17087
16962
|
}
|
|
17088
|
-
async function
|
|
17089
|
-
const out = { started: [], stopped: [], desired: [] };
|
|
16963
|
+
async function runReconcileThrottled(provider, allowStop) {
|
|
16964
|
+
const out = { started: [], stopped: [], desired: [], throttled: [] };
|
|
17090
16965
|
const desired = provider.desiredRunningAccounts();
|
|
17091
16966
|
const list = desired.list || [];
|
|
17092
16967
|
out.desired = list.map((a) => a.keyId);
|
|
@@ -17095,12 +16970,25 @@ var require_restart2 = __commonJS({
|
|
|
17095
16970
|
const inst = provider.instanceOf(acc);
|
|
17096
16971
|
if (!inst || inst.pid || inst.startingPromise) continue;
|
|
17097
16972
|
if (inst.status === INSTANCE_STATES.DEAD && !inst.pid) inst.status = INSTANCE_STATES.COLD;
|
|
16973
|
+
const b = budgetFor(inst);
|
|
16974
|
+
if (b.tripped) {
|
|
16975
|
+
inst._throttled = true;
|
|
16976
|
+
out.throttled.push(acc.keyId);
|
|
16977
|
+
continue;
|
|
16978
|
+
}
|
|
16979
|
+
inst._throttled = false;
|
|
16980
|
+
const wasRunning = !!inst.pid;
|
|
17098
16981
|
try {
|
|
17099
16982
|
const r = await provider.startInstance(inst);
|
|
16983
|
+
const startupFailure = !r.ok || !wasRunning && !inst.pid;
|
|
16984
|
+
b.note(startupFailure);
|
|
17100
16985
|
if (r && r.ok) {
|
|
17101
16986
|
await provider._waitHealthy(inst).catch(() => {
|
|
17102
16987
|
});
|
|
17103
16988
|
out.started.push(acc.keyId);
|
|
16989
|
+
if (b.tripped && provider.logger && provider.logger.warn) {
|
|
16990
|
+
provider.logger.warn("[reconcile] \u5B9E\u4F8B\u542F\u52A8\u53CD\u590D\u5931\u8D25\u5DF2\u8FBE\u4E0A\u9650 key=" + (acc.maskedKey || acc.keyId) + "\uFF0C\u505C\u6B62\u81EA\u52A8\u62C9\u8D77\uFF08\u7B49\u4EBA\u5DE5/\u7A97\u53E3\u8FC7\u671F\uFF09");
|
|
16991
|
+
}
|
|
17104
16992
|
if (provider.logger && provider.logger.info) {
|
|
17105
16993
|
const role = desired.active && acc.keyId === desired.active.keyId ? "\u5728\u7528" : "\u9884\u70ED";
|
|
17106
16994
|
provider.logger.info("[reconcile] \u62C9\u8D77\u5B9E\u4F8B key=" + acc.maskedKey + "\uFF08" + role + "\uFF09");
|
|
@@ -17109,8 +16997,8 @@ var require_restart2 = __commonJS({
|
|
|
17109
16997
|
} catch {
|
|
17110
16998
|
}
|
|
17111
16999
|
}
|
|
17112
|
-
if (!allowStop) return out;
|
|
17113
17000
|
for (const inst of (provider.instances || []).slice()) {
|
|
17001
|
+
if (!allowStop) break;
|
|
17114
17002
|
if (!inst.pid) {
|
|
17115
17003
|
if (!desiredIds.has(inst.keyId) && inst.port) {
|
|
17116
17004
|
try {
|
|
@@ -17155,7 +17043,7 @@ var require_restart2 = __commonJS({
|
|
|
17155
17043
|
}
|
|
17156
17044
|
}
|
|
17157
17045
|
if (provider._reconcileBusy) return provider._reconcileBusy;
|
|
17158
|
-
const p =
|
|
17046
|
+
const p = runReconcileThrottled(provider, allowStop);
|
|
17159
17047
|
provider._reconcileBusy = p;
|
|
17160
17048
|
try {
|
|
17161
17049
|
return await p;
|
|
@@ -17168,7 +17056,60 @@ var require_restart2 = __commonJS({
|
|
|
17168
17056
|
reconcileInstances(provider).catch(() => {
|
|
17169
17057
|
});
|
|
17170
17058
|
}
|
|
17171
|
-
module2.exports = { createRestartOrchestrator,
|
|
17059
|
+
module2.exports = { createRestartOrchestrator, runReconcileThrottled, reconcileInstances, reconcileNow, budgetFor, resetBudget, PROXY_INSTANCE_THROTTLE };
|
|
17060
|
+
}
|
|
17061
|
+
});
|
|
17062
|
+
|
|
17063
|
+
// src/app/control/process-lifecycle.js
|
|
17064
|
+
var require_process_lifecycle = __commonJS({
|
|
17065
|
+
"src/app/control/process-lifecycle.js"(exports2, module2) {
|
|
17066
|
+
"use strict";
|
|
17067
|
+
var procOS = require_process();
|
|
17068
|
+
var pidlook = require_pidlookup();
|
|
17069
|
+
var DEFAULTS = {
|
|
17070
|
+
stopGraceMs: 9e3,
|
|
17071
|
+
portFreeTimeoutMs: 5e3
|
|
17072
|
+
};
|
|
17073
|
+
function sleep(ms) {
|
|
17074
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
17075
|
+
}
|
|
17076
|
+
function isForeignOnPort(port, ownPid) {
|
|
17077
|
+
if (!Number.isInteger(port) || port <= 0) return false;
|
|
17078
|
+
const p = pidlook.findListeningPid(port);
|
|
17079
|
+
return p !== null && p !== ownPid;
|
|
17080
|
+
}
|
|
17081
|
+
async function waitPortFree(port, timeoutMs) {
|
|
17082
|
+
const dl = Date.now() + (timeoutMs || DEFAULTS.portFreeTimeoutMs);
|
|
17083
|
+
while (Date.now() < dl) {
|
|
17084
|
+
if (pidlook.findListeningPid(port) === null) return true;
|
|
17085
|
+
await sleep(150);
|
|
17086
|
+
}
|
|
17087
|
+
return pidlook.findListeningPid(port) === null;
|
|
17088
|
+
}
|
|
17089
|
+
async function stopProcess(opts) {
|
|
17090
|
+
const o = Object.assign({}, DEFAULTS, opts || {});
|
|
17091
|
+
const pid = typeof o.pid === "number" ? o.pid : null;
|
|
17092
|
+
const port = typeof o.port === "number" ? o.port : null;
|
|
17093
|
+
const ownGroup = !!o.ownGroup;
|
|
17094
|
+
if (pid && pid > 0) {
|
|
17095
|
+
procOS.killTree(pid, "SIGTERM", void 0, ownGroup ? { ownGroup: true } : void 0);
|
|
17096
|
+
}
|
|
17097
|
+
const dl = Date.now() + o.stopGraceMs;
|
|
17098
|
+
while (Date.now() < dl) {
|
|
17099
|
+
const alive = pid ? pidlook.isAlive ? pidlook.isAlive(pid) : false : false;
|
|
17100
|
+
if (!alive) break;
|
|
17101
|
+
await sleep(150);
|
|
17102
|
+
}
|
|
17103
|
+
if (port) {
|
|
17104
|
+
if (isForeignOnPort(port, pid)) {
|
|
17105
|
+
return { ok: false, stopped: false, foreign: true };
|
|
17106
|
+
}
|
|
17107
|
+
const free = await waitPortFree(port, o.portFreeTimeoutMs);
|
|
17108
|
+
if (!free) return { ok: false, stopped: false, portBusy: true };
|
|
17109
|
+
}
|
|
17110
|
+
return { ok: true, stopped: true };
|
|
17111
|
+
}
|
|
17112
|
+
module2.exports = { ProcessLifecycle: { stopProcess, waitPortFree, isForeignOnPort, DEFAULTS } };
|
|
17172
17113
|
}
|
|
17173
17114
|
});
|
|
17174
17115
|
|
|
@@ -17315,6 +17256,7 @@ var require_probe5 = __commonJS({
|
|
|
17315
17256
|
var carrier = require_carrier();
|
|
17316
17257
|
var procOS = require_process();
|
|
17317
17258
|
var { INSTANCE_STATES } = require_model2();
|
|
17259
|
+
var { ProcessLifecycle } = require_process_lifecycle();
|
|
17318
17260
|
var { getQuotaStrategy } = require_quota_strategies();
|
|
17319
17261
|
var { quotaOverallStatus } = require_quota();
|
|
17320
17262
|
var { cachedPkgBin, ensurePkgCached } = require_pkg_cache();
|
|
@@ -17343,7 +17285,7 @@ var require_probe5 = __commonJS({
|
|
|
17343
17285
|
if (provider.logger && provider.logger.warn) provider.logger.warn("[proxy-instance] \u91CD\u542F\u5E78\u5B58\u8005\u5F03\u7528\u91CD\u62C9 pid=" + boundPid + " port=" + inst.port + "\uFF08stdio \u5F52\u5C5E\u65E7\u4EE3\uFF0C\u7981 adopt\uFF09");
|
|
17344
17286
|
if (provider.events) provider.events.append("proxy_instance_survivor_reclaimed", { app: provider.proxyAppId, port: inst.port, pid: boundPid, reason: "restart-survivor-stdio-unsafe" });
|
|
17345
17287
|
try {
|
|
17346
|
-
|
|
17288
|
+
ProcessLifecycle.stopProcess({ pid: boundPid, port: inst.port });
|
|
17347
17289
|
} catch {
|
|
17348
17290
|
}
|
|
17349
17291
|
const dl = Date.now() + 3e3;
|
|
@@ -17533,7 +17475,7 @@ var require_probe5 = __commonJS({
|
|
|
17533
17475
|
if (provider.logger && provider.logger.warn) provider.logger.warn("[proxy-instance] \u751F\u547D\u5468\u671F\u76D1\u63A7\uFF1A\u5B9E\u4F8B\u65E0\u54CD\u5E94\uFF08\u7591\u4F3C\u5361\u6B7B\uFF09key=" + inst.maskedKey + " port=" + inst.port + " pid=" + inst.pid + " fails=" + inst._monitorFails + "\uFF0Ckill \u91CD\u62C9");
|
|
17534
17476
|
if (provider.events) provider.events.append("proxy_instance_hang_restart", { app: provider.proxyAppId, port: inst.port, pid: inst.pid, fails: inst._monitorFails });
|
|
17535
17477
|
try {
|
|
17536
|
-
|
|
17478
|
+
ProcessLifecycle.stopProcess({ pid: inst.pid, port: inst.port });
|
|
17537
17479
|
} catch {
|
|
17538
17480
|
}
|
|
17539
17481
|
inst.pid = null;
|
|
@@ -17688,7 +17630,8 @@ var require_process_pool = __commonJS({
|
|
|
17688
17630
|
"src/domains/router/providers/process-pool.js"(exports2, module2) {
|
|
17689
17631
|
"use strict";
|
|
17690
17632
|
var life = require_instance_lifecycle();
|
|
17691
|
-
var restart =
|
|
17633
|
+
var restart = require_restart();
|
|
17634
|
+
var { resetBudget } = restart;
|
|
17692
17635
|
var probe = require_probe5();
|
|
17693
17636
|
var pool = require_pool3();
|
|
17694
17637
|
var pidlook = require_pidlookup();
|
|
@@ -17821,6 +17764,10 @@ var require_process_pool = __commonJS({
|
|
|
17821
17764
|
}
|
|
17822
17765
|
inst._restartAt = Date.now() + 12e4;
|
|
17823
17766
|
inst._restartPending = null;
|
|
17767
|
+
try {
|
|
17768
|
+
resetBudget(inst);
|
|
17769
|
+
} catch {
|
|
17770
|
+
}
|
|
17824
17771
|
if (this.logger && this.logger.warn) this.logger.warn("[proxy-instance] \u5B9E\u4F8B\u91CD\u542F key=" + inst.maskedKey + " port=" + inst.port + " reason=" + reason);
|
|
17825
17772
|
const hadPid = !!inst.pid;
|
|
17826
17773
|
try {
|
|
@@ -17940,7 +17887,7 @@ var require_proxy = __commonJS({
|
|
|
17940
17887
|
var { npxLauncher } = require_npx_forms();
|
|
17941
17888
|
var { buildCommand } = require_command2();
|
|
17942
17889
|
var probe = require_probe5();
|
|
17943
|
-
var restart =
|
|
17890
|
+
var restart = require_restart();
|
|
17944
17891
|
var pool = require_pool3();
|
|
17945
17892
|
var life = require_instance_lifecycle();
|
|
17946
17893
|
var ProxyProvider = class extends withProcessPool(ProviderBase) {
|
|
@@ -18304,7 +18251,6 @@ var require_proxy_apps = __commonJS({
|
|
|
18304
18251
|
healthPath: "/health",
|
|
18305
18252
|
modelPath: "/v1/models",
|
|
18306
18253
|
upstream: "https://api.commandcode.ai",
|
|
18307
|
-
// keyEnv 是密钥注入的唯一 env 名(绝不进 cmdline);其余 env/超时一律不注入,跑上游默认配置。
|
|
18308
18254
|
keyEnv: "CC_API_KEY",
|
|
18309
18255
|
repo: "thaolaptrinh/commandcode-api-proxy",
|
|
18310
18256
|
registry: "commandcode-api-proxy",
|
|
@@ -19012,16 +18958,6 @@ var require_usage = __commonJS({
|
|
|
19012
18958
|
if (!this._dirty) return;
|
|
19013
18959
|
this._writeTotals();
|
|
19014
18960
|
}
|
|
19015
|
-
/**
|
|
19016
|
-
* 根因 E:缓存**新鲜度**与**可写性**两维度正交,不得耦合。
|
|
19017
|
-
*
|
|
19018
|
-
* 修前:`if (this.totals && this._canPersist()) return this.totals;`
|
|
19019
|
-
* —— 闸门关闭(daemon 模式下 setPersistEnabled(false))时该条件恒假 ⇒ 每次 recordUsage
|
|
19020
|
-
* 都重新读盘,而 _writeTotals 又因闸门关闭直接 return ⇒ 磁盘不变、内存增量被下次 load 覆盖
|
|
19021
|
-
* ⇒ **用量计数被永久吞掉**。
|
|
19022
|
-
*
|
|
19023
|
-
* 现在:load 只看内存缓存是否存在(新鲜度);是否落盘由 _writeTotals 单独决定(可写性)。
|
|
19024
|
-
*/
|
|
19025
18961
|
load() {
|
|
19026
18962
|
if (this.totals) return this.totals;
|
|
19027
18963
|
let t;
|
|
@@ -20058,6 +19994,7 @@ var require_scheduler2 = __commonJS({
|
|
|
20058
19994
|
function createScheduler(deps) {
|
|
20059
19995
|
const d = deps || {};
|
|
20060
19996
|
const state = d.state;
|
|
19997
|
+
const beat = d.beatScheduler || null;
|
|
20061
19998
|
const logger = d.logger || null;
|
|
20062
19999
|
const refreshProxyUpdateInfo = d.refreshProxyUpdateInfo || (() => Promise.resolve());
|
|
20063
20000
|
const refreshOfficialUsageAll = d.refreshOfficialUsageAll || (() => Promise.resolve());
|
|
@@ -20073,6 +20010,27 @@ var require_scheduler2 = __commonJS({
|
|
|
20073
20010
|
});
|
|
20074
20011
|
ensureProxyInstances().catch(() => {
|
|
20075
20012
|
});
|
|
20013
|
+
if (beat) {
|
|
20014
|
+
beat.unregister("router-maint");
|
|
20015
|
+
beat.unregister("router-lifecycle");
|
|
20016
|
+
beat.unregister("router-pricing");
|
|
20017
|
+
beat.register("router-maint", () => {
|
|
20018
|
+
refreshProxyUpdateInfo().catch(() => {
|
|
20019
|
+
});
|
|
20020
|
+
probeIfDue();
|
|
20021
|
+
ensureProxyInstances().catch(() => {
|
|
20022
|
+
});
|
|
20023
|
+
}, { every: Math.max(1, Math.round(3e5 / (d.tickMs || 5e3))) });
|
|
20024
|
+
beat.register("router-lifecycle", () => {
|
|
20025
|
+
monitorInstanceHealth().catch(() => {
|
|
20026
|
+
});
|
|
20027
|
+
}, { every: Math.max(1, Math.round(3e4 / (d.tickMs || 5e3))) });
|
|
20028
|
+
beat.register("router-pricing", () => {
|
|
20029
|
+
refreshOfficialPricingAll().catch(() => {
|
|
20030
|
+
});
|
|
20031
|
+
}, { every: Math.max(1, Math.round(216e5 / (d.tickMs || 5e3))) });
|
|
20032
|
+
return;
|
|
20033
|
+
}
|
|
20076
20034
|
if (state.maintTimer) clearInterval(state.maintTimer);
|
|
20077
20035
|
state.maintTimer = setInterval(() => {
|
|
20078
20036
|
refreshProxyUpdateInfo().catch(() => {
|
|
@@ -20094,6 +20052,12 @@ var require_scheduler2 = __commonJS({
|
|
|
20094
20052
|
}), 6 * 3600 * 1e3);
|
|
20095
20053
|
}
|
|
20096
20054
|
function stop() {
|
|
20055
|
+
if (beat) {
|
|
20056
|
+
beat.unregister("router-maint");
|
|
20057
|
+
beat.unregister("router-lifecycle");
|
|
20058
|
+
beat.unregister("router-pricing");
|
|
20059
|
+
return;
|
|
20060
|
+
}
|
|
20097
20061
|
if (state.maintTimer) {
|
|
20098
20062
|
clearInterval(state.maintTimer);
|
|
20099
20063
|
state.maintTimer = null;
|
|
@@ -20622,6 +20586,8 @@ var require_router3 = __commonJS({
|
|
|
20622
20586
|
var RouterService = class {
|
|
20623
20587
|
constructor(opts) {
|
|
20624
20588
|
this.config = opts.config;
|
|
20589
|
+
this._beatScheduler = opts.beatScheduler || null;
|
|
20590
|
+
this._beatTickMs = opts.tickMs || opts.config && opts.config.tickIntervalMs || 5e3;
|
|
20625
20591
|
this.dist = opts.dist || null;
|
|
20626
20592
|
this.logger = opts.logger || console;
|
|
20627
20593
|
this.events = opts.events || null;
|
|
@@ -20683,6 +20649,8 @@ var require_router3 = __commonJS({
|
|
|
20683
20649
|
state,
|
|
20684
20650
|
store: this.store,
|
|
20685
20651
|
logger: this.logger,
|
|
20652
|
+
beatScheduler: this._beatScheduler,
|
|
20653
|
+
tickMs: this._beatTickMs,
|
|
20686
20654
|
refreshProxyUpdateInfo: () => this.refreshProxyUpdateInfo(),
|
|
20687
20655
|
refreshOfficialUsageAll: () => this.refreshOfficialUsageAll(),
|
|
20688
20656
|
refreshOfficialPricingAll: () => this.refreshOfficialPricingAll()
|
|
@@ -21260,7 +21228,6 @@ var require_model3 = __commonJS({
|
|
|
21260
21228
|
allocation: inst.state ? inst.state.allocation || null : null,
|
|
21261
21229
|
usage: inst.state ? inst.state.usage || null : null,
|
|
21262
21230
|
restartCount: inst.state ? inst.state.restartCount || 0 : 0,
|
|
21263
|
-
// 启动失败限流(唯一一条规则)的可见量:窗口内计数 / 固定端口释放等待落点。
|
|
21264
21231
|
startupFailCount: inst.state ? inst.state.startupFailCount || 0 : 0,
|
|
21265
21232
|
restartAt: inst.state ? inst.state.restartAt || null : null,
|
|
21266
21233
|
lastFailure: inst.state ? inst.state.lastFailure || null : null,
|
|
@@ -21343,12 +21310,6 @@ var require_store5 = __commonJS({
|
|
|
21343
21310
|
_stripLegacyStateKeys(inst) {
|
|
21344
21311
|
if (inst.state && Object.prototype.hasOwnProperty.call(inst.state, "version")) delete inst.state.version;
|
|
21345
21312
|
}
|
|
21346
|
-
/**
|
|
21347
|
-
* 隔离损坏文件。
|
|
21348
|
-
* Lease I2:隔离前**再次校验版本戳**——若自读取失败以来文件已被他人更新,
|
|
21349
|
-
* 说明它不是损坏 ⇒ 放弃隔离(修前会直接 rename 掉这个更新的文件并把实例列表清空,即全量静默丢失)。
|
|
21350
|
-
* 且保留可回溯副本:先复制再改名,不直接丢弃。
|
|
21351
|
-
*/
|
|
21352
21313
|
_quarantineCorrupt(err) {
|
|
21353
21314
|
let locked = false;
|
|
21354
21315
|
try {
|
|
@@ -22589,25 +22550,7 @@ var require_ops2 = __commonJS({
|
|
|
22589
22550
|
store.save();
|
|
22590
22551
|
return { ok: true, instance: inst };
|
|
22591
22552
|
}
|
|
22592
|
-
|
|
22593
|
-
if (timer) clearInterval(timer);
|
|
22594
|
-
timer = setInterval(() => {
|
|
22595
|
-
for (const inst of store.instances) {
|
|
22596
|
-
if (inst.domain === "native") continue;
|
|
22597
|
-
try {
|
|
22598
|
-
lifecycle.supervise(inst.id);
|
|
22599
|
-
} catch (e) {
|
|
22600
|
-
logger.warn && logger.warn("[" + inst.id + "] supervise \u5931\u8D25: " + (e && e.message));
|
|
22601
|
-
}
|
|
22602
|
-
}
|
|
22603
|
-
try {
|
|
22604
|
-
lifecycle.governSweep();
|
|
22605
|
-
} catch (e) {
|
|
22606
|
-
logger.warn && logger.warn("governSweep: " + (e && e.message));
|
|
22607
|
-
}
|
|
22608
|
-
}, intervalMs || 5e3);
|
|
22609
|
-
}
|
|
22610
|
-
return { list, addInstance, removeInstance, updateInstance, startTimer };
|
|
22553
|
+
return { list, addInstance, removeInstance, updateInstance };
|
|
22611
22554
|
}
|
|
22612
22555
|
module2.exports = { createOps };
|
|
22613
22556
|
}
|
|
@@ -22830,7 +22773,6 @@ var require_instance = __commonJS({
|
|
|
22830
22773
|
map(fn) {
|
|
22831
22774
|
return this._store.instances.map(fn);
|
|
22832
22775
|
}
|
|
22833
|
-
// 能力判定读平台表(有副作用)⇒ 从 governor 取,不经 pure 的 sandbox.js。
|
|
22834
22776
|
get sandboxSupported() {
|
|
22835
22777
|
return governor.sandboxSupported(this._sandboxSupportedOverride);
|
|
22836
22778
|
}
|
|
@@ -22918,9 +22860,6 @@ var require_instance = __commonJS({
|
|
|
22918
22860
|
upgradeStatus(id) {
|
|
22919
22861
|
return this._upgrade.upgradeStatus(id);
|
|
22920
22862
|
}
|
|
22921
|
-
startTimer(ms) {
|
|
22922
|
-
return this._ops.startTimer(ms);
|
|
22923
|
-
}
|
|
22924
22863
|
sandboxRoot(inst) {
|
|
22925
22864
|
return sandbox.root(this.instancesRoot, inst);
|
|
22926
22865
|
}
|
|
@@ -23818,23 +23757,14 @@ var require_process_spec = __commonJS({
|
|
|
23818
23757
|
function defaultSpec() {
|
|
23819
23758
|
return {
|
|
23820
23759
|
runtime: null,
|
|
23821
|
-
// 解释器(如 node);为 null 表示 bin 可直接执行
|
|
23822
23760
|
bin: null,
|
|
23823
|
-
// 可执行文件或入口脚本
|
|
23824
23761
|
subcommand: null,
|
|
23825
|
-
// 子命令(如 'web' / 'plugin')
|
|
23826
23762
|
args: [],
|
|
23827
|
-
// 用户参数
|
|
23828
23763
|
port: null,
|
|
23829
|
-
// --port 值(一等公民,不再各处拼装)
|
|
23830
23764
|
patchFile: null,
|
|
23831
|
-
// 插件 overlay(一等公民,不再事后 splice)
|
|
23832
23765
|
storeDir: null,
|
|
23833
|
-
// pnpm --store-dir
|
|
23834
23766
|
install: false,
|
|
23835
|
-
// 是否安装类操作(决定是否注入安全标志)
|
|
23836
23767
|
extraFlags: []
|
|
23837
|
-
// 其他固定标志
|
|
23838
23768
|
};
|
|
23839
23769
|
}
|
|
23840
23770
|
function validate(spec) {
|
|
@@ -24044,7 +23974,7 @@ var require_cli = __commonJS({
|
|
|
24044
23974
|
});
|
|
24045
23975
|
|
|
24046
23976
|
// src/domains/plugin/restart.js
|
|
24047
|
-
var
|
|
23977
|
+
var require_restart2 = __commonJS({
|
|
24048
23978
|
"src/domains/plugin/restart.js"(exports2, module2) {
|
|
24049
23979
|
"use strict";
|
|
24050
23980
|
function targetRunning(ctx, target) {
|
|
@@ -24085,7 +24015,7 @@ var require_restart3 = __commonJS({
|
|
|
24085
24015
|
log("\u91CD\u542F\u5B9E\u4F8B\u300C" + (target.name || target.id) + "\u300D\u4F7F\u63D2\u4EF6\u53D8\u66F4\u751F\u6548\u2026");
|
|
24086
24016
|
if (ctx.events) ctx.events.append("plugin_restart_started", { name: target.name || target.id, target: target.id, kind });
|
|
24087
24017
|
try {
|
|
24088
|
-
ctx.instances.stopInstance(target.id);
|
|
24018
|
+
await ctx.instances.stopInstance(target.id);
|
|
24089
24019
|
} catch (e) {
|
|
24090
24020
|
log("\u505C\u6B62\u5B9E\u4F8B\u5931\u8D25: " + e.message);
|
|
24091
24021
|
}
|
|
@@ -24109,28 +24039,25 @@ var require_restart3 = __commonJS({
|
|
|
24109
24039
|
return true;
|
|
24110
24040
|
}
|
|
24111
24041
|
if (target.kind === "native") {
|
|
24112
|
-
|
|
24113
|
-
|
|
24042
|
+
const nr = ctx.onNativeRestart;
|
|
24043
|
+
if (typeof nr !== "function") {
|
|
24044
|
+
log("\u539F\u751F DSH \u672A\u914D\u7F6E\u91CD\u542F\u56DE\u8C03\uFF1A\u63D2\u4EF6\u53D8\u66F4\u5C06\u5728\u4E0B\u6B21\u542F\u52A8\u65F6\u751F\u6548");
|
|
24114
24045
|
return false;
|
|
24115
24046
|
}
|
|
24116
|
-
|
|
24117
|
-
|
|
24118
|
-
|
|
24119
|
-
|
|
24120
|
-
|
|
24121
|
-
|
|
24122
|
-
return false;
|
|
24123
|
-
}
|
|
24124
|
-
if (rr && rr.ok === false) {
|
|
24125
|
-
log("\u539F\u751F DSH \u91CD\u542F\u8BF7\u6C42\u672A\u751F\u6548\uFF1A" + (rr && rr.error || "unknown"));
|
|
24126
|
-
return false;
|
|
24127
|
-
}
|
|
24128
|
-
log("\u5DF2\u8BF7\u6C42\u91CD\u542F\u539F\u751F DSH \u4F7F\u63D2\u4EF6\u53D8\u66F4\u751F\u6548");
|
|
24129
|
-
if (ctx.events) ctx.events.append("plugin_restart_done", { name: "\u539F\u751F\u5B9E\u4F8B", target: "native", kind, via: "supervisor" });
|
|
24130
|
-
return true;
|
|
24047
|
+
let rr;
|
|
24048
|
+
try {
|
|
24049
|
+
rr = ctx.onNativeRestart();
|
|
24050
|
+
} catch (e) {
|
|
24051
|
+
log("\u539F\u751F DSH \u91CD\u542F\u8BF7\u6C42\u5931\u8D25: " + e.message);
|
|
24052
|
+
return false;
|
|
24131
24053
|
}
|
|
24132
|
-
|
|
24133
|
-
|
|
24054
|
+
if (rr && rr.ok === false) {
|
|
24055
|
+
log("\u539F\u751F DSH \u91CD\u542F\u8BF7\u6C42\u672A\u751F\u6548\uFF1A" + (rr && rr.error || "unknown"));
|
|
24056
|
+
return false;
|
|
24057
|
+
}
|
|
24058
|
+
log("\u5DF2\u8BF7\u6C42\u91CD\u542F\u539F\u751F DSH \u4F7F\u63D2\u4EF6\u53D8\u66F4\u751F\u6548");
|
|
24059
|
+
if (ctx.events) ctx.events.append("plugin_restart_done", { name: "\u539F\u751F\u5B9E\u4F8B", target: "native", kind, via: "supervisor" });
|
|
24060
|
+
return true;
|
|
24134
24061
|
}
|
|
24135
24062
|
return false;
|
|
24136
24063
|
} catch (e) {
|
|
@@ -24704,7 +24631,7 @@ var require_plugin = __commonJS({
|
|
|
24704
24631
|
var store = require_store6();
|
|
24705
24632
|
var targets = require_targets();
|
|
24706
24633
|
var cli = require_cli();
|
|
24707
|
-
var restart =
|
|
24634
|
+
var restart = require_restart2();
|
|
24708
24635
|
var { createJobs } = require_jobs();
|
|
24709
24636
|
var { createLayers } = require_layers();
|
|
24710
24637
|
var ops = require_ops3();
|
|
@@ -24822,7 +24749,8 @@ var require_managed_object = __commonJS({
|
|
|
24822
24749
|
"sandbox-instance": { label: "\u6C99\u7BB1\u5B9E\u4F8B", startable: true, guardable: true },
|
|
24823
24750
|
"router-daemon": { label: "\u667A\u80FD\u8DEF\u7531 daemon", startable: true, guardable: true },
|
|
24824
24751
|
"lan-daemon": { label: "\u8FDC\u7A0B\u63A7\u5236 daemon", startable: true, guardable: true },
|
|
24825
|
-
plugin: { label: "\u63D2\u4EF6\uFF08\u805A\u5408\uFF09", startable: false, guardable: false }
|
|
24752
|
+
plugin: { label: "\u63D2\u4EF6\uFF08\u805A\u5408\uFF09", startable: false, guardable: false },
|
|
24753
|
+
shell: { label: "\u684C\u9762\u58F3", startable: false, guardable: false }
|
|
24826
24754
|
};
|
|
24827
24755
|
var _customKinds = {};
|
|
24828
24756
|
function kindMeta(kind) {
|
|
@@ -24954,9 +24882,17 @@ var require_registry4 = __commonJS({
|
|
|
24954
24882
|
var path2 = require("node:path");
|
|
24955
24883
|
var { writeAtomic } = require_fs();
|
|
24956
24884
|
var { DESIRED, MANAGED_KINDS, kindMeta, registerKind: registerManagedKind, createEntry, normalizeOwnership } = require_managed_object();
|
|
24885
|
+
var { legacyToEntryPhase } = require_phase();
|
|
24957
24886
|
var PHASES = ["stopped", "installing", "starting", "running", "draining", "failed"];
|
|
24958
|
-
var LEGACY_PHASES = { backoff: "failed", restarting: "starting" };
|
|
24959
24887
|
var { runHeartbeat } = require_heartbeat();
|
|
24888
|
+
var pmClient = require_pm_client();
|
|
24889
|
+
var configDefaults = require_config();
|
|
24890
|
+
var RESTART_FALLBACK = { windowMs: 6e4, burst: 5 };
|
|
24891
|
+
var restartDefaults = () => {
|
|
24892
|
+
const r = configDefaults && configDefaults.restart;
|
|
24893
|
+
if (r && Number.isFinite(r.windowMs) && Number.isFinite(r.burst)) return { windowMs: r.windowMs, burst: r.burst };
|
|
24894
|
+
return RESTART_FALLBACK;
|
|
24895
|
+
};
|
|
24960
24896
|
var ManagedRegistry = class {
|
|
24961
24897
|
constructor(opts) {
|
|
24962
24898
|
this.file = opts && opts.file;
|
|
@@ -25002,7 +24938,8 @@ var require_registry4 = __commonJS({
|
|
|
25002
24938
|
try {
|
|
25003
24939
|
if (!o || !kindMeta(o.kind)) continue;
|
|
25004
24940
|
const e = createEntry({ kind: o.kind, id: o.id, name: o.name, desired: o.desired, ownership: o.ownership });
|
|
25005
|
-
|
|
24941
|
+
const np = legacyToEntryPhase(o.phase);
|
|
24942
|
+
if (PHASES.includes(np)) e.phase = np;
|
|
25006
24943
|
if (Number.isInteger(o.restartCount) && o.restartCount >= 0) e.restartCount = o.restartCount;
|
|
25007
24944
|
if (o.startupFailWindowStart === null || typeof o.startupFailWindowStart === "number") e.startupFailWindowStart = o.startupFailWindowStart;
|
|
25008
24945
|
if (Number.isInteger(o.startupFailCount) && o.startupFailCount >= 0) e.startupFailCount = o.startupFailCount;
|
|
@@ -25070,8 +25007,6 @@ var require_registry4 = __commonJS({
|
|
|
25070
25007
|
const i = this._objects.indexOf(e);
|
|
25071
25008
|
if (i >= 0) this._objects.splice(i, 1);
|
|
25072
25009
|
}
|
|
25073
|
-
// 自定义 kind 扩展点:零调用但刻意保留(见 managed-object.js 的说明)——
|
|
25074
|
-
// 它是「新增受管对象类型」的唯一入口,删除等于永久关闭扩展能力。
|
|
25075
25010
|
registerKind(kind, meta) {
|
|
25076
25011
|
registerManagedKind(kind, meta);
|
|
25077
25012
|
return this;
|
|
@@ -25091,6 +25026,8 @@ var require_registry4 = __commonJS({
|
|
|
25091
25026
|
this._syncPortsOwner(e, true);
|
|
25092
25027
|
this._save();
|
|
25093
25028
|
this._event("managed_object_registered", { kind: e.kind, id: e.id, name: e.name });
|
|
25029
|
+
const rd = restartDefaults();
|
|
25030
|
+
pmClient.register({ id: e.id, spawn_cmd: [], restart_window_ms: rd.windowMs, restart_burst: rd.burst });
|
|
25094
25031
|
return e;
|
|
25095
25032
|
}
|
|
25096
25033
|
update(id, patch) {
|
|
@@ -25100,6 +25037,7 @@ var require_registry4 = __commonJS({
|
|
|
25100
25037
|
if (p.desired !== void 0) {
|
|
25101
25038
|
if (!DESIRED.includes(p.desired)) return { ok: false, error: "\u975E\u6CD5 desired: " + p.desired };
|
|
25102
25039
|
e.desired = p.desired;
|
|
25040
|
+
pmClient.setDesired(e.id, p.desired);
|
|
25103
25041
|
}
|
|
25104
25042
|
if (p.name !== void 0) e.name = String(p.name || e.id);
|
|
25105
25043
|
if (p.ownership !== void 0) {
|
|
@@ -25131,6 +25069,7 @@ var require_registry4 = __commonJS({
|
|
|
25131
25069
|
this._drop(e);
|
|
25132
25070
|
this._save();
|
|
25133
25071
|
this._event("managed_object_removed", { kind: e.kind, id: e.id });
|
|
25072
|
+
pmClient.setDesired(e.id, "stopped");
|
|
25134
25073
|
return { ok: true };
|
|
25135
25074
|
}
|
|
25136
25075
|
_releasePort(port, ownerId) {
|
|
@@ -25175,6 +25114,17 @@ var require_registry4 = __commonJS({
|
|
|
25175
25114
|
};
|
|
25176
25115
|
return e;
|
|
25177
25116
|
}
|
|
25117
|
+
setRestartCount(id, n) {
|
|
25118
|
+
const e = this.get(id);
|
|
25119
|
+
if (!e) return null;
|
|
25120
|
+
const v = typeof n === "number" && n >= 0 ? Math.floor(n) : 0;
|
|
25121
|
+
if (e.restartCount !== v) {
|
|
25122
|
+
e.restartCount = v;
|
|
25123
|
+
this._event("managed_object_restart_count", { kind: e.kind, id: e.id, count: v });
|
|
25124
|
+
this._save();
|
|
25125
|
+
}
|
|
25126
|
+
return e;
|
|
25127
|
+
}
|
|
25178
25128
|
setPhase(id, p) {
|
|
25179
25129
|
const e = this.get(id);
|
|
25180
25130
|
if (!e) return null;
|
|
@@ -25184,6 +25134,7 @@ var require_registry4 = __commonJS({
|
|
|
25184
25134
|
e.lastTransitionAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
25185
25135
|
this._event("managed_object_phase", { kind: e.kind, id: e.id, phase: p });
|
|
25186
25136
|
this._save();
|
|
25137
|
+
pmClient.onPhase(e.id, p);
|
|
25187
25138
|
}
|
|
25188
25139
|
return e;
|
|
25189
25140
|
}
|
|
@@ -26026,7 +25977,6 @@ var require_installer = __commonJS({
|
|
|
26026
25977
|
_manifest() {
|
|
26027
25978
|
return manifest.read(this);
|
|
26028
25979
|
}
|
|
26029
|
-
// W5:生产零调用,仅 native-test.js 使用(写 manifest 的夹具入口)。保留为测试缝。
|
|
26030
25980
|
_saveManifest(m) {
|
|
26031
25981
|
return manifest.save(this, m);
|
|
26032
25982
|
}
|
|
@@ -26343,6 +26293,8 @@ var require_domains = __commonJS({
|
|
|
26343
26293
|
}
|
|
26344
26294
|
host.router = new RouterService({
|
|
26345
26295
|
config: host.config,
|
|
26296
|
+
beatScheduler: host._beatScheduler,
|
|
26297
|
+
tickMs: host.config.tickIntervalMs || 5e3,
|
|
26346
26298
|
providerFile: path2.join(swDir, "providers.json"),
|
|
26347
26299
|
usageTotalsFile: path2.join(swDir, "router-usage-totals.json"),
|
|
26348
26300
|
logger: host.logger,
|
|
@@ -26364,7 +26316,6 @@ var require_domains = __commonJS({
|
|
|
26364
26316
|
tasks: host.tasks,
|
|
26365
26317
|
tokenService: host.tokenService,
|
|
26366
26318
|
dshBin: host.config.command && host.config.command[1] ? host.config.command[1] : "dsh",
|
|
26367
|
-
// 实例域限流参数:与主链同一条规则、按域参数化(窗口 600s > 5 × 30s 启动窗口);单源取自域常量。
|
|
26368
26319
|
throttle: THROTTLE_DEFAULTS
|
|
26369
26320
|
});
|
|
26370
26321
|
host.instances.load();
|
|
@@ -26481,7 +26432,6 @@ var require_adapters = __commonJS({
|
|
|
26481
26432
|
kind: "lan",
|
|
26482
26433
|
name: "\u8FDC\u7A0B\u63A7\u5236",
|
|
26483
26434
|
logger,
|
|
26484
|
-
// start 的结果必须来自真实执行:reconcile/syncFrpc 各自如实返回 ok,任一失败即 ok:false(此前恒 true)。
|
|
26485
26435
|
start: async () => {
|
|
26486
26436
|
try {
|
|
26487
26437
|
const rec = await lan.reconcile();
|
|
@@ -26729,7 +26679,7 @@ var require_lifecycle3 = __commonJS({
|
|
|
26729
26679
|
return send(200, { sessionState: sup.sessionState ? sup.sessionState() : "unknown" });
|
|
26730
26680
|
}
|
|
26731
26681
|
if (req.method === "POST" && pathname === "/session/stop") {
|
|
26732
|
-
if (!originAllowed(req
|
|
26682
|
+
if (!originAllowed(req)) {
|
|
26733
26683
|
req.resume();
|
|
26734
26684
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26735
26685
|
}
|
|
@@ -26752,7 +26702,7 @@ var require_lifecycle3 = __commonJS({
|
|
|
26752
26702
|
return lc ? send(200, lc.snapshot()) : send(404, { error: "\u6A21\u5757\u672A\u6CE8\u518C: " + id });
|
|
26753
26703
|
}
|
|
26754
26704
|
if (req.method === "POST" && action) {
|
|
26755
|
-
if (!originAllowed(req
|
|
26705
|
+
if (!originAllowed(req)) {
|
|
26756
26706
|
req.resume();
|
|
26757
26707
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26758
26708
|
}
|
|
@@ -26857,7 +26807,7 @@ var require_native = __commonJS({
|
|
|
26857
26807
|
});
|
|
26858
26808
|
}
|
|
26859
26809
|
if (req.method === "POST" && pathname === "/native/check-update") {
|
|
26860
|
-
if (!originAllowed(req
|
|
26810
|
+
if (!originAllowed(req)) {
|
|
26861
26811
|
req.resume();
|
|
26862
26812
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26863
26813
|
}
|
|
@@ -26865,7 +26815,7 @@ var require_native = __commonJS({
|
|
|
26865
26815
|
return;
|
|
26866
26816
|
}
|
|
26867
26817
|
if (req.method === "POST" && pathname === "/native/install") {
|
|
26868
|
-
if (!originAllowed(req
|
|
26818
|
+
if (!originAllowed(req)) {
|
|
26869
26819
|
req.resume();
|
|
26870
26820
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26871
26821
|
}
|
|
@@ -26883,7 +26833,7 @@ var require_native = __commonJS({
|
|
|
26883
26833
|
return;
|
|
26884
26834
|
}
|
|
26885
26835
|
if (req.method === "POST" && pathname === "/native/upgrade") {
|
|
26886
|
-
if (!originAllowed(req
|
|
26836
|
+
if (!originAllowed(req)) {
|
|
26887
26837
|
req.resume();
|
|
26888
26838
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26889
26839
|
}
|
|
@@ -26904,7 +26854,7 @@ var require_native = __commonJS({
|
|
|
26904
26854
|
return;
|
|
26905
26855
|
}
|
|
26906
26856
|
if (req.method === "POST" && pathname === "/native/uninstall") {
|
|
26907
|
-
if (!originAllowed(req
|
|
26857
|
+
if (!originAllowed(req)) {
|
|
26908
26858
|
req.resume();
|
|
26909
26859
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26910
26860
|
}
|
|
@@ -26913,7 +26863,7 @@ var require_native = __commonJS({
|
|
|
26913
26863
|
return send(202, { ok: true, accepted: true, state: "uninstalling" });
|
|
26914
26864
|
}
|
|
26915
26865
|
if (req.method === "POST" && pathname === "/native/settings") {
|
|
26916
|
-
if (!originAllowed(req
|
|
26866
|
+
if (!originAllowed(req)) {
|
|
26917
26867
|
req.resume();
|
|
26918
26868
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26919
26869
|
}
|
|
@@ -26975,14 +26925,14 @@ var require_guard = __commonJS({
|
|
|
26975
26925
|
}
|
|
26976
26926
|
if (req.method === "POST" && pathname === "/guard/version/check") {
|
|
26977
26927
|
req.resume();
|
|
26978
|
-
if (!originAllowed(req
|
|
26928
|
+
if (!originAllowed(req)) return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26979
26929
|
return sup.guardVersionCheck().then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
26980
26930
|
}
|
|
26981
26931
|
if (req.method === "GET" && pathname === "/autostart") {
|
|
26982
26932
|
return send(200, sup.autostartStatus());
|
|
26983
26933
|
}
|
|
26984
26934
|
if (req.method === "POST" && pathname === "/autostart") {
|
|
26985
|
-
if (!originAllowed(req
|
|
26935
|
+
if (!originAllowed(req)) {
|
|
26986
26936
|
req.resume();
|
|
26987
26937
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26988
26938
|
}
|
|
@@ -27003,7 +26953,7 @@ var require_guard = __commonJS({
|
|
|
27003
26953
|
return send(200, sup.lanPanelStatus());
|
|
27004
26954
|
}
|
|
27005
26955
|
if (req.method === "POST" && pathname === "/settings/lan") {
|
|
27006
|
-
if (!originAllowed(req
|
|
26956
|
+
if (!originAllowed(req)) {
|
|
27007
26957
|
req.resume();
|
|
27008
26958
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27009
26959
|
}
|
|
@@ -27024,7 +26974,7 @@ var require_guard = __commonJS({
|
|
|
27024
26974
|
return send(200, sup.accessKeyStatus());
|
|
27025
26975
|
}
|
|
27026
26976
|
if (req.method === "POST" && pathname === "/settings/access-key") {
|
|
27027
|
-
if (!originAllowed(req
|
|
26977
|
+
if (!originAllowed(req)) {
|
|
27028
26978
|
req.resume();
|
|
27029
26979
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27030
26980
|
}
|
|
@@ -27046,7 +26996,7 @@ var require_guard = __commonJS({
|
|
|
27046
26996
|
return send(200, sup.closeActionStatus());
|
|
27047
26997
|
}
|
|
27048
26998
|
if (req.method === "POST" && pathname === "/settings/close-action") {
|
|
27049
|
-
if (!originAllowed(req
|
|
26999
|
+
if (!originAllowed(req)) {
|
|
27050
27000
|
req.resume();
|
|
27051
27001
|
return send(403, {});
|
|
27052
27002
|
}
|
|
@@ -27067,7 +27017,7 @@ var require_guard = __commonJS({
|
|
|
27067
27017
|
return send(200, sup.externalBrowserStatus());
|
|
27068
27018
|
}
|
|
27069
27019
|
if (req.method === "POST" && pathname === "/settings/external-browser") {
|
|
27070
|
-
if (!originAllowed(req
|
|
27020
|
+
if (!originAllowed(req)) {
|
|
27071
27021
|
req.resume();
|
|
27072
27022
|
return send(403, {});
|
|
27073
27023
|
}
|
|
@@ -27089,7 +27039,7 @@ var require_guard = __commonJS({
|
|
|
27089
27039
|
return;
|
|
27090
27040
|
}
|
|
27091
27041
|
if (req.method === "POST" && pathname === "/shutdown") {
|
|
27092
|
-
if (!originAllowed(req
|
|
27042
|
+
if (!originAllowed(req)) {
|
|
27093
27043
|
req.resume();
|
|
27094
27044
|
return send(403, {});
|
|
27095
27045
|
}
|
|
@@ -27104,7 +27054,7 @@ var require_guard = __commonJS({
|
|
|
27104
27054
|
return;
|
|
27105
27055
|
}
|
|
27106
27056
|
if (req.method === "GET" && pathname === "/self-update/status") {
|
|
27107
|
-
if (!originAllowed(req
|
|
27057
|
+
if (!originAllowed(req)) {
|
|
27108
27058
|
req.resume();
|
|
27109
27059
|
return send(403, {});
|
|
27110
27060
|
}
|
|
@@ -27130,14 +27080,14 @@ var require_guard = __commonJS({
|
|
|
27130
27080
|
});
|
|
27131
27081
|
}
|
|
27132
27082
|
if (req.method === "GET" && pathname === "/env/dsh") {
|
|
27133
|
-
if (!originAllowed(req
|
|
27083
|
+
if (!originAllowed(req)) {
|
|
27134
27084
|
req.resume();
|
|
27135
27085
|
return send(403, {});
|
|
27136
27086
|
}
|
|
27137
27087
|
return send(200, sup.dshenvStatus());
|
|
27138
27088
|
}
|
|
27139
27089
|
if (req.method === "GET" && pathname === "/env/status") {
|
|
27140
|
-
if (!originAllowed(req
|
|
27090
|
+
if (!originAllowed(req)) {
|
|
27141
27091
|
req.resume();
|
|
27142
27092
|
return send(403, {});
|
|
27143
27093
|
}
|
|
@@ -27147,7 +27097,7 @@ var require_guard = __commonJS({
|
|
|
27147
27097
|
return sup.nodeLtsStatus().then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
27148
27098
|
}
|
|
27149
27099
|
if (req.method === "GET" && pathname === "/env/environment") {
|
|
27150
|
-
if (!originAllowed(req
|
|
27100
|
+
if (!originAllowed(req)) {
|
|
27151
27101
|
req.resume();
|
|
27152
27102
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27153
27103
|
}
|
|
@@ -27155,7 +27105,7 @@ var require_guard = __commonJS({
|
|
|
27155
27105
|
return Promise.resolve(force ? environment.refresh({ persist: true, force: true }) : environment.form()).then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: "\u73AF\u5883\u8868\u5355\u88C5\u914D\u5931\u8D25\uFF1A" + (e && e.message || e) }));
|
|
27156
27106
|
}
|
|
27157
27107
|
if (req.method === "GET" && pathname === "/env/environment/last") {
|
|
27158
|
-
if (!originAllowed(req
|
|
27108
|
+
if (!originAllowed(req)) {
|
|
27159
27109
|
req.resume();
|
|
27160
27110
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27161
27111
|
}
|
|
@@ -27166,7 +27116,7 @@ var require_guard = __commonJS({
|
|
|
27166
27116
|
req.resume();
|
|
27167
27117
|
return send(403, { ok: false, error: "\u4EC5\u5185\u6838\u6240\u5728\u673A\u5668\u53EF\u8BF7\u5185\u6838\u8C03\u8D77\u6D4F\u89C8\u5668\uFF0C\u8BF7\u590D\u5236\u6216\u81EA\u884C\u6253\u5F00\u8BE5\u5730\u5740" });
|
|
27168
27118
|
}
|
|
27169
|
-
if (!originAllowed(req
|
|
27119
|
+
if (!originAllowed(req)) {
|
|
27170
27120
|
req.resume();
|
|
27171
27121
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27172
27122
|
}
|
|
@@ -27211,7 +27161,7 @@ var require_router4 = __commonJS({
|
|
|
27211
27161
|
return Promise.resolve(sup.routerStatusView()).then((r) => send(200, r)).catch((e) => send(500, { ok: false, running: false, error: e && e.message || String(e) }));
|
|
27212
27162
|
}
|
|
27213
27163
|
if (req.method === "POST" && pathname.startsWith("/router/")) {
|
|
27214
|
-
if (!originAllowed(req
|
|
27164
|
+
if (!originAllowed(req)) {
|
|
27215
27165
|
req.resume();
|
|
27216
27166
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27217
27167
|
}
|
|
@@ -27228,7 +27178,7 @@ var require_router4 = __commonJS({
|
|
|
27228
27178
|
return Promise.resolve(sup.routerProviders()).then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
27229
27179
|
}
|
|
27230
27180
|
if (req.method === "POST" && pathname === "/router/providers/add") {
|
|
27231
|
-
if (!originAllowed(req
|
|
27181
|
+
if (!originAllowed(req)) {
|
|
27232
27182
|
req.resume();
|
|
27233
27183
|
return send(403, {});
|
|
27234
27184
|
}
|
|
@@ -27247,7 +27197,7 @@ var require_router4 = __commonJS({
|
|
|
27247
27197
|
return;
|
|
27248
27198
|
}
|
|
27249
27199
|
if (req.method === "POST" && pathname === "/router/proxy/login/start") {
|
|
27250
|
-
if (!originAllowed(req
|
|
27200
|
+
if (!originAllowed(req)) {
|
|
27251
27201
|
req.resume();
|
|
27252
27202
|
return send(403, {});
|
|
27253
27203
|
}
|
|
@@ -27255,7 +27205,7 @@ var require_router4 = __commonJS({
|
|
|
27255
27205
|
return;
|
|
27256
27206
|
}
|
|
27257
27207
|
if (req.method === "POST" && pathname === "/router/proxy/login/wait") {
|
|
27258
|
-
if (!originAllowed(req
|
|
27208
|
+
if (!originAllowed(req)) {
|
|
27259
27209
|
req.resume();
|
|
27260
27210
|
return send(403, {});
|
|
27261
27211
|
}
|
|
@@ -27272,7 +27222,7 @@ var require_router4 = __commonJS({
|
|
|
27272
27222
|
return;
|
|
27273
27223
|
}
|
|
27274
27224
|
if (req.method === "POST" && pathname === "/router/proxy/update/check") {
|
|
27275
|
-
if (!originAllowed(req
|
|
27225
|
+
if (!originAllowed(req)) {
|
|
27276
27226
|
req.resume();
|
|
27277
27227
|
return send(403, {});
|
|
27278
27228
|
}
|
|
@@ -27280,7 +27230,7 @@ var require_router4 = __commonJS({
|
|
|
27280
27230
|
return;
|
|
27281
27231
|
}
|
|
27282
27232
|
if (req.method === "POST" && pathname === "/router/proxy/update/apply") {
|
|
27283
|
-
if (!originAllowed(req
|
|
27233
|
+
if (!originAllowed(req)) {
|
|
27284
27234
|
req.resume();
|
|
27285
27235
|
return send(403, {});
|
|
27286
27236
|
}
|
|
@@ -27299,7 +27249,7 @@ var require_router4 = __commonJS({
|
|
|
27299
27249
|
return Promise.resolve(sup.routerApi().proxyUpdateStatus(u.searchParams.get("appId") || "")).then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
27300
27250
|
}
|
|
27301
27251
|
if (req.method === "POST" && pathname === "/router/providers/proxy/key") {
|
|
27302
|
-
if (!originAllowed(req
|
|
27252
|
+
if (!originAllowed(req)) {
|
|
27303
27253
|
req.resume();
|
|
27304
27254
|
return send(403, {});
|
|
27305
27255
|
}
|
|
@@ -27314,7 +27264,7 @@ var require_router4 = __commonJS({
|
|
|
27314
27264
|
return;
|
|
27315
27265
|
}
|
|
27316
27266
|
if (req.method === "POST" && pathname === "/router/providers/proxy/select") {
|
|
27317
|
-
if (!originAllowed(req
|
|
27267
|
+
if (!originAllowed(req)) {
|
|
27318
27268
|
req.resume();
|
|
27319
27269
|
return send(403, {});
|
|
27320
27270
|
}
|
|
@@ -27329,7 +27279,7 @@ var require_router4 = __commonJS({
|
|
|
27329
27279
|
return;
|
|
27330
27280
|
}
|
|
27331
27281
|
if (req.method === "POST" && pathname === "/router/providers/proxy/key/remove") {
|
|
27332
|
-
if (!originAllowed(req
|
|
27282
|
+
if (!originAllowed(req)) {
|
|
27333
27283
|
req.resume();
|
|
27334
27284
|
return send(403, {});
|
|
27335
27285
|
}
|
|
@@ -27344,7 +27294,7 @@ var require_router4 = __commonJS({
|
|
|
27344
27294
|
return;
|
|
27345
27295
|
}
|
|
27346
27296
|
if (req.method === "POST" && pathname === "/router/providers/keys/set") {
|
|
27347
|
-
if (!originAllowed(req
|
|
27297
|
+
if (!originAllowed(req)) {
|
|
27348
27298
|
req.resume();
|
|
27349
27299
|
return send(403, {});
|
|
27350
27300
|
}
|
|
@@ -27360,7 +27310,7 @@ var require_router4 = __commonJS({
|
|
|
27360
27310
|
return;
|
|
27361
27311
|
}
|
|
27362
27312
|
if (req.method === "POST" && pathname === "/router/providers/remove") {
|
|
27363
|
-
if (!originAllowed(req
|
|
27313
|
+
if (!originAllowed(req)) {
|
|
27364
27314
|
req.resume();
|
|
27365
27315
|
return send(403, {});
|
|
27366
27316
|
}
|
|
@@ -27375,7 +27325,7 @@ var require_router4 = __commonJS({
|
|
|
27375
27325
|
return;
|
|
27376
27326
|
}
|
|
27377
27327
|
if (req.method === "POST" && pathname === "/router/providers/key/use") {
|
|
27378
|
-
if (!originAllowed(req
|
|
27328
|
+
if (!originAllowed(req)) {
|
|
27379
27329
|
req.resume();
|
|
27380
27330
|
return send(403, {});
|
|
27381
27331
|
}
|
|
@@ -27391,7 +27341,7 @@ var require_router4 = __commonJS({
|
|
|
27391
27341
|
return;
|
|
27392
27342
|
}
|
|
27393
27343
|
if (req.method === "POST" && pathname === "/router/providers/account/discard") {
|
|
27394
|
-
if (!originAllowed(req
|
|
27344
|
+
if (!originAllowed(req)) {
|
|
27395
27345
|
req.resume();
|
|
27396
27346
|
return send(403, {});
|
|
27397
27347
|
}
|
|
@@ -27406,7 +27356,7 @@ var require_router4 = __commonJS({
|
|
|
27406
27356
|
return;
|
|
27407
27357
|
}
|
|
27408
27358
|
if (req.method === "POST" && pathname === "/router/providers/refresh") {
|
|
27409
|
-
if (!originAllowed(req
|
|
27359
|
+
if (!originAllowed(req)) {
|
|
27410
27360
|
req.resume();
|
|
27411
27361
|
return send(403, {});
|
|
27412
27362
|
}
|
|
@@ -27422,7 +27372,7 @@ var require_router4 = __commonJS({
|
|
|
27422
27372
|
return;
|
|
27423
27373
|
}
|
|
27424
27374
|
if (req.method === "POST" && pathname === "/router/providers/activate") {
|
|
27425
|
-
if (!originAllowed(req
|
|
27375
|
+
if (!originAllowed(req)) {
|
|
27426
27376
|
req.resume();
|
|
27427
27377
|
return send(403, {});
|
|
27428
27378
|
}
|
|
@@ -27438,7 +27388,7 @@ var require_router4 = __commonJS({
|
|
|
27438
27388
|
return;
|
|
27439
27389
|
}
|
|
27440
27390
|
if (req.method === "POST" && pathname === "/router/providers/deactivate") {
|
|
27441
|
-
if (!originAllowed(req
|
|
27391
|
+
if (!originAllowed(req)) {
|
|
27442
27392
|
req.resume();
|
|
27443
27393
|
return send(403, {});
|
|
27444
27394
|
}
|
|
@@ -27488,7 +27438,7 @@ var require_plugins = __commonJS({
|
|
|
27488
27438
|
return send(200, sup.pluginManager.installStatus(u.searchParams.get("job")));
|
|
27489
27439
|
}
|
|
27490
27440
|
if (req.method === "POST" && pathname.startsWith("/plugins/")) {
|
|
27491
|
-
if (!originAllowed(req
|
|
27441
|
+
if (!originAllowed(req)) {
|
|
27492
27442
|
req.resume();
|
|
27493
27443
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27494
27444
|
}
|
|
@@ -27564,7 +27514,7 @@ var require_dist = __commonJS({
|
|
|
27564
27514
|
return;
|
|
27565
27515
|
}
|
|
27566
27516
|
if (req.method === "POST" && pathname === "/dist/registry/set") {
|
|
27567
|
-
if (!originAllowed(req
|
|
27517
|
+
if (!originAllowed(req)) {
|
|
27568
27518
|
req.resume();
|
|
27569
27519
|
return send(403, {});
|
|
27570
27520
|
}
|
|
@@ -27583,7 +27533,7 @@ var require_dist = __commonJS({
|
|
|
27583
27533
|
return;
|
|
27584
27534
|
}
|
|
27585
27535
|
if (req.method === "POST" && pathname === "/dist/registry/refresh") {
|
|
27586
|
-
if (!originAllowed(req
|
|
27536
|
+
if (!originAllowed(req)) {
|
|
27587
27537
|
req.resume();
|
|
27588
27538
|
return send(403, {});
|
|
27589
27539
|
}
|
|
@@ -27591,7 +27541,7 @@ var require_dist = __commonJS({
|
|
|
27591
27541
|
return;
|
|
27592
27542
|
}
|
|
27593
27543
|
if (req.method === "POST" && pathname === "/dist/registry/probe") {
|
|
27594
|
-
if (!originAllowed(req
|
|
27544
|
+
if (!originAllowed(req)) {
|
|
27595
27545
|
req.resume();
|
|
27596
27546
|
return send(403, {});
|
|
27597
27547
|
}
|
|
@@ -27662,6 +27612,112 @@ var require_exchange = __commonJS({
|
|
|
27662
27612
|
}
|
|
27663
27613
|
});
|
|
27664
27614
|
|
|
27615
|
+
// src/platform/security/identity.js
|
|
27616
|
+
var require_identity2 = __commonJS({
|
|
27617
|
+
"src/platform/security/identity.js"(exports2, module2) {
|
|
27618
|
+
"use strict";
|
|
27619
|
+
var { normalizeRemoteAddress, isLoopbackAddress } = require_ip();
|
|
27620
|
+
function socketIsLoopback(req) {
|
|
27621
|
+
return isLoopbackAddress(req && req.socket && req.socket.remoteAddress);
|
|
27622
|
+
}
|
|
27623
|
+
function identify(req) {
|
|
27624
|
+
return {
|
|
27625
|
+
remote: normalizeRemoteAddress(req && req.socket && req.socket.remoteAddress),
|
|
27626
|
+
loopback: socketIsLoopback(req)
|
|
27627
|
+
};
|
|
27628
|
+
}
|
|
27629
|
+
module2.exports = { identify };
|
|
27630
|
+
}
|
|
27631
|
+
});
|
|
27632
|
+
|
|
27633
|
+
// src/api/identity.js
|
|
27634
|
+
var require_identity3 = __commonJS({
|
|
27635
|
+
"src/api/identity.js"(exports2, module2) {
|
|
27636
|
+
"use strict";
|
|
27637
|
+
var { normalizeRemoteAddress, isLoopbackAddress, isPrivateIpv4 } = require_ip();
|
|
27638
|
+
var { identify } = require_identity2();
|
|
27639
|
+
module2.exports = {
|
|
27640
|
+
identify,
|
|
27641
|
+
normalizeRemoteAddress,
|
|
27642
|
+
isPrivateIpv4,
|
|
27643
|
+
isLoopbackAddress
|
|
27644
|
+
};
|
|
27645
|
+
}
|
|
27646
|
+
});
|
|
27647
|
+
|
|
27648
|
+
// src/api/security.js
|
|
27649
|
+
var require_security = __commonJS({
|
|
27650
|
+
"src/api/security.js"(exports2, module2) {
|
|
27651
|
+
"use strict";
|
|
27652
|
+
var crypto = require("node:crypto");
|
|
27653
|
+
var { isPrivateIpv4 } = require_identity3();
|
|
27654
|
+
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
|
|
27655
|
+
function isLocalOrLanHost(h) {
|
|
27656
|
+
if (!h) return false;
|
|
27657
|
+
const s = String(h).toLowerCase();
|
|
27658
|
+
if (LOOPBACK_HOSTS.has(s)) return true;
|
|
27659
|
+
const bare = s.startsWith("[") && s.endsWith("]") ? s.slice(1, -1) : s;
|
|
27660
|
+
if (bare === "::1") return true;
|
|
27661
|
+
return isPrivateIpv4(bare);
|
|
27662
|
+
}
|
|
27663
|
+
function isShellOrigin(protocol, hostname) {
|
|
27664
|
+
const h = String(hostname || "").toLowerCase();
|
|
27665
|
+
if (protocol === "tauri:") return h === "localhost" || /(^|\.)tauri\.localhost$/.test(h);
|
|
27666
|
+
if (protocol === "http:" || protocol === "https:") return h === "tauri.localhost";
|
|
27667
|
+
return false;
|
|
27668
|
+
}
|
|
27669
|
+
function normalizeHostname(h) {
|
|
27670
|
+
const s = String(h || "").toLowerCase();
|
|
27671
|
+
return s.startsWith("[") && s.endsWith("]") ? s.slice(1, -1) : s;
|
|
27672
|
+
}
|
|
27673
|
+
function originAllowed(req, apiPort) {
|
|
27674
|
+
const host = req.headers.host;
|
|
27675
|
+
if (!host) return false;
|
|
27676
|
+
let hostname = "";
|
|
27677
|
+
{
|
|
27678
|
+
const m = /^(\[[^\]]+\]|[^:]+)(?::\d+)?$/.exec(String(host).trim());
|
|
27679
|
+
hostname = m ? m[1] : String(host).trim();
|
|
27680
|
+
if (!isLocalOrLanHost(hostname)) return false;
|
|
27681
|
+
}
|
|
27682
|
+
const o = req.headers.origin;
|
|
27683
|
+
if (!o) return true;
|
|
27684
|
+
try {
|
|
27685
|
+
const u = new URL(o);
|
|
27686
|
+
if (isShellOrigin(u.protocol, u.hostname)) return true;
|
|
27687
|
+
if (!isLocalOrLanHost(u.hostname)) return false;
|
|
27688
|
+
if (host && normalizeHostname(u.hostname) !== normalizeHostname(hostname)) return false;
|
|
27689
|
+
const port = u.port === "" ? u.protocol === "https:" ? "443" : "80" : u.port;
|
|
27690
|
+
return port === String(apiPort);
|
|
27691
|
+
} catch {
|
|
27692
|
+
return false;
|
|
27693
|
+
}
|
|
27694
|
+
}
|
|
27695
|
+
function safeKeyEqual(a, b) {
|
|
27696
|
+
const ha = crypto.createHash("sha256").update(String(a || "")).digest();
|
|
27697
|
+
const hb = crypto.createHash("sha256").update(String(b || "")).digest();
|
|
27698
|
+
return crypto.timingSafeEqual(ha, hb);
|
|
27699
|
+
}
|
|
27700
|
+
function requestHasAccessKey(req, key) {
|
|
27701
|
+
if (!key) return true;
|
|
27702
|
+
const ah = req.headers.authorization;
|
|
27703
|
+
if (typeof ah === "string" && ah.startsWith("Bearer ") && safeKeyEqual(ah.slice(7), key)) return true;
|
|
27704
|
+
try {
|
|
27705
|
+
const q = new URL(req.url, "http://localhost").searchParams.get("access_key");
|
|
27706
|
+
if (q && safeKeyEqual(q, key)) return true;
|
|
27707
|
+
} catch {
|
|
27708
|
+
}
|
|
27709
|
+
return false;
|
|
27710
|
+
}
|
|
27711
|
+
function liveApiPort(server, sup) {
|
|
27712
|
+
const live = server && typeof server.address === "function" ? server.address() : null;
|
|
27713
|
+
if (live && Number.isInteger(live.port) && live.port > 0) return live.port;
|
|
27714
|
+
const cfg = sup && sup.config && sup.config.apiPort;
|
|
27715
|
+
return Number.isInteger(cfg) ? cfg : null;
|
|
27716
|
+
}
|
|
27717
|
+
module2.exports = { originAllowed, isLocalOrLanHost, isShellOrigin, requestHasAccessKey, liveApiPort };
|
|
27718
|
+
}
|
|
27719
|
+
});
|
|
27720
|
+
|
|
27665
27721
|
// src/api/domains/instances.js
|
|
27666
27722
|
var require_instances = __commonJS({
|
|
27667
27723
|
"src/api/domains/instances.js"(exports2, module2) {
|
|
@@ -27669,6 +27725,7 @@ var require_instances = __commonJS({
|
|
|
27669
27725
|
var execPath = require_exec_path();
|
|
27670
27726
|
var crypto = require("node:crypto");
|
|
27671
27727
|
var { bootstrapDshCookie } = require_exchange();
|
|
27728
|
+
var { liveApiPort } = require_security();
|
|
27672
27729
|
var OPEN_WEB_CODES = /* @__PURE__ */ new Map();
|
|
27673
27730
|
var OPEN_WEB_CODE_TTL_MS = 3e4;
|
|
27674
27731
|
function _sweepExpiredOpenWebCodes() {
|
|
@@ -27702,16 +27759,16 @@ var require_instances = __commonJS({
|
|
|
27702
27759
|
return (sup.instances.list() || []).find((x) => x.id === id) || null;
|
|
27703
27760
|
}
|
|
27704
27761
|
function handleOpen(ctx) {
|
|
27705
|
-
const { sup, req, res, identity, originAllowed, tokOf } = ctx;
|
|
27762
|
+
const { sup, req, res, identity, originAllowed, tokOf, server } = ctx;
|
|
27706
27763
|
const url = new URL(req.url, "http://localhost");
|
|
27707
|
-
const apiPort = sup
|
|
27764
|
+
const apiPort = liveApiPort(server, sup);
|
|
27708
27765
|
const code = url.searchParams.get("code");
|
|
27709
27766
|
const deny = (status, msg) => {
|
|
27710
27767
|
res.writeHead(status, { "Content-Type": "text/plain; charset=utf-8" });
|
|
27711
27768
|
res.end(msg);
|
|
27712
27769
|
};
|
|
27713
27770
|
if (!identity.loopback) return deny(403, "\u4EC5\u5141\u8BB8\u672C\u673A\u8BBF\u95EE");
|
|
27714
|
-
if (!originAllowed(req
|
|
27771
|
+
if (!originAllowed(req)) return deny(403, "origin not allowed");
|
|
27715
27772
|
const rec = consumeOpenWebCode(code);
|
|
27716
27773
|
if (!rec) return deny(code ? 400 : 404, code ? "\u6388\u6743\u7801\u65E0\u6548\u6216\u5DF2\u8FC7\u671F" : "\u7F3A\u5C11\u6388\u6743\u7801");
|
|
27717
27774
|
const it = findInstanceOrMain(sup, rec.id);
|
|
@@ -27777,7 +27834,7 @@ var require_instances = __commonJS({
|
|
|
27777
27834
|
return sharedErr + "\uFF1B" + FORMS + "\uFF1B\u9700\u8981\u5176\u5B83\u53EF\u6267\u884C\u8BF7\u8D70\u63D2\u4EF6\u5B89\u88C5\u901A\u9053";
|
|
27778
27835
|
}
|
|
27779
27836
|
function handle(ctx) {
|
|
27780
|
-
const { sup, req, res, pathname, identity, send, collectBody, originAllowed, tokOf, browser } = ctx;
|
|
27837
|
+
const { sup, req, res, pathname, identity, send, collectBody, originAllowed, tokOf, browser, server } = ctx;
|
|
27781
27838
|
function openInSystemBrowser(url) {
|
|
27782
27839
|
return browser.openBrowser(url, { logger: sup.logger });
|
|
27783
27840
|
}
|
|
@@ -27804,7 +27861,7 @@ var require_instances = __commonJS({
|
|
|
27804
27861
|
return render();
|
|
27805
27862
|
}
|
|
27806
27863
|
if (req.method === "POST" && pathname.startsWith("/instances/")) {
|
|
27807
|
-
if (!originAllowed(req
|
|
27864
|
+
if (!originAllowed(req)) {
|
|
27808
27865
|
req.resume();
|
|
27809
27866
|
return send(403, {});
|
|
27810
27867
|
}
|
|
@@ -27841,7 +27898,7 @@ var require_instances = __commonJS({
|
|
|
27841
27898
|
if (!it) return send(404, { ok: false, error: "\u5B9E\u4F8B\u4E0D\u5B58\u5728" });
|
|
27842
27899
|
if (!(Number(it.port) > 0)) return send(400, { ok: false, error: "\u975E\u6CD5\u7AEF\u53E3" });
|
|
27843
27900
|
const code = issueOpenWebCode(j.id);
|
|
27844
|
-
const url = "http://127.0.0.1:" + sup.config.apiPort + "/open?code=" + code;
|
|
27901
|
+
const url = "http://127.0.0.1:" + (liveApiPort(server, sup) || sup.config.apiPort) + "/open?code=" + code;
|
|
27845
27902
|
return Promise.resolve(openInSystemBrowser(url)).then((r) => {
|
|
27846
27903
|
if (!r.ok) dropOpenWebCode(code);
|
|
27847
27904
|
return send(r.ok ? 200 : 500, r);
|
|
@@ -27886,7 +27943,7 @@ var require_relay = __commonJS({
|
|
|
27886
27943
|
return Promise.resolve(sup.listLan()).then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
27887
27944
|
}
|
|
27888
27945
|
if (req.method === "POST" && pathname.startsWith("/remote/")) {
|
|
27889
|
-
if (!originAllowed(req
|
|
27946
|
+
if (!originAllowed(req)) {
|
|
27890
27947
|
req.resume();
|
|
27891
27948
|
return send(403, {});
|
|
27892
27949
|
}
|
|
@@ -27949,7 +28006,7 @@ var require_shell2 = __commonJS({
|
|
|
27949
28006
|
}
|
|
27950
28007
|
}
|
|
27951
28008
|
if (req.method === "POST" && pathname === "/shell/health") {
|
|
27952
|
-
if (!originAllowed(req
|
|
28009
|
+
if (!originAllowed(req)) {
|
|
27953
28010
|
req.resume();
|
|
27954
28011
|
return send(403, {});
|
|
27955
28012
|
}
|
|
@@ -27966,28 +28023,8 @@ var require_shell2 = __commonJS({
|
|
|
27966
28023
|
}
|
|
27967
28024
|
});
|
|
27968
28025
|
}
|
|
27969
|
-
if (req.method === "POST" && pathname === "/shell/update-pending") {
|
|
27970
|
-
if (!originAllowed(req, sup.config.apiPort)) {
|
|
27971
|
-
req.resume();
|
|
27972
|
-
return send(403, {});
|
|
27973
|
-
}
|
|
27974
|
-
return collectBody(req, res, 8192, (body) => {
|
|
27975
|
-
let j = {};
|
|
27976
|
-
try {
|
|
27977
|
-
j = body ? JSON.parse(body) : {};
|
|
27978
|
-
} catch {
|
|
27979
|
-
}
|
|
27980
|
-
try {
|
|
27981
|
-
const rec = shell.markPending(j.from || null, j.to || null);
|
|
27982
|
-
if (sup.events) sup.events.append(BRAND2.EVENT_SHELL_UPDATE_PENDING, { from: rec.from, to: rec.to });
|
|
27983
|
-
return send(200, { ok: true, journal: rec });
|
|
27984
|
-
} catch (e) {
|
|
27985
|
-
return send(500, { ok: false, error: e.message });
|
|
27986
|
-
}
|
|
27987
|
-
});
|
|
27988
|
-
}
|
|
27989
28026
|
if (req.method === "POST" && pathname === "/shell/check-update") {
|
|
27990
|
-
if (!originAllowed(req
|
|
28027
|
+
if (!originAllowed(req)) {
|
|
27991
28028
|
req.resume();
|
|
27992
28029
|
return send(403, {});
|
|
27993
28030
|
}
|
|
@@ -27999,23 +28036,6 @@ var require_shell2 = __commonJS({
|
|
|
27999
28036
|
return send(200, r);
|
|
28000
28037
|
}).catch((e) => send(500, { ok: false, error: e.message }));
|
|
28001
28038
|
}
|
|
28002
|
-
if (req.method === "POST" && pathname === "/shell/restart") {
|
|
28003
|
-
if (!originAllowed(req, sup.config.apiPort)) {
|
|
28004
|
-
req.resume();
|
|
28005
|
-
return send(403, {});
|
|
28006
|
-
}
|
|
28007
|
-
if (typeof sup._sessionHalting === "function" && sup._sessionHalting()) {
|
|
28008
|
-
req.resume();
|
|
28009
|
-
return send(409, { ok: false, error: "\u4F1A\u8BDD\u5DF2\u9000\u51FA/\u9000\u51FA\u4E2D\uFF0C\u62D2\u7EDD\u91CD\u542F\u684C\u9762\u58F3" });
|
|
28010
|
-
}
|
|
28011
|
-
req.resume();
|
|
28012
|
-
return Promise.resolve(shell.restartShell({
|
|
28013
|
-
shouldAbort: () => typeof sup._sessionHalting === "function" && sup._sessionHalting()
|
|
28014
|
-
})).then((r) => {
|
|
28015
|
-
if (sup.events) sup.events.append(BRAND2.EVENT_SHELL_RESTART_REQUESTED, { ok: r.ok, killed: r.killed || [], pid: r.pid || null });
|
|
28016
|
-
return send(r.ok ? 200 : 500, r);
|
|
28017
|
-
}).catch((e) => send(500, { ok: false, error: e.message }));
|
|
28018
|
-
}
|
|
28019
28039
|
if (req.method === "GET" || req.method === "POST") return send(404, { error: "not found", path: pathname });
|
|
28020
28040
|
return send(405, { error: "method not allowed" });
|
|
28021
28041
|
}
|
|
@@ -28179,106 +28199,6 @@ var require_static = __commonJS({
|
|
|
28179
28199
|
}
|
|
28180
28200
|
});
|
|
28181
28201
|
|
|
28182
|
-
// src/platform/security/identity.js
|
|
28183
|
-
var require_identity2 = __commonJS({
|
|
28184
|
-
"src/platform/security/identity.js"(exports2, module2) {
|
|
28185
|
-
"use strict";
|
|
28186
|
-
var { normalizeRemoteAddress, isLoopbackAddress } = require_ip();
|
|
28187
|
-
function socketIsLoopback(req) {
|
|
28188
|
-
return isLoopbackAddress(req && req.socket && req.socket.remoteAddress);
|
|
28189
|
-
}
|
|
28190
|
-
function identify(req) {
|
|
28191
|
-
return {
|
|
28192
|
-
remote: normalizeRemoteAddress(req && req.socket && req.socket.remoteAddress),
|
|
28193
|
-
loopback: socketIsLoopback(req)
|
|
28194
|
-
};
|
|
28195
|
-
}
|
|
28196
|
-
module2.exports = { identify };
|
|
28197
|
-
}
|
|
28198
|
-
});
|
|
28199
|
-
|
|
28200
|
-
// src/api/identity.js
|
|
28201
|
-
var require_identity3 = __commonJS({
|
|
28202
|
-
"src/api/identity.js"(exports2, module2) {
|
|
28203
|
-
"use strict";
|
|
28204
|
-
var { normalizeRemoteAddress, isLoopbackAddress, isPrivateIpv4 } = require_ip();
|
|
28205
|
-
var { identify } = require_identity2();
|
|
28206
|
-
module2.exports = {
|
|
28207
|
-
identify,
|
|
28208
|
-
normalizeRemoteAddress,
|
|
28209
|
-
isPrivateIpv4,
|
|
28210
|
-
isLoopbackAddress
|
|
28211
|
-
};
|
|
28212
|
-
}
|
|
28213
|
-
});
|
|
28214
|
-
|
|
28215
|
-
// src/api/security.js
|
|
28216
|
-
var require_security = __commonJS({
|
|
28217
|
-
"src/api/security.js"(exports2, module2) {
|
|
28218
|
-
"use strict";
|
|
28219
|
-
var crypto = require("node:crypto");
|
|
28220
|
-
var { isPrivateIpv4 } = require_identity3();
|
|
28221
|
-
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
|
|
28222
|
-
function isLocalOrLanHost(h) {
|
|
28223
|
-
if (!h) return false;
|
|
28224
|
-
const s = String(h).toLowerCase();
|
|
28225
|
-
if (LOOPBACK_HOSTS.has(s)) return true;
|
|
28226
|
-
const bare = s.startsWith("[") && s.endsWith("]") ? s.slice(1, -1) : s;
|
|
28227
|
-
if (bare === "::1") return true;
|
|
28228
|
-
return isPrivateIpv4(bare);
|
|
28229
|
-
}
|
|
28230
|
-
function isShellOrigin(protocol, hostname) {
|
|
28231
|
-
const h = String(hostname || "").toLowerCase();
|
|
28232
|
-
if (protocol === "tauri:") return h === "localhost" || /(^|\.)tauri\.localhost$/.test(h);
|
|
28233
|
-
if (protocol === "http:" || protocol === "https:") return h === "tauri.localhost";
|
|
28234
|
-
return false;
|
|
28235
|
-
}
|
|
28236
|
-
function normalizeHostname(h) {
|
|
28237
|
-
const s = String(h || "").toLowerCase();
|
|
28238
|
-
return s.startsWith("[") && s.endsWith("]") ? s.slice(1, -1) : s;
|
|
28239
|
-
}
|
|
28240
|
-
function originAllowed(req, apiPort) {
|
|
28241
|
-
const host = req.headers.host;
|
|
28242
|
-
if (!host) return false;
|
|
28243
|
-
let hostname = "";
|
|
28244
|
-
{
|
|
28245
|
-
const m = /^(\[[^\]]+\]|[^:]+)(?::\d+)?$/.exec(String(host).trim());
|
|
28246
|
-
hostname = m ? m[1] : String(host).trim();
|
|
28247
|
-
if (!isLocalOrLanHost(hostname)) return false;
|
|
28248
|
-
}
|
|
28249
|
-
const o = req.headers.origin;
|
|
28250
|
-
if (!o) return true;
|
|
28251
|
-
try {
|
|
28252
|
-
const u = new URL(o);
|
|
28253
|
-
if (isShellOrigin(u.protocol, u.hostname)) return true;
|
|
28254
|
-
if (!isLocalOrLanHost(u.hostname)) return false;
|
|
28255
|
-
if (host && normalizeHostname(u.hostname) !== normalizeHostname(hostname)) return false;
|
|
28256
|
-
const port = u.port === "" ? u.protocol === "https:" ? "443" : "80" : u.port;
|
|
28257
|
-
return port === String(apiPort);
|
|
28258
|
-
} catch {
|
|
28259
|
-
return false;
|
|
28260
|
-
}
|
|
28261
|
-
}
|
|
28262
|
-
function safeKeyEqual(a, b) {
|
|
28263
|
-
const ha = crypto.createHash("sha256").update(String(a || "")).digest();
|
|
28264
|
-
const hb = crypto.createHash("sha256").update(String(b || "")).digest();
|
|
28265
|
-
return crypto.timingSafeEqual(ha, hb);
|
|
28266
|
-
}
|
|
28267
|
-
function requestHasAccessKey(req, key) {
|
|
28268
|
-
if (!key) return true;
|
|
28269
|
-
const ah = req.headers.authorization;
|
|
28270
|
-
if (typeof ah === "string" && ah.startsWith("Bearer ") && safeKeyEqual(ah.slice(7), key)) return true;
|
|
28271
|
-
try {
|
|
28272
|
-
const q = new URL(req.url, "http://localhost").searchParams.get("access_key");
|
|
28273
|
-
if (q && safeKeyEqual(q, key)) return true;
|
|
28274
|
-
} catch {
|
|
28275
|
-
}
|
|
28276
|
-
return false;
|
|
28277
|
-
}
|
|
28278
|
-
module2.exports = { originAllowed, isLocalOrLanHost, isShellOrigin, requestHasAccessKey };
|
|
28279
|
-
}
|
|
28280
|
-
});
|
|
28281
|
-
|
|
28282
28202
|
// src/api/transport/server.js
|
|
28283
28203
|
var require_server = __commonJS({
|
|
28284
28204
|
"src/api/transport/server.js"(exports2, module2) {
|
|
@@ -28288,7 +28208,7 @@ var require_server = __commonJS({
|
|
|
28288
28208
|
var { collectBody } = require_body();
|
|
28289
28209
|
var { serveStatic } = require_static();
|
|
28290
28210
|
var { identify } = require_identity3();
|
|
28291
|
-
var { originAllowed, requestHasAccessKey, isShellOrigin } = require_security();
|
|
28211
|
+
var { originAllowed, requestHasAccessKey, isShellOrigin, liveApiPort } = require_security();
|
|
28292
28212
|
var browserExit = require_browser();
|
|
28293
28213
|
var environmentExit = require_environment();
|
|
28294
28214
|
function safeFail(res, err, where) {
|
|
@@ -28311,7 +28231,7 @@ var require_server = __commonJS({
|
|
|
28311
28231
|
function createServer(sup, deps) {
|
|
28312
28232
|
const browser = deps && deps.browser || browserExit;
|
|
28313
28233
|
const environment = deps && deps.environment || environmentExit;
|
|
28314
|
-
|
|
28234
|
+
const server = http2.createServer((req, res) => {
|
|
28315
28235
|
const shellOrigin = (() => {
|
|
28316
28236
|
const o = req.headers.origin;
|
|
28317
28237
|
if (!o) return null;
|
|
@@ -28341,6 +28261,7 @@ var require_server = __commonJS({
|
|
|
28341
28261
|
return "";
|
|
28342
28262
|
};
|
|
28343
28263
|
const identity = identify(req);
|
|
28264
|
+
const originAllowedLive = (req2) => originAllowed(req2, liveApiPort(server, sup));
|
|
28344
28265
|
const accessKey = sup && sup.config && sup.config.apiAccessKey || null;
|
|
28345
28266
|
if (!identity.loopback && req.method !== "OPTIONS" && (!accessKey || !requestHasAccessKey(req, accessKey))) {
|
|
28346
28267
|
res.writeHead(401, { "Content-Type": "application/json" });
|
|
@@ -28378,7 +28299,7 @@ var require_server = __commonJS({
|
|
|
28378
28299
|
} catch (e) {
|
|
28379
28300
|
return send(400, { error: "bad request encoding" });
|
|
28380
28301
|
}
|
|
28381
|
-
const ctx = { sup, req, res, pathname: decodedPathname, identity, send, collectBody, originAllowed, tokOf, browser, environment };
|
|
28302
|
+
const ctx = { sup, req, res, pathname: decodedPathname, identity, send, collectBody, originAllowed: originAllowedLive, tokOf, browser, environment, server };
|
|
28382
28303
|
for (const d of API_DOMAINS) {
|
|
28383
28304
|
if (d.owns(pathname)) {
|
|
28384
28305
|
try {
|
|
@@ -28404,6 +28325,7 @@ var require_server = __commonJS({
|
|
|
28404
28325
|
}
|
|
28405
28326
|
return send(405, { error: "method not allowed" });
|
|
28406
28327
|
});
|
|
28328
|
+
return server;
|
|
28407
28329
|
}
|
|
28408
28330
|
module2.exports = { createServer };
|
|
28409
28331
|
}
|
|
@@ -28423,7 +28345,7 @@ var require_api = __commonJS({
|
|
|
28423
28345
|
var require_session = __commonJS({
|
|
28424
28346
|
"src/domains/relay/session.js"(exports2, module2) {
|
|
28425
28347
|
"use strict";
|
|
28426
|
-
var { cookieByName } =
|
|
28348
|
+
var { cookieByName } = require_core3();
|
|
28427
28349
|
var { bootstrapDshCookie } = require_exchange();
|
|
28428
28350
|
function createSession(opts) {
|
|
28429
28351
|
const o = opts || {};
|
|
@@ -28565,7 +28487,7 @@ var require_tunnel = __commonJS({
|
|
|
28565
28487
|
"src/domains/relay/tunnel.js"(exports2, module2) {
|
|
28566
28488
|
"use strict";
|
|
28567
28489
|
var net = require("node:net");
|
|
28568
|
-
var { isTrustedSource, hasValidToken, upstreamPath } =
|
|
28490
|
+
var { isTrustedSource, hasValidToken, upstreamPath } = require_core3();
|
|
28569
28491
|
function buildRawRequest(req, authority, cookie) {
|
|
28570
28492
|
let raw = req.method + " " + upstreamPath(req.url) + " HTTP/1.1\r\n";
|
|
28571
28493
|
for (const [k, v] of Object.entries(req.headers)) {
|
|
@@ -28651,7 +28573,7 @@ var require_proxy2 = __commonJS({
|
|
|
28651
28573
|
"use strict";
|
|
28652
28574
|
var http2 = require("node:http");
|
|
28653
28575
|
var crypto = require("node:crypto");
|
|
28654
|
-
var { isTrustedSource, tokenGateDecision, backoffGate, upstreamPath, redactLogPath, normalizeRemoteMode, POLYFILL_SCRIPT } =
|
|
28576
|
+
var { isTrustedSource, tokenGateDecision, backoffGate, upstreamPath, redactLogPath, normalizeRemoteMode, POLYFILL_SCRIPT } = require_core3();
|
|
28655
28577
|
var { createSession } = require_session();
|
|
28656
28578
|
var { createTunnelHandler } = require_tunnel();
|
|
28657
28579
|
var HTML_INJECT_MAX_BYTES = 2 * 1024 * 1024;
|
|
@@ -28676,7 +28598,7 @@ var require_proxy2 = __commonJS({
|
|
|
28676
28598
|
}
|
|
28677
28599
|
};
|
|
28678
28600
|
}
|
|
28679
|
-
function pipeWithHold(ur, res,
|
|
28601
|
+
function pipeWithHold(ur, res, clientReqLog, logger) {
|
|
28680
28602
|
let clientGone = false;
|
|
28681
28603
|
const log = (lv, msg) => {
|
|
28682
28604
|
if (logger && logger[lv]) {
|
|
@@ -28725,7 +28647,7 @@ var require_proxy2 = __commonJS({
|
|
|
28725
28647
|
return headers;
|
|
28726
28648
|
}
|
|
28727
28649
|
function handleUpstream(ur, res, clientReqPath, onStatus, logger) {
|
|
28728
|
-
const
|
|
28650
|
+
const clientReqLog = redactLogPath(clientReqPath);
|
|
28729
28651
|
if (onStatus) onStatus(ur.statusCode);
|
|
28730
28652
|
const h = { ...ur.headers };
|
|
28731
28653
|
const isHtml = String(h["content-type"] || "").includes("text/html");
|
|
@@ -28737,7 +28659,7 @@ var require_proxy2 = __commonJS({
|
|
|
28737
28659
|
}
|
|
28738
28660
|
res.writeHead(ur.statusCode || 502, h);
|
|
28739
28661
|
if (!isHtml) {
|
|
28740
|
-
pipeWithHold(ur, res,
|
|
28662
|
+
pipeWithHold(ur, res, clientReqLog, logger);
|
|
28741
28663
|
return;
|
|
28742
28664
|
}
|
|
28743
28665
|
const chunks = [];
|
|
@@ -28771,7 +28693,7 @@ var require_proxy2 = __commonJS({
|
|
|
28771
28693
|
chunks.push(c);
|
|
28772
28694
|
return;
|
|
28773
28695
|
}
|
|
28774
|
-
log("HTML \u8D85\u4E0A\u9650 " + HTML_INJECT_MAX_BYTES + "B\uFF08\u5DF2\u6536 " + total + "B\uFF09\uFF0C\u653E\u5F03 polyfill \u6CE8\u5165\u6309\u6D41\u900F\u4F20 " + (
|
|
28696
|
+
log("HTML \u8D85\u4E0A\u9650 " + HTML_INJECT_MAX_BYTES + "B\uFF08\u5DF2\u6536 " + total + "B\uFF09\uFF0C\u653E\u5F03 polyfill \u6CE8\u5165\u6309\u6D41\u900F\u4F20 " + (clientReqLog || ""));
|
|
28775
28697
|
const selfForward = !ur.readableEnded;
|
|
28776
28698
|
switchToPassThrough();
|
|
28777
28699
|
if (selfForward) res.write(c);
|
|
@@ -28951,14 +28873,8 @@ var require_ports3 = __commonJS({
|
|
|
28951
28873
|
return registry.claimSlot(segment, owner, {
|
|
28952
28874
|
preferred: o.preferred,
|
|
28953
28875
|
bindingPreferred: !!o.bindingPreferred,
|
|
28954
|
-
// RL-4:跨账本防撞。router caller 不传 reservedPorts(分配器跳过该检查,行为不变);
|
|
28955
|
-
// 仅 relay 传入 router 账本已占端口,free-scan/preferred-claim 跳过 ⇒ 不会抢 router 的端口。
|
|
28956
28876
|
reservedPorts: reservedPorts || void 0,
|
|
28957
28877
|
onBindingLost: o.onBindingLost,
|
|
28958
|
-
// 审计 RL-3:reclaimCmdMark 必须出现在 relay daemon 的真实命令行里,否则 pgrepList 永远匹配不到 ⇒ 回收是死代码。
|
|
28959
|
-
// relay daemon 经 runtime.js 以 `node .../domains/relay/daemon.js -c <cfg>` 拉起(scripts.js:8),
|
|
28960
|
-
// 命令行含 `domains/relay/daemon.js`(与 process.js#reclaimOrphans 用的 _cmdMarks 同源),故此处用同一标记。
|
|
28961
|
-
// configPath 为空时 fail-closed 不回收:宁可留占用走冲突分支,也不按 cmdMark 误杀同名进程(reclaimByCmdMark 内部也已要求 cfgStr 必填)。
|
|
28962
28878
|
reclaimCmdMark: "domains/relay/daemon.js",
|
|
28963
28879
|
reclaimCfg: o.configPath || "",
|
|
28964
28880
|
waitMs: 8e3
|
|
@@ -29157,7 +29073,7 @@ var require_frp = __commonJS({
|
|
|
29157
29073
|
var path2 = require("node:path");
|
|
29158
29074
|
var spawnOS = require_spawn();
|
|
29159
29075
|
var { writeAtomic } = require_fs();
|
|
29160
|
-
var { buildFrpcToml, validateFrpServerSettings } =
|
|
29076
|
+
var { buildFrpcToml, validateFrpServerSettings } = require_core3();
|
|
29161
29077
|
var { frpPlatformTag, download, installFrpc } = require_frp_install();
|
|
29162
29078
|
var FrpManager = class {
|
|
29163
29079
|
constructor(opts) {
|
|
@@ -29601,7 +29517,7 @@ var require_ops5 = __commonJS({
|
|
|
29601
29517
|
var managed = require_managed();
|
|
29602
29518
|
var portsvc = require_ports3();
|
|
29603
29519
|
var { FrpManager } = require_frp();
|
|
29604
|
-
var { normalizeRemoteMode, validateWanAccess, normalizeFrpSettings, validateFrpServerSettings, projectRemoteView } =
|
|
29520
|
+
var { normalizeRemoteMode, validateWanAccess, normalizeFrpSettings, validateFrpServerSettings, projectRemoteView } = require_core3();
|
|
29605
29521
|
var reconcile = require_reconcile();
|
|
29606
29522
|
var lanServers = require_lan_servers();
|
|
29607
29523
|
function applyRelayToken(host, existing, want) {
|