@lob-ox/core-darwin-x64 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -5
- package/bin/lobox +0 -2
- package/core.cjs +811 -975
- 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.10");
|
|
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);
|
|
@@ -8559,7 +8424,7 @@ var require_bootstrap = __commonJS({
|
|
|
8559
8424
|
}
|
|
8560
8425
|
}
|
|
8561
8426
|
}
|
|
8562
|
-
module2.exports = { _bootstrap,
|
|
8427
|
+
module2.exports = { _bootstrap, _registerFixedPorts, _bindNativeDshCommand, _refreshEnvironmentForm };
|
|
8563
8428
|
}
|
|
8564
8429
|
});
|
|
8565
8430
|
|
|
@@ -8615,14 +8480,17 @@ var require_api_rebind = __commonJS({
|
|
|
8615
8480
|
});
|
|
8616
8481
|
server.listen(host.config.apiPort, host.config.apiHost, () => {
|
|
8617
8482
|
bind._tries = 0;
|
|
8483
|
+
const bound = server.address();
|
|
8484
|
+
const realPort = bound && Number.isInteger(bound.port) ? bound.port : host.config.apiPort;
|
|
8618
8485
|
host.api = server;
|
|
8486
|
+
if (realPort !== host.config.apiPort) host.config.apiPort = realPort;
|
|
8619
8487
|
try {
|
|
8620
|
-
portsShared.registerSole("supervisor-api",
|
|
8488
|
+
portsShared.registerSole("supervisor-api", realPort);
|
|
8621
8489
|
} catch (e) {
|
|
8622
8490
|
host.logger.warn("ports.registerSole(supervisor-api) \u5931\u8D25: " + (e && e.message || e));
|
|
8623
8491
|
}
|
|
8624
|
-
host.events.append("api_listening", { host: host.config.apiHost, port:
|
|
8625
|
-
host.logger.info("api listening on " + host.config.apiHost + ":" +
|
|
8492
|
+
host.events.append("api_listening", { host: host.config.apiHost, port: realPort });
|
|
8493
|
+
host.logger.info("api listening on " + host.config.apiHost + ":" + realPort);
|
|
8626
8494
|
});
|
|
8627
8495
|
};
|
|
8628
8496
|
bind._tries = 0;
|
|
@@ -8644,19 +8512,21 @@ var require_api_rebind = __commonJS({
|
|
|
8644
8512
|
host.logger.error("api error: " + (err ? err.message : String(err)));
|
|
8645
8513
|
});
|
|
8646
8514
|
server.listen(port, host.config.apiHost, () => {
|
|
8515
|
+
const bound = server.address();
|
|
8516
|
+
const realPort = bound && Number.isInteger(bound.port) ? bound.port : port;
|
|
8647
8517
|
host.api = server;
|
|
8648
8518
|
const prev = host.config.apiPort;
|
|
8649
|
-
if (
|
|
8650
|
-
host.config.apiPort =
|
|
8651
|
-
if (host.configPath) host.persistConfigPatch({ apiPort:
|
|
8519
|
+
if (realPort !== prev) {
|
|
8520
|
+
host.config.apiPort = realPort;
|
|
8521
|
+
if (host.configPath) host.persistConfigPatch({ apiPort: realPort });
|
|
8652
8522
|
}
|
|
8653
8523
|
try {
|
|
8654
|
-
portsShared.registerSole("supervisor-api",
|
|
8524
|
+
portsShared.registerSole("supervisor-api", realPort);
|
|
8655
8525
|
} catch (e) {
|
|
8656
8526
|
host.logger.warn("ports.registerSole(supervisor-api) \u5931\u8D25: " + e.message);
|
|
8657
8527
|
}
|
|
8658
|
-
host.events.append("api_listening", { host: host.config.apiHost, port });
|
|
8659
|
-
host.logger.info("api listening on " + host.config.apiHost + ":" +
|
|
8528
|
+
host.events.append("api_listening", { host: host.config.apiHost, port: realPort });
|
|
8529
|
+
host.logger.info("api listening on " + host.config.apiHost + ":" + realPort);
|
|
8660
8530
|
});
|
|
8661
8531
|
return server;
|
|
8662
8532
|
};
|
|
@@ -10099,14 +9969,10 @@ var require_shutdown = __commonJS({
|
|
|
10099
9969
|
host.events.append("guard_exit", {});
|
|
10100
9970
|
host.logger.info("guard shutting down");
|
|
10101
9971
|
host.writeState(true);
|
|
10102
|
-
if (host.
|
|
10103
|
-
if (host._heartbeatTimer) clearInterval(host._heartbeatTimer);
|
|
9972
|
+
if (host._beatScheduler) host._beatScheduler.stop();
|
|
10104
9973
|
if (host._killTimer) clearTimeout(host._killTimer);
|
|
10105
9974
|
if (host._adoptKillTimer) clearTimeout(host._adoptKillTimer);
|
|
10106
9975
|
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
9976
|
if (host.api) {
|
|
10111
9977
|
try {
|
|
10112
9978
|
host.api.close();
|
|
@@ -10151,37 +10017,10 @@ var require_shutdown = __commonJS({
|
|
|
10151
10017
|
} catch (e) {
|
|
10152
10018
|
host.logger.warn && host.logger.warn("shutdownAll persist shellHalted: " + e.message);
|
|
10153
10019
|
}
|
|
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
10020
|
host.logger.info("[session] \u9000\u51FA\u6D41\u7A0B\u5F00\u59CB\uFF1A\u505C\u6B62\u5168\u90E8\u88AB\u7BA1\u5BF9\u8C61\u2026");
|
|
10183
10021
|
host.events && host.events.append("shutdown_all", {});
|
|
10184
10022
|
abortInflightNpm(host, "session-exit");
|
|
10023
|
+
if (host._beatScheduler) host._beatScheduler.stop();
|
|
10185
10024
|
host._stopMainDsh();
|
|
10186
10025
|
await host._stopAllSandboxes();
|
|
10187
10026
|
const stopDaemon = async (kind) => {
|
|
@@ -10417,6 +10256,12 @@ var require_instance_adapter = __commonJS({
|
|
|
10417
10256
|
} catch (e) {
|
|
10418
10257
|
d.logger() && d.logger().warn && d.logger().warn("sandbox setPhase: " + (e && e.message || e));
|
|
10419
10258
|
}
|
|
10259
|
+
try {
|
|
10260
|
+
const rc = Number(inst.state && inst.state.restartCount) || 0;
|
|
10261
|
+
if (entry.restartCount !== rc) d.managedObjects().setRestartCount(entry.id, rc);
|
|
10262
|
+
} catch (e) {
|
|
10263
|
+
d.logger() && d.logger().warn && d.logger().warn("sandbox setRestartCount: " + (e && e.message || e));
|
|
10264
|
+
}
|
|
10420
10265
|
}
|
|
10421
10266
|
}
|
|
10422
10267
|
};
|
|
@@ -11034,6 +10879,7 @@ var require_process2 = __commonJS({
|
|
|
11034
10879
|
var native = require_command();
|
|
11035
10880
|
var BRAND2 = require_brand();
|
|
11036
10881
|
var { findManagedDshPort, applyMainPort } = require_port_rederive();
|
|
10882
|
+
var pmClient = require_pm_client();
|
|
11037
10883
|
var DEPS = /* @__PURE__ */ new WeakMap();
|
|
11038
10884
|
var HELPERS = [
|
|
11039
10885
|
"MissingNotified",
|
|
@@ -11089,7 +10935,6 @@ var require_process2 = __commonJS({
|
|
|
11089
10935
|
const d = depsOf(this);
|
|
11090
10936
|
return native.nativeCommand(d.config(), d.pluginManager());
|
|
11091
10937
|
},
|
|
11092
|
-
// 启动窗口(毫秒):唯一的时间常量,spawn 时落成 startDeadline,窗口内退出即「启动失败」。
|
|
11093
10938
|
startWindowMs() {
|
|
11094
10939
|
const d = depsOf(this);
|
|
11095
10940
|
const secs = Number(d.config().startsecs);
|
|
@@ -11169,6 +11014,7 @@ var require_process2 = __commonJS({
|
|
|
11169
11014
|
errBuf.flush();
|
|
11170
11015
|
if (d.mChild() !== child) return;
|
|
11171
11016
|
d.events().append(BRAND2.EVENT_HARNESS_EXITED, { code, signal, phase: d.state().phase() });
|
|
11017
|
+
pmClient.recordExit("main", code, signal, d.state().phase() === "STARTING");
|
|
11172
11018
|
d.mSetChild(null);
|
|
11173
11019
|
if (d.stopping()) return;
|
|
11174
11020
|
if (d.state().desired() !== "running") return;
|
|
@@ -11178,6 +11024,7 @@ var require_process2 = __commonJS({
|
|
|
11178
11024
|
const why = code !== null ? String(code) : "sig" + signal;
|
|
11179
11025
|
const inStartup = phase === "STARTING";
|
|
11180
11026
|
if (inStartup || d.state().guardian()) {
|
|
11027
|
+
pmClient.requestRestart("main");
|
|
11181
11028
|
d.beginRestart("exit:" + why, { startupFailure: inStartup });
|
|
11182
11029
|
} else {
|
|
11183
11030
|
d.writeCrashHalted(true);
|
|
@@ -11254,8 +11101,6 @@ var require_process2 = __commonJS({
|
|
|
11254
11101
|
d.tokenService().scheduleCapture("main");
|
|
11255
11102
|
d.state().write();
|
|
11256
11103
|
},
|
|
11257
|
-
// 重启:活过 startsecs 后退出(或人工重启)⇒ 正常重启,不记启动失败;窗口内退出 ⇒ 记一次启动失败并由限流裁决。
|
|
11258
|
-
// 相位只有 STARTING / RUNNING / FAILED:重启=回到 STARTING(下一次 spawn 会开新的 startsecs 窗口)。
|
|
11259
11104
|
_beginRestart(reason, opts) {
|
|
11260
11105
|
const d = depsOf(this);
|
|
11261
11106
|
const manual = !!(opts && opts.manual);
|
|
@@ -11396,7 +11241,6 @@ var require_signals = __commonJS({
|
|
|
11396
11241
|
return null;
|
|
11397
11242
|
}
|
|
11398
11243
|
},
|
|
11399
|
-
// 归属凭据:spawn 与 adopt 两条取得所有权的路线都要写;落盘走 writeAtomic + 0600。
|
|
11400
11244
|
_writeMainOwner(dshPid, port) {
|
|
11401
11245
|
const d = depsOf(this);
|
|
11402
11246
|
try {
|
|
@@ -11452,7 +11296,6 @@ var require_signals = __commonJS({
|
|
|
11452
11296
|
}
|
|
11453
11297
|
}, d.config().stopGraceMs));
|
|
11454
11298
|
},
|
|
11455
|
-
// 代际 gen 保护共享的 _adoptKillTimer 槽位:定时器只在「本代仍是当前代」时置空。
|
|
11456
11299
|
_killAdopted(pid) {
|
|
11457
11300
|
const d = depsOf(this);
|
|
11458
11301
|
const gen = (d.readAdoptKillGen() || 0) + 1;
|
|
@@ -11517,7 +11360,35 @@ var require_guardian = __commonJS({
|
|
|
11517
11360
|
}
|
|
11518
11361
|
return { start, count, tripped: count >= burst };
|
|
11519
11362
|
}
|
|
11520
|
-
|
|
11363
|
+
function makeBudget(cfg) {
|
|
11364
|
+
const windowMs = cfg && Number(cfg.windowMs) > 0 ? Number(cfg.windowMs) : 6e4;
|
|
11365
|
+
const burst = cfg && Number(cfg.burst) >= 1 ? Number(cfg.burst) : 5;
|
|
11366
|
+
let state = { start: null, count: 0 };
|
|
11367
|
+
const self = {
|
|
11368
|
+
windowMs,
|
|
11369
|
+
burst,
|
|
11370
|
+
get count() {
|
|
11371
|
+
return state.count;
|
|
11372
|
+
},
|
|
11373
|
+
get tripped() {
|
|
11374
|
+
return state.count >= burst;
|
|
11375
|
+
},
|
|
11376
|
+
note(startupFailure) {
|
|
11377
|
+
if (startupFailure === false || startupFailure == null) {
|
|
11378
|
+
return { tripped: false, count: state.count, halted: false };
|
|
11379
|
+
}
|
|
11380
|
+
const dec = bumpStartupFailure(state, Date.now(), { windowMs, burst });
|
|
11381
|
+
state.start = dec.start;
|
|
11382
|
+
state.count = dec.count;
|
|
11383
|
+
return { tripped: dec.tripped, count: state.count, halted: dec.tripped };
|
|
11384
|
+
},
|
|
11385
|
+
reset() {
|
|
11386
|
+
state = { start: null, count: 0 };
|
|
11387
|
+
}
|
|
11388
|
+
};
|
|
11389
|
+
return self;
|
|
11390
|
+
}
|
|
11391
|
+
module2.exports = { shouldGuard, bumpStartupFailure, makeBudget };
|
|
11521
11392
|
}
|
|
11522
11393
|
});
|
|
11523
11394
|
|
|
@@ -11526,6 +11397,7 @@ var require_startup_throttle = __commonJS({
|
|
|
11526
11397
|
"src/app/main/startup-throttle.js"(exports2, module2) {
|
|
11527
11398
|
"use strict";
|
|
11528
11399
|
var guardian = require_guardian();
|
|
11400
|
+
var pmClient = require_pm_client();
|
|
11529
11401
|
var DEPS = /* @__PURE__ */ new WeakMap();
|
|
11530
11402
|
function depsOf(host) {
|
|
11531
11403
|
let d = DEPS.get(host);
|
|
@@ -11565,8 +11437,6 @@ var require_startup_throttle = __commonJS({
|
|
|
11565
11437
|
}
|
|
11566
11438
|
module2.exports = {
|
|
11567
11439
|
methods: {
|
|
11568
|
-
// 唯一一条限流:startupFailWindowMs 内「启动窗口内退出」达 startupFailBurst 次 ⇒ phase=FAILED。
|
|
11569
|
-
// 到点即停自动重启:不排队、不退避、不指数等待;恢复的唯一入口是人工重试(_retryStartupFailure)。
|
|
11570
11440
|
_noteStartupFailure() {
|
|
11571
11441
|
const d = depsOf(this);
|
|
11572
11442
|
const windowMs = d.config().startupFailWindowMs || 6e4;
|
|
@@ -11591,11 +11461,11 @@ var require_startup_throttle = __commonJS({
|
|
|
11591
11461
|
);
|
|
11592
11462
|
return { failed: true, count: dec.count };
|
|
11593
11463
|
},
|
|
11594
|
-
// 手动重试入口:清计数后回到 STARTING(随后由 STARTING 分支重新 spawn,新的 startsecs 窗口)。
|
|
11595
11464
|
_retryStartupFailure() {
|
|
11596
11465
|
const d = depsOf(this);
|
|
11597
11466
|
d.mSetStartupFailWindowStart(null);
|
|
11598
11467
|
d.mSetStartupFailCount(0);
|
|
11468
|
+
pmClient.resetBackoff("main");
|
|
11599
11469
|
d.events().append("startup_retry", {});
|
|
11600
11470
|
d.logger().warn("\u542F\u52A8\u5931\u8D25\u8BA1\u6570\u5DF2\u6E05\u96F6\uFF1A\u4EBA\u5DE5\u91CD\u8BD5\uFF0C\u56DE\u5230 STARTING");
|
|
11601
11471
|
return { ok: true };
|
|
@@ -12145,8 +12015,6 @@ var require_runtime2 = __commonJS({
|
|
|
12145
12015
|
spawnEnv: () => ({ DSH_SUPERVISOR_CONFIG: cfgPath }),
|
|
12146
12016
|
logger: d.logger(),
|
|
12147
12017
|
events: d.events(),
|
|
12148
|
-
// `this` 是宿主(本方法经 host._daemonLifecycle(kind) 调用);箭头函数捕获它。
|
|
12149
|
-
// 此前写作 host._exitIntended(),而 host 只存在于 depsOf(host) 形参作用域 ⇒ 延迟回调求值时 ReferenceError。
|
|
12150
12018
|
exitIntended: () => this._exitIntended()
|
|
12151
12019
|
});
|
|
12152
12020
|
return lc[kind];
|
|
@@ -13014,7 +12882,7 @@ var require_credential = __commonJS({
|
|
|
13014
12882
|
});
|
|
13015
12883
|
|
|
13016
12884
|
// src/domains/relay/core.js
|
|
13017
|
-
var
|
|
12885
|
+
var require_core3 = __commonJS({
|
|
13018
12886
|
"src/domains/relay/core.js"(exports2, module2) {
|
|
13019
12887
|
"use strict";
|
|
13020
12888
|
var crypto = require("node:crypto");
|
|
@@ -13042,14 +12910,52 @@ var require_core4 = __commonJS({
|
|
|
13042
12910
|
}
|
|
13043
12911
|
return null;
|
|
13044
12912
|
}
|
|
13045
|
-
function
|
|
13046
|
-
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
|
|
13051
|
-
|
|
12913
|
+
function stripGateTokenAndPreserve(rawUrl) {
|
|
12914
|
+
if (!rawUrl) return "/";
|
|
12915
|
+
let url = rawUrl;
|
|
12916
|
+
const hashIdx = url.indexOf("#");
|
|
12917
|
+
if (hashIdx >= 0) url = url.slice(0, hashIdx);
|
|
12918
|
+
const qIdx = url.indexOf("?");
|
|
12919
|
+
const path2 = qIdx >= 0 ? url.slice(0, qIdx) : url;
|
|
12920
|
+
if (qIdx < 0) return path2 || "/";
|
|
12921
|
+
const query = url.slice(qIdx + 1);
|
|
12922
|
+
if (!query) return path2 || "/";
|
|
12923
|
+
const kept = [];
|
|
12924
|
+
for (const pair of query.split("&")) {
|
|
12925
|
+
if (!pair) {
|
|
12926
|
+
kept.push(pair);
|
|
12927
|
+
continue;
|
|
12928
|
+
}
|
|
12929
|
+
const eq = pair.indexOf("=");
|
|
12930
|
+
const rawKey = eq >= 0 ? pair.slice(0, eq) : pair;
|
|
12931
|
+
let key = rawKey;
|
|
12932
|
+
try {
|
|
12933
|
+
key = decodeURIComponent(rawKey);
|
|
12934
|
+
} catch {
|
|
12935
|
+
}
|
|
12936
|
+
if (key === "token") continue;
|
|
12937
|
+
kept.push(pair);
|
|
13052
12938
|
}
|
|
12939
|
+
const out = path2 || "/";
|
|
12940
|
+
return kept.length ? out + "?" + kept.join("&") : out;
|
|
12941
|
+
}
|
|
12942
|
+
function upstreamPath(rawUrl) {
|
|
12943
|
+
return stripGateTokenAndPreserve(rawUrl);
|
|
12944
|
+
}
|
|
12945
|
+
var POLYFILL_SCRIPT = `<script>
|
|
12946
|
+
if (typeof crypto.randomUUID !== 'function') {
|
|
12947
|
+
crypto.randomUUID = function () {
|
|
12948
|
+
var b = crypto.getRandomValues(new Uint8Array(16));
|
|
12949
|
+
b[6] = (b[6] & 0x0f) | 0x40;
|
|
12950
|
+
b[8] = (b[8] & 0x3f) | 0x80;
|
|
12951
|
+
var h = '';
|
|
12952
|
+
for (var i = 0; i < 16; i++) h += (i === 4 || i === 6 || i === 8 || i === 12 ? '-' : '') + ('0' + b[i].toString(16)).slice(-2);
|
|
12953
|
+
return h;
|
|
12954
|
+
};
|
|
12955
|
+
}
|
|
12956
|
+
</script>`;
|
|
12957
|
+
function redactLogPath(rawUrl) {
|
|
12958
|
+
return rawUrl ? stripGateTokenAndPreserve(rawUrl) : "";
|
|
13053
12959
|
}
|
|
13054
12960
|
function lanGateCookieValue(token, salt) {
|
|
13055
12961
|
const t = String(token == null ? "" : token);
|
|
@@ -13057,23 +12963,6 @@ var require_core4 = __commonJS({
|
|
|
13057
12963
|
if (!t || !s) return "";
|
|
13058
12964
|
return crypto.createHash("sha256").update(s + "\n" + t).digest("hex");
|
|
13059
12965
|
}
|
|
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
12966
|
function tokenGateDecision(req, token, salt, mode) {
|
|
13078
12967
|
if (!token) return normalizeRemoteMode(mode) === "lan" ? { ok: true } : { ok: false, unauthorized: true };
|
|
13079
12968
|
const url = new URL(req.url, "http://localhost");
|
|
@@ -13096,27 +12985,22 @@ var require_core4 = __commonJS({
|
|
|
13096
12985
|
}
|
|
13097
12986
|
return { ok: false, unauthorized: true };
|
|
13098
12987
|
}
|
|
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=[^&]*/, "");
|
|
12988
|
+
function hasValidToken(req, token, salt, mode) {
|
|
12989
|
+
if (!token) return normalizeRemoteMode(mode) === "lan";
|
|
12990
|
+
const url = new URL(req.url, "http://localhost");
|
|
12991
|
+
const queryToken = url.searchParams.get("token");
|
|
12992
|
+
if (queryToken && safeEqual(queryToken, token)) return true;
|
|
12993
|
+
const cookies = req.headers.cookie || "";
|
|
12994
|
+
const m = LAN_COOKIE_RE.exec(cookies);
|
|
12995
|
+
if (m) {
|
|
12996
|
+
try {
|
|
12997
|
+
const want = lanGateCookieValue(token, salt);
|
|
12998
|
+
return !!want && safeEqual(decodeURIComponent(m[1]), want);
|
|
12999
|
+
} catch {
|
|
13000
|
+
return false;
|
|
13001
|
+
}
|
|
13119
13002
|
}
|
|
13003
|
+
return false;
|
|
13120
13004
|
}
|
|
13121
13005
|
function buildFrpcToml(settings, instances) {
|
|
13122
13006
|
const s = settings || {};
|
|
@@ -13147,8 +13031,6 @@ if (typeof crypto.randomUUID !== 'function') {
|
|
|
13147
13031
|
return {
|
|
13148
13032
|
serverAddr: String(j.serverAddr !== void 0 ? j.serverAddr : cur.serverAddr).trim(),
|
|
13149
13033
|
serverPort: Number(j.serverPort) || cur.serverPort,
|
|
13150
|
-
// authToken:null/undefined 归一为空串(frpc 遇空串不写 auth.token,避免 String(null)==="null" 被当成共享密钥);
|
|
13151
|
-
// 非空串统一 trim,与 serverAddr 同口径。
|
|
13152
13034
|
authToken: j.authToken === void 0 ? cur.authToken : j.authToken == null ? "" : String(j.authToken).trim(),
|
|
13153
13035
|
user: String(j.user || cur.user || "dsh")
|
|
13154
13036
|
};
|
|
@@ -13231,7 +13113,7 @@ if (typeof crypto.randomUUID !== 'function') {
|
|
|
13231
13113
|
var require_lan2 = __commonJS({
|
|
13232
13114
|
"src/app/domain-actions/lan.js"(exports2, module2) {
|
|
13233
13115
|
"use strict";
|
|
13234
|
-
var { validateWanAccess, generateRemoteToken } =
|
|
13116
|
+
var { validateWanAccess, generateRemoteToken } = require_core3();
|
|
13235
13117
|
var { remoteTokenStrength } = require_credential();
|
|
13236
13118
|
var BRAND2 = require_brand();
|
|
13237
13119
|
function lanModule(deps) {
|
|
@@ -13598,13 +13480,6 @@ var require_env = __commonJS({
|
|
|
13598
13480
|
} catch {
|
|
13599
13481
|
return null;
|
|
13600
13482
|
}
|
|
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
13483
|
})()
|
|
13609
13484
|
};
|
|
13610
13485
|
},
|
|
@@ -13819,7 +13694,6 @@ var require_versions = __commonJS({
|
|
|
13819
13694
|
}
|
|
13820
13695
|
return dir;
|
|
13821
13696
|
},
|
|
13822
|
-
// 同步 spawn 会冻结事件循环,消费方含 HTTP 路径,故 git 子进程异步执行。
|
|
13823
13697
|
async guardVersionLocal() {
|
|
13824
13698
|
const d = depsOf(this);
|
|
13825
13699
|
const root = d.vcsRoot();
|
|
@@ -13876,7 +13750,6 @@ var require_access = __commonJS({
|
|
|
13876
13750
|
const cfg = this.config || {};
|
|
13877
13751
|
return { configured: !!cfg.apiAccessKey, host: cfg.apiHost || void 0 };
|
|
13878
13752
|
},
|
|
13879
|
-
// 清空密钥必须同时回关 LAN(apiHost→127.0.0.1):只清 key 不动 apiHost 会留下「绑定 0.0.0.0 且零认证」的暴露窗口。
|
|
13880
13753
|
setAccessKey(key) {
|
|
13881
13754
|
try {
|
|
13882
13755
|
const cfg = this.config || {};
|
|
@@ -14787,7 +14660,6 @@ var require_pool2 = __commonJS({
|
|
|
14787
14660
|
this._backfillAt.delete(id);
|
|
14788
14661
|
this.clear(id);
|
|
14789
14662
|
}
|
|
14790
|
-
// journalctl 同步查询会冻结生命周期 tick 的事件循环,故 journal 档非阻塞发射(见 capture.js)。
|
|
14791
14663
|
capture(id) {
|
|
14792
14664
|
const src = this._sources.get(id);
|
|
14793
14665
|
if (!src) return null;
|
|
@@ -15104,6 +14976,35 @@ var require_npm = __commonJS({
|
|
|
15104
14976
|
}
|
|
15105
14977
|
});
|
|
15106
14978
|
|
|
14979
|
+
// src/domains/shell/core.js
|
|
14980
|
+
var require_core4 = __commonJS({
|
|
14981
|
+
"src/domains/shell/core.js"(exports2, module2) {
|
|
14982
|
+
"use strict";
|
|
14983
|
+
function isUpdatePhase(phase) {
|
|
14984
|
+
const p = String(phase || "");
|
|
14985
|
+
return p === "restarting" || p.indexOf("shell-update") === 0;
|
|
14986
|
+
}
|
|
14987
|
+
function deriveState(id, journal) {
|
|
14988
|
+
const j = journal || {};
|
|
14989
|
+
if (!j.to) return { state: "idle", reason: "\u65E0\u8FDB\u884C\u4E2D\u7684\u66F4\u65B0", journal: j, identity: id };
|
|
14990
|
+
const cur = id && id.version ? String(id.version) : null;
|
|
14991
|
+
if (cur && cur === j.to && id && id.phase === "ready") {
|
|
14992
|
+
const next = j.confirmed === true ? j : Object.assign({}, j, { confirmed: true });
|
|
14993
|
+
return { state: "confirmed", version: cur, reason: "\u58F3\u5DF2\u5065\u5EB7\u8FD0\u884C\u65B0\u7248\u672C", journal: next, identity: id };
|
|
14994
|
+
}
|
|
14995
|
+
return {
|
|
14996
|
+
state: "pending",
|
|
14997
|
+
target: j.to,
|
|
14998
|
+
current: cur,
|
|
14999
|
+
reason: cur === j.to ? "\u7B49\u5F85\u58F3\u4E0A\u62A5\u5C31\u7EEA" : "\u7B49\u5F85\u58F3\u91CD\u542F\u5230\u65B0\u7248\u672C",
|
|
15000
|
+
journal: j,
|
|
15001
|
+
identity: id
|
|
15002
|
+
};
|
|
15003
|
+
}
|
|
15004
|
+
module2.exports = { isUpdatePhase, deriveState };
|
|
15005
|
+
}
|
|
15006
|
+
});
|
|
15007
|
+
|
|
15107
15008
|
// src/domains/shell/journal.js
|
|
15108
15009
|
var require_journal = __commonJS({
|
|
15109
15010
|
"src/domains/shell/journal.js"(exports2, module2) {
|
|
@@ -15112,7 +15013,7 @@ var require_journal = __commonJS({
|
|
|
15112
15013
|
var fs2 = require("node:fs");
|
|
15113
15014
|
var path2 = require("node:path");
|
|
15114
15015
|
var { writeAtomic } = require_fs();
|
|
15115
|
-
var { deriveState } =
|
|
15016
|
+
var { deriveState } = require_core4();
|
|
15116
15017
|
function shellDir() {
|
|
15117
15018
|
return stateRoot2.shellDir();
|
|
15118
15019
|
}
|
|
@@ -15191,116 +15092,6 @@ var require_journal = __commonJS({
|
|
|
15191
15092
|
}
|
|
15192
15093
|
});
|
|
15193
15094
|
|
|
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
15095
|
// src/domains/shell/index.js
|
|
15305
15096
|
var require_shell = __commonJS({
|
|
15306
15097
|
"src/domains/shell/index.js"(exports2, module2) {
|
|
@@ -15314,8 +15105,7 @@ var require_shell = __commonJS({
|
|
|
15314
15105
|
health,
|
|
15315
15106
|
status
|
|
15316
15107
|
} = require_journal();
|
|
15317
|
-
|
|
15318
|
-
module2.exports = { status, evaluate, health, markPending, identity, readJournal, shellDir, checkUpdate, restartShell, SHELL_RELEASE_PKG };
|
|
15108
|
+
module2.exports = { status, evaluate, health, markPending, identity, readJournal, shellDir };
|
|
15319
15109
|
}
|
|
15320
15110
|
});
|
|
15321
15111
|
|
|
@@ -15618,8 +15408,6 @@ var require_intents = __commonJS({
|
|
|
15618
15408
|
if (this._pending.has(intent)) this._pending.delete(intent);
|
|
15619
15409
|
return p;
|
|
15620
15410
|
}
|
|
15621
|
-
// W5:生产零调用,仅 session-lifecycle-test.js 用于「模拟重启后内存态为空」的夹具。
|
|
15622
|
-
// 保留(它是一个合理的测试缝),不视为待删死代码。
|
|
15623
15411
|
clear() {
|
|
15624
15412
|
this._pending.clear();
|
|
15625
15413
|
}
|
|
@@ -15806,7 +15594,6 @@ var require_core5 = __commonJS({
|
|
|
15806
15594
|
routerAutostart: s.routerAutostart,
|
|
15807
15595
|
routerMode: s.routerMode,
|
|
15808
15596
|
updateCheck: s.updateCheck,
|
|
15809
|
-
shellWatchdog: s.shellWatchdog,
|
|
15810
15597
|
lastRefresh: s.lastRefresh
|
|
15811
15598
|
};
|
|
15812
15599
|
}
|
|
@@ -15864,12 +15651,10 @@ var require_core5 = __commonJS({
|
|
|
15864
15651
|
host._upgradeHold = false;
|
|
15865
15652
|
host._upgradeHoldSince = null;
|
|
15866
15653
|
host._timer = null;
|
|
15654
|
+
host._beatScheduler = null;
|
|
15867
15655
|
host._heartbeatBusy = false;
|
|
15868
15656
|
host._killTimer = null;
|
|
15869
15657
|
host._adoptKillTimer = null;
|
|
15870
|
-
host._initialCheckTimer = null;
|
|
15871
|
-
host._upgradeTimer = null;
|
|
15872
|
-
host._shellWatchdogTimer = null;
|
|
15873
15658
|
host._lastOccupiedWarn = 0;
|
|
15874
15659
|
host._lastMainPortRederive = 0;
|
|
15875
15660
|
host._lastPortUp = false;
|
|
@@ -17127,11 +16912,21 @@ var require_instance_lifecycle = __commonJS({
|
|
|
17127
16912
|
});
|
|
17128
16913
|
|
|
17129
16914
|
// src/domains/router/providers/restart.js
|
|
17130
|
-
var
|
|
16915
|
+
var require_restart = __commonJS({
|
|
17131
16916
|
"src/domains/router/providers/restart.js"(exports2, module2) {
|
|
17132
16917
|
"use strict";
|
|
17133
16918
|
var { INSTANCE_STATES } = require_model2();
|
|
17134
16919
|
var ports = require_ports().shared;
|
|
16920
|
+
var { makeBudget } = require_guardian();
|
|
16921
|
+
var PROXY_INSTANCE_THROTTLE = { windowMs: 10 * 60 * 1e3, burst: 5 };
|
|
16922
|
+
function budgetFor(inst) {
|
|
16923
|
+
if (!inst) return makeBudget(PROXY_INSTANCE_THROTTLE);
|
|
16924
|
+
if (!inst._restartBudget) inst._restartBudget = makeBudget(PROXY_INSTANCE_THROTTLE);
|
|
16925
|
+
return inst._restartBudget;
|
|
16926
|
+
}
|
|
16927
|
+
function resetBudget(inst) {
|
|
16928
|
+
if (inst) inst._restartBudget = makeBudget(PROXY_INSTANCE_THROTTLE);
|
|
16929
|
+
}
|
|
17135
16930
|
function createRestartOrchestrator(deps) {
|
|
17136
16931
|
const d = deps || {};
|
|
17137
16932
|
const { startInstance, waitHealthy, isAlive, logger } = d;
|
|
@@ -17165,8 +16960,8 @@ var require_restart2 = __commonJS({
|
|
|
17165
16960
|
}
|
|
17166
16961
|
return { respawn };
|
|
17167
16962
|
}
|
|
17168
|
-
async function
|
|
17169
|
-
const out = { started: [], stopped: [], desired: [] };
|
|
16963
|
+
async function runReconcileThrottled(provider, allowStop) {
|
|
16964
|
+
const out = { started: [], stopped: [], desired: [], throttled: [] };
|
|
17170
16965
|
const desired = provider.desiredRunningAccounts();
|
|
17171
16966
|
const list = desired.list || [];
|
|
17172
16967
|
out.desired = list.map((a) => a.keyId);
|
|
@@ -17175,12 +16970,25 @@ var require_restart2 = __commonJS({
|
|
|
17175
16970
|
const inst = provider.instanceOf(acc);
|
|
17176
16971
|
if (!inst || inst.pid || inst.startingPromise) continue;
|
|
17177
16972
|
if (inst.status === INSTANCE_STATES.DEAD && !inst.pid) inst.status = INSTANCE_STATES.COLD;
|
|
16973
|
+
const b = budgetFor(inst);
|
|
16974
|
+
if (b.tripped) {
|
|
16975
|
+
inst._throttled = true;
|
|
16976
|
+
out.throttled.push(acc.keyId);
|
|
16977
|
+
continue;
|
|
16978
|
+
}
|
|
16979
|
+
inst._throttled = false;
|
|
16980
|
+
const wasRunning = !!inst.pid;
|
|
17178
16981
|
try {
|
|
17179
16982
|
const r = await provider.startInstance(inst);
|
|
16983
|
+
const startupFailure = !r.ok || !wasRunning && !inst.pid;
|
|
16984
|
+
b.note(startupFailure);
|
|
17180
16985
|
if (r && r.ok) {
|
|
17181
16986
|
await provider._waitHealthy(inst).catch(() => {
|
|
17182
16987
|
});
|
|
17183
16988
|
out.started.push(acc.keyId);
|
|
16989
|
+
if (b.tripped && provider.logger && provider.logger.warn) {
|
|
16990
|
+
provider.logger.warn("[reconcile] \u5B9E\u4F8B\u542F\u52A8\u53CD\u590D\u5931\u8D25\u5DF2\u8FBE\u4E0A\u9650 key=" + (acc.maskedKey || acc.keyId) + "\uFF0C\u505C\u6B62\u81EA\u52A8\u62C9\u8D77\uFF08\u7B49\u4EBA\u5DE5/\u7A97\u53E3\u8FC7\u671F\uFF09");
|
|
16991
|
+
}
|
|
17184
16992
|
if (provider.logger && provider.logger.info) {
|
|
17185
16993
|
const role = desired.active && acc.keyId === desired.active.keyId ? "\u5728\u7528" : "\u9884\u70ED";
|
|
17186
16994
|
provider.logger.info("[reconcile] \u62C9\u8D77\u5B9E\u4F8B key=" + acc.maskedKey + "\uFF08" + role + "\uFF09");
|
|
@@ -17189,8 +16997,8 @@ var require_restart2 = __commonJS({
|
|
|
17189
16997
|
} catch {
|
|
17190
16998
|
}
|
|
17191
16999
|
}
|
|
17192
|
-
if (!allowStop) return out;
|
|
17193
17000
|
for (const inst of (provider.instances || []).slice()) {
|
|
17001
|
+
if (!allowStop) break;
|
|
17194
17002
|
if (!inst.pid) {
|
|
17195
17003
|
if (!desiredIds.has(inst.keyId) && inst.port) {
|
|
17196
17004
|
try {
|
|
@@ -17235,7 +17043,7 @@ var require_restart2 = __commonJS({
|
|
|
17235
17043
|
}
|
|
17236
17044
|
}
|
|
17237
17045
|
if (provider._reconcileBusy) return provider._reconcileBusy;
|
|
17238
|
-
const p =
|
|
17046
|
+
const p = runReconcileThrottled(provider, allowStop);
|
|
17239
17047
|
provider._reconcileBusy = p;
|
|
17240
17048
|
try {
|
|
17241
17049
|
return await p;
|
|
@@ -17248,7 +17056,60 @@ var require_restart2 = __commonJS({
|
|
|
17248
17056
|
reconcileInstances(provider).catch(() => {
|
|
17249
17057
|
});
|
|
17250
17058
|
}
|
|
17251
|
-
module2.exports = { createRestartOrchestrator,
|
|
17059
|
+
module2.exports = { createRestartOrchestrator, runReconcileThrottled, reconcileInstances, reconcileNow, budgetFor, resetBudget, PROXY_INSTANCE_THROTTLE };
|
|
17060
|
+
}
|
|
17061
|
+
});
|
|
17062
|
+
|
|
17063
|
+
// src/app/control/process-lifecycle.js
|
|
17064
|
+
var require_process_lifecycle = __commonJS({
|
|
17065
|
+
"src/app/control/process-lifecycle.js"(exports2, module2) {
|
|
17066
|
+
"use strict";
|
|
17067
|
+
var procOS = require_process();
|
|
17068
|
+
var pidlook = require_pidlookup();
|
|
17069
|
+
var DEFAULTS = {
|
|
17070
|
+
stopGraceMs: 9e3,
|
|
17071
|
+
portFreeTimeoutMs: 5e3
|
|
17072
|
+
};
|
|
17073
|
+
function sleep(ms) {
|
|
17074
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
17075
|
+
}
|
|
17076
|
+
function isForeignOnPort(port, ownPid) {
|
|
17077
|
+
if (!Number.isInteger(port) || port <= 0) return false;
|
|
17078
|
+
const p = pidlook.findListeningPid(port);
|
|
17079
|
+
return p !== null && p !== ownPid;
|
|
17080
|
+
}
|
|
17081
|
+
async function waitPortFree(port, timeoutMs) {
|
|
17082
|
+
const dl = Date.now() + (timeoutMs || DEFAULTS.portFreeTimeoutMs);
|
|
17083
|
+
while (Date.now() < dl) {
|
|
17084
|
+
if (pidlook.findListeningPid(port) === null) return true;
|
|
17085
|
+
await sleep(150);
|
|
17086
|
+
}
|
|
17087
|
+
return pidlook.findListeningPid(port) === null;
|
|
17088
|
+
}
|
|
17089
|
+
async function stopProcess(opts) {
|
|
17090
|
+
const o = Object.assign({}, DEFAULTS, opts || {});
|
|
17091
|
+
const pid = typeof o.pid === "number" ? o.pid : null;
|
|
17092
|
+
const port = typeof o.port === "number" ? o.port : null;
|
|
17093
|
+
const ownGroup = !!o.ownGroup;
|
|
17094
|
+
if (pid && pid > 0) {
|
|
17095
|
+
procOS.killTree(pid, "SIGTERM", void 0, ownGroup ? { ownGroup: true } : void 0);
|
|
17096
|
+
}
|
|
17097
|
+
const dl = Date.now() + o.stopGraceMs;
|
|
17098
|
+
while (Date.now() < dl) {
|
|
17099
|
+
const alive = pid ? pidlook.isAlive ? pidlook.isAlive(pid) : false : false;
|
|
17100
|
+
if (!alive) break;
|
|
17101
|
+
await sleep(150);
|
|
17102
|
+
}
|
|
17103
|
+
if (port) {
|
|
17104
|
+
if (isForeignOnPort(port, pid)) {
|
|
17105
|
+
return { ok: false, stopped: false, foreign: true };
|
|
17106
|
+
}
|
|
17107
|
+
const free = await waitPortFree(port, o.portFreeTimeoutMs);
|
|
17108
|
+
if (!free) return { ok: false, stopped: false, portBusy: true };
|
|
17109
|
+
}
|
|
17110
|
+
return { ok: true, stopped: true };
|
|
17111
|
+
}
|
|
17112
|
+
module2.exports = { ProcessLifecycle: { stopProcess, waitPortFree, isForeignOnPort, DEFAULTS } };
|
|
17252
17113
|
}
|
|
17253
17114
|
});
|
|
17254
17115
|
|
|
@@ -17395,6 +17256,7 @@ var require_probe5 = __commonJS({
|
|
|
17395
17256
|
var carrier = require_carrier();
|
|
17396
17257
|
var procOS = require_process();
|
|
17397
17258
|
var { INSTANCE_STATES } = require_model2();
|
|
17259
|
+
var { ProcessLifecycle } = require_process_lifecycle();
|
|
17398
17260
|
var { getQuotaStrategy } = require_quota_strategies();
|
|
17399
17261
|
var { quotaOverallStatus } = require_quota();
|
|
17400
17262
|
var { cachedPkgBin, ensurePkgCached } = require_pkg_cache();
|
|
@@ -17423,7 +17285,7 @@ var require_probe5 = __commonJS({
|
|
|
17423
17285
|
if (provider.logger && provider.logger.warn) provider.logger.warn("[proxy-instance] \u91CD\u542F\u5E78\u5B58\u8005\u5F03\u7528\u91CD\u62C9 pid=" + boundPid + " port=" + inst.port + "\uFF08stdio \u5F52\u5C5E\u65E7\u4EE3\uFF0C\u7981 adopt\uFF09");
|
|
17424
17286
|
if (provider.events) provider.events.append("proxy_instance_survivor_reclaimed", { app: provider.proxyAppId, port: inst.port, pid: boundPid, reason: "restart-survivor-stdio-unsafe" });
|
|
17425
17287
|
try {
|
|
17426
|
-
|
|
17288
|
+
ProcessLifecycle.stopProcess({ pid: boundPid, port: inst.port });
|
|
17427
17289
|
} catch {
|
|
17428
17290
|
}
|
|
17429
17291
|
const dl = Date.now() + 3e3;
|
|
@@ -17613,7 +17475,7 @@ var require_probe5 = __commonJS({
|
|
|
17613
17475
|
if (provider.logger && provider.logger.warn) provider.logger.warn("[proxy-instance] \u751F\u547D\u5468\u671F\u76D1\u63A7\uFF1A\u5B9E\u4F8B\u65E0\u54CD\u5E94\uFF08\u7591\u4F3C\u5361\u6B7B\uFF09key=" + inst.maskedKey + " port=" + inst.port + " pid=" + inst.pid + " fails=" + inst._monitorFails + "\uFF0Ckill \u91CD\u62C9");
|
|
17614
17476
|
if (provider.events) provider.events.append("proxy_instance_hang_restart", { app: provider.proxyAppId, port: inst.port, pid: inst.pid, fails: inst._monitorFails });
|
|
17615
17477
|
try {
|
|
17616
|
-
|
|
17478
|
+
ProcessLifecycle.stopProcess({ pid: inst.pid, port: inst.port });
|
|
17617
17479
|
} catch {
|
|
17618
17480
|
}
|
|
17619
17481
|
inst.pid = null;
|
|
@@ -17768,7 +17630,8 @@ var require_process_pool = __commonJS({
|
|
|
17768
17630
|
"src/domains/router/providers/process-pool.js"(exports2, module2) {
|
|
17769
17631
|
"use strict";
|
|
17770
17632
|
var life = require_instance_lifecycle();
|
|
17771
|
-
var restart =
|
|
17633
|
+
var restart = require_restart();
|
|
17634
|
+
var { resetBudget } = restart;
|
|
17772
17635
|
var probe = require_probe5();
|
|
17773
17636
|
var pool = require_pool3();
|
|
17774
17637
|
var pidlook = require_pidlookup();
|
|
@@ -17901,6 +17764,10 @@ var require_process_pool = __commonJS({
|
|
|
17901
17764
|
}
|
|
17902
17765
|
inst._restartAt = Date.now() + 12e4;
|
|
17903
17766
|
inst._restartPending = null;
|
|
17767
|
+
try {
|
|
17768
|
+
resetBudget(inst);
|
|
17769
|
+
} catch {
|
|
17770
|
+
}
|
|
17904
17771
|
if (this.logger && this.logger.warn) this.logger.warn("[proxy-instance] \u5B9E\u4F8B\u91CD\u542F key=" + inst.maskedKey + " port=" + inst.port + " reason=" + reason);
|
|
17905
17772
|
const hadPid = !!inst.pid;
|
|
17906
17773
|
try {
|
|
@@ -18020,7 +17887,7 @@ var require_proxy = __commonJS({
|
|
|
18020
17887
|
var { npxLauncher } = require_npx_forms();
|
|
18021
17888
|
var { buildCommand } = require_command2();
|
|
18022
17889
|
var probe = require_probe5();
|
|
18023
|
-
var restart =
|
|
17890
|
+
var restart = require_restart();
|
|
18024
17891
|
var pool = require_pool3();
|
|
18025
17892
|
var life = require_instance_lifecycle();
|
|
18026
17893
|
var ProxyProvider = class extends withProcessPool(ProviderBase) {
|
|
@@ -18384,7 +18251,6 @@ var require_proxy_apps = __commonJS({
|
|
|
18384
18251
|
healthPath: "/health",
|
|
18385
18252
|
modelPath: "/v1/models",
|
|
18386
18253
|
upstream: "https://api.commandcode.ai",
|
|
18387
|
-
// keyEnv 是密钥注入的唯一 env 名(绝不进 cmdline);其余 env/超时一律不注入,跑上游默认配置。
|
|
18388
18254
|
keyEnv: "CC_API_KEY",
|
|
18389
18255
|
repo: "thaolaptrinh/commandcode-api-proxy",
|
|
18390
18256
|
registry: "commandcode-api-proxy",
|
|
@@ -19092,16 +18958,6 @@ var require_usage = __commonJS({
|
|
|
19092
18958
|
if (!this._dirty) return;
|
|
19093
18959
|
this._writeTotals();
|
|
19094
18960
|
}
|
|
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
18961
|
load() {
|
|
19106
18962
|
if (this.totals) return this.totals;
|
|
19107
18963
|
let t;
|
|
@@ -20138,6 +19994,7 @@ var require_scheduler2 = __commonJS({
|
|
|
20138
19994
|
function createScheduler(deps) {
|
|
20139
19995
|
const d = deps || {};
|
|
20140
19996
|
const state = d.state;
|
|
19997
|
+
const beat = d.beatScheduler || null;
|
|
20141
19998
|
const logger = d.logger || null;
|
|
20142
19999
|
const refreshProxyUpdateInfo = d.refreshProxyUpdateInfo || (() => Promise.resolve());
|
|
20143
20000
|
const refreshOfficialUsageAll = d.refreshOfficialUsageAll || (() => Promise.resolve());
|
|
@@ -20153,6 +20010,27 @@ var require_scheduler2 = __commonJS({
|
|
|
20153
20010
|
});
|
|
20154
20011
|
ensureProxyInstances().catch(() => {
|
|
20155
20012
|
});
|
|
20013
|
+
if (beat) {
|
|
20014
|
+
beat.unregister("router-maint");
|
|
20015
|
+
beat.unregister("router-lifecycle");
|
|
20016
|
+
beat.unregister("router-pricing");
|
|
20017
|
+
beat.register("router-maint", () => {
|
|
20018
|
+
refreshProxyUpdateInfo().catch(() => {
|
|
20019
|
+
});
|
|
20020
|
+
probeIfDue();
|
|
20021
|
+
ensureProxyInstances().catch(() => {
|
|
20022
|
+
});
|
|
20023
|
+
}, { every: Math.max(1, Math.round(3e5 / (d.tickMs || 5e3))) });
|
|
20024
|
+
beat.register("router-lifecycle", () => {
|
|
20025
|
+
monitorInstanceHealth().catch(() => {
|
|
20026
|
+
});
|
|
20027
|
+
}, { every: Math.max(1, Math.round(3e4 / (d.tickMs || 5e3))) });
|
|
20028
|
+
beat.register("router-pricing", () => {
|
|
20029
|
+
refreshOfficialPricingAll().catch(() => {
|
|
20030
|
+
});
|
|
20031
|
+
}, { every: Math.max(1, Math.round(216e5 / (d.tickMs || 5e3))) });
|
|
20032
|
+
return;
|
|
20033
|
+
}
|
|
20156
20034
|
if (state.maintTimer) clearInterval(state.maintTimer);
|
|
20157
20035
|
state.maintTimer = setInterval(() => {
|
|
20158
20036
|
refreshProxyUpdateInfo().catch(() => {
|
|
@@ -20174,6 +20052,12 @@ var require_scheduler2 = __commonJS({
|
|
|
20174
20052
|
}), 6 * 3600 * 1e3);
|
|
20175
20053
|
}
|
|
20176
20054
|
function stop() {
|
|
20055
|
+
if (beat) {
|
|
20056
|
+
beat.unregister("router-maint");
|
|
20057
|
+
beat.unregister("router-lifecycle");
|
|
20058
|
+
beat.unregister("router-pricing");
|
|
20059
|
+
return;
|
|
20060
|
+
}
|
|
20177
20061
|
if (state.maintTimer) {
|
|
20178
20062
|
clearInterval(state.maintTimer);
|
|
20179
20063
|
state.maintTimer = null;
|
|
@@ -20702,6 +20586,8 @@ var require_router3 = __commonJS({
|
|
|
20702
20586
|
var RouterService = class {
|
|
20703
20587
|
constructor(opts) {
|
|
20704
20588
|
this.config = opts.config;
|
|
20589
|
+
this._beatScheduler = opts.beatScheduler || null;
|
|
20590
|
+
this._beatTickMs = opts.tickMs || opts.config && opts.config.tickIntervalMs || 5e3;
|
|
20705
20591
|
this.dist = opts.dist || null;
|
|
20706
20592
|
this.logger = opts.logger || console;
|
|
20707
20593
|
this.events = opts.events || null;
|
|
@@ -20763,6 +20649,8 @@ var require_router3 = __commonJS({
|
|
|
20763
20649
|
state,
|
|
20764
20650
|
store: this.store,
|
|
20765
20651
|
logger: this.logger,
|
|
20652
|
+
beatScheduler: this._beatScheduler,
|
|
20653
|
+
tickMs: this._beatTickMs,
|
|
20766
20654
|
refreshProxyUpdateInfo: () => this.refreshProxyUpdateInfo(),
|
|
20767
20655
|
refreshOfficialUsageAll: () => this.refreshOfficialUsageAll(),
|
|
20768
20656
|
refreshOfficialPricingAll: () => this.refreshOfficialPricingAll()
|
|
@@ -21340,7 +21228,6 @@ var require_model3 = __commonJS({
|
|
|
21340
21228
|
allocation: inst.state ? inst.state.allocation || null : null,
|
|
21341
21229
|
usage: inst.state ? inst.state.usage || null : null,
|
|
21342
21230
|
restartCount: inst.state ? inst.state.restartCount || 0 : 0,
|
|
21343
|
-
// 启动失败限流(唯一一条规则)的可见量:窗口内计数 / 固定端口释放等待落点。
|
|
21344
21231
|
startupFailCount: inst.state ? inst.state.startupFailCount || 0 : 0,
|
|
21345
21232
|
restartAt: inst.state ? inst.state.restartAt || null : null,
|
|
21346
21233
|
lastFailure: inst.state ? inst.state.lastFailure || null : null,
|
|
@@ -21423,12 +21310,6 @@ var require_store5 = __commonJS({
|
|
|
21423
21310
|
_stripLegacyStateKeys(inst) {
|
|
21424
21311
|
if (inst.state && Object.prototype.hasOwnProperty.call(inst.state, "version")) delete inst.state.version;
|
|
21425
21312
|
}
|
|
21426
|
-
/**
|
|
21427
|
-
* 隔离损坏文件。
|
|
21428
|
-
* Lease I2:隔离前**再次校验版本戳**——若自读取失败以来文件已被他人更新,
|
|
21429
|
-
* 说明它不是损坏 ⇒ 放弃隔离(修前会直接 rename 掉这个更新的文件并把实例列表清空,即全量静默丢失)。
|
|
21430
|
-
* 且保留可回溯副本:先复制再改名,不直接丢弃。
|
|
21431
|
-
*/
|
|
21432
21313
|
_quarantineCorrupt(err) {
|
|
21433
21314
|
let locked = false;
|
|
21434
21315
|
try {
|
|
@@ -22669,25 +22550,7 @@ var require_ops2 = __commonJS({
|
|
|
22669
22550
|
store.save();
|
|
22670
22551
|
return { ok: true, instance: inst };
|
|
22671
22552
|
}
|
|
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 };
|
|
22553
|
+
return { list, addInstance, removeInstance, updateInstance };
|
|
22691
22554
|
}
|
|
22692
22555
|
module2.exports = { createOps };
|
|
22693
22556
|
}
|
|
@@ -22910,7 +22773,6 @@ var require_instance = __commonJS({
|
|
|
22910
22773
|
map(fn) {
|
|
22911
22774
|
return this._store.instances.map(fn);
|
|
22912
22775
|
}
|
|
22913
|
-
// 能力判定读平台表(有副作用)⇒ 从 governor 取,不经 pure 的 sandbox.js。
|
|
22914
22776
|
get sandboxSupported() {
|
|
22915
22777
|
return governor.sandboxSupported(this._sandboxSupportedOverride);
|
|
22916
22778
|
}
|
|
@@ -22998,9 +22860,6 @@ var require_instance = __commonJS({
|
|
|
22998
22860
|
upgradeStatus(id) {
|
|
22999
22861
|
return this._upgrade.upgradeStatus(id);
|
|
23000
22862
|
}
|
|
23001
|
-
startTimer(ms) {
|
|
23002
|
-
return this._ops.startTimer(ms);
|
|
23003
|
-
}
|
|
23004
22863
|
sandboxRoot(inst) {
|
|
23005
22864
|
return sandbox.root(this.instancesRoot, inst);
|
|
23006
22865
|
}
|
|
@@ -23898,23 +23757,14 @@ var require_process_spec = __commonJS({
|
|
|
23898
23757
|
function defaultSpec() {
|
|
23899
23758
|
return {
|
|
23900
23759
|
runtime: null,
|
|
23901
|
-
// 解释器(如 node);为 null 表示 bin 可直接执行
|
|
23902
23760
|
bin: null,
|
|
23903
|
-
// 可执行文件或入口脚本
|
|
23904
23761
|
subcommand: null,
|
|
23905
|
-
// 子命令(如 'web' / 'plugin')
|
|
23906
23762
|
args: [],
|
|
23907
|
-
// 用户参数
|
|
23908
23763
|
port: null,
|
|
23909
|
-
// --port 值(一等公民,不再各处拼装)
|
|
23910
23764
|
patchFile: null,
|
|
23911
|
-
// 插件 overlay(一等公民,不再事后 splice)
|
|
23912
23765
|
storeDir: null,
|
|
23913
|
-
// pnpm --store-dir
|
|
23914
23766
|
install: false,
|
|
23915
|
-
// 是否安装类操作(决定是否注入安全标志)
|
|
23916
23767
|
extraFlags: []
|
|
23917
|
-
// 其他固定标志
|
|
23918
23768
|
};
|
|
23919
23769
|
}
|
|
23920
23770
|
function validate(spec) {
|
|
@@ -24124,7 +23974,7 @@ var require_cli = __commonJS({
|
|
|
24124
23974
|
});
|
|
24125
23975
|
|
|
24126
23976
|
// src/domains/plugin/restart.js
|
|
24127
|
-
var
|
|
23977
|
+
var require_restart2 = __commonJS({
|
|
24128
23978
|
"src/domains/plugin/restart.js"(exports2, module2) {
|
|
24129
23979
|
"use strict";
|
|
24130
23980
|
function targetRunning(ctx, target) {
|
|
@@ -24165,7 +24015,7 @@ var require_restart3 = __commonJS({
|
|
|
24165
24015
|
log("\u91CD\u542F\u5B9E\u4F8B\u300C" + (target.name || target.id) + "\u300D\u4F7F\u63D2\u4EF6\u53D8\u66F4\u751F\u6548\u2026");
|
|
24166
24016
|
if (ctx.events) ctx.events.append("plugin_restart_started", { name: target.name || target.id, target: target.id, kind });
|
|
24167
24017
|
try {
|
|
24168
|
-
ctx.instances.stopInstance(target.id);
|
|
24018
|
+
await ctx.instances.stopInstance(target.id);
|
|
24169
24019
|
} catch (e) {
|
|
24170
24020
|
log("\u505C\u6B62\u5B9E\u4F8B\u5931\u8D25: " + e.message);
|
|
24171
24021
|
}
|
|
@@ -24189,28 +24039,25 @@ var require_restart3 = __commonJS({
|
|
|
24189
24039
|
return true;
|
|
24190
24040
|
}
|
|
24191
24041
|
if (target.kind === "native") {
|
|
24192
|
-
|
|
24193
|
-
|
|
24042
|
+
const nr = ctx.onNativeRestart;
|
|
24043
|
+
if (typeof nr !== "function") {
|
|
24044
|
+
log("\u539F\u751F DSH \u672A\u914D\u7F6E\u91CD\u542F\u56DE\u8C03\uFF1A\u63D2\u4EF6\u53D8\u66F4\u5C06\u5728\u4E0B\u6B21\u542F\u52A8\u65F6\u751F\u6548");
|
|
24194
24045
|
return false;
|
|
24195
24046
|
}
|
|
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;
|
|
24047
|
+
let rr;
|
|
24048
|
+
try {
|
|
24049
|
+
rr = ctx.onNativeRestart();
|
|
24050
|
+
} catch (e) {
|
|
24051
|
+
log("\u539F\u751F DSH \u91CD\u542F\u8BF7\u6C42\u5931\u8D25: " + e.message);
|
|
24052
|
+
return false;
|
|
24211
24053
|
}
|
|
24212
|
-
|
|
24213
|
-
|
|
24054
|
+
if (rr && rr.ok === false) {
|
|
24055
|
+
log("\u539F\u751F DSH \u91CD\u542F\u8BF7\u6C42\u672A\u751F\u6548\uFF1A" + (rr && rr.error || "unknown"));
|
|
24056
|
+
return false;
|
|
24057
|
+
}
|
|
24058
|
+
log("\u5DF2\u8BF7\u6C42\u91CD\u542F\u539F\u751F DSH \u4F7F\u63D2\u4EF6\u53D8\u66F4\u751F\u6548");
|
|
24059
|
+
if (ctx.events) ctx.events.append("plugin_restart_done", { name: "\u539F\u751F\u5B9E\u4F8B", target: "native", kind, via: "supervisor" });
|
|
24060
|
+
return true;
|
|
24214
24061
|
}
|
|
24215
24062
|
return false;
|
|
24216
24063
|
} catch (e) {
|
|
@@ -24784,7 +24631,7 @@ var require_plugin = __commonJS({
|
|
|
24784
24631
|
var store = require_store6();
|
|
24785
24632
|
var targets = require_targets();
|
|
24786
24633
|
var cli = require_cli();
|
|
24787
|
-
var restart =
|
|
24634
|
+
var restart = require_restart2();
|
|
24788
24635
|
var { createJobs } = require_jobs();
|
|
24789
24636
|
var { createLayers } = require_layers();
|
|
24790
24637
|
var ops = require_ops3();
|
|
@@ -24902,7 +24749,8 @@ var require_managed_object = __commonJS({
|
|
|
24902
24749
|
"sandbox-instance": { label: "\u6C99\u7BB1\u5B9E\u4F8B", startable: true, guardable: true },
|
|
24903
24750
|
"router-daemon": { label: "\u667A\u80FD\u8DEF\u7531 daemon", startable: true, guardable: true },
|
|
24904
24751
|
"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 }
|
|
24752
|
+
plugin: { label: "\u63D2\u4EF6\uFF08\u805A\u5408\uFF09", startable: false, guardable: false },
|
|
24753
|
+
shell: { label: "\u684C\u9762\u58F3", startable: false, guardable: false }
|
|
24906
24754
|
};
|
|
24907
24755
|
var _customKinds = {};
|
|
24908
24756
|
function kindMeta(kind) {
|
|
@@ -25034,9 +24882,17 @@ var require_registry4 = __commonJS({
|
|
|
25034
24882
|
var path2 = require("node:path");
|
|
25035
24883
|
var { writeAtomic } = require_fs();
|
|
25036
24884
|
var { DESIRED, MANAGED_KINDS, kindMeta, registerKind: registerManagedKind, createEntry, normalizeOwnership } = require_managed_object();
|
|
24885
|
+
var { legacyToEntryPhase } = require_phase();
|
|
25037
24886
|
var PHASES = ["stopped", "installing", "starting", "running", "draining", "failed"];
|
|
25038
|
-
var LEGACY_PHASES = { backoff: "failed", restarting: "starting" };
|
|
25039
24887
|
var { runHeartbeat } = require_heartbeat();
|
|
24888
|
+
var pmClient = require_pm_client();
|
|
24889
|
+
var configDefaults = require_config();
|
|
24890
|
+
var RESTART_FALLBACK = { windowMs: 6e4, burst: 5 };
|
|
24891
|
+
var restartDefaults = () => {
|
|
24892
|
+
const r = configDefaults && configDefaults.restart;
|
|
24893
|
+
if (r && Number.isFinite(r.windowMs) && Number.isFinite(r.burst)) return { windowMs: r.windowMs, burst: r.burst };
|
|
24894
|
+
return RESTART_FALLBACK;
|
|
24895
|
+
};
|
|
25040
24896
|
var ManagedRegistry = class {
|
|
25041
24897
|
constructor(opts) {
|
|
25042
24898
|
this.file = opts && opts.file;
|
|
@@ -25082,7 +24938,8 @@ var require_registry4 = __commonJS({
|
|
|
25082
24938
|
try {
|
|
25083
24939
|
if (!o || !kindMeta(o.kind)) continue;
|
|
25084
24940
|
const e = createEntry({ kind: o.kind, id: o.id, name: o.name, desired: o.desired, ownership: o.ownership });
|
|
25085
|
-
|
|
24941
|
+
const np = legacyToEntryPhase(o.phase);
|
|
24942
|
+
if (PHASES.includes(np)) e.phase = np;
|
|
25086
24943
|
if (Number.isInteger(o.restartCount) && o.restartCount >= 0) e.restartCount = o.restartCount;
|
|
25087
24944
|
if (o.startupFailWindowStart === null || typeof o.startupFailWindowStart === "number") e.startupFailWindowStart = o.startupFailWindowStart;
|
|
25088
24945
|
if (Number.isInteger(o.startupFailCount) && o.startupFailCount >= 0) e.startupFailCount = o.startupFailCount;
|
|
@@ -25150,8 +25007,6 @@ var require_registry4 = __commonJS({
|
|
|
25150
25007
|
const i = this._objects.indexOf(e);
|
|
25151
25008
|
if (i >= 0) this._objects.splice(i, 1);
|
|
25152
25009
|
}
|
|
25153
|
-
// 自定义 kind 扩展点:零调用但刻意保留(见 managed-object.js 的说明)——
|
|
25154
|
-
// 它是「新增受管对象类型」的唯一入口,删除等于永久关闭扩展能力。
|
|
25155
25010
|
registerKind(kind, meta) {
|
|
25156
25011
|
registerManagedKind(kind, meta);
|
|
25157
25012
|
return this;
|
|
@@ -25171,6 +25026,8 @@ var require_registry4 = __commonJS({
|
|
|
25171
25026
|
this._syncPortsOwner(e, true);
|
|
25172
25027
|
this._save();
|
|
25173
25028
|
this._event("managed_object_registered", { kind: e.kind, id: e.id, name: e.name });
|
|
25029
|
+
const rd = restartDefaults();
|
|
25030
|
+
pmClient.register({ id: e.id, spawn_cmd: [], restart_window_ms: rd.windowMs, restart_burst: rd.burst });
|
|
25174
25031
|
return e;
|
|
25175
25032
|
}
|
|
25176
25033
|
update(id, patch) {
|
|
@@ -25180,6 +25037,7 @@ var require_registry4 = __commonJS({
|
|
|
25180
25037
|
if (p.desired !== void 0) {
|
|
25181
25038
|
if (!DESIRED.includes(p.desired)) return { ok: false, error: "\u975E\u6CD5 desired: " + p.desired };
|
|
25182
25039
|
e.desired = p.desired;
|
|
25040
|
+
pmClient.setDesired(e.id, p.desired);
|
|
25183
25041
|
}
|
|
25184
25042
|
if (p.name !== void 0) e.name = String(p.name || e.id);
|
|
25185
25043
|
if (p.ownership !== void 0) {
|
|
@@ -25211,6 +25069,7 @@ var require_registry4 = __commonJS({
|
|
|
25211
25069
|
this._drop(e);
|
|
25212
25070
|
this._save();
|
|
25213
25071
|
this._event("managed_object_removed", { kind: e.kind, id: e.id });
|
|
25072
|
+
pmClient.setDesired(e.id, "stopped");
|
|
25214
25073
|
return { ok: true };
|
|
25215
25074
|
}
|
|
25216
25075
|
_releasePort(port, ownerId) {
|
|
@@ -25255,6 +25114,17 @@ var require_registry4 = __commonJS({
|
|
|
25255
25114
|
};
|
|
25256
25115
|
return e;
|
|
25257
25116
|
}
|
|
25117
|
+
setRestartCount(id, n) {
|
|
25118
|
+
const e = this.get(id);
|
|
25119
|
+
if (!e) return null;
|
|
25120
|
+
const v = typeof n === "number" && n >= 0 ? Math.floor(n) : 0;
|
|
25121
|
+
if (e.restartCount !== v) {
|
|
25122
|
+
e.restartCount = v;
|
|
25123
|
+
this._event("managed_object_restart_count", { kind: e.kind, id: e.id, count: v });
|
|
25124
|
+
this._save();
|
|
25125
|
+
}
|
|
25126
|
+
return e;
|
|
25127
|
+
}
|
|
25258
25128
|
setPhase(id, p) {
|
|
25259
25129
|
const e = this.get(id);
|
|
25260
25130
|
if (!e) return null;
|
|
@@ -25264,6 +25134,7 @@ var require_registry4 = __commonJS({
|
|
|
25264
25134
|
e.lastTransitionAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
25265
25135
|
this._event("managed_object_phase", { kind: e.kind, id: e.id, phase: p });
|
|
25266
25136
|
this._save();
|
|
25137
|
+
pmClient.onPhase(e.id, p);
|
|
25267
25138
|
}
|
|
25268
25139
|
return e;
|
|
25269
25140
|
}
|
|
@@ -26106,7 +25977,6 @@ var require_installer = __commonJS({
|
|
|
26106
25977
|
_manifest() {
|
|
26107
25978
|
return manifest.read(this);
|
|
26108
25979
|
}
|
|
26109
|
-
// W5:生产零调用,仅 native-test.js 使用(写 manifest 的夹具入口)。保留为测试缝。
|
|
26110
25980
|
_saveManifest(m) {
|
|
26111
25981
|
return manifest.save(this, m);
|
|
26112
25982
|
}
|
|
@@ -26423,6 +26293,8 @@ var require_domains = __commonJS({
|
|
|
26423
26293
|
}
|
|
26424
26294
|
host.router = new RouterService({
|
|
26425
26295
|
config: host.config,
|
|
26296
|
+
beatScheduler: host._beatScheduler,
|
|
26297
|
+
tickMs: host.config.tickIntervalMs || 5e3,
|
|
26426
26298
|
providerFile: path2.join(swDir, "providers.json"),
|
|
26427
26299
|
usageTotalsFile: path2.join(swDir, "router-usage-totals.json"),
|
|
26428
26300
|
logger: host.logger,
|
|
@@ -26444,7 +26316,6 @@ var require_domains = __commonJS({
|
|
|
26444
26316
|
tasks: host.tasks,
|
|
26445
26317
|
tokenService: host.tokenService,
|
|
26446
26318
|
dshBin: host.config.command && host.config.command[1] ? host.config.command[1] : "dsh",
|
|
26447
|
-
// 实例域限流参数:与主链同一条规则、按域参数化(窗口 600s > 5 × 30s 启动窗口);单源取自域常量。
|
|
26448
26319
|
throttle: THROTTLE_DEFAULTS
|
|
26449
26320
|
});
|
|
26450
26321
|
host.instances.load();
|
|
@@ -26561,7 +26432,6 @@ var require_adapters = __commonJS({
|
|
|
26561
26432
|
kind: "lan",
|
|
26562
26433
|
name: "\u8FDC\u7A0B\u63A7\u5236",
|
|
26563
26434
|
logger,
|
|
26564
|
-
// start 的结果必须来自真实执行:reconcile/syncFrpc 各自如实返回 ok,任一失败即 ok:false(此前恒 true)。
|
|
26565
26435
|
start: async () => {
|
|
26566
26436
|
try {
|
|
26567
26437
|
const rec = await lan.reconcile();
|
|
@@ -26809,7 +26679,7 @@ var require_lifecycle3 = __commonJS({
|
|
|
26809
26679
|
return send(200, { sessionState: sup.sessionState ? sup.sessionState() : "unknown" });
|
|
26810
26680
|
}
|
|
26811
26681
|
if (req.method === "POST" && pathname === "/session/stop") {
|
|
26812
|
-
if (!originAllowed(req
|
|
26682
|
+
if (!originAllowed(req)) {
|
|
26813
26683
|
req.resume();
|
|
26814
26684
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26815
26685
|
}
|
|
@@ -26832,7 +26702,7 @@ var require_lifecycle3 = __commonJS({
|
|
|
26832
26702
|
return lc ? send(200, lc.snapshot()) : send(404, { error: "\u6A21\u5757\u672A\u6CE8\u518C: " + id });
|
|
26833
26703
|
}
|
|
26834
26704
|
if (req.method === "POST" && action) {
|
|
26835
|
-
if (!originAllowed(req
|
|
26705
|
+
if (!originAllowed(req)) {
|
|
26836
26706
|
req.resume();
|
|
26837
26707
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26838
26708
|
}
|
|
@@ -26937,7 +26807,7 @@ var require_native = __commonJS({
|
|
|
26937
26807
|
});
|
|
26938
26808
|
}
|
|
26939
26809
|
if (req.method === "POST" && pathname === "/native/check-update") {
|
|
26940
|
-
if (!originAllowed(req
|
|
26810
|
+
if (!originAllowed(req)) {
|
|
26941
26811
|
req.resume();
|
|
26942
26812
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26943
26813
|
}
|
|
@@ -26945,7 +26815,7 @@ var require_native = __commonJS({
|
|
|
26945
26815
|
return;
|
|
26946
26816
|
}
|
|
26947
26817
|
if (req.method === "POST" && pathname === "/native/install") {
|
|
26948
|
-
if (!originAllowed(req
|
|
26818
|
+
if (!originAllowed(req)) {
|
|
26949
26819
|
req.resume();
|
|
26950
26820
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26951
26821
|
}
|
|
@@ -26963,7 +26833,7 @@ var require_native = __commonJS({
|
|
|
26963
26833
|
return;
|
|
26964
26834
|
}
|
|
26965
26835
|
if (req.method === "POST" && pathname === "/native/upgrade") {
|
|
26966
|
-
if (!originAllowed(req
|
|
26836
|
+
if (!originAllowed(req)) {
|
|
26967
26837
|
req.resume();
|
|
26968
26838
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26969
26839
|
}
|
|
@@ -26984,7 +26854,7 @@ var require_native = __commonJS({
|
|
|
26984
26854
|
return;
|
|
26985
26855
|
}
|
|
26986
26856
|
if (req.method === "POST" && pathname === "/native/uninstall") {
|
|
26987
|
-
if (!originAllowed(req
|
|
26857
|
+
if (!originAllowed(req)) {
|
|
26988
26858
|
req.resume();
|
|
26989
26859
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26990
26860
|
}
|
|
@@ -26993,7 +26863,7 @@ var require_native = __commonJS({
|
|
|
26993
26863
|
return send(202, { ok: true, accepted: true, state: "uninstalling" });
|
|
26994
26864
|
}
|
|
26995
26865
|
if (req.method === "POST" && pathname === "/native/settings") {
|
|
26996
|
-
if (!originAllowed(req
|
|
26866
|
+
if (!originAllowed(req)) {
|
|
26997
26867
|
req.resume();
|
|
26998
26868
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26999
26869
|
}
|
|
@@ -27055,14 +26925,14 @@ var require_guard = __commonJS({
|
|
|
27055
26925
|
}
|
|
27056
26926
|
if (req.method === "POST" && pathname === "/guard/version/check") {
|
|
27057
26927
|
req.resume();
|
|
27058
|
-
if (!originAllowed(req
|
|
26928
|
+
if (!originAllowed(req)) return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27059
26929
|
return sup.guardVersionCheck().then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
27060
26930
|
}
|
|
27061
26931
|
if (req.method === "GET" && pathname === "/autostart") {
|
|
27062
26932
|
return send(200, sup.autostartStatus());
|
|
27063
26933
|
}
|
|
27064
26934
|
if (req.method === "POST" && pathname === "/autostart") {
|
|
27065
|
-
if (!originAllowed(req
|
|
26935
|
+
if (!originAllowed(req)) {
|
|
27066
26936
|
req.resume();
|
|
27067
26937
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27068
26938
|
}
|
|
@@ -27083,7 +26953,7 @@ var require_guard = __commonJS({
|
|
|
27083
26953
|
return send(200, sup.lanPanelStatus());
|
|
27084
26954
|
}
|
|
27085
26955
|
if (req.method === "POST" && pathname === "/settings/lan") {
|
|
27086
|
-
if (!originAllowed(req
|
|
26956
|
+
if (!originAllowed(req)) {
|
|
27087
26957
|
req.resume();
|
|
27088
26958
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27089
26959
|
}
|
|
@@ -27104,7 +26974,7 @@ var require_guard = __commonJS({
|
|
|
27104
26974
|
return send(200, sup.accessKeyStatus());
|
|
27105
26975
|
}
|
|
27106
26976
|
if (req.method === "POST" && pathname === "/settings/access-key") {
|
|
27107
|
-
if (!originAllowed(req
|
|
26977
|
+
if (!originAllowed(req)) {
|
|
27108
26978
|
req.resume();
|
|
27109
26979
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27110
26980
|
}
|
|
@@ -27126,7 +26996,7 @@ var require_guard = __commonJS({
|
|
|
27126
26996
|
return send(200, sup.closeActionStatus());
|
|
27127
26997
|
}
|
|
27128
26998
|
if (req.method === "POST" && pathname === "/settings/close-action") {
|
|
27129
|
-
if (!originAllowed(req
|
|
26999
|
+
if (!originAllowed(req)) {
|
|
27130
27000
|
req.resume();
|
|
27131
27001
|
return send(403, {});
|
|
27132
27002
|
}
|
|
@@ -27147,7 +27017,7 @@ var require_guard = __commonJS({
|
|
|
27147
27017
|
return send(200, sup.externalBrowserStatus());
|
|
27148
27018
|
}
|
|
27149
27019
|
if (req.method === "POST" && pathname === "/settings/external-browser") {
|
|
27150
|
-
if (!originAllowed(req
|
|
27020
|
+
if (!originAllowed(req)) {
|
|
27151
27021
|
req.resume();
|
|
27152
27022
|
return send(403, {});
|
|
27153
27023
|
}
|
|
@@ -27169,7 +27039,7 @@ var require_guard = __commonJS({
|
|
|
27169
27039
|
return;
|
|
27170
27040
|
}
|
|
27171
27041
|
if (req.method === "POST" && pathname === "/shutdown") {
|
|
27172
|
-
if (!originAllowed(req
|
|
27042
|
+
if (!originAllowed(req)) {
|
|
27173
27043
|
req.resume();
|
|
27174
27044
|
return send(403, {});
|
|
27175
27045
|
}
|
|
@@ -27184,7 +27054,7 @@ var require_guard = __commonJS({
|
|
|
27184
27054
|
return;
|
|
27185
27055
|
}
|
|
27186
27056
|
if (req.method === "GET" && pathname === "/self-update/status") {
|
|
27187
|
-
if (!originAllowed(req
|
|
27057
|
+
if (!originAllowed(req)) {
|
|
27188
27058
|
req.resume();
|
|
27189
27059
|
return send(403, {});
|
|
27190
27060
|
}
|
|
@@ -27210,14 +27080,14 @@ var require_guard = __commonJS({
|
|
|
27210
27080
|
});
|
|
27211
27081
|
}
|
|
27212
27082
|
if (req.method === "GET" && pathname === "/env/dsh") {
|
|
27213
|
-
if (!originAllowed(req
|
|
27083
|
+
if (!originAllowed(req)) {
|
|
27214
27084
|
req.resume();
|
|
27215
27085
|
return send(403, {});
|
|
27216
27086
|
}
|
|
27217
27087
|
return send(200, sup.dshenvStatus());
|
|
27218
27088
|
}
|
|
27219
27089
|
if (req.method === "GET" && pathname === "/env/status") {
|
|
27220
|
-
if (!originAllowed(req
|
|
27090
|
+
if (!originAllowed(req)) {
|
|
27221
27091
|
req.resume();
|
|
27222
27092
|
return send(403, {});
|
|
27223
27093
|
}
|
|
@@ -27227,7 +27097,7 @@ var require_guard = __commonJS({
|
|
|
27227
27097
|
return sup.nodeLtsStatus().then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
27228
27098
|
}
|
|
27229
27099
|
if (req.method === "GET" && pathname === "/env/environment") {
|
|
27230
|
-
if (!originAllowed(req
|
|
27100
|
+
if (!originAllowed(req)) {
|
|
27231
27101
|
req.resume();
|
|
27232
27102
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27233
27103
|
}
|
|
@@ -27235,7 +27105,7 @@ var require_guard = __commonJS({
|
|
|
27235
27105
|
return Promise.resolve(force ? environment.refresh({ persist: true, force: true }) : environment.form()).then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: "\u73AF\u5883\u8868\u5355\u88C5\u914D\u5931\u8D25\uFF1A" + (e && e.message || e) }));
|
|
27236
27106
|
}
|
|
27237
27107
|
if (req.method === "GET" && pathname === "/env/environment/last") {
|
|
27238
|
-
if (!originAllowed(req
|
|
27108
|
+
if (!originAllowed(req)) {
|
|
27239
27109
|
req.resume();
|
|
27240
27110
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27241
27111
|
}
|
|
@@ -27246,7 +27116,7 @@ var require_guard = __commonJS({
|
|
|
27246
27116
|
req.resume();
|
|
27247
27117
|
return send(403, { ok: false, error: "\u4EC5\u5185\u6838\u6240\u5728\u673A\u5668\u53EF\u8BF7\u5185\u6838\u8C03\u8D77\u6D4F\u89C8\u5668\uFF0C\u8BF7\u590D\u5236\u6216\u81EA\u884C\u6253\u5F00\u8BE5\u5730\u5740" });
|
|
27248
27118
|
}
|
|
27249
|
-
if (!originAllowed(req
|
|
27119
|
+
if (!originAllowed(req)) {
|
|
27250
27120
|
req.resume();
|
|
27251
27121
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27252
27122
|
}
|
|
@@ -27291,7 +27161,7 @@ var require_router4 = __commonJS({
|
|
|
27291
27161
|
return Promise.resolve(sup.routerStatusView()).then((r) => send(200, r)).catch((e) => send(500, { ok: false, running: false, error: e && e.message || String(e) }));
|
|
27292
27162
|
}
|
|
27293
27163
|
if (req.method === "POST" && pathname.startsWith("/router/")) {
|
|
27294
|
-
if (!originAllowed(req
|
|
27164
|
+
if (!originAllowed(req)) {
|
|
27295
27165
|
req.resume();
|
|
27296
27166
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27297
27167
|
}
|
|
@@ -27308,7 +27178,7 @@ var require_router4 = __commonJS({
|
|
|
27308
27178
|
return Promise.resolve(sup.routerProviders()).then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
27309
27179
|
}
|
|
27310
27180
|
if (req.method === "POST" && pathname === "/router/providers/add") {
|
|
27311
|
-
if (!originAllowed(req
|
|
27181
|
+
if (!originAllowed(req)) {
|
|
27312
27182
|
req.resume();
|
|
27313
27183
|
return send(403, {});
|
|
27314
27184
|
}
|
|
@@ -27327,7 +27197,7 @@ var require_router4 = __commonJS({
|
|
|
27327
27197
|
return;
|
|
27328
27198
|
}
|
|
27329
27199
|
if (req.method === "POST" && pathname === "/router/proxy/login/start") {
|
|
27330
|
-
if (!originAllowed(req
|
|
27200
|
+
if (!originAllowed(req)) {
|
|
27331
27201
|
req.resume();
|
|
27332
27202
|
return send(403, {});
|
|
27333
27203
|
}
|
|
@@ -27335,7 +27205,7 @@ var require_router4 = __commonJS({
|
|
|
27335
27205
|
return;
|
|
27336
27206
|
}
|
|
27337
27207
|
if (req.method === "POST" && pathname === "/router/proxy/login/wait") {
|
|
27338
|
-
if (!originAllowed(req
|
|
27208
|
+
if (!originAllowed(req)) {
|
|
27339
27209
|
req.resume();
|
|
27340
27210
|
return send(403, {});
|
|
27341
27211
|
}
|
|
@@ -27352,7 +27222,7 @@ var require_router4 = __commonJS({
|
|
|
27352
27222
|
return;
|
|
27353
27223
|
}
|
|
27354
27224
|
if (req.method === "POST" && pathname === "/router/proxy/update/check") {
|
|
27355
|
-
if (!originAllowed(req
|
|
27225
|
+
if (!originAllowed(req)) {
|
|
27356
27226
|
req.resume();
|
|
27357
27227
|
return send(403, {});
|
|
27358
27228
|
}
|
|
@@ -27360,7 +27230,7 @@ var require_router4 = __commonJS({
|
|
|
27360
27230
|
return;
|
|
27361
27231
|
}
|
|
27362
27232
|
if (req.method === "POST" && pathname === "/router/proxy/update/apply") {
|
|
27363
|
-
if (!originAllowed(req
|
|
27233
|
+
if (!originAllowed(req)) {
|
|
27364
27234
|
req.resume();
|
|
27365
27235
|
return send(403, {});
|
|
27366
27236
|
}
|
|
@@ -27379,7 +27249,7 @@ var require_router4 = __commonJS({
|
|
|
27379
27249
|
return Promise.resolve(sup.routerApi().proxyUpdateStatus(u.searchParams.get("appId") || "")).then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
27380
27250
|
}
|
|
27381
27251
|
if (req.method === "POST" && pathname === "/router/providers/proxy/key") {
|
|
27382
|
-
if (!originAllowed(req
|
|
27252
|
+
if (!originAllowed(req)) {
|
|
27383
27253
|
req.resume();
|
|
27384
27254
|
return send(403, {});
|
|
27385
27255
|
}
|
|
@@ -27394,7 +27264,7 @@ var require_router4 = __commonJS({
|
|
|
27394
27264
|
return;
|
|
27395
27265
|
}
|
|
27396
27266
|
if (req.method === "POST" && pathname === "/router/providers/proxy/select") {
|
|
27397
|
-
if (!originAllowed(req
|
|
27267
|
+
if (!originAllowed(req)) {
|
|
27398
27268
|
req.resume();
|
|
27399
27269
|
return send(403, {});
|
|
27400
27270
|
}
|
|
@@ -27409,7 +27279,7 @@ var require_router4 = __commonJS({
|
|
|
27409
27279
|
return;
|
|
27410
27280
|
}
|
|
27411
27281
|
if (req.method === "POST" && pathname === "/router/providers/proxy/key/remove") {
|
|
27412
|
-
if (!originAllowed(req
|
|
27282
|
+
if (!originAllowed(req)) {
|
|
27413
27283
|
req.resume();
|
|
27414
27284
|
return send(403, {});
|
|
27415
27285
|
}
|
|
@@ -27424,7 +27294,7 @@ var require_router4 = __commonJS({
|
|
|
27424
27294
|
return;
|
|
27425
27295
|
}
|
|
27426
27296
|
if (req.method === "POST" && pathname === "/router/providers/keys/set") {
|
|
27427
|
-
if (!originAllowed(req
|
|
27297
|
+
if (!originAllowed(req)) {
|
|
27428
27298
|
req.resume();
|
|
27429
27299
|
return send(403, {});
|
|
27430
27300
|
}
|
|
@@ -27440,7 +27310,7 @@ var require_router4 = __commonJS({
|
|
|
27440
27310
|
return;
|
|
27441
27311
|
}
|
|
27442
27312
|
if (req.method === "POST" && pathname === "/router/providers/remove") {
|
|
27443
|
-
if (!originAllowed(req
|
|
27313
|
+
if (!originAllowed(req)) {
|
|
27444
27314
|
req.resume();
|
|
27445
27315
|
return send(403, {});
|
|
27446
27316
|
}
|
|
@@ -27455,7 +27325,7 @@ var require_router4 = __commonJS({
|
|
|
27455
27325
|
return;
|
|
27456
27326
|
}
|
|
27457
27327
|
if (req.method === "POST" && pathname === "/router/providers/key/use") {
|
|
27458
|
-
if (!originAllowed(req
|
|
27328
|
+
if (!originAllowed(req)) {
|
|
27459
27329
|
req.resume();
|
|
27460
27330
|
return send(403, {});
|
|
27461
27331
|
}
|
|
@@ -27471,7 +27341,7 @@ var require_router4 = __commonJS({
|
|
|
27471
27341
|
return;
|
|
27472
27342
|
}
|
|
27473
27343
|
if (req.method === "POST" && pathname === "/router/providers/account/discard") {
|
|
27474
|
-
if (!originAllowed(req
|
|
27344
|
+
if (!originAllowed(req)) {
|
|
27475
27345
|
req.resume();
|
|
27476
27346
|
return send(403, {});
|
|
27477
27347
|
}
|
|
@@ -27486,7 +27356,7 @@ var require_router4 = __commonJS({
|
|
|
27486
27356
|
return;
|
|
27487
27357
|
}
|
|
27488
27358
|
if (req.method === "POST" && pathname === "/router/providers/refresh") {
|
|
27489
|
-
if (!originAllowed(req
|
|
27359
|
+
if (!originAllowed(req)) {
|
|
27490
27360
|
req.resume();
|
|
27491
27361
|
return send(403, {});
|
|
27492
27362
|
}
|
|
@@ -27502,7 +27372,7 @@ var require_router4 = __commonJS({
|
|
|
27502
27372
|
return;
|
|
27503
27373
|
}
|
|
27504
27374
|
if (req.method === "POST" && pathname === "/router/providers/activate") {
|
|
27505
|
-
if (!originAllowed(req
|
|
27375
|
+
if (!originAllowed(req)) {
|
|
27506
27376
|
req.resume();
|
|
27507
27377
|
return send(403, {});
|
|
27508
27378
|
}
|
|
@@ -27518,7 +27388,7 @@ var require_router4 = __commonJS({
|
|
|
27518
27388
|
return;
|
|
27519
27389
|
}
|
|
27520
27390
|
if (req.method === "POST" && pathname === "/router/providers/deactivate") {
|
|
27521
|
-
if (!originAllowed(req
|
|
27391
|
+
if (!originAllowed(req)) {
|
|
27522
27392
|
req.resume();
|
|
27523
27393
|
return send(403, {});
|
|
27524
27394
|
}
|
|
@@ -27568,7 +27438,7 @@ var require_plugins = __commonJS({
|
|
|
27568
27438
|
return send(200, sup.pluginManager.installStatus(u.searchParams.get("job")));
|
|
27569
27439
|
}
|
|
27570
27440
|
if (req.method === "POST" && pathname.startsWith("/plugins/")) {
|
|
27571
|
-
if (!originAllowed(req
|
|
27441
|
+
if (!originAllowed(req)) {
|
|
27572
27442
|
req.resume();
|
|
27573
27443
|
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
27574
27444
|
}
|
|
@@ -27644,7 +27514,7 @@ var require_dist = __commonJS({
|
|
|
27644
27514
|
return;
|
|
27645
27515
|
}
|
|
27646
27516
|
if (req.method === "POST" && pathname === "/dist/registry/set") {
|
|
27647
|
-
if (!originAllowed(req
|
|
27517
|
+
if (!originAllowed(req)) {
|
|
27648
27518
|
req.resume();
|
|
27649
27519
|
return send(403, {});
|
|
27650
27520
|
}
|
|
@@ -27663,7 +27533,7 @@ var require_dist = __commonJS({
|
|
|
27663
27533
|
return;
|
|
27664
27534
|
}
|
|
27665
27535
|
if (req.method === "POST" && pathname === "/dist/registry/refresh") {
|
|
27666
|
-
if (!originAllowed(req
|
|
27536
|
+
if (!originAllowed(req)) {
|
|
27667
27537
|
req.resume();
|
|
27668
27538
|
return send(403, {});
|
|
27669
27539
|
}
|
|
@@ -27671,7 +27541,7 @@ var require_dist = __commonJS({
|
|
|
27671
27541
|
return;
|
|
27672
27542
|
}
|
|
27673
27543
|
if (req.method === "POST" && pathname === "/dist/registry/probe") {
|
|
27674
|
-
if (!originAllowed(req
|
|
27544
|
+
if (!originAllowed(req)) {
|
|
27675
27545
|
req.resume();
|
|
27676
27546
|
return send(403, {});
|
|
27677
27547
|
}
|
|
@@ -27742,6 +27612,112 @@ var require_exchange = __commonJS({
|
|
|
27742
27612
|
}
|
|
27743
27613
|
});
|
|
27744
27614
|
|
|
27615
|
+
// src/platform/security/identity.js
|
|
27616
|
+
var require_identity2 = __commonJS({
|
|
27617
|
+
"src/platform/security/identity.js"(exports2, module2) {
|
|
27618
|
+
"use strict";
|
|
27619
|
+
var { normalizeRemoteAddress, isLoopbackAddress } = require_ip();
|
|
27620
|
+
function socketIsLoopback(req) {
|
|
27621
|
+
return isLoopbackAddress(req && req.socket && req.socket.remoteAddress);
|
|
27622
|
+
}
|
|
27623
|
+
function identify(req) {
|
|
27624
|
+
return {
|
|
27625
|
+
remote: normalizeRemoteAddress(req && req.socket && req.socket.remoteAddress),
|
|
27626
|
+
loopback: socketIsLoopback(req)
|
|
27627
|
+
};
|
|
27628
|
+
}
|
|
27629
|
+
module2.exports = { identify };
|
|
27630
|
+
}
|
|
27631
|
+
});
|
|
27632
|
+
|
|
27633
|
+
// src/api/identity.js
|
|
27634
|
+
var require_identity3 = __commonJS({
|
|
27635
|
+
"src/api/identity.js"(exports2, module2) {
|
|
27636
|
+
"use strict";
|
|
27637
|
+
var { normalizeRemoteAddress, isLoopbackAddress, isPrivateIpv4 } = require_ip();
|
|
27638
|
+
var { identify } = require_identity2();
|
|
27639
|
+
module2.exports = {
|
|
27640
|
+
identify,
|
|
27641
|
+
normalizeRemoteAddress,
|
|
27642
|
+
isPrivateIpv4,
|
|
27643
|
+
isLoopbackAddress
|
|
27644
|
+
};
|
|
27645
|
+
}
|
|
27646
|
+
});
|
|
27647
|
+
|
|
27648
|
+
// src/api/security.js
|
|
27649
|
+
var require_security = __commonJS({
|
|
27650
|
+
"src/api/security.js"(exports2, module2) {
|
|
27651
|
+
"use strict";
|
|
27652
|
+
var crypto = require("node:crypto");
|
|
27653
|
+
var { isPrivateIpv4 } = require_identity3();
|
|
27654
|
+
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
|
|
27655
|
+
function isLocalOrLanHost(h) {
|
|
27656
|
+
if (!h) return false;
|
|
27657
|
+
const s = String(h).toLowerCase();
|
|
27658
|
+
if (LOOPBACK_HOSTS.has(s)) return true;
|
|
27659
|
+
const bare = s.startsWith("[") && s.endsWith("]") ? s.slice(1, -1) : s;
|
|
27660
|
+
if (bare === "::1") return true;
|
|
27661
|
+
return isPrivateIpv4(bare);
|
|
27662
|
+
}
|
|
27663
|
+
function isShellOrigin(protocol, hostname) {
|
|
27664
|
+
const h = String(hostname || "").toLowerCase();
|
|
27665
|
+
if (protocol === "tauri:") return h === "localhost" || /(^|\.)tauri\.localhost$/.test(h);
|
|
27666
|
+
if (protocol === "http:" || protocol === "https:") return h === "tauri.localhost";
|
|
27667
|
+
return false;
|
|
27668
|
+
}
|
|
27669
|
+
function normalizeHostname(h) {
|
|
27670
|
+
const s = String(h || "").toLowerCase();
|
|
27671
|
+
return s.startsWith("[") && s.endsWith("]") ? s.slice(1, -1) : s;
|
|
27672
|
+
}
|
|
27673
|
+
function originAllowed(req, apiPort) {
|
|
27674
|
+
const host = req.headers.host;
|
|
27675
|
+
if (!host) return false;
|
|
27676
|
+
let hostname = "";
|
|
27677
|
+
{
|
|
27678
|
+
const m = /^(\[[^\]]+\]|[^:]+)(?::\d+)?$/.exec(String(host).trim());
|
|
27679
|
+
hostname = m ? m[1] : String(host).trim();
|
|
27680
|
+
if (!isLocalOrLanHost(hostname)) return false;
|
|
27681
|
+
}
|
|
27682
|
+
const o = req.headers.origin;
|
|
27683
|
+
if (!o) return true;
|
|
27684
|
+
try {
|
|
27685
|
+
const u = new URL(o);
|
|
27686
|
+
if (isShellOrigin(u.protocol, u.hostname)) return true;
|
|
27687
|
+
if (!isLocalOrLanHost(u.hostname)) return false;
|
|
27688
|
+
if (host && normalizeHostname(u.hostname) !== normalizeHostname(hostname)) return false;
|
|
27689
|
+
const port = u.port === "" ? u.protocol === "https:" ? "443" : "80" : u.port;
|
|
27690
|
+
return port === String(apiPort);
|
|
27691
|
+
} catch {
|
|
27692
|
+
return false;
|
|
27693
|
+
}
|
|
27694
|
+
}
|
|
27695
|
+
function safeKeyEqual(a, b) {
|
|
27696
|
+
const ha = crypto.createHash("sha256").update(String(a || "")).digest();
|
|
27697
|
+
const hb = crypto.createHash("sha256").update(String(b || "")).digest();
|
|
27698
|
+
return crypto.timingSafeEqual(ha, hb);
|
|
27699
|
+
}
|
|
27700
|
+
function requestHasAccessKey(req, key) {
|
|
27701
|
+
if (!key) return true;
|
|
27702
|
+
const ah = req.headers.authorization;
|
|
27703
|
+
if (typeof ah === "string" && ah.startsWith("Bearer ") && safeKeyEqual(ah.slice(7), key)) return true;
|
|
27704
|
+
try {
|
|
27705
|
+
const q = new URL(req.url, "http://localhost").searchParams.get("access_key");
|
|
27706
|
+
if (q && safeKeyEqual(q, key)) return true;
|
|
27707
|
+
} catch {
|
|
27708
|
+
}
|
|
27709
|
+
return false;
|
|
27710
|
+
}
|
|
27711
|
+
function liveApiPort(server, sup) {
|
|
27712
|
+
const live = server && typeof server.address === "function" ? server.address() : null;
|
|
27713
|
+
if (live && Number.isInteger(live.port) && live.port > 0) return live.port;
|
|
27714
|
+
const cfg = sup && sup.config && sup.config.apiPort;
|
|
27715
|
+
return Number.isInteger(cfg) ? cfg : null;
|
|
27716
|
+
}
|
|
27717
|
+
module2.exports = { originAllowed, isLocalOrLanHost, isShellOrigin, requestHasAccessKey, liveApiPort };
|
|
27718
|
+
}
|
|
27719
|
+
});
|
|
27720
|
+
|
|
27745
27721
|
// src/api/domains/instances.js
|
|
27746
27722
|
var require_instances = __commonJS({
|
|
27747
27723
|
"src/api/domains/instances.js"(exports2, module2) {
|
|
@@ -27749,6 +27725,7 @@ var require_instances = __commonJS({
|
|
|
27749
27725
|
var execPath = require_exec_path();
|
|
27750
27726
|
var crypto = require("node:crypto");
|
|
27751
27727
|
var { bootstrapDshCookie } = require_exchange();
|
|
27728
|
+
var { liveApiPort } = require_security();
|
|
27752
27729
|
var OPEN_WEB_CODES = /* @__PURE__ */ new Map();
|
|
27753
27730
|
var OPEN_WEB_CODE_TTL_MS = 3e4;
|
|
27754
27731
|
function _sweepExpiredOpenWebCodes() {
|
|
@@ -27782,16 +27759,16 @@ var require_instances = __commonJS({
|
|
|
27782
27759
|
return (sup.instances.list() || []).find((x) => x.id === id) || null;
|
|
27783
27760
|
}
|
|
27784
27761
|
function handleOpen(ctx) {
|
|
27785
|
-
const { sup, req, res, identity, originAllowed, tokOf } = ctx;
|
|
27762
|
+
const { sup, req, res, identity, originAllowed, tokOf, server } = ctx;
|
|
27786
27763
|
const url = new URL(req.url, "http://localhost");
|
|
27787
|
-
const apiPort = sup
|
|
27764
|
+
const apiPort = liveApiPort(server, sup);
|
|
27788
27765
|
const code = url.searchParams.get("code");
|
|
27789
27766
|
const deny = (status, msg) => {
|
|
27790
27767
|
res.writeHead(status, { "Content-Type": "text/plain; charset=utf-8" });
|
|
27791
27768
|
res.end(msg);
|
|
27792
27769
|
};
|
|
27793
27770
|
if (!identity.loopback) return deny(403, "\u4EC5\u5141\u8BB8\u672C\u673A\u8BBF\u95EE");
|
|
27794
|
-
if (!originAllowed(req
|
|
27771
|
+
if (!originAllowed(req)) return deny(403, "origin not allowed");
|
|
27795
27772
|
const rec = consumeOpenWebCode(code);
|
|
27796
27773
|
if (!rec) return deny(code ? 400 : 404, code ? "\u6388\u6743\u7801\u65E0\u6548\u6216\u5DF2\u8FC7\u671F" : "\u7F3A\u5C11\u6388\u6743\u7801");
|
|
27797
27774
|
const it = findInstanceOrMain(sup, rec.id);
|
|
@@ -27857,7 +27834,7 @@ var require_instances = __commonJS({
|
|
|
27857
27834
|
return sharedErr + "\uFF1B" + FORMS + "\uFF1B\u9700\u8981\u5176\u5B83\u53EF\u6267\u884C\u8BF7\u8D70\u63D2\u4EF6\u5B89\u88C5\u901A\u9053";
|
|
27858
27835
|
}
|
|
27859
27836
|
function handle(ctx) {
|
|
27860
|
-
const { sup, req, res, pathname, identity, send, collectBody, originAllowed, tokOf, browser } = ctx;
|
|
27837
|
+
const { sup, req, res, pathname, identity, send, collectBody, originAllowed, tokOf, browser, server } = ctx;
|
|
27861
27838
|
function openInSystemBrowser(url) {
|
|
27862
27839
|
return browser.openBrowser(url, { logger: sup.logger });
|
|
27863
27840
|
}
|
|
@@ -27884,7 +27861,7 @@ var require_instances = __commonJS({
|
|
|
27884
27861
|
return render();
|
|
27885
27862
|
}
|
|
27886
27863
|
if (req.method === "POST" && pathname.startsWith("/instances/")) {
|
|
27887
|
-
if (!originAllowed(req
|
|
27864
|
+
if (!originAllowed(req)) {
|
|
27888
27865
|
req.resume();
|
|
27889
27866
|
return send(403, {});
|
|
27890
27867
|
}
|
|
@@ -27921,7 +27898,7 @@ var require_instances = __commonJS({
|
|
|
27921
27898
|
if (!it) return send(404, { ok: false, error: "\u5B9E\u4F8B\u4E0D\u5B58\u5728" });
|
|
27922
27899
|
if (!(Number(it.port) > 0)) return send(400, { ok: false, error: "\u975E\u6CD5\u7AEF\u53E3" });
|
|
27923
27900
|
const code = issueOpenWebCode(j.id);
|
|
27924
|
-
const url = "http://127.0.0.1:" + sup.config.apiPort + "/open?code=" + code;
|
|
27901
|
+
const url = "http://127.0.0.1:" + (liveApiPort(server, sup) || sup.config.apiPort) + "/open?code=" + code;
|
|
27925
27902
|
return Promise.resolve(openInSystemBrowser(url)).then((r) => {
|
|
27926
27903
|
if (!r.ok) dropOpenWebCode(code);
|
|
27927
27904
|
return send(r.ok ? 200 : 500, r);
|
|
@@ -27966,7 +27943,7 @@ var require_relay = __commonJS({
|
|
|
27966
27943
|
return Promise.resolve(sup.listLan()).then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
27967
27944
|
}
|
|
27968
27945
|
if (req.method === "POST" && pathname.startsWith("/remote/")) {
|
|
27969
|
-
if (!originAllowed(req
|
|
27946
|
+
if (!originAllowed(req)) {
|
|
27970
27947
|
req.resume();
|
|
27971
27948
|
return send(403, {});
|
|
27972
27949
|
}
|
|
@@ -28029,7 +28006,7 @@ var require_shell2 = __commonJS({
|
|
|
28029
28006
|
}
|
|
28030
28007
|
}
|
|
28031
28008
|
if (req.method === "POST" && pathname === "/shell/health") {
|
|
28032
|
-
if (!originAllowed(req
|
|
28009
|
+
if (!originAllowed(req)) {
|
|
28033
28010
|
req.resume();
|
|
28034
28011
|
return send(403, {});
|
|
28035
28012
|
}
|
|
@@ -28046,28 +28023,8 @@ var require_shell2 = __commonJS({
|
|
|
28046
28023
|
}
|
|
28047
28024
|
});
|
|
28048
28025
|
}
|
|
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
28026
|
if (req.method === "POST" && pathname === "/shell/check-update") {
|
|
28070
|
-
if (!originAllowed(req
|
|
28027
|
+
if (!originAllowed(req)) {
|
|
28071
28028
|
req.resume();
|
|
28072
28029
|
return send(403, {});
|
|
28073
28030
|
}
|
|
@@ -28079,23 +28036,6 @@ var require_shell2 = __commonJS({
|
|
|
28079
28036
|
return send(200, r);
|
|
28080
28037
|
}).catch((e) => send(500, { ok: false, error: e.message }));
|
|
28081
28038
|
}
|
|
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
28039
|
if (req.method === "GET" || req.method === "POST") return send(404, { error: "not found", path: pathname });
|
|
28100
28040
|
return send(405, { error: "method not allowed" });
|
|
28101
28041
|
}
|
|
@@ -28259,106 +28199,6 @@ var require_static = __commonJS({
|
|
|
28259
28199
|
}
|
|
28260
28200
|
});
|
|
28261
28201
|
|
|
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
28202
|
// src/api/transport/server.js
|
|
28363
28203
|
var require_server = __commonJS({
|
|
28364
28204
|
"src/api/transport/server.js"(exports2, module2) {
|
|
@@ -28368,7 +28208,7 @@ var require_server = __commonJS({
|
|
|
28368
28208
|
var { collectBody } = require_body();
|
|
28369
28209
|
var { serveStatic } = require_static();
|
|
28370
28210
|
var { identify } = require_identity3();
|
|
28371
|
-
var { originAllowed, requestHasAccessKey, isShellOrigin } = require_security();
|
|
28211
|
+
var { originAllowed, requestHasAccessKey, isShellOrigin, liveApiPort } = require_security();
|
|
28372
28212
|
var browserExit = require_browser();
|
|
28373
28213
|
var environmentExit = require_environment();
|
|
28374
28214
|
function safeFail(res, err, where) {
|
|
@@ -28391,7 +28231,7 @@ var require_server = __commonJS({
|
|
|
28391
28231
|
function createServer(sup, deps) {
|
|
28392
28232
|
const browser = deps && deps.browser || browserExit;
|
|
28393
28233
|
const environment = deps && deps.environment || environmentExit;
|
|
28394
|
-
|
|
28234
|
+
const server = http2.createServer((req, res) => {
|
|
28395
28235
|
const shellOrigin = (() => {
|
|
28396
28236
|
const o = req.headers.origin;
|
|
28397
28237
|
if (!o) return null;
|
|
@@ -28421,6 +28261,7 @@ var require_server = __commonJS({
|
|
|
28421
28261
|
return "";
|
|
28422
28262
|
};
|
|
28423
28263
|
const identity = identify(req);
|
|
28264
|
+
const originAllowedLive = (req2) => originAllowed(req2, liveApiPort(server, sup));
|
|
28424
28265
|
const accessKey = sup && sup.config && sup.config.apiAccessKey || null;
|
|
28425
28266
|
if (!identity.loopback && req.method !== "OPTIONS" && (!accessKey || !requestHasAccessKey(req, accessKey))) {
|
|
28426
28267
|
res.writeHead(401, { "Content-Type": "application/json" });
|
|
@@ -28458,7 +28299,7 @@ var require_server = __commonJS({
|
|
|
28458
28299
|
} catch (e) {
|
|
28459
28300
|
return send(400, { error: "bad request encoding" });
|
|
28460
28301
|
}
|
|
28461
|
-
const ctx = { sup, req, res, pathname: decodedPathname, identity, send, collectBody, originAllowed, tokOf, browser, environment };
|
|
28302
|
+
const ctx = { sup, req, res, pathname: decodedPathname, identity, send, collectBody, originAllowed: originAllowedLive, tokOf, browser, environment, server };
|
|
28462
28303
|
for (const d of API_DOMAINS) {
|
|
28463
28304
|
if (d.owns(pathname)) {
|
|
28464
28305
|
try {
|
|
@@ -28484,6 +28325,7 @@ var require_server = __commonJS({
|
|
|
28484
28325
|
}
|
|
28485
28326
|
return send(405, { error: "method not allowed" });
|
|
28486
28327
|
});
|
|
28328
|
+
return server;
|
|
28487
28329
|
}
|
|
28488
28330
|
module2.exports = { createServer };
|
|
28489
28331
|
}
|
|
@@ -28503,7 +28345,7 @@ var require_api = __commonJS({
|
|
|
28503
28345
|
var require_session = __commonJS({
|
|
28504
28346
|
"src/domains/relay/session.js"(exports2, module2) {
|
|
28505
28347
|
"use strict";
|
|
28506
|
-
var { cookieByName } =
|
|
28348
|
+
var { cookieByName } = require_core3();
|
|
28507
28349
|
var { bootstrapDshCookie } = require_exchange();
|
|
28508
28350
|
function createSession(opts) {
|
|
28509
28351
|
const o = opts || {};
|
|
@@ -28645,7 +28487,7 @@ var require_tunnel = __commonJS({
|
|
|
28645
28487
|
"src/domains/relay/tunnel.js"(exports2, module2) {
|
|
28646
28488
|
"use strict";
|
|
28647
28489
|
var net = require("node:net");
|
|
28648
|
-
var { isTrustedSource, hasValidToken, upstreamPath } =
|
|
28490
|
+
var { isTrustedSource, hasValidToken, upstreamPath } = require_core3();
|
|
28649
28491
|
function buildRawRequest(req, authority, cookie) {
|
|
28650
28492
|
let raw = req.method + " " + upstreamPath(req.url) + " HTTP/1.1\r\n";
|
|
28651
28493
|
for (const [k, v] of Object.entries(req.headers)) {
|
|
@@ -28731,7 +28573,7 @@ var require_proxy2 = __commonJS({
|
|
|
28731
28573
|
"use strict";
|
|
28732
28574
|
var http2 = require("node:http");
|
|
28733
28575
|
var crypto = require("node:crypto");
|
|
28734
|
-
var { isTrustedSource, tokenGateDecision, backoffGate, upstreamPath, redactLogPath, normalizeRemoteMode, POLYFILL_SCRIPT } =
|
|
28576
|
+
var { isTrustedSource, tokenGateDecision, backoffGate, upstreamPath, redactLogPath, normalizeRemoteMode, POLYFILL_SCRIPT } = require_core3();
|
|
28735
28577
|
var { createSession } = require_session();
|
|
28736
28578
|
var { createTunnelHandler } = require_tunnel();
|
|
28737
28579
|
var HTML_INJECT_MAX_BYTES = 2 * 1024 * 1024;
|
|
@@ -28756,7 +28598,7 @@ var require_proxy2 = __commonJS({
|
|
|
28756
28598
|
}
|
|
28757
28599
|
};
|
|
28758
28600
|
}
|
|
28759
|
-
function pipeWithHold(ur, res,
|
|
28601
|
+
function pipeWithHold(ur, res, clientReqLog, logger) {
|
|
28760
28602
|
let clientGone = false;
|
|
28761
28603
|
const log = (lv, msg) => {
|
|
28762
28604
|
if (logger && logger[lv]) {
|
|
@@ -28805,7 +28647,7 @@ var require_proxy2 = __commonJS({
|
|
|
28805
28647
|
return headers;
|
|
28806
28648
|
}
|
|
28807
28649
|
function handleUpstream(ur, res, clientReqPath, onStatus, logger) {
|
|
28808
|
-
const
|
|
28650
|
+
const clientReqLog = redactLogPath(clientReqPath);
|
|
28809
28651
|
if (onStatus) onStatus(ur.statusCode);
|
|
28810
28652
|
const h = { ...ur.headers };
|
|
28811
28653
|
const isHtml = String(h["content-type"] || "").includes("text/html");
|
|
@@ -28817,7 +28659,7 @@ var require_proxy2 = __commonJS({
|
|
|
28817
28659
|
}
|
|
28818
28660
|
res.writeHead(ur.statusCode || 502, h);
|
|
28819
28661
|
if (!isHtml) {
|
|
28820
|
-
pipeWithHold(ur, res,
|
|
28662
|
+
pipeWithHold(ur, res, clientReqLog, logger);
|
|
28821
28663
|
return;
|
|
28822
28664
|
}
|
|
28823
28665
|
const chunks = [];
|
|
@@ -28851,7 +28693,7 @@ var require_proxy2 = __commonJS({
|
|
|
28851
28693
|
chunks.push(c);
|
|
28852
28694
|
return;
|
|
28853
28695
|
}
|
|
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 " + (
|
|
28696
|
+
log("HTML \u8D85\u4E0A\u9650 " + HTML_INJECT_MAX_BYTES + "B\uFF08\u5DF2\u6536 " + total + "B\uFF09\uFF0C\u653E\u5F03 polyfill \u6CE8\u5165\u6309\u6D41\u900F\u4F20 " + (clientReqLog || ""));
|
|
28855
28697
|
const selfForward = !ur.readableEnded;
|
|
28856
28698
|
switchToPassThrough();
|
|
28857
28699
|
if (selfForward) res.write(c);
|
|
@@ -29031,14 +28873,8 @@ var require_ports3 = __commonJS({
|
|
|
29031
28873
|
return registry.claimSlot(segment, owner, {
|
|
29032
28874
|
preferred: o.preferred,
|
|
29033
28875
|
bindingPreferred: !!o.bindingPreferred,
|
|
29034
|
-
// RL-4:跨账本防撞。router caller 不传 reservedPorts(分配器跳过该检查,行为不变);
|
|
29035
|
-
// 仅 relay 传入 router 账本已占端口,free-scan/preferred-claim 跳过 ⇒ 不会抢 router 的端口。
|
|
29036
28876
|
reservedPorts: reservedPorts || void 0,
|
|
29037
28877
|
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
28878
|
reclaimCmdMark: "domains/relay/daemon.js",
|
|
29043
28879
|
reclaimCfg: o.configPath || "",
|
|
29044
28880
|
waitMs: 8e3
|
|
@@ -29237,7 +29073,7 @@ var require_frp = __commonJS({
|
|
|
29237
29073
|
var path2 = require("node:path");
|
|
29238
29074
|
var spawnOS = require_spawn();
|
|
29239
29075
|
var { writeAtomic } = require_fs();
|
|
29240
|
-
var { buildFrpcToml, validateFrpServerSettings } =
|
|
29076
|
+
var { buildFrpcToml, validateFrpServerSettings } = require_core3();
|
|
29241
29077
|
var { frpPlatformTag, download, installFrpc } = require_frp_install();
|
|
29242
29078
|
var FrpManager = class {
|
|
29243
29079
|
constructor(opts) {
|
|
@@ -29681,7 +29517,7 @@ var require_ops5 = __commonJS({
|
|
|
29681
29517
|
var managed = require_managed();
|
|
29682
29518
|
var portsvc = require_ports3();
|
|
29683
29519
|
var { FrpManager } = require_frp();
|
|
29684
|
-
var { normalizeRemoteMode, validateWanAccess, normalizeFrpSettings, validateFrpServerSettings, projectRemoteView } =
|
|
29520
|
+
var { normalizeRemoteMode, validateWanAccess, normalizeFrpSettings, validateFrpServerSettings, projectRemoteView } = require_core3();
|
|
29685
29521
|
var reconcile = require_reconcile();
|
|
29686
29522
|
var lanServers = require_lan_servers();
|
|
29687
29523
|
function applyRelayToken(host, existing, want) {
|