@lob-ox/core-darwin-x64 0.0.8 → 0.0.11
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 +831 -977
- 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
|
@@ -998,8 +998,6 @@ var require_brand = __commonJS({
|
|
|
998
998
|
var CLI_SHIM_NAMES = ["lobox", "lobox.cmd", "lobox.ps1"];
|
|
999
999
|
var GUI_BIN_NAMES = ["lobox-shell", "lobox-shell.exe"];
|
|
1000
1000
|
var PROC_MATCH_GUARD = SHARED.proc.matchGuard;
|
|
1001
|
-
var PROC_MATCH_GUI = "lobox-shell";
|
|
1002
|
-
var PROC_MATCH_GUI_RE = "lobox-shell(\\.exe)?";
|
|
1003
1001
|
var BRIDGE_MSG_KERNEL_UPDATE_REQUEST = SHARED.bridge.msgKernelUpdateRequest;
|
|
1004
1002
|
var BRIDGE_MSG_KERNEL_UPDATE_RESULT = SHARED.bridge.msgKernelUpdateResult;
|
|
1005
1003
|
var BRIDGE_MSG_KERNEL_UPDATE_PROGRESS = SHARED.bridge.msgKernelUpdateProgress;
|
|
@@ -1016,9 +1014,7 @@ var require_brand = __commonJS({
|
|
|
1016
1014
|
var EVENT_HARNESS_REMOTE_TOKEN_CHANGED = "harness_remote_token_changed";
|
|
1017
1015
|
var EVENT_LAN_HARNESS_TOKEN_UPDATED = "lan_harness_token_updated";
|
|
1018
1016
|
var EVENT_UPGRADE_STOPPING_HARNESS = "upgrade_stopping_harness";
|
|
1019
|
-
var EVENT_SHELL_UPDATE_PENDING = "shell_update_pending";
|
|
1020
1017
|
var EVENT_SHELL_UPDATE_CHECKED = "shell_update_checked";
|
|
1021
|
-
var EVENT_SHELL_RESTART_REQUESTED = "shell_restart_requested";
|
|
1022
1018
|
var SYSTEMD_TEMPLATE_ASIDE_SUFFIX = ".disabled-by-lobox-";
|
|
1023
1019
|
function corePackageName(tag) {
|
|
1024
1020
|
return NPM_SCOPE + "/" + CORE_PKG_PREFIX + tag;
|
|
@@ -1120,8 +1116,6 @@ var require_brand = __commonJS({
|
|
|
1120
1116
|
CLI_SHIM_NAMES,
|
|
1121
1117
|
GUI_BIN_NAMES,
|
|
1122
1118
|
PROC_MATCH_GUARD,
|
|
1123
|
-
PROC_MATCH_GUI,
|
|
1124
|
-
PROC_MATCH_GUI_RE,
|
|
1125
1119
|
BRIDGE_MSG_KERNEL_UPDATE_REQUEST,
|
|
1126
1120
|
BRIDGE_MSG_KERNEL_UPDATE_RESULT,
|
|
1127
1121
|
BRIDGE_MSG_KERNEL_UPDATE_PROGRESS,
|
|
@@ -1138,9 +1132,7 @@ var require_brand = __commonJS({
|
|
|
1138
1132
|
EVENT_HARNESS_REMOTE_TOKEN_CHANGED,
|
|
1139
1133
|
EVENT_LAN_HARNESS_TOKEN_UPDATED,
|
|
1140
1134
|
EVENT_UPGRADE_STOPPING_HARNESS,
|
|
1141
|
-
EVENT_SHELL_UPDATE_PENDING,
|
|
1142
1135
|
EVENT_SHELL_UPDATE_CHECKED,
|
|
1143
|
-
EVENT_SHELL_RESTART_REQUESTED,
|
|
1144
1136
|
SYSTEMD_TEMPLATE_ASIDE_SUFFIX,
|
|
1145
1137
|
corePackageName,
|
|
1146
1138
|
stateRoot: stateRoot2,
|
|
@@ -1312,14 +1304,11 @@ var require_config = __commonJS({
|
|
|
1312
1304
|
};
|
|
1313
1305
|
}
|
|
1314
1306
|
var BASE_DEFAULTS = {
|
|
1315
|
-
// 守卫监控节拍(进程存活只由 child 的 exit/close 事件与平台 pidlookup 判定,见 app/main/*)。
|
|
1316
1307
|
tickIntervalMs: 5e3,
|
|
1317
|
-
// 启动窗口(秒):spawn 后 startsecs 内退出 ⇒ 记一次「启动失败」;活过 startsecs 后退出 ⇒ 正常重启,不计失败。
|
|
1318
1308
|
startsecs: 10,
|
|
1319
|
-
// 唯一一条限流:startupFailWindowMs 内「启动失败」达 startupFailBurst 次 ⇒ phase=FAILED,停止自动重启,等人工重试。
|
|
1320
|
-
// 不变量:startupFailWindowMs > startupFailBurst × startsecs×1000(60s > 5×10s);同一规则按域参数化,实例域见 domains/instance/state-machine.js。
|
|
1321
1309
|
startupFailWindowMs: 6e4,
|
|
1322
1310
|
startupFailBurst: 5,
|
|
1311
|
+
restart: { windowMs: 6e4, burst: 5, baseDelayMs: 2e3, maxDelayMs: 6e4 },
|
|
1323
1312
|
stopGraceMs: 1e4,
|
|
1324
1313
|
portReleaseWaitMs: 1e4,
|
|
1325
1314
|
apiHost: "127.0.0.1",
|
|
@@ -1347,7 +1336,6 @@ var require_config = __commonJS({
|
|
|
1347
1336
|
initialCheckDelayMs: 2e4,
|
|
1348
1337
|
upgradeTimeoutMs: 6e5,
|
|
1349
1338
|
installCommandTemplate: ["npm", "install", "-g", "{pkg}@{version}"],
|
|
1350
|
-
// apiAccessKey:非回环须带 Authorization: Bearer <key> 或 ?access_key=<key>,回环豁免;不配置则 LAN 受 RFC1918 约束、FRP 仍强制 remoteToken。
|
|
1351
1339
|
apiAccessKey: null,
|
|
1352
1340
|
closeAction: "hide",
|
|
1353
1341
|
externalBrowser: null
|
|
@@ -1483,7 +1471,7 @@ var require_version = __commonJS({
|
|
|
1483
1471
|
var fs2 = require("node:fs");
|
|
1484
1472
|
var path2 = require("node:path");
|
|
1485
1473
|
function guardVersion() {
|
|
1486
|
-
if (true) return String("0.0.
|
|
1474
|
+
if (true) return String("0.0.11");
|
|
1487
1475
|
try {
|
|
1488
1476
|
return JSON.parse(fs2.readFileSync(path2.join(__dirname, "..", "..", "package.json"), "utf8")).version || "unknown";
|
|
1489
1477
|
} catch {
|
|
@@ -1822,28 +1810,38 @@ var require_field_tables = __commonJS({
|
|
|
1822
1810
|
var require_phase = __commonJS({
|
|
1823
1811
|
"src/app/state/phase.js"(exports2, module2) {
|
|
1824
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
|
+
}
|
|
1825
1835
|
function legacyToEntryPhase(ph) {
|
|
1826
|
-
return
|
|
1827
|
-
STOPPED: "stopped",
|
|
1828
|
-
STARTING: "starting",
|
|
1829
|
-
RUNNING: "running",
|
|
1830
|
-
FAILED: "failed",
|
|
1831
|
-
OBSERVED: "stopped",
|
|
1832
|
-
RESTARTING: "starting",
|
|
1833
|
-
BACKOFF: "failed"
|
|
1834
|
-
}[ph] || "stopped";
|
|
1836
|
+
return LEGACY_TO_ENTRY[ph] || "stopped";
|
|
1835
1837
|
}
|
|
1836
|
-
function
|
|
1837
|
-
return
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
failed: "FAILED",
|
|
1842
|
-
restarting: "STARTING",
|
|
1843
|
-
backoff: "FAILED"
|
|
1844
|
-
}[ph] || "STOPPED";
|
|
1838
|
+
function isKnownEntry(ph) {
|
|
1839
|
+
return Object.prototype.hasOwnProperty.call(ENTRY_TO_LEGACY, ph);
|
|
1840
|
+
}
|
|
1841
|
+
function isKnownLegacy(ph) {
|
|
1842
|
+
return Object.prototype.hasOwnProperty.call(LEGACY_TO_ENTRY, ph);
|
|
1845
1843
|
}
|
|
1846
|
-
module2.exports = { legacyToEntryPhase,
|
|
1844
|
+
module2.exports = { entryToLegacyPhase, legacyToEntryPhase, isKnownEntry, isKnownLegacy };
|
|
1847
1845
|
}
|
|
1848
1846
|
});
|
|
1849
1847
|
|
|
@@ -2290,7 +2288,6 @@ var require_decide = __commonJS({
|
|
|
2290
2288
|
return {
|
|
2291
2289
|
phase,
|
|
2292
2290
|
desired: d.state().desired(),
|
|
2293
|
-
// 端口视角(不是存活判据):只喂孤儿接管/占用分支。
|
|
2294
2291
|
portUp: d.portUp() === true,
|
|
2295
2292
|
childAlive: childAlive(d.mChild()),
|
|
2296
2293
|
adoptedAlive: adoptedAlive(d.mAdoptPid()),
|
|
@@ -2302,7 +2299,6 @@ var require_decide = __commonJS({
|
|
|
2302
2299
|
manualRestart: d.manualRestart() === true,
|
|
2303
2300
|
spawnBlocked: !!(d.mSpawnBlockedUntil() && now < d.mSpawnBlockedUntil()),
|
|
2304
2301
|
startDeadlinePassed: startDeadlinePassed(startDeadline, now),
|
|
2305
|
-
// STARTING 且没有存活进程/没记启动窗口 = 已判定重启,等端口释放落点。
|
|
2306
2302
|
restartInFlight: phase === "STARTING" && startDeadline === null,
|
|
2307
2303
|
restartDue: d.mRestartAt() === null || now >= d.mRestartAt(),
|
|
2308
2304
|
crashHalted: d.crashHalted() === true,
|
|
@@ -4138,13 +4134,6 @@ var require_alloc = __commonJS({
|
|
|
4138
4134
|
this._releaseAlloc();
|
|
4139
4135
|
}
|
|
4140
4136
|
}
|
|
4141
|
-
/**
|
|
4142
|
-
* Lease I1:把"检查"与"置位"放在**同一个同步块**内。
|
|
4143
|
-
*
|
|
4144
|
-
* 修前:`while (r._allocLock) { await sleep(10); } r._allocLock = true;`
|
|
4145
|
-
* —— 检查与置位之间隔着 await,两个并发 claimSlot 可同时观察到 false 并都置 true(真 TOCTOU)。
|
|
4146
|
-
* 现在用 Lease.acquireSync 做同步 test-and-set;未取得则由调用方退避重试。
|
|
4147
|
-
*/
|
|
4148
4137
|
async _acquireAlloc() {
|
|
4149
4138
|
const r = this._registry;
|
|
4150
4139
|
let waited = 0;
|
|
@@ -4171,7 +4160,6 @@ var require_alloc = __commonJS({
|
|
|
4171
4160
|
}
|
|
4172
4161
|
}
|
|
4173
4162
|
}
|
|
4174
|
-
// 跨进程分配锁 best-effort:获取超时返回 null 并继续(fail-open 有界,登记后复检是第二道防线)。
|
|
4175
4163
|
async _acquireXLock() {
|
|
4176
4164
|
const f = String(this._registry._file || "") + ".alloc.lock";
|
|
4177
4165
|
const deadline = Date.now() + XLOCK_TIMEOUT_MS;
|
|
@@ -5047,320 +5035,138 @@ var require_policies = __commonJS({
|
|
|
5047
5035
|
}
|
|
5048
5036
|
});
|
|
5049
5037
|
|
|
5050
|
-
// src/
|
|
5051
|
-
var
|
|
5052
|
-
"src/
|
|
5053
|
-
"use strict";
|
|
5054
|
-
var BRAND2 = require_brand();
|
|
5055
|
-
var DEFAULTS = {
|
|
5056
|
-
enabled: true,
|
|
5057
|
-
intervalMs: 2e4,
|
|
5058
|
-
graceMs: 9e4,
|
|
5059
|
-
updateGraceMs: 3e5,
|
|
5060
|
-
maxRestarts: 5,
|
|
5061
|
-
windowMs: 18e5,
|
|
5062
|
-
phaseMaxAgeMs: 6e5,
|
|
5063
|
-
// 壳进程判据的**唯一来源**是跨语言单源(brand.js#PROC_MATCH_GUI,与 brand.rs 同名同值):
|
|
5064
|
-
// 此处再写一份字面量 = 改名漏一处 ⇒ pgrep 找不到壳(watchdog 反复拉起/双实例),或杀错进程。
|
|
5065
|
-
procPattern: BRAND2.PROC_MATCH_GUI
|
|
5066
|
-
};
|
|
5067
|
-
var HEADLESS_FLAGS = Object.freeze([
|
|
5068
|
-
"--shell-update-plan",
|
|
5069
|
-
"--core-plan",
|
|
5070
|
-
"--node-plan",
|
|
5071
|
-
"--mirror-plan",
|
|
5072
|
-
"--env-plan",
|
|
5073
|
-
"--service-plan",
|
|
5074
|
-
"--platform-matrix",
|
|
5075
|
-
"--run-guard",
|
|
5076
|
-
"--watchdog"
|
|
5077
|
-
]);
|
|
5078
|
-
var HEADLESS_RE = new RegExp(HEADLESS_FLAGS.join("|"));
|
|
5079
|
-
var SHELL_PROC_RE = new RegExp(BRAND2.PROC_MATCH_GUI_RE);
|
|
5080
|
-
function isShellProcess(proc) {
|
|
5081
|
-
const c = String(proc && proc.cmdline || "");
|
|
5082
|
-
if (HEADLESS_RE.test(c)) return false;
|
|
5083
|
-
return SHELL_PROC_RE.test(c);
|
|
5084
|
-
}
|
|
5085
|
-
function decide(i) {
|
|
5086
|
-
const c = i.config || {};
|
|
5087
|
-
if (i.alive > 0) return { action: "alive", reason: "\u58F3\u5728\u8FD0\u884C" };
|
|
5088
|
-
if (i.absentForMs === null || i.absentForMs === void 0) {
|
|
5089
|
-
return { action: "record", reason: "\u9996\u6B21\u89C2\u5BDF\u5230\u58F3\u7F3A\u5931\uFF0C\u5F00\u59CB\u8BA1\u65F6" };
|
|
5090
|
-
}
|
|
5091
|
-
const needMs = i.expectedAbsence ? c.updateGraceMs || DEFAULTS.updateGraceMs : c.graceMs || DEFAULTS.graceMs;
|
|
5092
|
-
if (i.absentForMs < needMs) {
|
|
5093
|
-
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 };
|
|
5094
|
-
}
|
|
5095
|
-
if (!i.sessionAvailable) {
|
|
5096
|
-
return { action: "skip", reason: "\u65E0\u56FE\u5F62\u4F1A\u8BDD\uFF08\u6CE8\u9500/\u7EAF\u7EC8\u7AEF\uFF09\uFF0C\u62C9\u8D77 GUI \u5FC5\u5931\u8D25" };
|
|
5097
|
-
}
|
|
5098
|
-
if ((i.restartsInWindow || 0) >= (c.maxRestarts || DEFAULTS.maxRestarts)) {
|
|
5099
|
-
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" };
|
|
5100
|
-
}
|
|
5101
|
-
if (!i.hasExe) {
|
|
5102
|
-
return { action: "skip", reason: "\u65E0\u6CD5\u5B9A\u4F4D\u58F3\u53EF\u6267\u884C\u6587\u4EF6\uFF08identity.json \u672A\u8BB0\u5F55 exe\uFF09" };
|
|
5103
|
-
}
|
|
5104
|
-
return { action: "restart", reason: "\u58F3\u7F3A\u5931\u4E14\u5DF2\u8FC7\u5BBD\u9650\u671F", needMs };
|
|
5105
|
-
}
|
|
5106
|
-
function isUpdatePhase(phase) {
|
|
5107
|
-
const p = String(phase || "");
|
|
5108
|
-
return p === "restarting" || p.indexOf("shell-update") === 0;
|
|
5109
|
-
}
|
|
5110
|
-
function exeFromCmdline(cmdline) {
|
|
5111
|
-
const s = String(cmdline || "").trim();
|
|
5112
|
-
if (!s) return null;
|
|
5113
|
-
if (s.startsWith('"')) {
|
|
5114
|
-
const end = s.indexOf('"', 1);
|
|
5115
|
-
return end > 1 ? s.slice(1, end) : null;
|
|
5116
|
-
}
|
|
5117
|
-
return s.split(/\s+/)[0] || null;
|
|
5118
|
-
}
|
|
5119
|
-
function deriveState(id, journal) {
|
|
5120
|
-
const j = journal || {};
|
|
5121
|
-
if (!j.to) return { state: "idle", reason: "\u65E0\u8FDB\u884C\u4E2D\u7684\u66F4\u65B0", journal: j, identity: id };
|
|
5122
|
-
const cur = id && id.version ? String(id.version) : null;
|
|
5123
|
-
if (cur && cur === j.to && id && id.phase === "ready") {
|
|
5124
|
-
const next = j.confirmed === true ? j : Object.assign({}, j, { confirmed: true });
|
|
5125
|
-
return { state: "confirmed", version: cur, reason: "\u58F3\u5DF2\u5065\u5EB7\u8FD0\u884C\u65B0\u7248\u672C", journal: next, identity: id };
|
|
5126
|
-
}
|
|
5127
|
-
return {
|
|
5128
|
-
state: "pending",
|
|
5129
|
-
target: j.to,
|
|
5130
|
-
current: cur,
|
|
5131
|
-
reason: cur === j.to ? "\u7B49\u5F85\u58F3\u4E0A\u62A5\u5C31\u7EEA" : "\u7B49\u5F85\u58F3\u91CD\u542F\u5230\u65B0\u7248\u672C",
|
|
5132
|
-
journal: j,
|
|
5133
|
-
identity: id
|
|
5134
|
-
};
|
|
5135
|
-
}
|
|
5136
|
-
module2.exports = { DEFAULTS, isShellProcess, decide, isUpdatePhase, exeFromCmdline, deriveState, HEADLESS_FLAGS };
|
|
5137
|
-
}
|
|
5138
|
-
});
|
|
5139
|
-
|
|
5140
|
-
// src/domains/shell/watchdog.js
|
|
5141
|
-
var require_watchdog = __commonJS({
|
|
5142
|
-
"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) {
|
|
5143
5041
|
"use strict";
|
|
5144
|
-
var
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
let missingSince = null;
|
|
5156
|
-
let restarts = [];
|
|
5157
|
-
let busy = false;
|
|
5158
|
-
let lastSkipReason = null;
|
|
5159
|
-
let everSawAlive = false;
|
|
5160
|
-
let expectedSince = null;
|
|
5161
|
-
let phaseStale = false;
|
|
5162
|
-
let phaseStaleWarned = false;
|
|
5163
|
-
let journalStale = false;
|
|
5164
|
-
let journalStaleWarned = false;
|
|
5165
|
-
const log = (m) => {
|
|
5166
|
-
try {
|
|
5167
|
-
logger.info && logger.info("[shell-watchdog] " + m);
|
|
5168
|
-
} catch {
|
|
5169
|
-
}
|
|
5170
|
-
};
|
|
5171
|
-
const warn = (m) => {
|
|
5172
|
-
try {
|
|
5173
|
-
logger.warn && logger.warn("[shell-watchdog] " + m);
|
|
5174
|
-
} catch {
|
|
5175
|
-
}
|
|
5176
|
-
};
|
|
5177
|
-
function shellProcs() {
|
|
5178
|
-
let procs = [];
|
|
5179
|
-
try {
|
|
5180
|
-
procs = pidlookup.pgrepList(procPattern) || [];
|
|
5181
|
-
} catch {
|
|
5182
|
-
procs = [];
|
|
5183
|
-
}
|
|
5184
|
-
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;
|
|
5185
5053
|
}
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
phaseStale = t - expectedSince >= maxAge;
|
|
5203
|
-
if (phaseStale && !phaseStaleWarned) {
|
|
5204
|
-
phaseStaleWarned = true;
|
|
5205
|
-
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");
|
|
5206
|
-
}
|
|
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;
|
|
5207
5070
|
}
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
j = shell.readJournal && shell.readJournal();
|
|
5212
|
-
} catch {
|
|
5213
|
-
}
|
|
5214
|
-
if (!j || !j.to || j.confirmed) {
|
|
5215
|
-
journalStale = false;
|
|
5216
|
-
journalStaleWarned = false;
|
|
5217
|
-
return;
|
|
5218
|
-
}
|
|
5219
|
-
const t0 = Date.parse(String(j.startedAt || ""));
|
|
5220
|
-
if (!Number.isFinite(t0)) {
|
|
5221
|
-
journalStale = false;
|
|
5222
|
-
return;
|
|
5223
|
-
}
|
|
5224
|
-
const maxAge = config.shellWatchdogPhaseMaxAgeMs || DEFAULTS.phaseMaxAgeMs;
|
|
5225
|
-
journalStale = t - t0 >= maxAge;
|
|
5226
|
-
if (journalStale && !journalStaleWarned) {
|
|
5227
|
-
journalStaleWarned = true;
|
|
5228
|
-
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");
|
|
5229
|
-
}
|
|
5071
|
+
unregister(name) {
|
|
5072
|
+
this._beats.delete(name);
|
|
5073
|
+
return this;
|
|
5230
5074
|
}
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
try {
|
|
5234
|
-
const id = shell.identity();
|
|
5235
|
-
phase = String(id && id.phase || "");
|
|
5236
|
-
} catch {
|
|
5237
|
-
}
|
|
5238
|
-
const inUpdate = isUpdatePhase(phase);
|
|
5239
|
-
if (inUpdate && !phaseStale) return true;
|
|
5240
|
-
try {
|
|
5241
|
-
const j = shell.readJournal && shell.readJournal();
|
|
5242
|
-
if (j && j.to && !j.confirmed) return !journalStale;
|
|
5243
|
-
} catch {
|
|
5244
|
-
}
|
|
5245
|
-
return false;
|
|
5075
|
+
has(name) {
|
|
5076
|
+
return this._beats.has(name);
|
|
5246
5077
|
}
|
|
5247
|
-
|
|
5248
|
-
if (
|
|
5078
|
+
async withLock(fn) {
|
|
5079
|
+
if (this._ticking || this._stopping) return { __skipped: "busy" };
|
|
5080
|
+
this._ticking = true;
|
|
5249
5081
|
try {
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
return null;
|
|
5082
|
+
return await fn();
|
|
5083
|
+
} finally {
|
|
5084
|
+
this._ticking = false;
|
|
5254
5085
|
}
|
|
5255
5086
|
}
|
|
5256
|
-
async
|
|
5257
|
-
if (
|
|
5258
|
-
|
|
5259
|
-
|
|
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;
|
|
5260
5093
|
try {
|
|
5261
|
-
|
|
5262
|
-
const
|
|
5263
|
-
|
|
5264
|
-
|
|
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;
|
|
5265
5106
|
try {
|
|
5266
|
-
|
|
5267
|
-
} catch {
|
|
5107
|
+
p = Promise.resolve(b.fn());
|
|
5108
|
+
} catch (e) {
|
|
5109
|
+
errors.push(name + ":" + (e && e.message));
|
|
5110
|
+
continue;
|
|
5268
5111
|
}
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
if (alive > 0 && !everSawAlive) {
|
|
5275
|
-
everSawAlive = true;
|
|
5276
|
-
log("\u5DF2\u89C2\u6D4B\u5230\u684C\u9762\u58F3\u5728\u8FD0\u884C\uFF08pid=" + procs[0].pid + "\uFF09");
|
|
5277
|
-
}
|
|
5278
|
-
const absentForMs = alive > 0 ? null : missingSince === null ? null : t - missingSince;
|
|
5279
|
-
updatePhaseTracking(t);
|
|
5280
|
-
updateJournalTracking(t);
|
|
5281
|
-
const expected = absentForMs === null ? false : expectedAbsence();
|
|
5282
|
-
const exe = exePath();
|
|
5283
|
-
restarts = restarts.filter((x) => t - x < (config.shellWatchdogWindowMs || DEFAULTS.windowMs));
|
|
5284
|
-
const d = decide({
|
|
5285
|
-
alive,
|
|
5286
|
-
absentForMs,
|
|
5287
|
-
expectedAbsence: expected,
|
|
5288
|
-
sessionAvailable: desktop.sessionAvailable(),
|
|
5289
|
-
restartsInWindow: restarts.length,
|
|
5290
|
-
hasExe: !!exe,
|
|
5291
|
-
config: {
|
|
5292
|
-
graceMs: config.shellWatchdogGraceMs || DEFAULTS.graceMs,
|
|
5293
|
-
updateGraceMs: config.shellWatchdogUpdateGraceMs || DEFAULTS.updateGraceMs,
|
|
5294
|
-
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
|
+
})]);
|
|
5295
5117
|
}
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
if (d.action === "wait") {
|
|
5308
|
-
lastSkipReason = d.reason + "\uFF08" + Math.round(absentForMs / 1e3) + "s/" + Math.round(d.needMs / 1e3) + "s\uFF09";
|
|
5309
|
-
return { waiting: d.reason };
|
|
5310
|
-
}
|
|
5311
|
-
if (d.action === "skip") {
|
|
5312
|
-
if (lastSkipReason !== d.reason) {
|
|
5313
|
-
lastSkipReason = d.reason;
|
|
5314
|
-
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));
|
|
5315
5129
|
}
|
|
5316
|
-
return { skipped: d.reason };
|
|
5317
|
-
}
|
|
5318
|
-
restarts.push(t);
|
|
5319
|
-
const r = await shell.restartShell({
|
|
5320
|
-
exePath: exe,
|
|
5321
|
-
procPattern,
|
|
5322
|
-
shouldAbort: typeof o.halted === "function" ? () => o.halted() : void 0
|
|
5323
|
-
});
|
|
5324
|
-
if (r && r.ok) {
|
|
5325
|
-
if (events) events.append("shell_watchdog_restart", { pid: r.pid, exe: r.exe, absentMs: absentForMs });
|
|
5326
|
-
log("\u684C\u9762\u58F3\u7F3A\u5931 " + Math.round(absentForMs / 1e3) + "s\uFF0C\u5DF2\u62C9\u8D77 pid=" + r.pid + " exe=" + r.exe);
|
|
5327
|
-
missingSince = null;
|
|
5328
|
-
} else {
|
|
5329
|
-
if (events) events.append("shell_watchdog_restart_failed", { error: r && r.error || "\u672A\u77E5", absentMs: absentForMs });
|
|
5330
|
-
warn("\u62C9\u8D77\u684C\u9762\u58F3\u5931\u8D25\uFF1A" + (r && r.error || "\u672A\u77E5"));
|
|
5331
5130
|
}
|
|
5332
|
-
return { restarted: !!(r && r.ok), error: r && r.error || null };
|
|
5333
|
-
} catch (e) {
|
|
5334
|
-
warn("\u76D1\u63A7\u5F02\u5E38\uFF1A" + (e && e.message || e));
|
|
5335
|
-
return { error: e && e.message || String(e) };
|
|
5336
5131
|
} finally {
|
|
5337
|
-
|
|
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
|
+
}
|
|
5338
5140
|
}
|
|
5141
|
+
return { done, errors };
|
|
5339
5142
|
}
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
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;
|
|
5346
5159
|
}
|
|
5347
|
-
return {
|
|
5348
|
-
enabled: config.shellWatchdog !== false,
|
|
5349
|
-
intervalMs: config.shellWatchdogIntervalMs || DEFAULTS.intervalMs,
|
|
5350
|
-
graceMs: config.shellWatchdogGraceMs || DEFAULTS.graceMs,
|
|
5351
|
-
updateGraceMs: config.shellWatchdogUpdateGraceMs || DEFAULTS.updateGraceMs,
|
|
5352
|
-
maxRestarts: config.shellWatchdogMaxRestarts || DEFAULTS.maxRestarts,
|
|
5353
|
-
absentForMs: missingSince === null ? null : t - missingSince,
|
|
5354
|
-
restartsInWindow: restarts.filter((x) => t - x < (config.shellWatchdogWindowMs || DEFAULTS.windowMs)).length,
|
|
5355
|
-
everSawAlive,
|
|
5356
|
-
lastSkipReason,
|
|
5357
|
-
session,
|
|
5358
|
-
expectedAbsence: expectedAbsence()
|
|
5359
|
-
};
|
|
5360
5160
|
}
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5161
|
+
resume() {
|
|
5162
|
+
this._stopping = false;
|
|
5163
|
+
}
|
|
5164
|
+
clear() {
|
|
5165
|
+
this._beats.clear();
|
|
5166
|
+
this.stop();
|
|
5167
|
+
}
|
|
5168
|
+
};
|
|
5169
|
+
module2.exports = { BeatScheduler };
|
|
5364
5170
|
}
|
|
5365
5171
|
});
|
|
5366
5172
|
|
|
@@ -5465,7 +5271,6 @@ var require_capability_profile = __commonJS({
|
|
|
5465
5271
|
"use strict";
|
|
5466
5272
|
var linux = {
|
|
5467
5273
|
sandboxLaunch: true,
|
|
5468
|
-
// 服务管理器一律走产品自身的进程管理(不借 systemd)⇒ 无 cgroup 强制,如实为 supervise。
|
|
5469
5274
|
sandboxEnforcement: "supervise",
|
|
5470
5275
|
pidAdoption: true,
|
|
5471
5276
|
processTreeKill: true,
|
|
@@ -7092,7 +6897,7 @@ var require_portable = __commonJS({
|
|
|
7092
6897
|
if (!pid || !Array.isArray(anchors) || !anchors.length) return false;
|
|
7093
6898
|
const cmd2 = pidlookup.readCmdline(pid);
|
|
7094
6899
|
if (!cmd2) return false;
|
|
7095
|
-
return anchors.
|
|
6900
|
+
return anchors.every((a) => a && cmd2.indexOf(String(a)) !== -1);
|
|
7096
6901
|
}
|
|
7097
6902
|
var portOf = (o) => {
|
|
7098
6903
|
const p = Number(o && o.port);
|
|
@@ -7135,15 +6940,6 @@ var require_portable = __commonJS({
|
|
|
7135
6940
|
kind: "portable",
|
|
7136
6941
|
supportsUnits: false,
|
|
7137
6942
|
supportsTransient: true,
|
|
7138
|
-
/**
|
|
7139
|
-
* 能力协商(根因 B 修法;与 router 域 `supports(cap)` 同一范式,下沉到平台层)。
|
|
7140
|
-
*
|
|
7141
|
-
* 判据来源:capability-profile.js 的 sandboxEnforcement —— 三平台均为 'supervise'
|
|
7142
|
-
* (= 产品自身监控,**无 cgroup 级强制**)。此前该字段全仓 0 处查询,
|
|
7143
|
-
* 于是 governor 在"限额根本无法生效"的前提下仍判违规并重启 ⇒ 永动机(P0)。
|
|
7144
|
-
*
|
|
7145
|
-
* 调用方(governor)必须先问后处置:不支持限额 ⇒ 只观测,绝不重启。
|
|
7146
|
-
*/
|
|
7147
6943
|
supports(cap) {
|
|
7148
6944
|
if (cap === "treeKill") return true;
|
|
7149
6945
|
if (cap === "limits") return false;
|
|
@@ -7185,11 +6981,6 @@ var require_portable = __commonJS({
|
|
|
7185
6981
|
}
|
|
7186
6982
|
return true;
|
|
7187
6983
|
},
|
|
7188
|
-
// 审计 P0-I5:原实现在 Windows 上用 Atomics.wait(nap)**同步冻结事件循环**做轮询、且 SIGKILL 兜底分支
|
|
7189
|
-
// 调用的 taskkill 完全异步不 await ⇒ 停止"无法确认"(常返回 false),进而实例仍被标 RUNNING、
|
|
7190
|
-
// upgrade.js 在上个进程仍占端口时继续重装 ⇒ 与端口预检撞车回滚(正是 upgrade.js 想防的故障)。
|
|
7191
|
-
// 修复:改为 async,用 real-timer 轮询(不阻塞事件循环),并等待 taskkill 真正结束(有界 10s,与 process.js killTree 同),
|
|
7192
|
-
// 给足停止窗口再判定;仍超时再报 false(如实,不再假成功)。timeoutMs 仍被 STOP_WAIT_CAP_MS 截断(与调用方意图无关)。
|
|
7193
6984
|
async stopUnit(unit, o) {
|
|
7194
6985
|
const opts = o || {};
|
|
7195
6986
|
const ours = findOurs(opts);
|
|
@@ -7296,19 +7087,6 @@ var require_portable = __commonJS({
|
|
|
7296
7087
|
}
|
|
7297
7088
|
return false;
|
|
7298
7089
|
},
|
|
7299
|
-
/**
|
|
7300
|
-
* 单元是否活跃 —— 返回 Outcome 三态(根因 A 修法)。
|
|
7301
|
-
*
|
|
7302
|
-
* 此前返回 null 表示"未知",而调用方 instance/ops.js:67 用 `active !== false` 判,
|
|
7303
|
-
* 于是 null(未知)被当成"仍活跃" ⇒ removeInstance 把未知报成删除成功(P0)。
|
|
7304
|
-
*
|
|
7305
|
-
* 关键修正:**无 anchors 时不得把"有人在监听"当成"我们的实例在跑"**。
|
|
7306
|
-
* 端口是共享事实、不是身份(与 monitor.js#matchesAnchors 同一条判据);
|
|
7307
|
-
* 缺锚点即无从验证身份 ⇒ 如实返回 unknown,由调用方决定(升级校验须失败并回滚)。
|
|
7308
|
-
*
|
|
7309
|
-
* 兼容:既有调用方若直接判真假,Outcome 对象恒为真值,行为同"true",不会静默反转;
|
|
7310
|
-
* 但显式判据(isOk/isFail/isUnknown)才能区分三态——见 shared/outcome.js。
|
|
7311
|
-
*/
|
|
7312
7090
|
isUnitActive(unit, o) {
|
|
7313
7091
|
const opts = o || {};
|
|
7314
7092
|
if (findOurs(opts)) return OUTCOME.OK;
|
|
@@ -7332,7 +7110,6 @@ var require_portable = __commonJS({
|
|
|
7332
7110
|
transientUnitFile() {
|
|
7333
7111
|
return null;
|
|
7334
7112
|
},
|
|
7335
|
-
// 审计 P0-I5:随 stopUnit 改为 async,cleanTransient 也须 await(不得再用 === false 同步判)。
|
|
7336
7113
|
async cleanTransient(unit, o) {
|
|
7337
7114
|
const opts = o || {};
|
|
7338
7115
|
const errors = [];
|
|
@@ -7371,7 +7148,6 @@ var require_service = __commonJS({
|
|
|
7371
7148
|
kind: UNSUPPORTED_KIND,
|
|
7372
7149
|
supportsUnits: false,
|
|
7373
7150
|
supportsTransient: false,
|
|
7374
|
-
// 能力协商:与 portable 同类,未知平台一律不支持(保持方法集一致)。
|
|
7375
7151
|
supports() {
|
|
7376
7152
|
return false;
|
|
7377
7153
|
},
|
|
@@ -8295,6 +8071,122 @@ var require_os = __commonJS({
|
|
|
8295
8071
|
}
|
|
8296
8072
|
});
|
|
8297
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
|
+
|
|
8298
8190
|
// src/app/assembly/bootstrap.js
|
|
8299
8191
|
var require_bootstrap = __commonJS({
|
|
8300
8192
|
"src/app/assembly/bootstrap.js"(exports2, module2) {
|
|
@@ -8305,11 +8197,20 @@ var require_bootstrap = __commonJS({
|
|
|
8305
8197
|
var path2 = require("node:path");
|
|
8306
8198
|
var fs2 = require("node:fs");
|
|
8307
8199
|
var ports = require_ports().shared;
|
|
8308
|
-
var { createShellWatchdog } = require_watchdog();
|
|
8309
8200
|
var pidlook = require_pidlookup();
|
|
8201
|
+
var { BeatScheduler } = require_synchrony();
|
|
8310
8202
|
var platform = require_os();
|
|
8311
8203
|
var ENV_FORM_STARTUP_DELAY_MS = 3e3;
|
|
8312
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
|
+
}
|
|
8313
8214
|
try {
|
|
8314
8215
|
host.events.append("guard_started", {
|
|
8315
8216
|
pid: process.pid,
|
|
@@ -8330,39 +8231,55 @@ var require_bootstrap = __commonJS({
|
|
|
8330
8231
|
routerAutostart: host.config.routerAutostart === true,
|
|
8331
8232
|
routerMode: null,
|
|
8332
8233
|
updateCheck: null,
|
|
8333
|
-
shellWatchdog: null,
|
|
8334
8234
|
lastRefresh: null
|
|
8335
8235
|
};
|
|
8336
|
-
host.
|
|
8337
|
-
host.
|
|
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);
|
|
8256
|
+
}
|
|
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;
|
|
8338
8280
|
host._lastHeartbeatAt = Date.now();
|
|
8339
8281
|
host._heartbeatStalls = 0;
|
|
8340
8282
|
host._heartbeatBeat = host._heartbeatBeat || 0;
|
|
8341
|
-
const heartbeatIv = host.config.tickIntervalMs || 5e3;
|
|
8342
|
-
host._heartbeatTimer = setInterval(() => {
|
|
8343
|
-
if (host._heartbeatBusy) return;
|
|
8344
|
-
host._heartbeatBusy = true;
|
|
8345
|
-
const iv = heartbeatIv;
|
|
8346
|
-
const beat = ++host._heartbeatBeat;
|
|
8347
|
-
host._lastHeartbeatAt = Date.now();
|
|
8348
|
-
const objCount = host.managedObjects && typeof host.managedObjects.count === "function" ? host.managedObjects.count() : 1;
|
|
8349
|
-
const stallMs = Math.max(3e4, iv * 12, objCount * 6 * iv + iv);
|
|
8350
|
-
const guard = setTimeout(() => {
|
|
8351
|
-
if (host._heartbeatBusy && beat === host._heartbeatBeat) {
|
|
8352
|
-
host._heartbeatBusy = false;
|
|
8353
|
-
host._heartbeatStalls++;
|
|
8354
|
-
if (host.logger && host.logger.warn) {
|
|
8355
|
-
host.logger.warn("[heartbeat] \u5355\u62CD\u8D85\u8FC7 " + stallMs + "ms \u672A\u7ED3\u7B97\uFF0C\u5F3A\u5236\u91CA\u653E\u9632\u505C\u6446\uFF08\u7B2C " + host._heartbeatStalls + " \u6B21\uFF09");
|
|
8356
|
-
}
|
|
8357
|
-
}
|
|
8358
|
-
}, stallMs);
|
|
8359
|
-
if (guard && typeof guard.unref === "function") guard.unref();
|
|
8360
|
-
Promise.resolve(host.managedObjects ? host.managedObjects.heartbeat(iv) : null).catch(() => {
|
|
8361
|
-
}).finally(() => {
|
|
8362
|
-
clearTimeout(guard);
|
|
8363
|
-
if (beat === host._heartbeatBeat) host._heartbeatBusy = false;
|
|
8364
|
-
});
|
|
8365
|
-
}, heartbeatIv);
|
|
8366
8283
|
if (host.lanDaemonEnabled()) {
|
|
8367
8284
|
host._syncLanState();
|
|
8368
8285
|
const lrt = host._ensureLanRuntime(true);
|
|
@@ -8372,7 +8289,6 @@ var require_bootstrap = __commonJS({
|
|
|
8372
8289
|
});
|
|
8373
8290
|
host.lan.syncFrpc();
|
|
8374
8291
|
}
|
|
8375
|
-
if (!host.managedObjects) host.instances.startTimer(host.config.tickIntervalMs || 5e3);
|
|
8376
8292
|
if (!host.lanDaemonEnabled()) {
|
|
8377
8293
|
for (const inst of host.instances.all()) {
|
|
8378
8294
|
if (inst.remoteMode === "lan" || inst.remoteMode === "wan") host.lan.syncProxy(inst).catch(() => {
|
|
@@ -8436,22 +8352,6 @@ var require_bootstrap = __commonJS({
|
|
|
8436
8352
|
initialDelayMs: checkDelayMs,
|
|
8437
8353
|
intervalMs: checkIntervalMs
|
|
8438
8354
|
};
|
|
8439
|
-
if (host.config.updateCheckEnabled !== false) {
|
|
8440
|
-
host._initialCheckTimer = setTimeout(() => {
|
|
8441
|
-
host.nativeManager.checkUpdate();
|
|
8442
|
-
}, checkDelayMs);
|
|
8443
|
-
host._upgradeTimer = setInterval(() => {
|
|
8444
|
-
host.nativeManager.checkUpdate();
|
|
8445
|
-
}, checkIntervalMs);
|
|
8446
|
-
}
|
|
8447
|
-
try {
|
|
8448
|
-
host._startShellWatchdog();
|
|
8449
|
-
} catch (e) {
|
|
8450
|
-
if (host.logger && host.logger.warn) {
|
|
8451
|
-
host.logger.warn("[shell-watchdog] \u542F\u52A8\u5F02\u5E38\uFF08\u4E0D\u5F71\u54CD\u5B88\u536B\u4E3B\u5FAA\u73AF\uFF09: " + (e && e.message || e));
|
|
8452
|
-
}
|
|
8453
|
-
}
|
|
8454
|
-
host._startupFacts.shellWatchdog = !!host.shellWatchdog;
|
|
8455
8355
|
const envTimer = setTimeout(() => {
|
|
8456
8356
|
try {
|
|
8457
8357
|
host._refreshEnvironmentForm();
|
|
@@ -8496,41 +8396,6 @@ var require_bootstrap = __commonJS({
|
|
|
8496
8396
|
return null;
|
|
8497
8397
|
});
|
|
8498
8398
|
}
|
|
8499
|
-
function _startShellWatchdog(host) {
|
|
8500
|
-
if (host.config.shellWatchdog === false) {
|
|
8501
|
-
host.logger.info && host.logger.info("[shell-watchdog] \u5DF2\u6309\u914D\u7F6E\u7981\u7528");
|
|
8502
|
-
return;
|
|
8503
|
-
}
|
|
8504
|
-
try {
|
|
8505
|
-
host.shellWatchdog = createShellWatchdog({
|
|
8506
|
-
shell: host.shellDomain,
|
|
8507
|
-
pidlookup: pidlook,
|
|
8508
|
-
desktop: platform.desktop,
|
|
8509
|
-
logger: host.logger,
|
|
8510
|
-
events: host.events,
|
|
8511
|
-
config: host.config,
|
|
8512
|
-
halted: () => host._shellExitIntended(),
|
|
8513
|
-
onShellAlive: () => {
|
|
8514
|
-
if (!host._shellHalted) return;
|
|
8515
|
-
if (host._stopping) return;
|
|
8516
|
-
if (host._sessionHalting && host._sessionHalting()) return;
|
|
8517
|
-
host._shellHalted = false;
|
|
8518
|
-
try {
|
|
8519
|
-
host.writeState(true);
|
|
8520
|
-
} catch {
|
|
8521
|
-
}
|
|
8522
|
-
}
|
|
8523
|
-
});
|
|
8524
|
-
host._shellWatchdogTimer = setInterval(() => {
|
|
8525
|
-
Promise.resolve(host.shellWatchdog.tick()).catch(() => {
|
|
8526
|
-
});
|
|
8527
|
-
}, host.shellWatchdog.intervalMs);
|
|
8528
|
-
if (host._shellWatchdogTimer.unref) host._shellWatchdogTimer.unref();
|
|
8529
|
-
host.logger.info && host.logger.info("[shell-watchdog] \u5DF2\u542F\u7528\uFF08\u5468\u671F " + Math.round(host.shellWatchdog.intervalMs / 1e3) + "s\uFF09");
|
|
8530
|
-
} catch (e) {
|
|
8531
|
-
host.logger.warn && host.logger.warn("[shell-watchdog] \u521D\u59CB\u5316\u5931\u8D25\uFF08\u4E0D\u5F71\u54CD\u5B88\u536B\uFF09: " + (e && e.message || e));
|
|
8532
|
-
}
|
|
8533
|
-
}
|
|
8534
8399
|
function _registerFixedPorts(host) {
|
|
8535
8400
|
ports.register("dsh-main", host.config.targetPort);
|
|
8536
8401
|
ports.registerSole("supervisor-api", host.config.apiPort);
|
|
@@ -8542,7 +8407,13 @@ var require_bootstrap = __commonJS({
|
|
|
8542
8407
|
const isBare = policies.isBareCommand(cur);
|
|
8543
8408
|
if (!isBare) return;
|
|
8544
8409
|
const d = execPath.resolveDsh();
|
|
8545
|
-
if (!d || !d.bin)
|
|
8410
|
+
if (!d || !d.bin) {
|
|
8411
|
+
try {
|
|
8412
|
+
host.logger.warn && host.logger.warn("\u539F\u751F DSH \u542F\u52A8\u671F\u7ED1\u5B9A\u8DF3\u8FC7\uFF1A\u672A\u89E3\u6790\u5230\u5165\u53E3\uFF08PATH \u53EF\u80FD\u5C1A\u672A\u767B\u8BB0\uFF09\uFF1Bspawn \u671F\u4F1A\u518D\u6B21\u89E3\u6790");
|
|
8413
|
+
} catch {
|
|
8414
|
+
}
|
|
8415
|
+
return;
|
|
8416
|
+
}
|
|
8546
8417
|
host.config.command = d.isJs ? [d.runtime || process.execPath, d.bin, ...cmd2.slice(2)] : [d.bin, ...cmd2.slice(2)];
|
|
8547
8418
|
try {
|
|
8548
8419
|
host.events && host.events.append(BRAND2.EVENT_HARNESS_COMMAND_BOUND, { from: cur || null, to: host.config.command[1] });
|
|
@@ -8559,7 +8430,7 @@ var require_bootstrap = __commonJS({
|
|
|
8559
8430
|
}
|
|
8560
8431
|
}
|
|
8561
8432
|
}
|
|
8562
|
-
module2.exports = { _bootstrap,
|
|
8433
|
+
module2.exports = { _bootstrap, _registerFixedPorts, _bindNativeDshCommand, _refreshEnvironmentForm };
|
|
8563
8434
|
}
|
|
8564
8435
|
});
|
|
8565
8436
|
|
|
@@ -8615,14 +8486,17 @@ var require_api_rebind = __commonJS({
|
|
|
8615
8486
|
});
|
|
8616
8487
|
server.listen(host.config.apiPort, host.config.apiHost, () => {
|
|
8617
8488
|
bind._tries = 0;
|
|
8489
|
+
const bound = server.address();
|
|
8490
|
+
const realPort = bound && Number.isInteger(bound.port) ? bound.port : host.config.apiPort;
|
|
8618
8491
|
host.api = server;
|
|
8492
|
+
if (realPort !== host.config.apiPort) host.config.apiPort = realPort;
|
|
8619
8493
|
try {
|
|
8620
|
-
portsShared.registerSole("supervisor-api",
|
|
8494
|
+
portsShared.registerSole("supervisor-api", realPort);
|
|
8621
8495
|
} catch (e) {
|
|
8622
8496
|
host.logger.warn("ports.registerSole(supervisor-api) \u5931\u8D25: " + (e && e.message || e));
|
|
8623
8497
|
}
|
|
8624
|
-
host.events.append("api_listening", { host: host.config.apiHost, port:
|
|
8625
|
-
host.logger.info("api listening on " + host.config.apiHost + ":" +
|
|
8498
|
+
host.events.append("api_listening", { host: host.config.apiHost, port: realPort });
|
|
8499
|
+
host.logger.info("api listening on " + host.config.apiHost + ":" + realPort);
|
|
8626
8500
|
});
|
|
8627
8501
|
};
|
|
8628
8502
|
bind._tries = 0;
|
|
@@ -8644,19 +8518,21 @@ var require_api_rebind = __commonJS({
|
|
|
8644
8518
|
host.logger.error("api error: " + (err ? err.message : String(err)));
|
|
8645
8519
|
});
|
|
8646
8520
|
server.listen(port, host.config.apiHost, () => {
|
|
8521
|
+
const bound = server.address();
|
|
8522
|
+
const realPort = bound && Number.isInteger(bound.port) ? bound.port : port;
|
|
8647
8523
|
host.api = server;
|
|
8648
8524
|
const prev = host.config.apiPort;
|
|
8649
|
-
if (
|
|
8650
|
-
host.config.apiPort =
|
|
8651
|
-
if (host.configPath) host.persistConfigPatch({ apiPort:
|
|
8525
|
+
if (realPort !== prev) {
|
|
8526
|
+
host.config.apiPort = realPort;
|
|
8527
|
+
if (host.configPath) host.persistConfigPatch({ apiPort: realPort });
|
|
8652
8528
|
}
|
|
8653
8529
|
try {
|
|
8654
|
-
portsShared.registerSole("supervisor-api",
|
|
8530
|
+
portsShared.registerSole("supervisor-api", realPort);
|
|
8655
8531
|
} catch (e) {
|
|
8656
8532
|
host.logger.warn("ports.registerSole(supervisor-api) \u5931\u8D25: " + e.message);
|
|
8657
8533
|
}
|
|
8658
|
-
host.events.append("api_listening", { host: host.config.apiHost, port });
|
|
8659
|
-
host.logger.info("api listening on " + host.config.apiHost + ":" +
|
|
8534
|
+
host.events.append("api_listening", { host: host.config.apiHost, port: realPort });
|
|
8535
|
+
host.logger.info("api listening on " + host.config.apiHost + ":" + realPort);
|
|
8660
8536
|
});
|
|
8661
8537
|
return server;
|
|
8662
8538
|
};
|
|
@@ -10099,14 +9975,10 @@ var require_shutdown = __commonJS({
|
|
|
10099
9975
|
host.events.append("guard_exit", {});
|
|
10100
9976
|
host.logger.info("guard shutting down");
|
|
10101
9977
|
host.writeState(true);
|
|
10102
|
-
if (host.
|
|
10103
|
-
if (host._heartbeatTimer) clearInterval(host._heartbeatTimer);
|
|
9978
|
+
if (host._beatScheduler) host._beatScheduler.stop();
|
|
10104
9979
|
if (host._killTimer) clearTimeout(host._killTimer);
|
|
10105
9980
|
if (host._adoptKillTimer) clearTimeout(host._adoptKillTimer);
|
|
10106
9981
|
abortInflightNpm(host, "guard-shutdown");
|
|
10107
|
-
if (host._initialCheckTimer) clearTimeout(host._initialCheckTimer);
|
|
10108
|
-
if (host._upgradeTimer) clearInterval(host._upgradeTimer);
|
|
10109
|
-
if (host._shellWatchdogTimer) clearInterval(host._shellWatchdogTimer);
|
|
10110
9982
|
if (host.api) {
|
|
10111
9983
|
try {
|
|
10112
9984
|
host.api.close();
|
|
@@ -10151,37 +10023,10 @@ var require_shutdown = __commonJS({
|
|
|
10151
10023
|
} catch (e) {
|
|
10152
10024
|
host.logger.warn && host.logger.warn("shutdownAll persist shellHalted: " + e.message);
|
|
10153
10025
|
}
|
|
10154
|
-
if (host._shellWatchdogTimer) {
|
|
10155
|
-
clearInterval(host._shellWatchdogTimer);
|
|
10156
|
-
host._shellWatchdogTimer = null;
|
|
10157
|
-
}
|
|
10158
|
-
if (host._heartbeatTimer) {
|
|
10159
|
-
clearInterval(host._heartbeatTimer);
|
|
10160
|
-
host._heartbeatTimer = null;
|
|
10161
|
-
}
|
|
10162
|
-
if (host._timer) {
|
|
10163
|
-
clearInterval(host._timer);
|
|
10164
|
-
host._timer = null;
|
|
10165
|
-
}
|
|
10166
|
-
if (host._initialCheckTimer) {
|
|
10167
|
-
clearTimeout(host._initialCheckTimer);
|
|
10168
|
-
host._initialCheckTimer = null;
|
|
10169
|
-
}
|
|
10170
|
-
if (host._upgradeTimer) {
|
|
10171
|
-
clearInterval(host._upgradeTimer);
|
|
10172
|
-
host._upgradeTimer = null;
|
|
10173
|
-
}
|
|
10174
|
-
if (host._killTimer) {
|
|
10175
|
-
clearTimeout(host._killTimer);
|
|
10176
|
-
host._killTimer = null;
|
|
10177
|
-
}
|
|
10178
|
-
if (host._adoptKillTimer) {
|
|
10179
|
-
clearTimeout(host._adoptKillTimer);
|
|
10180
|
-
host._adoptKillTimer = null;
|
|
10181
|
-
}
|
|
10182
10026
|
host.logger.info("[session] \u9000\u51FA\u6D41\u7A0B\u5F00\u59CB\uFF1A\u505C\u6B62\u5168\u90E8\u88AB\u7BA1\u5BF9\u8C61\u2026");
|
|
10183
10027
|
host.events && host.events.append("shutdown_all", {});
|
|
10184
10028
|
abortInflightNpm(host, "session-exit");
|
|
10029
|
+
if (host._beatScheduler) host._beatScheduler.stop();
|
|
10185
10030
|
host._stopMainDsh();
|
|
10186
10031
|
await host._stopAllSandboxes();
|
|
10187
10032
|
const stopDaemon = async (kind) => {
|
|
@@ -10417,6 +10262,12 @@ var require_instance_adapter = __commonJS({
|
|
|
10417
10262
|
} catch (e) {
|
|
10418
10263
|
d.logger() && d.logger().warn && d.logger().warn("sandbox setPhase: " + (e && e.message || e));
|
|
10419
10264
|
}
|
|
10265
|
+
try {
|
|
10266
|
+
const rc = Number(inst.state && inst.state.restartCount) || 0;
|
|
10267
|
+
if (entry.restartCount !== rc) d.managedObjects().setRestartCount(entry.id, rc);
|
|
10268
|
+
} catch (e) {
|
|
10269
|
+
d.logger() && d.logger().warn && d.logger().warn("sandbox setRestartCount: " + (e && e.message || e));
|
|
10270
|
+
}
|
|
10420
10271
|
}
|
|
10421
10272
|
}
|
|
10422
10273
|
};
|
|
@@ -10916,8 +10767,20 @@ var require_command = __commonJS({
|
|
|
10916
10767
|
"use strict";
|
|
10917
10768
|
var fs2 = require("node:fs");
|
|
10918
10769
|
var dshCli = require_dsh_cli();
|
|
10770
|
+
var execPath = require_exec_path();
|
|
10771
|
+
var policies = require_policies();
|
|
10772
|
+
function resolveBareCommand(command) {
|
|
10773
|
+
if (!Array.isArray(command) || command.length === 0) return command;
|
|
10774
|
+
const idx = command.length > 1 ? 1 : 0;
|
|
10775
|
+
const cur = command[idx];
|
|
10776
|
+
if (!policies.isBareCommand(cur)) return command;
|
|
10777
|
+
const d = execPath.resolveDsh();
|
|
10778
|
+
if (!d || !d.bin) return command;
|
|
10779
|
+
const rest = command.slice(idx + 1);
|
|
10780
|
+
return d.isJs ? [d.runtime || process.execPath, d.bin, ...rest] : [d.bin, ...rest];
|
|
10781
|
+
}
|
|
10919
10782
|
function nativeCommand(config, pluginManager) {
|
|
10920
|
-
const command = config.command || [];
|
|
10783
|
+
const command = resolveBareCommand(config.command || []);
|
|
10921
10784
|
const patchFile = pluginManager && pluginManager.overlayFile && fs2.existsSync(pluginManager.overlayFile) ? pluginManager.overlayFile : null;
|
|
10922
10785
|
const out = [];
|
|
10923
10786
|
let portSet = false;
|
|
@@ -11034,6 +10897,7 @@ var require_process2 = __commonJS({
|
|
|
11034
10897
|
var native = require_command();
|
|
11035
10898
|
var BRAND2 = require_brand();
|
|
11036
10899
|
var { findManagedDshPort, applyMainPort } = require_port_rederive();
|
|
10900
|
+
var pmClient = require_pm_client();
|
|
11037
10901
|
var DEPS = /* @__PURE__ */ new WeakMap();
|
|
11038
10902
|
var HELPERS = [
|
|
11039
10903
|
"MissingNotified",
|
|
@@ -11089,7 +10953,6 @@ var require_process2 = __commonJS({
|
|
|
11089
10953
|
const d = depsOf(this);
|
|
11090
10954
|
return native.nativeCommand(d.config(), d.pluginManager());
|
|
11091
10955
|
},
|
|
11092
|
-
// 启动窗口(毫秒):唯一的时间常量,spawn 时落成 startDeadline,窗口内退出即「启动失败」。
|
|
11093
10956
|
startWindowMs() {
|
|
11094
10957
|
const d = depsOf(this);
|
|
11095
10958
|
const secs = Number(d.config().startsecs);
|
|
@@ -11169,6 +11032,7 @@ var require_process2 = __commonJS({
|
|
|
11169
11032
|
errBuf.flush();
|
|
11170
11033
|
if (d.mChild() !== child) return;
|
|
11171
11034
|
d.events().append(BRAND2.EVENT_HARNESS_EXITED, { code, signal, phase: d.state().phase() });
|
|
11035
|
+
pmClient.recordExit("main", code, signal, d.state().phase() === "STARTING");
|
|
11172
11036
|
d.mSetChild(null);
|
|
11173
11037
|
if (d.stopping()) return;
|
|
11174
11038
|
if (d.state().desired() !== "running") return;
|
|
@@ -11178,6 +11042,7 @@ var require_process2 = __commonJS({
|
|
|
11178
11042
|
const why = code !== null ? String(code) : "sig" + signal;
|
|
11179
11043
|
const inStartup = phase === "STARTING";
|
|
11180
11044
|
if (inStartup || d.state().guardian()) {
|
|
11045
|
+
pmClient.requestRestart("main");
|
|
11181
11046
|
d.beginRestart("exit:" + why, { startupFailure: inStartup });
|
|
11182
11047
|
} else {
|
|
11183
11048
|
d.writeCrashHalted(true);
|
|
@@ -11254,8 +11119,6 @@ var require_process2 = __commonJS({
|
|
|
11254
11119
|
d.tokenService().scheduleCapture("main");
|
|
11255
11120
|
d.state().write();
|
|
11256
11121
|
},
|
|
11257
|
-
// 重启:活过 startsecs 后退出(或人工重启)⇒ 正常重启,不记启动失败;窗口内退出 ⇒ 记一次启动失败并由限流裁决。
|
|
11258
|
-
// 相位只有 STARTING / RUNNING / FAILED:重启=回到 STARTING(下一次 spawn 会开新的 startsecs 窗口)。
|
|
11259
11122
|
_beginRestart(reason, opts) {
|
|
11260
11123
|
const d = depsOf(this);
|
|
11261
11124
|
const manual = !!(opts && opts.manual);
|
|
@@ -11396,7 +11259,6 @@ var require_signals = __commonJS({
|
|
|
11396
11259
|
return null;
|
|
11397
11260
|
}
|
|
11398
11261
|
},
|
|
11399
|
-
// 归属凭据:spawn 与 adopt 两条取得所有权的路线都要写;落盘走 writeAtomic + 0600。
|
|
11400
11262
|
_writeMainOwner(dshPid, port) {
|
|
11401
11263
|
const d = depsOf(this);
|
|
11402
11264
|
try {
|
|
@@ -11452,7 +11314,6 @@ var require_signals = __commonJS({
|
|
|
11452
11314
|
}
|
|
11453
11315
|
}, d.config().stopGraceMs));
|
|
11454
11316
|
},
|
|
11455
|
-
// 代际 gen 保护共享的 _adoptKillTimer 槽位:定时器只在「本代仍是当前代」时置空。
|
|
11456
11317
|
_killAdopted(pid) {
|
|
11457
11318
|
const d = depsOf(this);
|
|
11458
11319
|
const gen = (d.readAdoptKillGen() || 0) + 1;
|
|
@@ -11517,7 +11378,35 @@ var require_guardian = __commonJS({
|
|
|
11517
11378
|
}
|
|
11518
11379
|
return { start, count, tripped: count >= burst };
|
|
11519
11380
|
}
|
|
11520
|
-
|
|
11381
|
+
function makeBudget(cfg) {
|
|
11382
|
+
const windowMs = cfg && Number(cfg.windowMs) > 0 ? Number(cfg.windowMs) : 6e4;
|
|
11383
|
+
const burst = cfg && Number(cfg.burst) >= 1 ? Number(cfg.burst) : 5;
|
|
11384
|
+
let state = { start: null, count: 0 };
|
|
11385
|
+
const self = {
|
|
11386
|
+
windowMs,
|
|
11387
|
+
burst,
|
|
11388
|
+
get count() {
|
|
11389
|
+
return state.count;
|
|
11390
|
+
},
|
|
11391
|
+
get tripped() {
|
|
11392
|
+
return state.count >= burst;
|
|
11393
|
+
},
|
|
11394
|
+
note(startupFailure) {
|
|
11395
|
+
if (startupFailure === false || startupFailure == null) {
|
|
11396
|
+
return { tripped: false, count: state.count, halted: false };
|
|
11397
|
+
}
|
|
11398
|
+
const dec = bumpStartupFailure(state, Date.now(), { windowMs, burst });
|
|
11399
|
+
state.start = dec.start;
|
|
11400
|
+
state.count = dec.count;
|
|
11401
|
+
return { tripped: dec.tripped, count: state.count, halted: dec.tripped };
|
|
11402
|
+
},
|
|
11403
|
+
reset() {
|
|
11404
|
+
state = { start: null, count: 0 };
|
|
11405
|
+
}
|
|
11406
|
+
};
|
|
11407
|
+
return self;
|
|
11408
|
+
}
|
|
11409
|
+
module2.exports = { shouldGuard, bumpStartupFailure, makeBudget };
|
|
11521
11410
|
}
|
|
11522
11411
|
});
|
|
11523
11412
|
|
|
@@ -11526,6 +11415,7 @@ var require_startup_throttle = __commonJS({
|
|
|
11526
11415
|
"src/app/main/startup-throttle.js"(exports2, module2) {
|
|
11527
11416
|
"use strict";
|
|
11528
11417
|
var guardian = require_guardian();
|
|
11418
|
+
var pmClient = require_pm_client();
|
|
11529
11419
|
var DEPS = /* @__PURE__ */ new WeakMap();
|
|
11530
11420
|
function depsOf(host) {
|
|
11531
11421
|
let d = DEPS.get(host);
|
|
@@ -11565,8 +11455,6 @@ var require_startup_throttle = __commonJS({
|
|
|
11565
11455
|
}
|
|
11566
11456
|
module2.exports = {
|
|
11567
11457
|
methods: {
|
|
11568
|
-
// 唯一一条限流:startupFailWindowMs 内「启动窗口内退出」达 startupFailBurst 次 ⇒ phase=FAILED。
|
|
11569
|
-
// 到点即停自动重启:不排队、不退避、不指数等待;恢复的唯一入口是人工重试(_retryStartupFailure)。
|
|
11570
11458
|
_noteStartupFailure() {
|
|
11571
11459
|
const d = depsOf(this);
|
|
11572
11460
|
const windowMs = d.config().startupFailWindowMs || 6e4;
|
|
@@ -11591,11 +11479,11 @@ var require_startup_throttle = __commonJS({
|
|
|
11591
11479
|
);
|
|
11592
11480
|
return { failed: true, count: dec.count };
|
|
11593
11481
|
},
|
|
11594
|
-
// 手动重试入口:清计数后回到 STARTING(随后由 STARTING 分支重新 spawn,新的 startsecs 窗口)。
|
|
11595
11482
|
_retryStartupFailure() {
|
|
11596
11483
|
const d = depsOf(this);
|
|
11597
11484
|
d.mSetStartupFailWindowStart(null);
|
|
11598
11485
|
d.mSetStartupFailCount(0);
|
|
11486
|
+
pmClient.resetBackoff("main");
|
|
11599
11487
|
d.events().append("startup_retry", {});
|
|
11600
11488
|
d.logger().warn("\u542F\u52A8\u5931\u8D25\u8BA1\u6570\u5DF2\u6E05\u96F6\uFF1A\u4EBA\u5DE5\u91CD\u8BD5\uFF0C\u56DE\u5230 STARTING");
|
|
11601
11489
|
return { ok: true };
|
|
@@ -12145,8 +12033,6 @@ var require_runtime2 = __commonJS({
|
|
|
12145
12033
|
spawnEnv: () => ({ DSH_SUPERVISOR_CONFIG: cfgPath }),
|
|
12146
12034
|
logger: d.logger(),
|
|
12147
12035
|
events: d.events(),
|
|
12148
|
-
// `this` 是宿主(本方法经 host._daemonLifecycle(kind) 调用);箭头函数捕获它。
|
|
12149
|
-
// 此前写作 host._exitIntended(),而 host 只存在于 depsOf(host) 形参作用域 ⇒ 延迟回调求值时 ReferenceError。
|
|
12150
12036
|
exitIntended: () => this._exitIntended()
|
|
12151
12037
|
});
|
|
12152
12038
|
return lc[kind];
|
|
@@ -13014,7 +12900,7 @@ var require_credential = __commonJS({
|
|
|
13014
12900
|
});
|
|
13015
12901
|
|
|
13016
12902
|
// src/domains/relay/core.js
|
|
13017
|
-
var
|
|
12903
|
+
var require_core3 = __commonJS({
|
|
13018
12904
|
"src/domains/relay/core.js"(exports2, module2) {
|
|
13019
12905
|
"use strict";
|
|
13020
12906
|
var crypto = require("node:crypto");
|
|
@@ -13042,14 +12928,52 @@ var require_core4 = __commonJS({
|
|
|
13042
12928
|
}
|
|
13043
12929
|
return null;
|
|
13044
12930
|
}
|
|
13045
|
-
function
|
|
13046
|
-
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
|
|
13051
|
-
|
|
12931
|
+
function stripGateTokenAndPreserve(rawUrl) {
|
|
12932
|
+
if (!rawUrl) return "/";
|
|
12933
|
+
let url = rawUrl;
|
|
12934
|
+
const hashIdx = url.indexOf("#");
|
|
12935
|
+
if (hashIdx >= 0) url = url.slice(0, hashIdx);
|
|
12936
|
+
const qIdx = url.indexOf("?");
|
|
12937
|
+
const path2 = qIdx >= 0 ? url.slice(0, qIdx) : url;
|
|
12938
|
+
if (qIdx < 0) return path2 || "/";
|
|
12939
|
+
const query = url.slice(qIdx + 1);
|
|
12940
|
+
if (!query) return path2 || "/";
|
|
12941
|
+
const kept = [];
|
|
12942
|
+
for (const pair of query.split("&")) {
|
|
12943
|
+
if (!pair) {
|
|
12944
|
+
kept.push(pair);
|
|
12945
|
+
continue;
|
|
12946
|
+
}
|
|
12947
|
+
const eq = pair.indexOf("=");
|
|
12948
|
+
const rawKey = eq >= 0 ? pair.slice(0, eq) : pair;
|
|
12949
|
+
let key = rawKey;
|
|
12950
|
+
try {
|
|
12951
|
+
key = decodeURIComponent(rawKey);
|
|
12952
|
+
} catch {
|
|
12953
|
+
}
|
|
12954
|
+
if (key === "token") continue;
|
|
12955
|
+
kept.push(pair);
|
|
13052
12956
|
}
|
|
12957
|
+
const out = path2 || "/";
|
|
12958
|
+
return kept.length ? out + "?" + kept.join("&") : out;
|
|
12959
|
+
}
|
|
12960
|
+
function upstreamPath(rawUrl) {
|
|
12961
|
+
return stripGateTokenAndPreserve(rawUrl);
|
|
12962
|
+
}
|
|
12963
|
+
var POLYFILL_SCRIPT = `<script>
|
|
12964
|
+
if (typeof crypto.randomUUID !== 'function') {
|
|
12965
|
+
crypto.randomUUID = function () {
|
|
12966
|
+
var b = crypto.getRandomValues(new Uint8Array(16));
|
|
12967
|
+
b[6] = (b[6] & 0x0f) | 0x40;
|
|
12968
|
+
b[8] = (b[8] & 0x3f) | 0x80;
|
|
12969
|
+
var h = '';
|
|
12970
|
+
for (var i = 0; i < 16; i++) h += (i === 4 || i === 6 || i === 8 || i === 12 ? '-' : '') + ('0' + b[i].toString(16)).slice(-2);
|
|
12971
|
+
return h;
|
|
12972
|
+
};
|
|
12973
|
+
}
|
|
12974
|
+
</script>`;
|
|
12975
|
+
function redactLogPath(rawUrl) {
|
|
12976
|
+
return rawUrl ? stripGateTokenAndPreserve(rawUrl) : "";
|
|
13053
12977
|
}
|
|
13054
12978
|
function lanGateCookieValue(token, salt) {
|
|
13055
12979
|
const t = String(token == null ? "" : token);
|
|
@@ -13057,23 +12981,6 @@ var require_core4 = __commonJS({
|
|
|
13057
12981
|
if (!t || !s) return "";
|
|
13058
12982
|
return crypto.createHash("sha256").update(s + "\n" + t).digest("hex");
|
|
13059
12983
|
}
|
|
13060
|
-
function hasValidToken(req, token, salt, mode) {
|
|
13061
|
-
if (!token) return normalizeRemoteMode(mode) === "lan";
|
|
13062
|
-
const url = new URL(req.url, "http://localhost");
|
|
13063
|
-
const queryToken = url.searchParams.get("token");
|
|
13064
|
-
if (queryToken && safeEqual(queryToken, token)) return true;
|
|
13065
|
-
const cookies = req.headers.cookie || "";
|
|
13066
|
-
const m = LAN_COOKIE_RE.exec(cookies);
|
|
13067
|
-
if (m) {
|
|
13068
|
-
try {
|
|
13069
|
-
const want = lanGateCookieValue(token, salt);
|
|
13070
|
-
return !!want && safeEqual(decodeURIComponent(m[1]), want);
|
|
13071
|
-
} catch {
|
|
13072
|
-
return false;
|
|
13073
|
-
}
|
|
13074
|
-
}
|
|
13075
|
-
return false;
|
|
13076
|
-
}
|
|
13077
12984
|
function tokenGateDecision(req, token, salt, mode) {
|
|
13078
12985
|
if (!token) return normalizeRemoteMode(mode) === "lan" ? { ok: true } : { ok: false, unauthorized: true };
|
|
13079
12986
|
const url = new URL(req.url, "http://localhost");
|
|
@@ -13096,27 +13003,22 @@ var require_core4 = __commonJS({
|
|
|
13096
13003
|
}
|
|
13097
13004
|
return { ok: false, unauthorized: true };
|
|
13098
13005
|
}
|
|
13099
|
-
|
|
13100
|
-
if (
|
|
13101
|
-
|
|
13102
|
-
|
|
13103
|
-
|
|
13104
|
-
|
|
13105
|
-
|
|
13106
|
-
|
|
13107
|
-
|
|
13108
|
-
|
|
13109
|
-
|
|
13110
|
-
|
|
13111
|
-
|
|
13112
|
-
|
|
13113
|
-
try {
|
|
13114
|
-
const u = new URL(rawUrl, "http://127.0.0.1");
|
|
13115
|
-
if (u.searchParams.has("token")) u.searchParams.delete("token");
|
|
13116
|
-
return u.pathname + (u.searchParams.toString() ? "?" + u.searchParams.toString() : "");
|
|
13117
|
-
} catch {
|
|
13118
|
-
return String(rawUrl || "").replace(/[?&]token=[^&]*/, "");
|
|
13006
|
+
function hasValidToken(req, token, salt, mode) {
|
|
13007
|
+
if (!token) return normalizeRemoteMode(mode) === "lan";
|
|
13008
|
+
const url = new URL(req.url, "http://localhost");
|
|
13009
|
+
const queryToken = url.searchParams.get("token");
|
|
13010
|
+
if (queryToken && safeEqual(queryToken, token)) return true;
|
|
13011
|
+
const cookies = req.headers.cookie || "";
|
|
13012
|
+
const m = LAN_COOKIE_RE.exec(cookies);
|
|
13013
|
+
if (m) {
|
|
13014
|
+
try {
|
|
13015
|
+
const want = lanGateCookieValue(token, salt);
|
|
13016
|
+
return !!want && safeEqual(decodeURIComponent(m[1]), want);
|
|
13017
|
+
} catch {
|
|
13018
|
+
return false;
|
|
13019
|
+
}
|
|
13119
13020
|
}
|
|
13021
|
+
return false;
|
|
13120
13022
|
}
|
|
13121
13023
|
function buildFrpcToml(settings, instances) {
|
|
13122
13024
|
const s = settings || {};
|
|
@@ -13147,8 +13049,6 @@ if (typeof crypto.randomUUID !== 'function') {
|
|
|
13147
13049
|
return {
|
|
13148
13050
|
serverAddr: String(j.serverAddr !== void 0 ? j.serverAddr : cur.serverAddr).trim(),
|
|
13149
13051
|
serverPort: Number(j.serverPort) || cur.serverPort,
|
|
13150
|
-
// authToken:null/undefined 归一为空串(frpc 遇空串不写 auth.token,避免 String(null)==="null" 被当成共享密钥);
|
|
13151
|
-
// 非空串统一 trim,与 serverAddr 同口径。
|
|
13152
13052
|
authToken: j.authToken === void 0 ? cur.authToken : j.authToken == null ? "" : String(j.authToken).trim(),
|
|
13153
13053
|
user: String(j.user || cur.user || "dsh")
|
|
13154
13054
|
};
|
|
@@ -13231,7 +13131,7 @@ if (typeof crypto.randomUUID !== 'function') {
|
|
|
13231
13131
|
var require_lan2 = __commonJS({
|
|
13232
13132
|
"src/app/domain-actions/lan.js"(exports2, module2) {
|
|
13233
13133
|
"use strict";
|
|
13234
|
-
var { validateWanAccess, generateRemoteToken } =
|
|
13134
|
+
var { validateWanAccess, generateRemoteToken } = require_core3();
|
|
13235
13135
|
var { remoteTokenStrength } = require_credential();
|
|
13236
13136
|
var BRAND2 = require_brand();
|
|
13237
13137
|
function lanModule(deps) {
|
|
@@ -13598,13 +13498,6 @@ var require_env = __commonJS({
|
|
|
13598
13498
|
} catch {
|
|
13599
13499
|
return null;
|
|
13600
13500
|
}
|
|
13601
|
-
})(),
|
|
13602
|
-
shellWatchdog: (() => {
|
|
13603
|
-
try {
|
|
13604
|
-
return this.shellWatchdog && typeof this.shellWatchdog.status === "function" ? this.shellWatchdog.status() : null;
|
|
13605
|
-
} catch {
|
|
13606
|
-
return null;
|
|
13607
|
-
}
|
|
13608
13501
|
})()
|
|
13609
13502
|
};
|
|
13610
13503
|
},
|
|
@@ -13819,7 +13712,6 @@ var require_versions = __commonJS({
|
|
|
13819
13712
|
}
|
|
13820
13713
|
return dir;
|
|
13821
13714
|
},
|
|
13822
|
-
// 同步 spawn 会冻结事件循环,消费方含 HTTP 路径,故 git 子进程异步执行。
|
|
13823
13715
|
async guardVersionLocal() {
|
|
13824
13716
|
const d = depsOf(this);
|
|
13825
13717
|
const root = d.vcsRoot();
|
|
@@ -13876,7 +13768,6 @@ var require_access = __commonJS({
|
|
|
13876
13768
|
const cfg = this.config || {};
|
|
13877
13769
|
return { configured: !!cfg.apiAccessKey, host: cfg.apiHost || void 0 };
|
|
13878
13770
|
},
|
|
13879
|
-
// 清空密钥必须同时回关 LAN(apiHost→127.0.0.1):只清 key 不动 apiHost 会留下「绑定 0.0.0.0 且零认证」的暴露窗口。
|
|
13880
13771
|
setAccessKey(key) {
|
|
13881
13772
|
try {
|
|
13882
13773
|
const cfg = this.config || {};
|
|
@@ -14787,7 +14678,6 @@ var require_pool2 = __commonJS({
|
|
|
14787
14678
|
this._backfillAt.delete(id);
|
|
14788
14679
|
this.clear(id);
|
|
14789
14680
|
}
|
|
14790
|
-
// journalctl 同步查询会冻结生命周期 tick 的事件循环,故 journal 档非阻塞发射(见 capture.js)。
|
|
14791
14681
|
capture(id) {
|
|
14792
14682
|
const src = this._sources.get(id);
|
|
14793
14683
|
if (!src) return null;
|
|
@@ -15104,6 +14994,35 @@ var require_npm = __commonJS({
|
|
|
15104
14994
|
}
|
|
15105
14995
|
});
|
|
15106
14996
|
|
|
14997
|
+
// src/domains/shell/core.js
|
|
14998
|
+
var require_core4 = __commonJS({
|
|
14999
|
+
"src/domains/shell/core.js"(exports2, module2) {
|
|
15000
|
+
"use strict";
|
|
15001
|
+
function isUpdatePhase(phase) {
|
|
15002
|
+
const p = String(phase || "");
|
|
15003
|
+
return p === "restarting" || p.indexOf("shell-update") === 0;
|
|
15004
|
+
}
|
|
15005
|
+
function deriveState(id, journal) {
|
|
15006
|
+
const j = journal || {};
|
|
15007
|
+
if (!j.to) return { state: "idle", reason: "\u65E0\u8FDB\u884C\u4E2D\u7684\u66F4\u65B0", journal: j, identity: id };
|
|
15008
|
+
const cur = id && id.version ? String(id.version) : null;
|
|
15009
|
+
if (cur && cur === j.to && id && id.phase === "ready") {
|
|
15010
|
+
const next = j.confirmed === true ? j : Object.assign({}, j, { confirmed: true });
|
|
15011
|
+
return { state: "confirmed", version: cur, reason: "\u58F3\u5DF2\u5065\u5EB7\u8FD0\u884C\u65B0\u7248\u672C", journal: next, identity: id };
|
|
15012
|
+
}
|
|
15013
|
+
return {
|
|
15014
|
+
state: "pending",
|
|
15015
|
+
target: j.to,
|
|
15016
|
+
current: cur,
|
|
15017
|
+
reason: cur === j.to ? "\u7B49\u5F85\u58F3\u4E0A\u62A5\u5C31\u7EEA" : "\u7B49\u5F85\u58F3\u91CD\u542F\u5230\u65B0\u7248\u672C",
|
|
15018
|
+
journal: j,
|
|
15019
|
+
identity: id
|
|
15020
|
+
};
|
|
15021
|
+
}
|
|
15022
|
+
module2.exports = { isUpdatePhase, deriveState };
|
|
15023
|
+
}
|
|
15024
|
+
});
|
|
15025
|
+
|
|
15107
15026
|
// src/domains/shell/journal.js
|
|
15108
15027
|
var require_journal = __commonJS({
|
|
15109
15028
|
"src/domains/shell/journal.js"(exports2, module2) {
|
|
@@ -15112,7 +15031,7 @@ var require_journal = __commonJS({
|
|
|
15112
15031
|
var fs2 = require("node:fs");
|
|
15113
15032
|
var path2 = require("node:path");
|
|
15114
15033
|
var { writeAtomic } = require_fs();
|
|
15115
|
-
var { deriveState } =
|
|
15034
|
+
var { deriveState } = require_core4();
|
|
15116
15035
|
function shellDir() {
|
|
15117
15036
|
return stateRoot2.shellDir();
|
|
15118
15037
|
}
|
|
@@ -15191,116 +15110,6 @@ var require_journal = __commonJS({
|
|
|
15191
15110
|
}
|
|
15192
15111
|
});
|
|
15193
15112
|
|
|
15194
|
-
// src/domains/shell/restart.js
|
|
15195
|
-
var require_restart = __commonJS({
|
|
15196
|
-
"src/domains/shell/restart.js"(exports2, module2) {
|
|
15197
|
-
"use strict";
|
|
15198
|
-
var spawnOS = require_spawn();
|
|
15199
|
-
var pidlook = require_pidlookup();
|
|
15200
|
-
var BRAND2 = require_brand();
|
|
15201
|
-
var { identity } = require_journal();
|
|
15202
|
-
var { exeFromCmdline, isShellProcess } = require_core3();
|
|
15203
|
-
var { semverCompare } = require_version2();
|
|
15204
|
-
var SHELL_RELEASE_PKG = "@lob-ox/shell-release";
|
|
15205
|
-
async function checkUpdate(dist, opts) {
|
|
15206
|
-
const id = identity();
|
|
15207
|
-
const installed = id && id.version ? String(id.version) : null;
|
|
15208
|
-
if (!dist || typeof dist.fetchLatestVersion !== "function") {
|
|
15209
|
-
return { ok: false, installed, latest: null, updateAvailable: false, error: "\u5206\u53D1\u670D\u52A1\u672A\u521D\u59CB\u5316" };
|
|
15210
|
-
}
|
|
15211
|
-
try {
|
|
15212
|
-
const latest = await dist.fetchLatestVersion(SHELL_RELEASE_PKG, "npm", { authoritative: (opts && opts.authoritative) === true });
|
|
15213
|
-
if (!latest) {
|
|
15214
|
-
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" };
|
|
15215
|
-
}
|
|
15216
|
-
const updateAvailable = Boolean(installed && semverCompare(latest, installed) > 0);
|
|
15217
|
-
return { ok: true, installed, latest, updateAvailable };
|
|
15218
|
-
} catch (e) {
|
|
15219
|
-
return { ok: false, installed, latest: null, updateAvailable: false, error: e && e.message || String(e) };
|
|
15220
|
-
}
|
|
15221
|
-
}
|
|
15222
|
-
async function restartShell(opts) {
|
|
15223
|
-
const o = opts || {};
|
|
15224
|
-
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
15225
|
-
const pattern = o.procPattern || BRAND2.PROC_MATCH_GUI;
|
|
15226
|
-
let procs = [];
|
|
15227
|
-
try {
|
|
15228
|
-
procs = pidlook.pgrepList(pattern) || [];
|
|
15229
|
-
} catch {
|
|
15230
|
-
procs = [];
|
|
15231
|
-
}
|
|
15232
|
-
procs = procs.filter((p) => isShellProcess(p));
|
|
15233
|
-
const exe = procs.length ? exeFromCmdline(procs[0].cmdline) : o.exePath || null;
|
|
15234
|
-
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" };
|
|
15235
|
-
const killed = [];
|
|
15236
|
-
for (const p of procs) {
|
|
15237
|
-
try {
|
|
15238
|
-
process.kill(p.pid, "SIGTERM");
|
|
15239
|
-
killed.push(p.pid);
|
|
15240
|
-
} catch {
|
|
15241
|
-
}
|
|
15242
|
-
}
|
|
15243
|
-
const waitGone = async (ms) => {
|
|
15244
|
-
const deadline = Date.now() + ms;
|
|
15245
|
-
while (Date.now() < deadline) {
|
|
15246
|
-
const alive = procs.some((p) => {
|
|
15247
|
-
try {
|
|
15248
|
-
return pidlook.isAlive(p.pid);
|
|
15249
|
-
} catch {
|
|
15250
|
-
return false;
|
|
15251
|
-
}
|
|
15252
|
-
});
|
|
15253
|
-
if (!alive) return true;
|
|
15254
|
-
await sleep(200);
|
|
15255
|
-
}
|
|
15256
|
-
return !procs.some((p) => {
|
|
15257
|
-
try {
|
|
15258
|
-
return pidlook.isAlive(p.pid);
|
|
15259
|
-
} catch {
|
|
15260
|
-
return false;
|
|
15261
|
-
}
|
|
15262
|
-
});
|
|
15263
|
-
};
|
|
15264
|
-
let gone = await waitGone(o.graceMs || 6e3);
|
|
15265
|
-
if (!gone) {
|
|
15266
|
-
for (const p of procs) {
|
|
15267
|
-
try {
|
|
15268
|
-
process.kill(p.pid, "SIGKILL");
|
|
15269
|
-
} catch {
|
|
15270
|
-
}
|
|
15271
|
-
}
|
|
15272
|
-
gone = await waitGone(2e3);
|
|
15273
|
-
}
|
|
15274
|
-
if (!gone) {
|
|
15275
|
-
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 };
|
|
15276
|
-
}
|
|
15277
|
-
if (typeof o.shouldAbort === "function") {
|
|
15278
|
-
try {
|
|
15279
|
-
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 };
|
|
15280
|
-
} catch {
|
|
15281
|
-
}
|
|
15282
|
-
}
|
|
15283
|
-
try {
|
|
15284
|
-
const child = spawnOS.detachedIgnored(exe, [], { env: process.env });
|
|
15285
|
-
child.on("error", (e) => {
|
|
15286
|
-
try {
|
|
15287
|
-
if (o.events && o.events.append) o.events.append("shell_restart_spawn_error", { exe, error: e && e.message || String(e) });
|
|
15288
|
-
} catch {
|
|
15289
|
-
}
|
|
15290
|
-
});
|
|
15291
|
-
child.unref();
|
|
15292
|
-
if (!child.pid) {
|
|
15293
|
-
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 };
|
|
15294
|
-
}
|
|
15295
|
-
return { ok: true, restarted: true, killed, pid: child.pid, exe };
|
|
15296
|
-
} catch (e) {
|
|
15297
|
-
return { ok: false, error: "\u62C9\u8D77\u65B0\u58F3\u5931\u8D25: " + (e && e.message || e), killed };
|
|
15298
|
-
}
|
|
15299
|
-
}
|
|
15300
|
-
module2.exports = { SHELL_RELEASE_PKG, checkUpdate, restartShell };
|
|
15301
|
-
}
|
|
15302
|
-
});
|
|
15303
|
-
|
|
15304
15113
|
// src/domains/shell/index.js
|
|
15305
15114
|
var require_shell = __commonJS({
|
|
15306
15115
|
"src/domains/shell/index.js"(exports2, module2) {
|
|
@@ -15314,8 +15123,7 @@ var require_shell = __commonJS({
|
|
|
15314
15123
|
health,
|
|
15315
15124
|
status
|
|
15316
15125
|
} = require_journal();
|
|
15317
|
-
|
|
15318
|
-
module2.exports = { status, evaluate, health, markPending, identity, readJournal, shellDir, checkUpdate, restartShell, SHELL_RELEASE_PKG };
|
|
15126
|
+
module2.exports = { status, evaluate, health, markPending, identity, readJournal, shellDir };
|
|
15319
15127
|
}
|
|
15320
15128
|
});
|
|
15321
15129
|
|
|
@@ -15618,8 +15426,6 @@ var require_intents = __commonJS({
|
|
|
15618
15426
|
if (this._pending.has(intent)) this._pending.delete(intent);
|
|
15619
15427
|
return p;
|
|
15620
15428
|
}
|
|
15621
|
-
// W5:生产零调用,仅 session-lifecycle-test.js 用于「模拟重启后内存态为空」的夹具。
|
|
15622
|
-
// 保留(它是一个合理的测试缝),不视为待删死代码。
|
|
15623
15429
|
clear() {
|
|
15624
15430
|
this._pending.clear();
|
|
15625
15431
|
}
|
|
@@ -15806,7 +15612,6 @@ var require_core5 = __commonJS({
|
|
|
15806
15612
|
routerAutostart: s.routerAutostart,
|
|
15807
15613
|
routerMode: s.routerMode,
|
|
15808
15614
|
updateCheck: s.updateCheck,
|
|
15809
|
-
shellWatchdog: s.shellWatchdog,
|
|
15810
15615
|
lastRefresh: s.lastRefresh
|
|
15811
15616
|
};
|
|
15812
15617
|
}
|
|
@@ -15864,12 +15669,10 @@ var require_core5 = __commonJS({
|
|
|
15864
15669
|
host._upgradeHold = false;
|
|
15865
15670
|
host._upgradeHoldSince = null;
|
|
15866
15671
|
host._timer = null;
|
|
15672
|
+
host._beatScheduler = null;
|
|
15867
15673
|
host._heartbeatBusy = false;
|
|
15868
15674
|
host._killTimer = null;
|
|
15869
15675
|
host._adoptKillTimer = null;
|
|
15870
|
-
host._initialCheckTimer = null;
|
|
15871
|
-
host._upgradeTimer = null;
|
|
15872
|
-
host._shellWatchdogTimer = null;
|
|
15873
15676
|
host._lastOccupiedWarn = 0;
|
|
15874
15677
|
host._lastMainPortRederive = 0;
|
|
15875
15678
|
host._lastPortUp = false;
|
|
@@ -17127,11 +16930,21 @@ var require_instance_lifecycle = __commonJS({
|
|
|
17127
16930
|
});
|
|
17128
16931
|
|
|
17129
16932
|
// src/domains/router/providers/restart.js
|
|
17130
|
-
var
|
|
16933
|
+
var require_restart = __commonJS({
|
|
17131
16934
|
"src/domains/router/providers/restart.js"(exports2, module2) {
|
|
17132
16935
|
"use strict";
|
|
17133
16936
|
var { INSTANCE_STATES } = require_model2();
|
|
17134
16937
|
var ports = require_ports().shared;
|
|
16938
|
+
var { makeBudget } = require_guardian();
|
|
16939
|
+
var PROXY_INSTANCE_THROTTLE = { windowMs: 10 * 60 * 1e3, burst: 5 };
|
|
16940
|
+
function budgetFor(inst) {
|
|
16941
|
+
if (!inst) return makeBudget(PROXY_INSTANCE_THROTTLE);
|
|
16942
|
+
if (!inst._restartBudget) inst._restartBudget = makeBudget(PROXY_INSTANCE_THROTTLE);
|
|
16943
|
+
return inst._restartBudget;
|
|
16944
|
+
}
|
|
16945
|
+
function resetBudget(inst) {
|
|
16946
|
+
if (inst) inst._restartBudget = makeBudget(PROXY_INSTANCE_THROTTLE);
|
|
16947
|
+
}
|
|
17135
16948
|
function createRestartOrchestrator(deps) {
|
|
17136
16949
|
const d = deps || {};
|
|
17137
16950
|
const { startInstance, waitHealthy, isAlive, logger } = d;
|
|
@@ -17165,8 +16978,8 @@ var require_restart2 = __commonJS({
|
|
|
17165
16978
|
}
|
|
17166
16979
|
return { respawn };
|
|
17167
16980
|
}
|
|
17168
|
-
async function
|
|
17169
|
-
const out = { started: [], stopped: [], desired: [] };
|
|
16981
|
+
async function runReconcileThrottled(provider, allowStop) {
|
|
16982
|
+
const out = { started: [], stopped: [], desired: [], throttled: [] };
|
|
17170
16983
|
const desired = provider.desiredRunningAccounts();
|
|
17171
16984
|
const list = desired.list || [];
|
|
17172
16985
|
out.desired = list.map((a) => a.keyId);
|
|
@@ -17175,12 +16988,25 @@ var require_restart2 = __commonJS({
|
|
|
17175
16988
|
const inst = provider.instanceOf(acc);
|
|
17176
16989
|
if (!inst || inst.pid || inst.startingPromise) continue;
|
|
17177
16990
|
if (inst.status === INSTANCE_STATES.DEAD && !inst.pid) inst.status = INSTANCE_STATES.COLD;
|
|
16991
|
+
const b = budgetFor(inst);
|
|
16992
|
+
if (b.tripped) {
|
|
16993
|
+
inst._throttled = true;
|
|
16994
|
+
out.throttled.push(acc.keyId);
|
|
16995
|
+
continue;
|
|
16996
|
+
}
|
|
16997
|
+
inst._throttled = false;
|
|
16998
|
+
const wasRunning = !!inst.pid;
|
|
17178
16999
|
try {
|
|
17179
17000
|
const r = await provider.startInstance(inst);
|
|
17001
|
+
const startupFailure = !r.ok || !wasRunning && !inst.pid;
|
|
17002
|
+
b.note(startupFailure);
|
|
17180
17003
|
if (r && r.ok) {
|
|
17181
17004
|
await provider._waitHealthy(inst).catch(() => {
|
|
17182
17005
|
});
|
|
17183
17006
|
out.started.push(acc.keyId);
|
|
17007
|
+
if (b.tripped && provider.logger && provider.logger.warn) {
|
|
17008
|
+
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");
|
|
17009
|
+
}
|
|
17184
17010
|
if (provider.logger && provider.logger.info) {
|
|
17185
17011
|
const role = desired.active && acc.keyId === desired.active.keyId ? "\u5728\u7528" : "\u9884\u70ED";
|
|
17186
17012
|
provider.logger.info("[reconcile] \u62C9\u8D77\u5B9E\u4F8B key=" + acc.maskedKey + "\uFF08" + role + "\uFF09");
|
|
@@ -17189,8 +17015,8 @@ var require_restart2 = __commonJS({
|
|
|
17189
17015
|
} catch {
|
|
17190
17016
|
}
|
|
17191
17017
|
}
|
|
17192
|
-
if (!allowStop) return out;
|
|
17193
17018
|
for (const inst of (provider.instances || []).slice()) {
|
|
17019
|
+
if (!allowStop) break;
|
|
17194
17020
|
if (!inst.pid) {
|
|
17195
17021
|
if (!desiredIds.has(inst.keyId) && inst.port) {
|
|
17196
17022
|
try {
|
|
@@ -17235,7 +17061,7 @@ var require_restart2 = __commonJS({
|
|
|
17235
17061
|
}
|
|
17236
17062
|
}
|
|
17237
17063
|
if (provider._reconcileBusy) return provider._reconcileBusy;
|
|
17238
|
-
const p =
|
|
17064
|
+
const p = runReconcileThrottled(provider, allowStop);
|
|
17239
17065
|
provider._reconcileBusy = p;
|
|
17240
17066
|
try {
|
|
17241
17067
|
return await p;
|
|
@@ -17248,7 +17074,60 @@ var require_restart2 = __commonJS({
|
|
|
17248
17074
|
reconcileInstances(provider).catch(() => {
|
|
17249
17075
|
});
|
|
17250
17076
|
}
|
|
17251
|
-
module2.exports = { createRestartOrchestrator,
|
|
17077
|
+
module2.exports = { createRestartOrchestrator, runReconcileThrottled, reconcileInstances, reconcileNow, budgetFor, resetBudget, PROXY_INSTANCE_THROTTLE };
|
|
17078
|
+
}
|
|
17079
|
+
});
|
|
17080
|
+
|
|
17081
|
+
// src/app/control/process-lifecycle.js
|
|
17082
|
+
var require_process_lifecycle = __commonJS({
|
|
17083
|
+
"src/app/control/process-lifecycle.js"(exports2, module2) {
|
|
17084
|
+
"use strict";
|
|
17085
|
+
var procOS = require_process();
|
|
17086
|
+
var pidlook = require_pidlookup();
|
|
17087
|
+
var DEFAULTS = {
|
|
17088
|
+
stopGraceMs: 9e3,
|
|
17089
|
+
portFreeTimeoutMs: 5e3
|
|
17090
|
+
};
|
|
17091
|
+
function sleep(ms) {
|
|
17092
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
17093
|
+
}
|
|
17094
|
+
function isForeignOnPort(port, ownPid) {
|
|
17095
|
+
if (!Number.isInteger(port) || port <= 0) return false;
|
|
17096
|
+
const p = pidlook.findListeningPid(port);
|
|
17097
|
+
return p !== null && p !== ownPid;
|
|
17098
|
+
}
|
|
17099
|
+
async function waitPortFree(port, timeoutMs) {
|
|
17100
|
+
const dl = Date.now() + (timeoutMs || DEFAULTS.portFreeTimeoutMs);
|
|
17101
|
+
while (Date.now() < dl) {
|
|
17102
|
+
if (pidlook.findListeningPid(port) === null) return true;
|
|
17103
|
+
await sleep(150);
|
|
17104
|
+
}
|
|
17105
|
+
return pidlook.findListeningPid(port) === null;
|
|
17106
|
+
}
|
|
17107
|
+
async function stopProcess(opts) {
|
|
17108
|
+
const o = Object.assign({}, DEFAULTS, opts || {});
|
|
17109
|
+
const pid = typeof o.pid === "number" ? o.pid : null;
|
|
17110
|
+
const port = typeof o.port === "number" ? o.port : null;
|
|
17111
|
+
const ownGroup = !!o.ownGroup;
|
|
17112
|
+
if (pid && pid > 0) {
|
|
17113
|
+
procOS.killTree(pid, "SIGTERM", void 0, ownGroup ? { ownGroup: true } : void 0);
|
|
17114
|
+
}
|
|
17115
|
+
const dl = Date.now() + o.stopGraceMs;
|
|
17116
|
+
while (Date.now() < dl) {
|
|
17117
|
+
const alive = pid ? pidlook.isAlive ? pidlook.isAlive(pid) : false : false;
|
|
17118
|
+
if (!alive) break;
|
|
17119
|
+
await sleep(150);
|
|
17120
|
+
}
|
|
17121
|
+
if (port) {
|
|
17122
|
+
if (isForeignOnPort(port, pid)) {
|
|
17123
|
+
return { ok: false, stopped: false, foreign: true };
|
|
17124
|
+
}
|
|
17125
|
+
const free = await waitPortFree(port, o.portFreeTimeoutMs);
|
|
17126
|
+
if (!free) return { ok: false, stopped: false, portBusy: true };
|
|
17127
|
+
}
|
|
17128
|
+
return { ok: true, stopped: true };
|
|
17129
|
+
}
|
|
17130
|
+
module2.exports = { ProcessLifecycle: { stopProcess, waitPortFree, isForeignOnPort, DEFAULTS } };
|
|
17252
17131
|
}
|
|
17253
17132
|
});
|
|
17254
17133
|
|
|
@@ -17395,6 +17274,7 @@ var require_probe5 = __commonJS({
|
|
|
17395
17274
|
var carrier = require_carrier();
|
|
17396
17275
|
var procOS = require_process();
|
|
17397
17276
|
var { INSTANCE_STATES } = require_model2();
|
|
17277
|
+
var { ProcessLifecycle } = require_process_lifecycle();
|
|
17398
17278
|
var { getQuotaStrategy } = require_quota_strategies();
|
|
17399
17279
|
var { quotaOverallStatus } = require_quota();
|
|
17400
17280
|
var { cachedPkgBin, ensurePkgCached } = require_pkg_cache();
|
|
@@ -17423,7 +17303,7 @@ var require_probe5 = __commonJS({
|
|
|
17423
17303
|
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");
|
|
17424
17304
|
if (provider.events) provider.events.append("proxy_instance_survivor_reclaimed", { app: provider.proxyAppId, port: inst.port, pid: boundPid, reason: "restart-survivor-stdio-unsafe" });
|
|
17425
17305
|
try {
|
|
17426
|
-
|
|
17306
|
+
ProcessLifecycle.stopProcess({ pid: boundPid, port: inst.port });
|
|
17427
17307
|
} catch {
|
|
17428
17308
|
}
|
|
17429
17309
|
const dl = Date.now() + 3e3;
|
|
@@ -17613,7 +17493,7 @@ var require_probe5 = __commonJS({
|
|
|
17613
17493
|
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");
|
|
17614
17494
|
if (provider.events) provider.events.append("proxy_instance_hang_restart", { app: provider.proxyAppId, port: inst.port, pid: inst.pid, fails: inst._monitorFails });
|
|
17615
17495
|
try {
|
|
17616
|
-
|
|
17496
|
+
ProcessLifecycle.stopProcess({ pid: inst.pid, port: inst.port });
|
|
17617
17497
|
} catch {
|
|
17618
17498
|
}
|
|
17619
17499
|
inst.pid = null;
|
|
@@ -17768,7 +17648,8 @@ var require_process_pool = __commonJS({
|
|
|
17768
17648
|
"src/domains/router/providers/process-pool.js"(exports2, module2) {
|
|
17769
17649
|
"use strict";
|
|
17770
17650
|
var life = require_instance_lifecycle();
|
|
17771
|
-
var restart =
|
|
17651
|
+
var restart = require_restart();
|
|
17652
|
+
var { resetBudget } = restart;
|
|
17772
17653
|
var probe = require_probe5();
|
|
17773
17654
|
var pool = require_pool3();
|
|
17774
17655
|
var pidlook = require_pidlookup();
|
|
@@ -17901,6 +17782,10 @@ var require_process_pool = __commonJS({
|
|
|
17901
17782
|
}
|
|
17902
17783
|
inst._restartAt = Date.now() + 12e4;
|
|
17903
17784
|
inst._restartPending = null;
|
|
17785
|
+
try {
|
|
17786
|
+
resetBudget(inst);
|
|
17787
|
+
} catch {
|
|
17788
|
+
}
|
|
17904
17789
|
if (this.logger && this.logger.warn) this.logger.warn("[proxy-instance] \u5B9E\u4F8B\u91CD\u542F key=" + inst.maskedKey + " port=" + inst.port + " reason=" + reason);
|
|
17905
17790
|
const hadPid = !!inst.pid;
|
|
17906
17791
|
try {
|
|
@@ -18020,7 +17905,7 @@ var require_proxy = __commonJS({
|
|
|
18020
17905
|
var { npxLauncher } = require_npx_forms();
|
|
18021
17906
|
var { buildCommand } = require_command2();
|
|
18022
17907
|
var probe = require_probe5();
|
|
18023
|
-
var restart =
|
|
17908
|
+
var restart = require_restart();
|
|
18024
17909
|
var pool = require_pool3();
|
|
18025
17910
|
var life = require_instance_lifecycle();
|
|
18026
17911
|
var ProxyProvider = class extends withProcessPool(ProviderBase) {
|
|
@@ -18384,7 +18269,6 @@ var require_proxy_apps = __commonJS({
|
|
|
18384
18269
|
healthPath: "/health",
|
|
18385
18270
|
modelPath: "/v1/models",
|
|
18386
18271
|
upstream: "https://api.commandcode.ai",
|
|
18387
|
-
// keyEnv 是密钥注入的唯一 env 名(绝不进 cmdline);其余 env/超时一律不注入,跑上游默认配置。
|
|
18388
18272
|
keyEnv: "CC_API_KEY",
|
|
18389
18273
|
repo: "thaolaptrinh/commandcode-api-proxy",
|
|
18390
18274
|
registry: "commandcode-api-proxy",
|
|
@@ -19092,16 +18976,6 @@ var require_usage = __commonJS({
|
|
|
19092
18976
|
if (!this._dirty) return;
|
|
19093
18977
|
this._writeTotals();
|
|
19094
18978
|
}
|
|
19095
|
-
/**
|
|
19096
|
-
* 根因 E:缓存**新鲜度**与**可写性**两维度正交,不得耦合。
|
|
19097
|
-
*
|
|
19098
|
-
* 修前:`if (this.totals && this._canPersist()) return this.totals;`
|
|
19099
|
-
* —— 闸门关闭(daemon 模式下 setPersistEnabled(false))时该条件恒假 ⇒ 每次 recordUsage
|
|
19100
|
-
* 都重新读盘,而 _writeTotals 又因闸门关闭直接 return ⇒ 磁盘不变、内存增量被下次 load 覆盖
|
|
19101
|
-
* ⇒ **用量计数被永久吞掉**。
|
|
19102
|
-
*
|
|
19103
|
-
* 现在:load 只看内存缓存是否存在(新鲜度);是否落盘由 _writeTotals 单独决定(可写性)。
|
|
19104
|
-
*/
|
|
19105
18979
|
load() {
|
|
19106
18980
|
if (this.totals) return this.totals;
|
|
19107
18981
|
let t;
|
|
@@ -20138,6 +20012,7 @@ var require_scheduler2 = __commonJS({
|
|
|
20138
20012
|
function createScheduler(deps) {
|
|
20139
20013
|
const d = deps || {};
|
|
20140
20014
|
const state = d.state;
|
|
20015
|
+
const beat = d.beatScheduler || null;
|
|
20141
20016
|
const logger = d.logger || null;
|
|
20142
20017
|
const refreshProxyUpdateInfo = d.refreshProxyUpdateInfo || (() => Promise.resolve());
|
|
20143
20018
|
const refreshOfficialUsageAll = d.refreshOfficialUsageAll || (() => Promise.resolve());
|
|
@@ -20153,6 +20028,27 @@ var require_scheduler2 = __commonJS({
|
|
|
20153
20028
|
});
|
|
20154
20029
|
ensureProxyInstances().catch(() => {
|
|
20155
20030
|
});
|
|
20031
|
+
if (beat) {
|
|
20032
|
+
beat.unregister("router-maint");
|
|
20033
|
+
beat.unregister("router-lifecycle");
|
|
20034
|
+
beat.unregister("router-pricing");
|
|
20035
|
+
beat.register("router-maint", () => {
|
|
20036
|
+
refreshProxyUpdateInfo().catch(() => {
|
|
20037
|
+
});
|
|
20038
|
+
probeIfDue();
|
|
20039
|
+
ensureProxyInstances().catch(() => {
|
|
20040
|
+
});
|
|
20041
|
+
}, { every: Math.max(1, Math.round(3e5 / (d.tickMs || 5e3))) });
|
|
20042
|
+
beat.register("router-lifecycle", () => {
|
|
20043
|
+
monitorInstanceHealth().catch(() => {
|
|
20044
|
+
});
|
|
20045
|
+
}, { every: Math.max(1, Math.round(3e4 / (d.tickMs || 5e3))) });
|
|
20046
|
+
beat.register("router-pricing", () => {
|
|
20047
|
+
refreshOfficialPricingAll().catch(() => {
|
|
20048
|
+
});
|
|
20049
|
+
}, { every: Math.max(1, Math.round(216e5 / (d.tickMs || 5e3))) });
|
|
20050
|
+
return;
|
|
20051
|
+
}
|
|
20156
20052
|
if (state.maintTimer) clearInterval(state.maintTimer);
|
|
20157
20053
|
state.maintTimer = setInterval(() => {
|
|
20158
20054
|
refreshProxyUpdateInfo().catch(() => {
|
|
@@ -20174,6 +20070,12 @@ var require_scheduler2 = __commonJS({
|
|
|
20174
20070
|
}), 6 * 3600 * 1e3);
|
|
20175
20071
|
}
|
|
20176
20072
|
function stop() {
|
|
20073
|
+
if (beat) {
|
|
20074
|
+
beat.unregister("router-maint");
|
|
20075
|
+
beat.unregister("router-lifecycle");
|
|
20076
|
+
beat.unregister("router-pricing");
|
|
20077
|
+
return;
|
|
20078
|
+
}
|
|
20177
20079
|
if (state.maintTimer) {
|
|
20178
20080
|
clearInterval(state.maintTimer);
|
|
20179
20081
|
state.maintTimer = null;
|
|
@@ -20702,6 +20604,8 @@ var require_router3 = __commonJS({
|
|
|
20702
20604
|
var RouterService = class {
|
|
20703
20605
|
constructor(opts) {
|
|
20704
20606
|
this.config = opts.config;
|
|
20607
|
+
this._beatScheduler = opts.beatScheduler || null;
|
|
20608
|
+
this._beatTickMs = opts.tickMs || opts.config && opts.config.tickIntervalMs || 5e3;
|
|
20705
20609
|
this.dist = opts.dist || null;
|
|
20706
20610
|
this.logger = opts.logger || console;
|
|
20707
20611
|
this.events = opts.events || null;
|
|
@@ -20763,6 +20667,8 @@ var require_router3 = __commonJS({
|
|
|
20763
20667
|
state,
|
|
20764
20668
|
store: this.store,
|
|
20765
20669
|
logger: this.logger,
|
|
20670
|
+
beatScheduler: this._beatScheduler,
|
|
20671
|
+
tickMs: this._beatTickMs,
|
|
20766
20672
|
refreshProxyUpdateInfo: () => this.refreshProxyUpdateInfo(),
|
|
20767
20673
|
refreshOfficialUsageAll: () => this.refreshOfficialUsageAll(),
|
|
20768
20674
|
refreshOfficialPricingAll: () => this.refreshOfficialPricingAll()
|
|
@@ -21340,7 +21246,6 @@ var require_model3 = __commonJS({
|
|
|
21340
21246
|
allocation: inst.state ? inst.state.allocation || null : null,
|
|
21341
21247
|
usage: inst.state ? inst.state.usage || null : null,
|
|
21342
21248
|
restartCount: inst.state ? inst.state.restartCount || 0 : 0,
|
|
21343
|
-
// 启动失败限流(唯一一条规则)的可见量:窗口内计数 / 固定端口释放等待落点。
|
|
21344
21249
|
startupFailCount: inst.state ? inst.state.startupFailCount || 0 : 0,
|
|
21345
21250
|
restartAt: inst.state ? inst.state.restartAt || null : null,
|
|
21346
21251
|
lastFailure: inst.state ? inst.state.lastFailure || null : null,
|
|
@@ -21423,12 +21328,6 @@ var require_store5 = __commonJS({
|
|
|
21423
21328
|
_stripLegacyStateKeys(inst) {
|
|
21424
21329
|
if (inst.state && Object.prototype.hasOwnProperty.call(inst.state, "version")) delete inst.state.version;
|
|
21425
21330
|
}
|
|
21426
|
-
/**
|
|
21427
|
-
* 隔离损坏文件。
|
|
21428
|
-
* Lease I2:隔离前**再次校验版本戳**——若自读取失败以来文件已被他人更新,
|
|
21429
|
-
* 说明它不是损坏 ⇒ 放弃隔离(修前会直接 rename 掉这个更新的文件并把实例列表清空,即全量静默丢失)。
|
|
21430
|
-
* 且保留可回溯副本:先复制再改名,不直接丢弃。
|
|
21431
|
-
*/
|
|
21432
21331
|
_quarantineCorrupt(err) {
|
|
21433
21332
|
let locked = false;
|
|
21434
21333
|
try {
|
|
@@ -22669,25 +22568,7 @@ var require_ops2 = __commonJS({
|
|
|
22669
22568
|
store.save();
|
|
22670
22569
|
return { ok: true, instance: inst };
|
|
22671
22570
|
}
|
|
22672
|
-
|
|
22673
|
-
if (timer) clearInterval(timer);
|
|
22674
|
-
timer = setInterval(() => {
|
|
22675
|
-
for (const inst of store.instances) {
|
|
22676
|
-
if (inst.domain === "native") continue;
|
|
22677
|
-
try {
|
|
22678
|
-
lifecycle.supervise(inst.id);
|
|
22679
|
-
} catch (e) {
|
|
22680
|
-
logger.warn && logger.warn("[" + inst.id + "] supervise \u5931\u8D25: " + (e && e.message));
|
|
22681
|
-
}
|
|
22682
|
-
}
|
|
22683
|
-
try {
|
|
22684
|
-
lifecycle.governSweep();
|
|
22685
|
-
} catch (e) {
|
|
22686
|
-
logger.warn && logger.warn("governSweep: " + (e && e.message));
|
|
22687
|
-
}
|
|
22688
|
-
}, intervalMs || 5e3);
|
|
22689
|
-
}
|
|
22690
|
-
return { list, addInstance, removeInstance, updateInstance, startTimer };
|
|
22571
|
+
return { list, addInstance, removeInstance, updateInstance };
|
|
22691
22572
|
}
|
|
22692
22573
|
module2.exports = { createOps };
|
|
22693
22574
|
}
|
|
@@ -22910,7 +22791,6 @@ var require_instance = __commonJS({
|
|
|
22910
22791
|
map(fn) {
|
|
22911
22792
|
return this._store.instances.map(fn);
|
|
22912
22793
|
}
|
|
22913
|
-
// 能力判定读平台表(有副作用)⇒ 从 governor 取,不经 pure 的 sandbox.js。
|
|
22914
22794
|
get sandboxSupported() {
|
|
22915
22795
|
return governor.sandboxSupported(this._sandboxSupportedOverride);
|
|
22916
22796
|
}
|
|
@@ -22998,9 +22878,6 @@ var require_instance = __commonJS({
|
|
|
22998
22878
|
upgradeStatus(id) {
|
|
22999
22879
|
return this._upgrade.upgradeStatus(id);
|
|
23000
22880
|
}
|
|
23001
|
-
startTimer(ms) {
|
|
23002
|
-
return this._ops.startTimer(ms);
|
|
23003
|
-
}
|
|
23004
22881
|
sandboxRoot(inst) {
|
|
23005
22882
|
return sandbox.root(this.instancesRoot, inst);
|
|
23006
22883
|
}
|
|
@@ -23898,23 +23775,14 @@ var require_process_spec = __commonJS({
|
|
|
23898
23775
|
function defaultSpec() {
|
|
23899
23776
|
return {
|
|
23900
23777
|
runtime: null,
|
|
23901
|
-
// 解释器(如 node);为 null 表示 bin 可直接执行
|
|
23902
23778
|
bin: null,
|
|
23903
|
-
// 可执行文件或入口脚本
|
|
23904
23779
|
subcommand: null,
|
|
23905
|
-
// 子命令(如 'web' / 'plugin')
|
|
23906
23780
|
args: [],
|
|
23907
|
-
// 用户参数
|
|
23908
23781
|
port: null,
|
|
23909
|
-
// --port 值(一等公民,不再各处拼装)
|
|
23910
23782
|
patchFile: null,
|
|
23911
|
-
// 插件 overlay(一等公民,不再事后 splice)
|
|
23912
23783
|
storeDir: null,
|
|
23913
|
-
// pnpm --store-dir
|
|
23914
23784
|
install: false,
|
|
23915
|
-
// 是否安装类操作(决定是否注入安全标志)
|
|
23916
23785
|
extraFlags: []
|
|
23917
|
-
// 其他固定标志
|
|
23918
23786
|
};
|
|
23919
23787
|
}
|
|
23920
23788
|
function validate(spec) {
|
|
@@ -24124,7 +23992,7 @@ var require_cli = __commonJS({
|
|
|
24124
23992
|
});
|
|
24125
23993
|
|
|
24126
23994
|
// src/domains/plugin/restart.js
|
|
24127
|
-
var
|
|
23995
|
+
var require_restart2 = __commonJS({
|
|
24128
23996
|
"src/domains/plugin/restart.js"(exports2, module2) {
|
|
24129
23997
|
"use strict";
|
|
24130
23998
|
function targetRunning(ctx, target) {
|
|
@@ -24165,7 +24033,7 @@ var require_restart3 = __commonJS({
|
|
|
24165
24033
|
log("\u91CD\u542F\u5B9E\u4F8B\u300C" + (target.name || target.id) + "\u300D\u4F7F\u63D2\u4EF6\u53D8\u66F4\u751F\u6548\u2026");
|
|
24166
24034
|
if (ctx.events) ctx.events.append("plugin_restart_started", { name: target.name || target.id, target: target.id, kind });
|
|
24167
24035
|
try {
|
|
24168
|
-
ctx.instances.stopInstance(target.id);
|
|
24036
|
+
await ctx.instances.stopInstance(target.id);
|
|
24169
24037
|
} catch (e) {
|
|
24170
24038
|
log("\u505C\u6B62\u5B9E\u4F8B\u5931\u8D25: " + e.message);
|
|
24171
24039
|
}
|
|
@@ -24189,28 +24057,25 @@ var require_restart3 = __commonJS({
|
|
|
24189
24057
|
return true;
|
|
24190
24058
|
}
|
|
24191
24059
|
if (target.kind === "native") {
|
|
24192
|
-
|
|
24193
|
-
|
|
24060
|
+
const nr = ctx.onNativeRestart;
|
|
24061
|
+
if (typeof nr !== "function") {
|
|
24062
|
+
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");
|
|
24194
24063
|
return false;
|
|
24195
24064
|
}
|
|
24196
|
-
|
|
24197
|
-
|
|
24198
|
-
|
|
24199
|
-
|
|
24200
|
-
|
|
24201
|
-
|
|
24202
|
-
return false;
|
|
24203
|
-
}
|
|
24204
|
-
if (rr && rr.ok === false) {
|
|
24205
|
-
log("\u539F\u751F DSH \u91CD\u542F\u8BF7\u6C42\u672A\u751F\u6548\uFF1A" + (rr && rr.error || "unknown"));
|
|
24206
|
-
return false;
|
|
24207
|
-
}
|
|
24208
|
-
log("\u5DF2\u8BF7\u6C42\u91CD\u542F\u539F\u751F DSH \u4F7F\u63D2\u4EF6\u53D8\u66F4\u751F\u6548");
|
|
24209
|
-
if (ctx.events) ctx.events.append("plugin_restart_done", { name: "\u539F\u751F\u5B9E\u4F8B", target: "native", kind, via: "supervisor" });
|
|
24210
|
-
return true;
|
|
24065
|
+
let rr;
|
|
24066
|
+
try {
|
|
24067
|
+
rr = ctx.onNativeRestart();
|
|
24068
|
+
} catch (e) {
|
|
24069
|
+
log("\u539F\u751F DSH \u91CD\u542F\u8BF7\u6C42\u5931\u8D25: " + e.message);
|
|
24070
|
+
return false;
|
|
24211
24071
|
}
|
|
24212
|
-
|
|
24213
|
-
|
|
24072
|
+
if (rr && rr.ok === false) {
|
|
24073
|
+
log("\u539F\u751F DSH \u91CD\u542F\u8BF7\u6C42\u672A\u751F\u6548\uFF1A" + (rr && rr.error || "unknown"));
|
|
24074
|
+
return false;
|
|
24075
|
+
}
|
|
24076
|
+
log("\u5DF2\u8BF7\u6C42\u91CD\u542F\u539F\u751F DSH \u4F7F\u63D2\u4EF6\u53D8\u66F4\u751F\u6548");
|
|
24077
|
+
if (ctx.events) ctx.events.append("plugin_restart_done", { name: "\u539F\u751F\u5B9E\u4F8B", target: "native", kind, via: "supervisor" });
|
|
24078
|
+
return true;
|
|
24214
24079
|
}
|
|
24215
24080
|
return false;
|
|
24216
24081
|
} catch (e) {
|
|
@@ -24784,7 +24649,7 @@ var require_plugin = __commonJS({
|
|
|
24784
24649
|
var store = require_store6();
|
|
24785
24650
|
var targets = require_targets();
|
|
24786
24651
|
var cli = require_cli();
|
|
24787
|
-
var restart =
|
|
24652
|
+
var restart = require_restart2();
|
|
24788
24653
|
var { createJobs } = require_jobs();
|
|
24789
24654
|
var { createLayers } = require_layers();
|
|
24790
24655
|
var ops = require_ops3();
|
|
@@ -24902,7 +24767,8 @@ var require_managed_object = __commonJS({
|
|
|
24902
24767
|
"sandbox-instance": { label: "\u6C99\u7BB1\u5B9E\u4F8B", startable: true, guardable: true },
|
|
24903
24768
|
"router-daemon": { label: "\u667A\u80FD\u8DEF\u7531 daemon", startable: true, guardable: true },
|
|
24904
24769
|
"lan-daemon": { label: "\u8FDC\u7A0B\u63A7\u5236 daemon", startable: true, guardable: true },
|
|
24905
|
-
plugin: { label: "\u63D2\u4EF6\uFF08\u805A\u5408\uFF09", startable: false, guardable: false }
|
|
24770
|
+
plugin: { label: "\u63D2\u4EF6\uFF08\u805A\u5408\uFF09", startable: false, guardable: false },
|
|
24771
|
+
shell: { label: "\u684C\u9762\u58F3", startable: false, guardable: false }
|
|
24906
24772
|
};
|
|
24907
24773
|
var _customKinds = {};
|
|
24908
24774
|
function kindMeta(kind) {
|
|
@@ -25034,9 +24900,17 @@ var require_registry4 = __commonJS({
|
|
|
25034
24900
|
var path2 = require("node:path");
|
|
25035
24901
|
var { writeAtomic } = require_fs();
|
|
25036
24902
|
var { DESIRED, MANAGED_KINDS, kindMeta, registerKind: registerManagedKind, createEntry, normalizeOwnership } = require_managed_object();
|
|
24903
|
+
var { legacyToEntryPhase } = require_phase();
|
|
25037
24904
|
var PHASES = ["stopped", "installing", "starting", "running", "draining", "failed"];
|
|
25038
|
-
var LEGACY_PHASES = { backoff: "failed", restarting: "starting" };
|
|
25039
24905
|
var { runHeartbeat } = require_heartbeat();
|
|
24906
|
+
var pmClient = require_pm_client();
|
|
24907
|
+
var configDefaults = require_config();
|
|
24908
|
+
var RESTART_FALLBACK = { windowMs: 6e4, burst: 5 };
|
|
24909
|
+
var restartDefaults = () => {
|
|
24910
|
+
const r = configDefaults && configDefaults.restart;
|
|
24911
|
+
if (r && Number.isFinite(r.windowMs) && Number.isFinite(r.burst)) return { windowMs: r.windowMs, burst: r.burst };
|
|
24912
|
+
return RESTART_FALLBACK;
|
|
24913
|
+
};
|
|
25040
24914
|
var ManagedRegistry = class {
|
|
25041
24915
|
constructor(opts) {
|
|
25042
24916
|
this.file = opts && opts.file;
|
|
@@ -25082,7 +24956,8 @@ var require_registry4 = __commonJS({
|
|
|
25082
24956
|
try {
|
|
25083
24957
|
if (!o || !kindMeta(o.kind)) continue;
|
|
25084
24958
|
const e = createEntry({ kind: o.kind, id: o.id, name: o.name, desired: o.desired, ownership: o.ownership });
|
|
25085
|
-
|
|
24959
|
+
const np = legacyToEntryPhase(o.phase);
|
|
24960
|
+
if (PHASES.includes(np)) e.phase = np;
|
|
25086
24961
|
if (Number.isInteger(o.restartCount) && o.restartCount >= 0) e.restartCount = o.restartCount;
|
|
25087
24962
|
if (o.startupFailWindowStart === null || typeof o.startupFailWindowStart === "number") e.startupFailWindowStart = o.startupFailWindowStart;
|
|
25088
24963
|
if (Number.isInteger(o.startupFailCount) && o.startupFailCount >= 0) e.startupFailCount = o.startupFailCount;
|
|
@@ -25150,8 +25025,6 @@ var require_registry4 = __commonJS({
|
|
|
25150
25025
|
const i = this._objects.indexOf(e);
|
|
25151
25026
|
if (i >= 0) this._objects.splice(i, 1);
|
|
25152
25027
|
}
|
|
25153
|
-
// 自定义 kind 扩展点:零调用但刻意保留(见 managed-object.js 的说明)——
|
|
25154
|
-
// 它是「新增受管对象类型」的唯一入口,删除等于永久关闭扩展能力。
|
|
25155
25028
|
registerKind(kind, meta) {
|
|
25156
25029
|
registerManagedKind(kind, meta);
|
|
25157
25030
|
return this;
|
|
@@ -25171,6 +25044,8 @@ var require_registry4 = __commonJS({
|
|
|
25171
25044
|
this._syncPortsOwner(e, true);
|
|
25172
25045
|
this._save();
|
|
25173
25046
|
this._event("managed_object_registered", { kind: e.kind, id: e.id, name: e.name });
|
|
25047
|
+
const rd = restartDefaults();
|
|
25048
|
+
pmClient.register({ id: e.id, spawn_cmd: [], restart_window_ms: rd.windowMs, restart_burst: rd.burst });
|
|
25174
25049
|
return e;
|
|
25175
25050
|
}
|
|
25176
25051
|
update(id, patch) {
|
|
@@ -25180,6 +25055,7 @@ var require_registry4 = __commonJS({
|
|
|
25180
25055
|
if (p.desired !== void 0) {
|
|
25181
25056
|
if (!DESIRED.includes(p.desired)) return { ok: false, error: "\u975E\u6CD5 desired: " + p.desired };
|
|
25182
25057
|
e.desired = p.desired;
|
|
25058
|
+
pmClient.setDesired(e.id, p.desired);
|
|
25183
25059
|
}
|
|
25184
25060
|
if (p.name !== void 0) e.name = String(p.name || e.id);
|
|
25185
25061
|
if (p.ownership !== void 0) {
|
|
@@ -25211,6 +25087,7 @@ var require_registry4 = __commonJS({
|
|
|
25211
25087
|
this._drop(e);
|
|
25212
25088
|
this._save();
|
|
25213
25089
|
this._event("managed_object_removed", { kind: e.kind, id: e.id });
|
|
25090
|
+
pmClient.setDesired(e.id, "stopped");
|
|
25214
25091
|
return { ok: true };
|
|
25215
25092
|
}
|
|
25216
25093
|
_releasePort(port, ownerId) {
|
|
@@ -25255,6 +25132,17 @@ var require_registry4 = __commonJS({
|
|
|
25255
25132
|
};
|
|
25256
25133
|
return e;
|
|
25257
25134
|
}
|
|
25135
|
+
setRestartCount(id, n) {
|
|
25136
|
+
const e = this.get(id);
|
|
25137
|
+
if (!e) return null;
|
|
25138
|
+
const v = typeof n === "number" && n >= 0 ? Math.floor(n) : 0;
|
|
25139
|
+
if (e.restartCount !== v) {
|
|
25140
|
+
e.restartCount = v;
|
|
25141
|
+
this._event("managed_object_restart_count", { kind: e.kind, id: e.id, count: v });
|
|
25142
|
+
this._save();
|
|
25143
|
+
}
|
|
25144
|
+
return e;
|
|
25145
|
+
}
|
|
25258
25146
|
setPhase(id, p) {
|
|
25259
25147
|
const e = this.get(id);
|
|
25260
25148
|
if (!e) return null;
|
|
@@ -25264,6 +25152,7 @@ var require_registry4 = __commonJS({
|
|
|
25264
25152
|
e.lastTransitionAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
25265
25153
|
this._event("managed_object_phase", { kind: e.kind, id: e.id, phase: p });
|
|
25266
25154
|
this._save();
|
|
25155
|
+
pmClient.onPhase(e.id, p);
|
|
25267
25156
|
}
|
|
25268
25157
|
return e;
|
|
25269
25158
|
}
|
|
@@ -26106,7 +25995,6 @@ var require_installer = __commonJS({
|
|
|
26106
25995
|
_manifest() {
|
|
26107
25996
|
return manifest.read(this);
|
|
26108
25997
|
}
|
|
26109
|
-
// W5:生产零调用,仅 native-test.js 使用(写 manifest 的夹具入口)。保留为测试缝。
|
|
26110
25998
|
_saveManifest(m) {
|
|
26111
25999
|
return manifest.save(this, m);
|
|
26112
26000
|
}
|
|
@@ -26423,6 +26311,8 @@ var require_domains = __commonJS({
|
|
|
26423
26311
|
}
|
|
26424
26312
|
host.router = new RouterService({
|
|
26425
26313
|
config: host.config,
|
|
26314
|
+
beatScheduler: host._beatScheduler,
|
|
26315
|
+
tickMs: host.config.tickIntervalMs || 5e3,
|
|
26426
26316
|
providerFile: path2.join(swDir, "providers.json"),
|
|
26427
26317
|
usageTotalsFile: path2.join(swDir, "router-usage-totals.json"),
|
|
26428
26318
|
logger: host.logger,
|
|
@@ -26444,7 +26334,6 @@ var require_domains = __commonJS({
|
|
|
26444
26334
|
tasks: host.tasks,
|
|
26445
26335
|
tokenService: host.tokenService,
|
|
26446
26336
|
dshBin: host.config.command && host.config.command[1] ? host.config.command[1] : "dsh",
|
|
26447
|
-
// 实例域限流参数:与主链同一条规则、按域参数化(窗口 600s > 5 × 30s 启动窗口);单源取自域常量。
|
|
26448
26337
|
throttle: THROTTLE_DEFAULTS
|
|
26449
26338
|
});
|
|
26450
26339
|
host.instances.load();
|
|
@@ -26561,7 +26450,6 @@ var require_adapters = __commonJS({
|
|
|
26561
26450
|
kind: "lan",
|
|
26562
26451
|
name: "\u8FDC\u7A0B\u63A7\u5236",
|
|
26563
26452
|
logger,
|
|
26564
|
-
// start 的结果必须来自真实执行:reconcile/syncFrpc 各自如实返回 ok,任一失败即 ok:false(此前恒 true)。
|
|
26565
26453
|
start: async () => {
|
|
26566
26454
|
try {
|
|
26567
26455
|
const rec = await lan.reconcile();
|
|
@@ -26809,7 +26697,7 @@ var require_lifecycle3 = __commonJS({
|
|
|
26809
26697
|
return send(200, { sessionState: sup.sessionState ? sup.sessionState() : "unknown" });
|
|
26810
26698
|
}
|
|
26811
26699
|
if (req.method === "POST" && pathname === "/session/stop") {
|
|
26812
|
-
if (!originAllowed(req
|
|
26700
|
+
if (!originAllowed(req)) {
|
|
26813
26701
|
req.resume();
|
|
26814
26702
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26815
26703
|
}
|
|
@@ -26832,7 +26720,7 @@ var require_lifecycle3 = __commonJS({
|
|
|
26832
26720
|
return lc ? send(200, lc.snapshot()) : send(404, { error: "\u6A21\u5757\u672A\u6CE8\u518C: " + id });
|
|
26833
26721
|
}
|
|
26834
26722
|
if (req.method === "POST" && action) {
|
|
26835
|
-
if (!originAllowed(req
|
|
26723
|
+
if (!originAllowed(req)) {
|
|
26836
26724
|
req.resume();
|
|
26837
26725
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26838
26726
|
}
|
|
@@ -26937,7 +26825,7 @@ var require_native = __commonJS({
|
|
|
26937
26825
|
});
|
|
26938
26826
|
}
|
|
26939
26827
|
if (req.method === "POST" && pathname === "/native/check-update") {
|
|
26940
|
-
if (!originAllowed(req
|
|
26828
|
+
if (!originAllowed(req)) {
|
|
26941
26829
|
req.resume();
|
|
26942
26830
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26943
26831
|
}
|
|
@@ -26945,7 +26833,7 @@ var require_native = __commonJS({
|
|
|
26945
26833
|
return;
|
|
26946
26834
|
}
|
|
26947
26835
|
if (req.method === "POST" && pathname === "/native/install") {
|
|
26948
|
-
if (!originAllowed(req
|
|
26836
|
+
if (!originAllowed(req)) {
|
|
26949
26837
|
req.resume();
|
|
26950
26838
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26951
26839
|
}
|
|
@@ -26963,7 +26851,7 @@ var require_native = __commonJS({
|
|
|
26963
26851
|
return;
|
|
26964
26852
|
}
|
|
26965
26853
|
if (req.method === "POST" && pathname === "/native/upgrade") {
|
|
26966
|
-
if (!originAllowed(req
|
|
26854
|
+
if (!originAllowed(req)) {
|
|
26967
26855
|
req.resume();
|
|
26968
26856
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26969
26857
|
}
|
|
@@ -26984,7 +26872,7 @@ var require_native = __commonJS({
|
|
|
26984
26872
|
return;
|
|
26985
26873
|
}
|
|
26986
26874
|
if (req.method === "POST" && pathname === "/native/uninstall") {
|
|
26987
|
-
if (!originAllowed(req
|
|
26875
|
+
if (!originAllowed(req)) {
|
|
26988
26876
|
req.resume();
|
|
26989
26877
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26990
26878
|
}
|
|
@@ -26993,7 +26881,7 @@ var require_native = __commonJS({
|
|
|
26993
26881
|
return send(202, { ok: true, accepted: true, state: "uninstalling" });
|
|
26994
26882
|
}
|
|
26995
26883
|
if (req.method === "POST" && pathname === "/native/settings") {
|
|
26996
|
-
if (!originAllowed(req
|
|
26884
|
+
if (!originAllowed(req)) {
|
|
26997
26885
|
req.resume();
|
|
26998
26886
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26999
26887
|
}
|
|
@@ -27055,14 +26943,14 @@ var require_guard = __commonJS({
|
|
|
27055
26943
|
}
|
|
27056
26944
|
if (req.method === "POST" && pathname === "/guard/version/check") {
|
|
27057
26945
|
req.resume();
|
|
27058
|
-
if (!originAllowed(req
|
|
26946
|
+
if (!originAllowed(req)) return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27059
26947
|
return sup.guardVersionCheck().then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
27060
26948
|
}
|
|
27061
26949
|
if (req.method === "GET" && pathname === "/autostart") {
|
|
27062
26950
|
return send(200, sup.autostartStatus());
|
|
27063
26951
|
}
|
|
27064
26952
|
if (req.method === "POST" && pathname === "/autostart") {
|
|
27065
|
-
if (!originAllowed(req
|
|
26953
|
+
if (!originAllowed(req)) {
|
|
27066
26954
|
req.resume();
|
|
27067
26955
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27068
26956
|
}
|
|
@@ -27083,7 +26971,7 @@ var require_guard = __commonJS({
|
|
|
27083
26971
|
return send(200, sup.lanPanelStatus());
|
|
27084
26972
|
}
|
|
27085
26973
|
if (req.method === "POST" && pathname === "/settings/lan") {
|
|
27086
|
-
if (!originAllowed(req
|
|
26974
|
+
if (!originAllowed(req)) {
|
|
27087
26975
|
req.resume();
|
|
27088
26976
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27089
26977
|
}
|
|
@@ -27104,7 +26992,7 @@ var require_guard = __commonJS({
|
|
|
27104
26992
|
return send(200, sup.accessKeyStatus());
|
|
27105
26993
|
}
|
|
27106
26994
|
if (req.method === "POST" && pathname === "/settings/access-key") {
|
|
27107
|
-
if (!originAllowed(req
|
|
26995
|
+
if (!originAllowed(req)) {
|
|
27108
26996
|
req.resume();
|
|
27109
26997
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27110
26998
|
}
|
|
@@ -27126,7 +27014,7 @@ var require_guard = __commonJS({
|
|
|
27126
27014
|
return send(200, sup.closeActionStatus());
|
|
27127
27015
|
}
|
|
27128
27016
|
if (req.method === "POST" && pathname === "/settings/close-action") {
|
|
27129
|
-
if (!originAllowed(req
|
|
27017
|
+
if (!originAllowed(req)) {
|
|
27130
27018
|
req.resume();
|
|
27131
27019
|
return send(403, {});
|
|
27132
27020
|
}
|
|
@@ -27147,7 +27035,7 @@ var require_guard = __commonJS({
|
|
|
27147
27035
|
return send(200, sup.externalBrowserStatus());
|
|
27148
27036
|
}
|
|
27149
27037
|
if (req.method === "POST" && pathname === "/settings/external-browser") {
|
|
27150
|
-
if (!originAllowed(req
|
|
27038
|
+
if (!originAllowed(req)) {
|
|
27151
27039
|
req.resume();
|
|
27152
27040
|
return send(403, {});
|
|
27153
27041
|
}
|
|
@@ -27169,7 +27057,7 @@ var require_guard = __commonJS({
|
|
|
27169
27057
|
return;
|
|
27170
27058
|
}
|
|
27171
27059
|
if (req.method === "POST" && pathname === "/shutdown") {
|
|
27172
|
-
if (!originAllowed(req
|
|
27060
|
+
if (!originAllowed(req)) {
|
|
27173
27061
|
req.resume();
|
|
27174
27062
|
return send(403, {});
|
|
27175
27063
|
}
|
|
@@ -27184,7 +27072,7 @@ var require_guard = __commonJS({
|
|
|
27184
27072
|
return;
|
|
27185
27073
|
}
|
|
27186
27074
|
if (req.method === "GET" && pathname === "/self-update/status") {
|
|
27187
|
-
if (!originAllowed(req
|
|
27075
|
+
if (!originAllowed(req)) {
|
|
27188
27076
|
req.resume();
|
|
27189
27077
|
return send(403, {});
|
|
27190
27078
|
}
|
|
@@ -27210,14 +27098,14 @@ var require_guard = __commonJS({
|
|
|
27210
27098
|
});
|
|
27211
27099
|
}
|
|
27212
27100
|
if (req.method === "GET" && pathname === "/env/dsh") {
|
|
27213
|
-
if (!originAllowed(req
|
|
27101
|
+
if (!originAllowed(req)) {
|
|
27214
27102
|
req.resume();
|
|
27215
27103
|
return send(403, {});
|
|
27216
27104
|
}
|
|
27217
27105
|
return send(200, sup.dshenvStatus());
|
|
27218
27106
|
}
|
|
27219
27107
|
if (req.method === "GET" && pathname === "/env/status") {
|
|
27220
|
-
if (!originAllowed(req
|
|
27108
|
+
if (!originAllowed(req)) {
|
|
27221
27109
|
req.resume();
|
|
27222
27110
|
return send(403, {});
|
|
27223
27111
|
}
|
|
@@ -27227,7 +27115,7 @@ var require_guard = __commonJS({
|
|
|
27227
27115
|
return sup.nodeLtsStatus().then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
27228
27116
|
}
|
|
27229
27117
|
if (req.method === "GET" && pathname === "/env/environment") {
|
|
27230
|
-
if (!originAllowed(req
|
|
27118
|
+
if (!originAllowed(req)) {
|
|
27231
27119
|
req.resume();
|
|
27232
27120
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27233
27121
|
}
|
|
@@ -27235,7 +27123,7 @@ var require_guard = __commonJS({
|
|
|
27235
27123
|
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) }));
|
|
27236
27124
|
}
|
|
27237
27125
|
if (req.method === "GET" && pathname === "/env/environment/last") {
|
|
27238
|
-
if (!originAllowed(req
|
|
27126
|
+
if (!originAllowed(req)) {
|
|
27239
27127
|
req.resume();
|
|
27240
27128
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27241
27129
|
}
|
|
@@ -27246,7 +27134,7 @@ var require_guard = __commonJS({
|
|
|
27246
27134
|
req.resume();
|
|
27247
27135
|
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" });
|
|
27248
27136
|
}
|
|
27249
|
-
if (!originAllowed(req
|
|
27137
|
+
if (!originAllowed(req)) {
|
|
27250
27138
|
req.resume();
|
|
27251
27139
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27252
27140
|
}
|
|
@@ -27291,7 +27179,7 @@ var require_router4 = __commonJS({
|
|
|
27291
27179
|
return Promise.resolve(sup.routerStatusView()).then((r) => send(200, r)).catch((e) => send(500, { ok: false, running: false, error: e && e.message || String(e) }));
|
|
27292
27180
|
}
|
|
27293
27181
|
if (req.method === "POST" && pathname.startsWith("/router/")) {
|
|
27294
|
-
if (!originAllowed(req
|
|
27182
|
+
if (!originAllowed(req)) {
|
|
27295
27183
|
req.resume();
|
|
27296
27184
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27297
27185
|
}
|
|
@@ -27308,7 +27196,7 @@ var require_router4 = __commonJS({
|
|
|
27308
27196
|
return Promise.resolve(sup.routerProviders()).then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
27309
27197
|
}
|
|
27310
27198
|
if (req.method === "POST" && pathname === "/router/providers/add") {
|
|
27311
|
-
if (!originAllowed(req
|
|
27199
|
+
if (!originAllowed(req)) {
|
|
27312
27200
|
req.resume();
|
|
27313
27201
|
return send(403, {});
|
|
27314
27202
|
}
|
|
@@ -27327,7 +27215,7 @@ var require_router4 = __commonJS({
|
|
|
27327
27215
|
return;
|
|
27328
27216
|
}
|
|
27329
27217
|
if (req.method === "POST" && pathname === "/router/proxy/login/start") {
|
|
27330
|
-
if (!originAllowed(req
|
|
27218
|
+
if (!originAllowed(req)) {
|
|
27331
27219
|
req.resume();
|
|
27332
27220
|
return send(403, {});
|
|
27333
27221
|
}
|
|
@@ -27335,7 +27223,7 @@ var require_router4 = __commonJS({
|
|
|
27335
27223
|
return;
|
|
27336
27224
|
}
|
|
27337
27225
|
if (req.method === "POST" && pathname === "/router/proxy/login/wait") {
|
|
27338
|
-
if (!originAllowed(req
|
|
27226
|
+
if (!originAllowed(req)) {
|
|
27339
27227
|
req.resume();
|
|
27340
27228
|
return send(403, {});
|
|
27341
27229
|
}
|
|
@@ -27352,7 +27240,7 @@ var require_router4 = __commonJS({
|
|
|
27352
27240
|
return;
|
|
27353
27241
|
}
|
|
27354
27242
|
if (req.method === "POST" && pathname === "/router/proxy/update/check") {
|
|
27355
|
-
if (!originAllowed(req
|
|
27243
|
+
if (!originAllowed(req)) {
|
|
27356
27244
|
req.resume();
|
|
27357
27245
|
return send(403, {});
|
|
27358
27246
|
}
|
|
@@ -27360,7 +27248,7 @@ var require_router4 = __commonJS({
|
|
|
27360
27248
|
return;
|
|
27361
27249
|
}
|
|
27362
27250
|
if (req.method === "POST" && pathname === "/router/proxy/update/apply") {
|
|
27363
|
-
if (!originAllowed(req
|
|
27251
|
+
if (!originAllowed(req)) {
|
|
27364
27252
|
req.resume();
|
|
27365
27253
|
return send(403, {});
|
|
27366
27254
|
}
|
|
@@ -27379,7 +27267,7 @@ var require_router4 = __commonJS({
|
|
|
27379
27267
|
return Promise.resolve(sup.routerApi().proxyUpdateStatus(u.searchParams.get("appId") || "")).then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
27380
27268
|
}
|
|
27381
27269
|
if (req.method === "POST" && pathname === "/router/providers/proxy/key") {
|
|
27382
|
-
if (!originAllowed(req
|
|
27270
|
+
if (!originAllowed(req)) {
|
|
27383
27271
|
req.resume();
|
|
27384
27272
|
return send(403, {});
|
|
27385
27273
|
}
|
|
@@ -27394,7 +27282,7 @@ var require_router4 = __commonJS({
|
|
|
27394
27282
|
return;
|
|
27395
27283
|
}
|
|
27396
27284
|
if (req.method === "POST" && pathname === "/router/providers/proxy/select") {
|
|
27397
|
-
if (!originAllowed(req
|
|
27285
|
+
if (!originAllowed(req)) {
|
|
27398
27286
|
req.resume();
|
|
27399
27287
|
return send(403, {});
|
|
27400
27288
|
}
|
|
@@ -27409,7 +27297,7 @@ var require_router4 = __commonJS({
|
|
|
27409
27297
|
return;
|
|
27410
27298
|
}
|
|
27411
27299
|
if (req.method === "POST" && pathname === "/router/providers/proxy/key/remove") {
|
|
27412
|
-
if (!originAllowed(req
|
|
27300
|
+
if (!originAllowed(req)) {
|
|
27413
27301
|
req.resume();
|
|
27414
27302
|
return send(403, {});
|
|
27415
27303
|
}
|
|
@@ -27424,7 +27312,7 @@ var require_router4 = __commonJS({
|
|
|
27424
27312
|
return;
|
|
27425
27313
|
}
|
|
27426
27314
|
if (req.method === "POST" && pathname === "/router/providers/keys/set") {
|
|
27427
|
-
if (!originAllowed(req
|
|
27315
|
+
if (!originAllowed(req)) {
|
|
27428
27316
|
req.resume();
|
|
27429
27317
|
return send(403, {});
|
|
27430
27318
|
}
|
|
@@ -27440,7 +27328,7 @@ var require_router4 = __commonJS({
|
|
|
27440
27328
|
return;
|
|
27441
27329
|
}
|
|
27442
27330
|
if (req.method === "POST" && pathname === "/router/providers/remove") {
|
|
27443
|
-
if (!originAllowed(req
|
|
27331
|
+
if (!originAllowed(req)) {
|
|
27444
27332
|
req.resume();
|
|
27445
27333
|
return send(403, {});
|
|
27446
27334
|
}
|
|
@@ -27455,7 +27343,7 @@ var require_router4 = __commonJS({
|
|
|
27455
27343
|
return;
|
|
27456
27344
|
}
|
|
27457
27345
|
if (req.method === "POST" && pathname === "/router/providers/key/use") {
|
|
27458
|
-
if (!originAllowed(req
|
|
27346
|
+
if (!originAllowed(req)) {
|
|
27459
27347
|
req.resume();
|
|
27460
27348
|
return send(403, {});
|
|
27461
27349
|
}
|
|
@@ -27471,7 +27359,7 @@ var require_router4 = __commonJS({
|
|
|
27471
27359
|
return;
|
|
27472
27360
|
}
|
|
27473
27361
|
if (req.method === "POST" && pathname === "/router/providers/account/discard") {
|
|
27474
|
-
if (!originAllowed(req
|
|
27362
|
+
if (!originAllowed(req)) {
|
|
27475
27363
|
req.resume();
|
|
27476
27364
|
return send(403, {});
|
|
27477
27365
|
}
|
|
@@ -27486,7 +27374,7 @@ var require_router4 = __commonJS({
|
|
|
27486
27374
|
return;
|
|
27487
27375
|
}
|
|
27488
27376
|
if (req.method === "POST" && pathname === "/router/providers/refresh") {
|
|
27489
|
-
if (!originAllowed(req
|
|
27377
|
+
if (!originAllowed(req)) {
|
|
27490
27378
|
req.resume();
|
|
27491
27379
|
return send(403, {});
|
|
27492
27380
|
}
|
|
@@ -27502,7 +27390,7 @@ var require_router4 = __commonJS({
|
|
|
27502
27390
|
return;
|
|
27503
27391
|
}
|
|
27504
27392
|
if (req.method === "POST" && pathname === "/router/providers/activate") {
|
|
27505
|
-
if (!originAllowed(req
|
|
27393
|
+
if (!originAllowed(req)) {
|
|
27506
27394
|
req.resume();
|
|
27507
27395
|
return send(403, {});
|
|
27508
27396
|
}
|
|
@@ -27518,7 +27406,7 @@ var require_router4 = __commonJS({
|
|
|
27518
27406
|
return;
|
|
27519
27407
|
}
|
|
27520
27408
|
if (req.method === "POST" && pathname === "/router/providers/deactivate") {
|
|
27521
|
-
if (!originAllowed(req
|
|
27409
|
+
if (!originAllowed(req)) {
|
|
27522
27410
|
req.resume();
|
|
27523
27411
|
return send(403, {});
|
|
27524
27412
|
}
|
|
@@ -27568,7 +27456,7 @@ var require_plugins = __commonJS({
|
|
|
27568
27456
|
return send(200, sup.pluginManager.installStatus(u.searchParams.get("job")));
|
|
27569
27457
|
}
|
|
27570
27458
|
if (req.method === "POST" && pathname.startsWith("/plugins/")) {
|
|
27571
|
-
if (!originAllowed(req
|
|
27459
|
+
if (!originAllowed(req)) {
|
|
27572
27460
|
req.resume();
|
|
27573
27461
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27574
27462
|
}
|
|
@@ -27644,7 +27532,7 @@ var require_dist = __commonJS({
|
|
|
27644
27532
|
return;
|
|
27645
27533
|
}
|
|
27646
27534
|
if (req.method === "POST" && pathname === "/dist/registry/set") {
|
|
27647
|
-
if (!originAllowed(req
|
|
27535
|
+
if (!originAllowed(req)) {
|
|
27648
27536
|
req.resume();
|
|
27649
27537
|
return send(403, {});
|
|
27650
27538
|
}
|
|
@@ -27663,7 +27551,7 @@ var require_dist = __commonJS({
|
|
|
27663
27551
|
return;
|
|
27664
27552
|
}
|
|
27665
27553
|
if (req.method === "POST" && pathname === "/dist/registry/refresh") {
|
|
27666
|
-
if (!originAllowed(req
|
|
27554
|
+
if (!originAllowed(req)) {
|
|
27667
27555
|
req.resume();
|
|
27668
27556
|
return send(403, {});
|
|
27669
27557
|
}
|
|
@@ -27671,7 +27559,7 @@ var require_dist = __commonJS({
|
|
|
27671
27559
|
return;
|
|
27672
27560
|
}
|
|
27673
27561
|
if (req.method === "POST" && pathname === "/dist/registry/probe") {
|
|
27674
|
-
if (!originAllowed(req
|
|
27562
|
+
if (!originAllowed(req)) {
|
|
27675
27563
|
req.resume();
|
|
27676
27564
|
return send(403, {});
|
|
27677
27565
|
}
|
|
@@ -27742,6 +27630,112 @@ var require_exchange = __commonJS({
|
|
|
27742
27630
|
}
|
|
27743
27631
|
});
|
|
27744
27632
|
|
|
27633
|
+
// src/platform/security/identity.js
|
|
27634
|
+
var require_identity2 = __commonJS({
|
|
27635
|
+
"src/platform/security/identity.js"(exports2, module2) {
|
|
27636
|
+
"use strict";
|
|
27637
|
+
var { normalizeRemoteAddress, isLoopbackAddress } = require_ip();
|
|
27638
|
+
function socketIsLoopback(req) {
|
|
27639
|
+
return isLoopbackAddress(req && req.socket && req.socket.remoteAddress);
|
|
27640
|
+
}
|
|
27641
|
+
function identify(req) {
|
|
27642
|
+
return {
|
|
27643
|
+
remote: normalizeRemoteAddress(req && req.socket && req.socket.remoteAddress),
|
|
27644
|
+
loopback: socketIsLoopback(req)
|
|
27645
|
+
};
|
|
27646
|
+
}
|
|
27647
|
+
module2.exports = { identify };
|
|
27648
|
+
}
|
|
27649
|
+
});
|
|
27650
|
+
|
|
27651
|
+
// src/api/identity.js
|
|
27652
|
+
var require_identity3 = __commonJS({
|
|
27653
|
+
"src/api/identity.js"(exports2, module2) {
|
|
27654
|
+
"use strict";
|
|
27655
|
+
var { normalizeRemoteAddress, isLoopbackAddress, isPrivateIpv4 } = require_ip();
|
|
27656
|
+
var { identify } = require_identity2();
|
|
27657
|
+
module2.exports = {
|
|
27658
|
+
identify,
|
|
27659
|
+
normalizeRemoteAddress,
|
|
27660
|
+
isPrivateIpv4,
|
|
27661
|
+
isLoopbackAddress
|
|
27662
|
+
};
|
|
27663
|
+
}
|
|
27664
|
+
});
|
|
27665
|
+
|
|
27666
|
+
// src/api/security.js
|
|
27667
|
+
var require_security = __commonJS({
|
|
27668
|
+
"src/api/security.js"(exports2, module2) {
|
|
27669
|
+
"use strict";
|
|
27670
|
+
var crypto = require("node:crypto");
|
|
27671
|
+
var { isPrivateIpv4 } = require_identity3();
|
|
27672
|
+
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
|
|
27673
|
+
function isLocalOrLanHost(h) {
|
|
27674
|
+
if (!h) return false;
|
|
27675
|
+
const s = String(h).toLowerCase();
|
|
27676
|
+
if (LOOPBACK_HOSTS.has(s)) return true;
|
|
27677
|
+
const bare = s.startsWith("[") && s.endsWith("]") ? s.slice(1, -1) : s;
|
|
27678
|
+
if (bare === "::1") return true;
|
|
27679
|
+
return isPrivateIpv4(bare);
|
|
27680
|
+
}
|
|
27681
|
+
function isShellOrigin(protocol, hostname) {
|
|
27682
|
+
const h = String(hostname || "").toLowerCase();
|
|
27683
|
+
if (protocol === "tauri:") return h === "localhost" || /(^|\.)tauri\.localhost$/.test(h);
|
|
27684
|
+
if (protocol === "http:" || protocol === "https:") return h === "tauri.localhost";
|
|
27685
|
+
return false;
|
|
27686
|
+
}
|
|
27687
|
+
function normalizeHostname(h) {
|
|
27688
|
+
const s = String(h || "").toLowerCase();
|
|
27689
|
+
return s.startsWith("[") && s.endsWith("]") ? s.slice(1, -1) : s;
|
|
27690
|
+
}
|
|
27691
|
+
function originAllowed(req, apiPort) {
|
|
27692
|
+
const host = req.headers.host;
|
|
27693
|
+
if (!host) return false;
|
|
27694
|
+
let hostname = "";
|
|
27695
|
+
{
|
|
27696
|
+
const m = /^(\[[^\]]+\]|[^:]+)(?::\d+)?$/.exec(String(host).trim());
|
|
27697
|
+
hostname = m ? m[1] : String(host).trim();
|
|
27698
|
+
if (!isLocalOrLanHost(hostname)) return false;
|
|
27699
|
+
}
|
|
27700
|
+
const o = req.headers.origin;
|
|
27701
|
+
if (!o) return true;
|
|
27702
|
+
try {
|
|
27703
|
+
const u = new URL(o);
|
|
27704
|
+
if (isShellOrigin(u.protocol, u.hostname)) return true;
|
|
27705
|
+
if (!isLocalOrLanHost(u.hostname)) return false;
|
|
27706
|
+
if (host && normalizeHostname(u.hostname) !== normalizeHostname(hostname)) return false;
|
|
27707
|
+
const port = u.port === "" ? u.protocol === "https:" ? "443" : "80" : u.port;
|
|
27708
|
+
return port === String(apiPort);
|
|
27709
|
+
} catch {
|
|
27710
|
+
return false;
|
|
27711
|
+
}
|
|
27712
|
+
}
|
|
27713
|
+
function safeKeyEqual(a, b) {
|
|
27714
|
+
const ha = crypto.createHash("sha256").update(String(a || "")).digest();
|
|
27715
|
+
const hb = crypto.createHash("sha256").update(String(b || "")).digest();
|
|
27716
|
+
return crypto.timingSafeEqual(ha, hb);
|
|
27717
|
+
}
|
|
27718
|
+
function requestHasAccessKey(req, key) {
|
|
27719
|
+
if (!key) return true;
|
|
27720
|
+
const ah = req.headers.authorization;
|
|
27721
|
+
if (typeof ah === "string" && ah.startsWith("Bearer ") && safeKeyEqual(ah.slice(7), key)) return true;
|
|
27722
|
+
try {
|
|
27723
|
+
const q = new URL(req.url, "http://localhost").searchParams.get("access_key");
|
|
27724
|
+
if (q && safeKeyEqual(q, key)) return true;
|
|
27725
|
+
} catch {
|
|
27726
|
+
}
|
|
27727
|
+
return false;
|
|
27728
|
+
}
|
|
27729
|
+
function liveApiPort(server, sup) {
|
|
27730
|
+
const live = server && typeof server.address === "function" ? server.address() : null;
|
|
27731
|
+
if (live && Number.isInteger(live.port) && live.port > 0) return live.port;
|
|
27732
|
+
const cfg = sup && sup.config && sup.config.apiPort;
|
|
27733
|
+
return Number.isInteger(cfg) ? cfg : null;
|
|
27734
|
+
}
|
|
27735
|
+
module2.exports = { originAllowed, isLocalOrLanHost, isShellOrigin, requestHasAccessKey, liveApiPort };
|
|
27736
|
+
}
|
|
27737
|
+
});
|
|
27738
|
+
|
|
27745
27739
|
// src/api/domains/instances.js
|
|
27746
27740
|
var require_instances = __commonJS({
|
|
27747
27741
|
"src/api/domains/instances.js"(exports2, module2) {
|
|
@@ -27749,6 +27743,7 @@ var require_instances = __commonJS({
|
|
|
27749
27743
|
var execPath = require_exec_path();
|
|
27750
27744
|
var crypto = require("node:crypto");
|
|
27751
27745
|
var { bootstrapDshCookie } = require_exchange();
|
|
27746
|
+
var { liveApiPort } = require_security();
|
|
27752
27747
|
var OPEN_WEB_CODES = /* @__PURE__ */ new Map();
|
|
27753
27748
|
var OPEN_WEB_CODE_TTL_MS = 3e4;
|
|
27754
27749
|
function _sweepExpiredOpenWebCodes() {
|
|
@@ -27782,16 +27777,16 @@ var require_instances = __commonJS({
|
|
|
27782
27777
|
return (sup.instances.list() || []).find((x) => x.id === id) || null;
|
|
27783
27778
|
}
|
|
27784
27779
|
function handleOpen(ctx) {
|
|
27785
|
-
const { sup, req, res, identity, originAllowed, tokOf } = ctx;
|
|
27780
|
+
const { sup, req, res, identity, originAllowed, tokOf, server } = ctx;
|
|
27786
27781
|
const url = new URL(req.url, "http://localhost");
|
|
27787
|
-
const apiPort = sup
|
|
27782
|
+
const apiPort = liveApiPort(server, sup);
|
|
27788
27783
|
const code = url.searchParams.get("code");
|
|
27789
27784
|
const deny = (status, msg) => {
|
|
27790
27785
|
res.writeHead(status, { "Content-Type": "text/plain; charset=utf-8" });
|
|
27791
27786
|
res.end(msg);
|
|
27792
27787
|
};
|
|
27793
27788
|
if (!identity.loopback) return deny(403, "\u4EC5\u5141\u8BB8\u672C\u673A\u8BBF\u95EE");
|
|
27794
|
-
if (!originAllowed(req
|
|
27789
|
+
if (!originAllowed(req)) return deny(403, "origin not allowed");
|
|
27795
27790
|
const rec = consumeOpenWebCode(code);
|
|
27796
27791
|
if (!rec) return deny(code ? 400 : 404, code ? "\u6388\u6743\u7801\u65E0\u6548\u6216\u5DF2\u8FC7\u671F" : "\u7F3A\u5C11\u6388\u6743\u7801");
|
|
27797
27792
|
const it = findInstanceOrMain(sup, rec.id);
|
|
@@ -27857,7 +27852,7 @@ var require_instances = __commonJS({
|
|
|
27857
27852
|
return sharedErr + "\uFF1B" + FORMS + "\uFF1B\u9700\u8981\u5176\u5B83\u53EF\u6267\u884C\u8BF7\u8D70\u63D2\u4EF6\u5B89\u88C5\u901A\u9053";
|
|
27858
27853
|
}
|
|
27859
27854
|
function handle(ctx) {
|
|
27860
|
-
const { sup, req, res, pathname, identity, send, collectBody, originAllowed, tokOf, browser } = ctx;
|
|
27855
|
+
const { sup, req, res, pathname, identity, send, collectBody, originAllowed, tokOf, browser, server } = ctx;
|
|
27861
27856
|
function openInSystemBrowser(url) {
|
|
27862
27857
|
return browser.openBrowser(url, { logger: sup.logger });
|
|
27863
27858
|
}
|
|
@@ -27884,7 +27879,7 @@ var require_instances = __commonJS({
|
|
|
27884
27879
|
return render();
|
|
27885
27880
|
}
|
|
27886
27881
|
if (req.method === "POST" && pathname.startsWith("/instances/")) {
|
|
27887
|
-
if (!originAllowed(req
|
|
27882
|
+
if (!originAllowed(req)) {
|
|
27888
27883
|
req.resume();
|
|
27889
27884
|
return send(403, {});
|
|
27890
27885
|
}
|
|
@@ -27921,7 +27916,7 @@ var require_instances = __commonJS({
|
|
|
27921
27916
|
if (!it) return send(404, { ok: false, error: "\u5B9E\u4F8B\u4E0D\u5B58\u5728" });
|
|
27922
27917
|
if (!(Number(it.port) > 0)) return send(400, { ok: false, error: "\u975E\u6CD5\u7AEF\u53E3" });
|
|
27923
27918
|
const code = issueOpenWebCode(j.id);
|
|
27924
|
-
const url = "http://127.0.0.1:" + sup.config.apiPort + "/open?code=" + code;
|
|
27919
|
+
const url = "http://127.0.0.1:" + (liveApiPort(server, sup) || sup.config.apiPort) + "/open?code=" + code;
|
|
27925
27920
|
return Promise.resolve(openInSystemBrowser(url)).then((r) => {
|
|
27926
27921
|
if (!r.ok) dropOpenWebCode(code);
|
|
27927
27922
|
return send(r.ok ? 200 : 500, r);
|
|
@@ -27966,7 +27961,7 @@ var require_relay = __commonJS({
|
|
|
27966
27961
|
return Promise.resolve(sup.listLan()).then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
27967
27962
|
}
|
|
27968
27963
|
if (req.method === "POST" && pathname.startsWith("/remote/")) {
|
|
27969
|
-
if (!originAllowed(req
|
|
27964
|
+
if (!originAllowed(req)) {
|
|
27970
27965
|
req.resume();
|
|
27971
27966
|
return send(403, {});
|
|
27972
27967
|
}
|
|
@@ -28029,7 +28024,7 @@ var require_shell2 = __commonJS({
|
|
|
28029
28024
|
}
|
|
28030
28025
|
}
|
|
28031
28026
|
if (req.method === "POST" && pathname === "/shell/health") {
|
|
28032
|
-
if (!originAllowed(req
|
|
28027
|
+
if (!originAllowed(req)) {
|
|
28033
28028
|
req.resume();
|
|
28034
28029
|
return send(403, {});
|
|
28035
28030
|
}
|
|
@@ -28046,28 +28041,8 @@ var require_shell2 = __commonJS({
|
|
|
28046
28041
|
}
|
|
28047
28042
|
});
|
|
28048
28043
|
}
|
|
28049
|
-
if (req.method === "POST" && pathname === "/shell/update-pending") {
|
|
28050
|
-
if (!originAllowed(req, sup.config.apiPort)) {
|
|
28051
|
-
req.resume();
|
|
28052
|
-
return send(403, {});
|
|
28053
|
-
}
|
|
28054
|
-
return collectBody(req, res, 8192, (body) => {
|
|
28055
|
-
let j = {};
|
|
28056
|
-
try {
|
|
28057
|
-
j = body ? JSON.parse(body) : {};
|
|
28058
|
-
} catch {
|
|
28059
|
-
}
|
|
28060
|
-
try {
|
|
28061
|
-
const rec = shell.markPending(j.from || null, j.to || null);
|
|
28062
|
-
if (sup.events) sup.events.append(BRAND2.EVENT_SHELL_UPDATE_PENDING, { from: rec.from, to: rec.to });
|
|
28063
|
-
return send(200, { ok: true, journal: rec });
|
|
28064
|
-
} catch (e) {
|
|
28065
|
-
return send(500, { ok: false, error: e.message });
|
|
28066
|
-
}
|
|
28067
|
-
});
|
|
28068
|
-
}
|
|
28069
28044
|
if (req.method === "POST" && pathname === "/shell/check-update") {
|
|
28070
|
-
if (!originAllowed(req
|
|
28045
|
+
if (!originAllowed(req)) {
|
|
28071
28046
|
req.resume();
|
|
28072
28047
|
return send(403, {});
|
|
28073
28048
|
}
|
|
@@ -28079,23 +28054,6 @@ var require_shell2 = __commonJS({
|
|
|
28079
28054
|
return send(200, r);
|
|
28080
28055
|
}).catch((e) => send(500, { ok: false, error: e.message }));
|
|
28081
28056
|
}
|
|
28082
|
-
if (req.method === "POST" && pathname === "/shell/restart") {
|
|
28083
|
-
if (!originAllowed(req, sup.config.apiPort)) {
|
|
28084
|
-
req.resume();
|
|
28085
|
-
return send(403, {});
|
|
28086
|
-
}
|
|
28087
|
-
if (typeof sup._sessionHalting === "function" && sup._sessionHalting()) {
|
|
28088
|
-
req.resume();
|
|
28089
|
-
return send(409, { ok: false, error: "\u4F1A\u8BDD\u5DF2\u9000\u51FA/\u9000\u51FA\u4E2D\uFF0C\u62D2\u7EDD\u91CD\u542F\u684C\u9762\u58F3" });
|
|
28090
|
-
}
|
|
28091
|
-
req.resume();
|
|
28092
|
-
return Promise.resolve(shell.restartShell({
|
|
28093
|
-
shouldAbort: () => typeof sup._sessionHalting === "function" && sup._sessionHalting()
|
|
28094
|
-
})).then((r) => {
|
|
28095
|
-
if (sup.events) sup.events.append(BRAND2.EVENT_SHELL_RESTART_REQUESTED, { ok: r.ok, killed: r.killed || [], pid: r.pid || null });
|
|
28096
|
-
return send(r.ok ? 200 : 500, r);
|
|
28097
|
-
}).catch((e) => send(500, { ok: false, error: e.message }));
|
|
28098
|
-
}
|
|
28099
28057
|
if (req.method === "GET" || req.method === "POST") return send(404, { error: "not found", path: pathname });
|
|
28100
28058
|
return send(405, { error: "method not allowed" });
|
|
28101
28059
|
}
|
|
@@ -28259,106 +28217,6 @@ var require_static = __commonJS({
|
|
|
28259
28217
|
}
|
|
28260
28218
|
});
|
|
28261
28219
|
|
|
28262
|
-
// src/platform/security/identity.js
|
|
28263
|
-
var require_identity2 = __commonJS({
|
|
28264
|
-
"src/platform/security/identity.js"(exports2, module2) {
|
|
28265
|
-
"use strict";
|
|
28266
|
-
var { normalizeRemoteAddress, isLoopbackAddress } = require_ip();
|
|
28267
|
-
function socketIsLoopback(req) {
|
|
28268
|
-
return isLoopbackAddress(req && req.socket && req.socket.remoteAddress);
|
|
28269
|
-
}
|
|
28270
|
-
function identify(req) {
|
|
28271
|
-
return {
|
|
28272
|
-
remote: normalizeRemoteAddress(req && req.socket && req.socket.remoteAddress),
|
|
28273
|
-
loopback: socketIsLoopback(req)
|
|
28274
|
-
};
|
|
28275
|
-
}
|
|
28276
|
-
module2.exports = { identify };
|
|
28277
|
-
}
|
|
28278
|
-
});
|
|
28279
|
-
|
|
28280
|
-
// src/api/identity.js
|
|
28281
|
-
var require_identity3 = __commonJS({
|
|
28282
|
-
"src/api/identity.js"(exports2, module2) {
|
|
28283
|
-
"use strict";
|
|
28284
|
-
var { normalizeRemoteAddress, isLoopbackAddress, isPrivateIpv4 } = require_ip();
|
|
28285
|
-
var { identify } = require_identity2();
|
|
28286
|
-
module2.exports = {
|
|
28287
|
-
identify,
|
|
28288
|
-
normalizeRemoteAddress,
|
|
28289
|
-
isPrivateIpv4,
|
|
28290
|
-
isLoopbackAddress
|
|
28291
|
-
};
|
|
28292
|
-
}
|
|
28293
|
-
});
|
|
28294
|
-
|
|
28295
|
-
// src/api/security.js
|
|
28296
|
-
var require_security = __commonJS({
|
|
28297
|
-
"src/api/security.js"(exports2, module2) {
|
|
28298
|
-
"use strict";
|
|
28299
|
-
var crypto = require("node:crypto");
|
|
28300
|
-
var { isPrivateIpv4 } = require_identity3();
|
|
28301
|
-
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
|
|
28302
|
-
function isLocalOrLanHost(h) {
|
|
28303
|
-
if (!h) return false;
|
|
28304
|
-
const s = String(h).toLowerCase();
|
|
28305
|
-
if (LOOPBACK_HOSTS.has(s)) return true;
|
|
28306
|
-
const bare = s.startsWith("[") && s.endsWith("]") ? s.slice(1, -1) : s;
|
|
28307
|
-
if (bare === "::1") return true;
|
|
28308
|
-
return isPrivateIpv4(bare);
|
|
28309
|
-
}
|
|
28310
|
-
function isShellOrigin(protocol, hostname) {
|
|
28311
|
-
const h = String(hostname || "").toLowerCase();
|
|
28312
|
-
if (protocol === "tauri:") return h === "localhost" || /(^|\.)tauri\.localhost$/.test(h);
|
|
28313
|
-
if (protocol === "http:" || protocol === "https:") return h === "tauri.localhost";
|
|
28314
|
-
return false;
|
|
28315
|
-
}
|
|
28316
|
-
function normalizeHostname(h) {
|
|
28317
|
-
const s = String(h || "").toLowerCase();
|
|
28318
|
-
return s.startsWith("[") && s.endsWith("]") ? s.slice(1, -1) : s;
|
|
28319
|
-
}
|
|
28320
|
-
function originAllowed(req, apiPort) {
|
|
28321
|
-
const host = req.headers.host;
|
|
28322
|
-
if (!host) return false;
|
|
28323
|
-
let hostname = "";
|
|
28324
|
-
{
|
|
28325
|
-
const m = /^(\[[^\]]+\]|[^:]+)(?::\d+)?$/.exec(String(host).trim());
|
|
28326
|
-
hostname = m ? m[1] : String(host).trim();
|
|
28327
|
-
if (!isLocalOrLanHost(hostname)) return false;
|
|
28328
|
-
}
|
|
28329
|
-
const o = req.headers.origin;
|
|
28330
|
-
if (!o) return true;
|
|
28331
|
-
try {
|
|
28332
|
-
const u = new URL(o);
|
|
28333
|
-
if (isShellOrigin(u.protocol, u.hostname)) return true;
|
|
28334
|
-
if (!isLocalOrLanHost(u.hostname)) return false;
|
|
28335
|
-
if (host && normalizeHostname(u.hostname) !== normalizeHostname(hostname)) return false;
|
|
28336
|
-
const port = u.port === "" ? u.protocol === "https:" ? "443" : "80" : u.port;
|
|
28337
|
-
return port === String(apiPort);
|
|
28338
|
-
} catch {
|
|
28339
|
-
return false;
|
|
28340
|
-
}
|
|
28341
|
-
}
|
|
28342
|
-
function safeKeyEqual(a, b) {
|
|
28343
|
-
const ha = crypto.createHash("sha256").update(String(a || "")).digest();
|
|
28344
|
-
const hb = crypto.createHash("sha256").update(String(b || "")).digest();
|
|
28345
|
-
return crypto.timingSafeEqual(ha, hb);
|
|
28346
|
-
}
|
|
28347
|
-
function requestHasAccessKey(req, key) {
|
|
28348
|
-
if (!key) return true;
|
|
28349
|
-
const ah = req.headers.authorization;
|
|
28350
|
-
if (typeof ah === "string" && ah.startsWith("Bearer ") && safeKeyEqual(ah.slice(7), key)) return true;
|
|
28351
|
-
try {
|
|
28352
|
-
const q = new URL(req.url, "http://localhost").searchParams.get("access_key");
|
|
28353
|
-
if (q && safeKeyEqual(q, key)) return true;
|
|
28354
|
-
} catch {
|
|
28355
|
-
}
|
|
28356
|
-
return false;
|
|
28357
|
-
}
|
|
28358
|
-
module2.exports = { originAllowed, isLocalOrLanHost, isShellOrigin, requestHasAccessKey };
|
|
28359
|
-
}
|
|
28360
|
-
});
|
|
28361
|
-
|
|
28362
28220
|
// src/api/transport/server.js
|
|
28363
28221
|
var require_server = __commonJS({
|
|
28364
28222
|
"src/api/transport/server.js"(exports2, module2) {
|
|
@@ -28368,7 +28226,7 @@ var require_server = __commonJS({
|
|
|
28368
28226
|
var { collectBody } = require_body();
|
|
28369
28227
|
var { serveStatic } = require_static();
|
|
28370
28228
|
var { identify } = require_identity3();
|
|
28371
|
-
var { originAllowed, requestHasAccessKey, isShellOrigin } = require_security();
|
|
28229
|
+
var { originAllowed, requestHasAccessKey, isShellOrigin, liveApiPort } = require_security();
|
|
28372
28230
|
var browserExit = require_browser();
|
|
28373
28231
|
var environmentExit = require_environment();
|
|
28374
28232
|
function safeFail(res, err, where) {
|
|
@@ -28391,7 +28249,7 @@ var require_server = __commonJS({
|
|
|
28391
28249
|
function createServer(sup, deps) {
|
|
28392
28250
|
const browser = deps && deps.browser || browserExit;
|
|
28393
28251
|
const environment = deps && deps.environment || environmentExit;
|
|
28394
|
-
|
|
28252
|
+
const server = http2.createServer((req, res) => {
|
|
28395
28253
|
const shellOrigin = (() => {
|
|
28396
28254
|
const o = req.headers.origin;
|
|
28397
28255
|
if (!o) return null;
|
|
@@ -28421,6 +28279,7 @@ var require_server = __commonJS({
|
|
|
28421
28279
|
return "";
|
|
28422
28280
|
};
|
|
28423
28281
|
const identity = identify(req);
|
|
28282
|
+
const originAllowedLive = (req2) => originAllowed(req2, liveApiPort(server, sup));
|
|
28424
28283
|
const accessKey = sup && sup.config && sup.config.apiAccessKey || null;
|
|
28425
28284
|
if (!identity.loopback && req.method !== "OPTIONS" && (!accessKey || !requestHasAccessKey(req, accessKey))) {
|
|
28426
28285
|
res.writeHead(401, { "Content-Type": "application/json" });
|
|
@@ -28458,7 +28317,7 @@ var require_server = __commonJS({
|
|
|
28458
28317
|
} catch (e) {
|
|
28459
28318
|
return send(400, { error: "bad request encoding" });
|
|
28460
28319
|
}
|
|
28461
|
-
const ctx = { sup, req, res, pathname: decodedPathname, identity, send, collectBody, originAllowed, tokOf, browser, environment };
|
|
28320
|
+
const ctx = { sup, req, res, pathname: decodedPathname, identity, send, collectBody, originAllowed: originAllowedLive, tokOf, browser, environment, server };
|
|
28462
28321
|
for (const d of API_DOMAINS) {
|
|
28463
28322
|
if (d.owns(pathname)) {
|
|
28464
28323
|
try {
|
|
@@ -28484,6 +28343,7 @@ var require_server = __commonJS({
|
|
|
28484
28343
|
}
|
|
28485
28344
|
return send(405, { error: "method not allowed" });
|
|
28486
28345
|
});
|
|
28346
|
+
return server;
|
|
28487
28347
|
}
|
|
28488
28348
|
module2.exports = { createServer };
|
|
28489
28349
|
}
|
|
@@ -28503,7 +28363,7 @@ var require_api = __commonJS({
|
|
|
28503
28363
|
var require_session = __commonJS({
|
|
28504
28364
|
"src/domains/relay/session.js"(exports2, module2) {
|
|
28505
28365
|
"use strict";
|
|
28506
|
-
var { cookieByName } =
|
|
28366
|
+
var { cookieByName } = require_core3();
|
|
28507
28367
|
var { bootstrapDshCookie } = require_exchange();
|
|
28508
28368
|
function createSession(opts) {
|
|
28509
28369
|
const o = opts || {};
|
|
@@ -28645,7 +28505,7 @@ var require_tunnel = __commonJS({
|
|
|
28645
28505
|
"src/domains/relay/tunnel.js"(exports2, module2) {
|
|
28646
28506
|
"use strict";
|
|
28647
28507
|
var net = require("node:net");
|
|
28648
|
-
var { isTrustedSource, hasValidToken, upstreamPath } =
|
|
28508
|
+
var { isTrustedSource, hasValidToken, upstreamPath } = require_core3();
|
|
28649
28509
|
function buildRawRequest(req, authority, cookie) {
|
|
28650
28510
|
let raw = req.method + " " + upstreamPath(req.url) + " HTTP/1.1\r\n";
|
|
28651
28511
|
for (const [k, v] of Object.entries(req.headers)) {
|
|
@@ -28731,7 +28591,7 @@ var require_proxy2 = __commonJS({
|
|
|
28731
28591
|
"use strict";
|
|
28732
28592
|
var http2 = require("node:http");
|
|
28733
28593
|
var crypto = require("node:crypto");
|
|
28734
|
-
var { isTrustedSource, tokenGateDecision, backoffGate, upstreamPath, redactLogPath, normalizeRemoteMode, POLYFILL_SCRIPT } =
|
|
28594
|
+
var { isTrustedSource, tokenGateDecision, backoffGate, upstreamPath, redactLogPath, normalizeRemoteMode, POLYFILL_SCRIPT } = require_core3();
|
|
28735
28595
|
var { createSession } = require_session();
|
|
28736
28596
|
var { createTunnelHandler } = require_tunnel();
|
|
28737
28597
|
var HTML_INJECT_MAX_BYTES = 2 * 1024 * 1024;
|
|
@@ -28756,7 +28616,7 @@ var require_proxy2 = __commonJS({
|
|
|
28756
28616
|
}
|
|
28757
28617
|
};
|
|
28758
28618
|
}
|
|
28759
|
-
function pipeWithHold(ur, res,
|
|
28619
|
+
function pipeWithHold(ur, res, clientReqLog, logger) {
|
|
28760
28620
|
let clientGone = false;
|
|
28761
28621
|
const log = (lv, msg) => {
|
|
28762
28622
|
if (logger && logger[lv]) {
|
|
@@ -28805,7 +28665,7 @@ var require_proxy2 = __commonJS({
|
|
|
28805
28665
|
return headers;
|
|
28806
28666
|
}
|
|
28807
28667
|
function handleUpstream(ur, res, clientReqPath, onStatus, logger) {
|
|
28808
|
-
const
|
|
28668
|
+
const clientReqLog = redactLogPath(clientReqPath);
|
|
28809
28669
|
if (onStatus) onStatus(ur.statusCode);
|
|
28810
28670
|
const h = { ...ur.headers };
|
|
28811
28671
|
const isHtml = String(h["content-type"] || "").includes("text/html");
|
|
@@ -28817,7 +28677,7 @@ var require_proxy2 = __commonJS({
|
|
|
28817
28677
|
}
|
|
28818
28678
|
res.writeHead(ur.statusCode || 502, h);
|
|
28819
28679
|
if (!isHtml) {
|
|
28820
|
-
pipeWithHold(ur, res,
|
|
28680
|
+
pipeWithHold(ur, res, clientReqLog, logger);
|
|
28821
28681
|
return;
|
|
28822
28682
|
}
|
|
28823
28683
|
const chunks = [];
|
|
@@ -28851,7 +28711,7 @@ var require_proxy2 = __commonJS({
|
|
|
28851
28711
|
chunks.push(c);
|
|
28852
28712
|
return;
|
|
28853
28713
|
}
|
|
28854
|
-
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 " + (
|
|
28714
|
+
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 || ""));
|
|
28855
28715
|
const selfForward = !ur.readableEnded;
|
|
28856
28716
|
switchToPassThrough();
|
|
28857
28717
|
if (selfForward) res.write(c);
|
|
@@ -29031,14 +28891,8 @@ var require_ports3 = __commonJS({
|
|
|
29031
28891
|
return registry.claimSlot(segment, owner, {
|
|
29032
28892
|
preferred: o.preferred,
|
|
29033
28893
|
bindingPreferred: !!o.bindingPreferred,
|
|
29034
|
-
// RL-4:跨账本防撞。router caller 不传 reservedPorts(分配器跳过该检查,行为不变);
|
|
29035
|
-
// 仅 relay 传入 router 账本已占端口,free-scan/preferred-claim 跳过 ⇒ 不会抢 router 的端口。
|
|
29036
28894
|
reservedPorts: reservedPorts || void 0,
|
|
29037
28895
|
onBindingLost: o.onBindingLost,
|
|
29038
|
-
// 审计 RL-3:reclaimCmdMark 必须出现在 relay daemon 的真实命令行里,否则 pgrepList 永远匹配不到 ⇒ 回收是死代码。
|
|
29039
|
-
// relay daemon 经 runtime.js 以 `node .../domains/relay/daemon.js -c <cfg>` 拉起(scripts.js:8),
|
|
29040
|
-
// 命令行含 `domains/relay/daemon.js`(与 process.js#reclaimOrphans 用的 _cmdMarks 同源),故此处用同一标记。
|
|
29041
|
-
// configPath 为空时 fail-closed 不回收:宁可留占用走冲突分支,也不按 cmdMark 误杀同名进程(reclaimByCmdMark 内部也已要求 cfgStr 必填)。
|
|
29042
28896
|
reclaimCmdMark: "domains/relay/daemon.js",
|
|
29043
28897
|
reclaimCfg: o.configPath || "",
|
|
29044
28898
|
waitMs: 8e3
|
|
@@ -29237,7 +29091,7 @@ var require_frp = __commonJS({
|
|
|
29237
29091
|
var path2 = require("node:path");
|
|
29238
29092
|
var spawnOS = require_spawn();
|
|
29239
29093
|
var { writeAtomic } = require_fs();
|
|
29240
|
-
var { buildFrpcToml, validateFrpServerSettings } =
|
|
29094
|
+
var { buildFrpcToml, validateFrpServerSettings } = require_core3();
|
|
29241
29095
|
var { frpPlatformTag, download, installFrpc } = require_frp_install();
|
|
29242
29096
|
var FrpManager = class {
|
|
29243
29097
|
constructor(opts) {
|
|
@@ -29681,7 +29535,7 @@ var require_ops5 = __commonJS({
|
|
|
29681
29535
|
var managed = require_managed();
|
|
29682
29536
|
var portsvc = require_ports3();
|
|
29683
29537
|
var { FrpManager } = require_frp();
|
|
29684
|
-
var { normalizeRemoteMode, validateWanAccess, normalizeFrpSettings, validateFrpServerSettings, projectRemoteView } =
|
|
29538
|
+
var { normalizeRemoteMode, validateWanAccess, normalizeFrpSettings, validateFrpServerSettings, projectRemoteView } = require_core3();
|
|
29685
29539
|
var reconcile = require_reconcile();
|
|
29686
29540
|
var lanServers = require_lan_servers();
|
|
29687
29541
|
function applyRelayToken(host, existing, want) {
|