@yoooclaw/phone-notifications 1.11.10 → 1.11.13
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/dist/index.cjs +117 -110
- package/dist/index.cjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5574,7 +5574,7 @@ function readBuildInjectedVersion() {
|
|
|
5574
5574
|
if (false) {
|
|
5575
5575
|
return void 0;
|
|
5576
5576
|
}
|
|
5577
|
-
const version = "1.11.
|
|
5577
|
+
const version = "1.11.13".trim();
|
|
5578
5578
|
return version || void 0;
|
|
5579
5579
|
}
|
|
5580
5580
|
function readPluginVersionFromPackageJson() {
|
|
@@ -12303,19 +12303,72 @@ var import_websocket = __toESM(require_websocket(), 1);
|
|
|
12303
12303
|
var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
12304
12304
|
var wrapper_default = import_websocket.default;
|
|
12305
12305
|
|
|
12306
|
-
// src/tunnel/
|
|
12307
|
-
function previewText(text, max =
|
|
12306
|
+
// src/tunnel/utils.ts
|
|
12307
|
+
function previewText(text, max = 200) {
|
|
12308
|
+
if (!text) return "";
|
|
12308
12309
|
return text.length <= max ? text : `${text.substring(0, max)}\u2026`;
|
|
12309
12310
|
}
|
|
12310
|
-
var HANDSHAKE_TIMEOUT_MS = 15e3;
|
|
12311
|
-
var CONNECT_WATCHDOG_MS = 2e4;
|
|
12312
12311
|
function maskSecret(value) {
|
|
12313
12312
|
if (!value) return "empty";
|
|
12314
12313
|
if (value.length <= 8) {
|
|
12315
|
-
return `${value.slice(0, 2)}
|
|
12314
|
+
return `${value.slice(0, 2)}...${value.slice(-2)}`;
|
|
12315
|
+
}
|
|
12316
|
+
return `${value.slice(0, 4)}...${value.slice(-4)}`;
|
|
12317
|
+
}
|
|
12318
|
+
function redactUrlSecrets(rawUrl) {
|
|
12319
|
+
try {
|
|
12320
|
+
const url = new URL(rawUrl);
|
|
12321
|
+
for (const key of ["apiKey", "token", "access_token"]) {
|
|
12322
|
+
const value = url.searchParams.get(key);
|
|
12323
|
+
if (value) {
|
|
12324
|
+
url.searchParams.set(key, maskSecret(value));
|
|
12325
|
+
}
|
|
12326
|
+
}
|
|
12327
|
+
return url.toString();
|
|
12328
|
+
} catch {
|
|
12329
|
+
return rawUrl.replace(
|
|
12330
|
+
/([?&](?:apiKey|token|access_token)=)([^&]+)/gi,
|
|
12331
|
+
(_match, prefix, value) => {
|
|
12332
|
+
let decoded = value;
|
|
12333
|
+
try {
|
|
12334
|
+
decoded = decodeURIComponent(value);
|
|
12335
|
+
} catch {
|
|
12336
|
+
}
|
|
12337
|
+
return `${prefix}${maskSecret(decoded)}`;
|
|
12338
|
+
}
|
|
12339
|
+
);
|
|
12340
|
+
}
|
|
12341
|
+
}
|
|
12342
|
+
function findHeaderValue(headers, key) {
|
|
12343
|
+
if (!headers) return void 0;
|
|
12344
|
+
const lowerKey = key.toLowerCase();
|
|
12345
|
+
for (const [headerKey, headerValue] of Object.entries(headers)) {
|
|
12346
|
+
if (headerKey.toLowerCase() === lowerKey) {
|
|
12347
|
+
return headerValue;
|
|
12348
|
+
}
|
|
12316
12349
|
}
|
|
12317
|
-
return
|
|
12350
|
+
return void 0;
|
|
12318
12351
|
}
|
|
12352
|
+
function summarizeRequestHeaders(headers) {
|
|
12353
|
+
const contentType = findHeaderValue(headers, "content-type");
|
|
12354
|
+
const requestId = findHeaderValue(headers, "x-request-id");
|
|
12355
|
+
const parts = [];
|
|
12356
|
+
if (contentType) {
|
|
12357
|
+
parts.push(`contentType=${contentType}`);
|
|
12358
|
+
}
|
|
12359
|
+
if (requestId) {
|
|
12360
|
+
parts.push(`xRequestId=${previewText(requestId, 120)}`);
|
|
12361
|
+
}
|
|
12362
|
+
return parts.length ? `, ${parts.join(", ")}` : "";
|
|
12363
|
+
}
|
|
12364
|
+
|
|
12365
|
+
// src/tunnel/relay-client.ts
|
|
12366
|
+
function previewText2(text, max = 500) {
|
|
12367
|
+
return text.length <= max ? text : `${text.substring(0, max)}\u2026`;
|
|
12368
|
+
}
|
|
12369
|
+
var HANDSHAKE_TIMEOUT_MS = 15e3;
|
|
12370
|
+
var CONNECT_WATCHDOG_MS = 2e4;
|
|
12371
|
+
var SEND_SKIPPED_LOG_INTERVAL_MS = 3e4;
|
|
12319
12372
|
var RelayClient = class {
|
|
12320
12373
|
constructor(opts) {
|
|
12321
12374
|
this.opts = opts;
|
|
@@ -12329,6 +12382,8 @@ var RelayClient = class {
|
|
|
12329
12382
|
aborted = false;
|
|
12330
12383
|
lastInboundAt = 0;
|
|
12331
12384
|
stopPromise = null;
|
|
12385
|
+
skippedSendLogLastAt = null;
|
|
12386
|
+
skippedSendLogSuppressed = 0;
|
|
12332
12387
|
/** 写连接状态到磁盘 */
|
|
12333
12388
|
writeStatus(state, lastDisconnectReason) {
|
|
12334
12389
|
if (!this.opts.statusFilePath) return;
|
|
@@ -12432,9 +12487,7 @@ var RelayClient = class {
|
|
|
12432
12487
|
);
|
|
12433
12488
|
this.ws.send(payload);
|
|
12434
12489
|
} else {
|
|
12435
|
-
this.
|
|
12436
|
-
`Relay tunnel: \u25B6 send skipped, ws not open (readyState=${this.ws?.readyState ?? "null"}), frame type=${frame.type}`
|
|
12437
|
-
);
|
|
12490
|
+
this.logSendSkipped("send", `frame type=${frame.type}`);
|
|
12438
12491
|
}
|
|
12439
12492
|
}
|
|
12440
12493
|
/** 原样透传文本到 Relay(用于 Gateway WS 响应直接回传) */
|
|
@@ -12445,9 +12498,7 @@ var RelayClient = class {
|
|
|
12445
12498
|
);
|
|
12446
12499
|
this.ws.send(text);
|
|
12447
12500
|
} else {
|
|
12448
|
-
this.
|
|
12449
|
-
`Relay tunnel: \u25B6 sendRaw skipped, ws not open (readyState=${this.ws?.readyState ?? "null"})`
|
|
12450
|
-
);
|
|
12501
|
+
this.logSendSkipped("sendRaw");
|
|
12451
12502
|
}
|
|
12452
12503
|
}
|
|
12453
12504
|
/** 启动连接,带自动重连,直到 abortSignal 触发 */
|
|
@@ -12473,7 +12524,7 @@ var RelayClient = class {
|
|
|
12473
12524
|
this.cleanup(true);
|
|
12474
12525
|
const rawApiKey = this.opts.apiKey.startsWith("Bearer ") ? this.opts.apiKey.slice("Bearer ".length) : this.opts.apiKey;
|
|
12475
12526
|
this.opts.logger.info(
|
|
12476
|
-
`Relay tunnel: connecting to ${this.opts.tunnelUrl} (attempt=${this.reconnectAttempt}, heartbeat=${this.opts.heartbeatSec}s, apiKey=${maskSecret(rawApiKey)})`
|
|
12527
|
+
`Relay tunnel: connecting to ${redactUrlSecrets(this.opts.tunnelUrl)} (attempt=${this.reconnectAttempt}, heartbeat=${this.opts.heartbeatSec}s, apiKey=${maskSecret(rawApiKey)})`
|
|
12477
12528
|
);
|
|
12478
12529
|
this.writeStatus("connecting");
|
|
12479
12530
|
return new Promise((resolve) => {
|
|
@@ -12567,7 +12618,7 @@ var RelayClient = class {
|
|
|
12567
12618
|
const reasonStr = reason.toString();
|
|
12568
12619
|
const lastInboundAgoMs = this.lastInboundAt ? Date.now() - this.lastInboundAt : null;
|
|
12569
12620
|
const isCurrentSocket = this.ws === ws;
|
|
12570
|
-
const logMessage = `Relay tunnel: disconnected (code=${code}, reason=${
|
|
12621
|
+
const logMessage = `Relay tunnel: disconnected (code=${code}, reason=${previewText2(reasonStr, 200)}, lastInboundAgoMs=${lastInboundAgoMs ?? "N/A"}, reconnectAttempt=${this.reconnectAttempt})`;
|
|
12571
12622
|
if (this.aborted || !isCurrentSocket) {
|
|
12572
12623
|
this.opts.logger.info(logMessage);
|
|
12573
12624
|
} else {
|
|
@@ -12582,11 +12633,12 @@ var RelayClient = class {
|
|
|
12582
12633
|
settle();
|
|
12583
12634
|
});
|
|
12584
12635
|
ws.on("error", (err2) => {
|
|
12636
|
+
clearConnectWatchdog();
|
|
12585
12637
|
this.opts.logger.error(
|
|
12586
|
-
`Relay tunnel: WebSocket error: ${err2.message} (readyState=${ws.readyState}, reconnectAttempt=${this.reconnectAttempt}, url=${wsUrl.toString()})`
|
|
12638
|
+
`Relay tunnel: WebSocket error: ${err2.message} (readyState=${ws.readyState}, reconnectAttempt=${this.reconnectAttempt}, url=${redactUrlSecrets(wsUrl.toString())})`
|
|
12587
12639
|
);
|
|
12588
12640
|
if (this.ws === ws) {
|
|
12589
|
-
this.
|
|
12641
|
+
this.forceReconnectFromSocket(ws, `error: ${err2.message}`);
|
|
12590
12642
|
}
|
|
12591
12643
|
settle();
|
|
12592
12644
|
});
|
|
@@ -12608,14 +12660,14 @@ var RelayClient = class {
|
|
|
12608
12660
|
return;
|
|
12609
12661
|
}
|
|
12610
12662
|
this.opts.logger.info(
|
|
12611
|
-
`Relay tunnel: \u2605 received message (${text.length} chars): ${
|
|
12663
|
+
`Relay tunnel: \u2605 received message (${text.length} chars): ${previewText2(text)}`
|
|
12612
12664
|
);
|
|
12613
12665
|
let frame;
|
|
12614
12666
|
try {
|
|
12615
12667
|
frame = JSON.parse(text);
|
|
12616
12668
|
} catch {
|
|
12617
12669
|
this.opts.logger.warn(
|
|
12618
|
-
`Relay tunnel: received invalid frame, ignoring (preview=${
|
|
12670
|
+
`Relay tunnel: received invalid frame, ignoring (preview=${previewText2(text, 200)})`
|
|
12619
12671
|
);
|
|
12620
12672
|
return;
|
|
12621
12673
|
}
|
|
@@ -12651,7 +12703,8 @@ var RelayClient = class {
|
|
|
12651
12703
|
return this.opts.heartbeatSec * 3 * 1e3;
|
|
12652
12704
|
}
|
|
12653
12705
|
sendHeartbeat() {
|
|
12654
|
-
|
|
12706
|
+
const ws = this.ws;
|
|
12707
|
+
if (ws?.readyState !== wrapper_default.OPEN) {
|
|
12655
12708
|
return;
|
|
12656
12709
|
}
|
|
12657
12710
|
const idleMs = Date.now() - this.lastInboundAt;
|
|
@@ -12660,19 +12713,16 @@ var RelayClient = class {
|
|
|
12660
12713
|
this.opts.logger.warn(
|
|
12661
12714
|
`Relay tunnel: heartbeat timeout, no inbound activity for ${idleMs}ms (threshold=${timeoutMs}ms)`
|
|
12662
12715
|
);
|
|
12663
|
-
|
|
12664
|
-
this.ws.terminate();
|
|
12665
|
-
} catch {
|
|
12666
|
-
}
|
|
12716
|
+
this.forceReconnectFromSocket(ws, `heartbeat-timeout idleMs=${idleMs}`);
|
|
12667
12717
|
return;
|
|
12668
12718
|
}
|
|
12669
12719
|
this.opts.logger.info('Relay tunnel: \u2192 heartbeat "ping"');
|
|
12670
12720
|
try {
|
|
12671
|
-
|
|
12721
|
+
ws.send("ping");
|
|
12672
12722
|
} catch {
|
|
12673
12723
|
}
|
|
12674
12724
|
try {
|
|
12675
|
-
|
|
12725
|
+
ws.ping();
|
|
12676
12726
|
} catch {
|
|
12677
12727
|
}
|
|
12678
12728
|
}
|
|
@@ -12700,6 +12750,34 @@ var RelayClient = class {
|
|
|
12700
12750
|
this.ws = null;
|
|
12701
12751
|
}
|
|
12702
12752
|
}
|
|
12753
|
+
forceReconnectFromSocket(ws, reason) {
|
|
12754
|
+
if (this.aborted || this.ws !== ws) return;
|
|
12755
|
+
this.stopHeartbeat();
|
|
12756
|
+
this.ws = null;
|
|
12757
|
+
this.writeStatus("disconnected", reason);
|
|
12758
|
+
this.scheduleReconnect();
|
|
12759
|
+
try {
|
|
12760
|
+
if (ws.readyState !== wrapper_default.CLOSED) {
|
|
12761
|
+
ws.terminate();
|
|
12762
|
+
}
|
|
12763
|
+
} catch {
|
|
12764
|
+
}
|
|
12765
|
+
}
|
|
12766
|
+
logSendSkipped(kind, detail) {
|
|
12767
|
+
const now = Date.now();
|
|
12768
|
+
const shouldLog = this.skippedSendLogLastAt === null || now - this.skippedSendLogLastAt >= SEND_SKIPPED_LOG_INTERVAL_MS;
|
|
12769
|
+
if (!shouldLog) {
|
|
12770
|
+
this.skippedSendLogSuppressed++;
|
|
12771
|
+
return;
|
|
12772
|
+
}
|
|
12773
|
+
const suppressedSuffix = this.skippedSendLogSuppressed > 0 ? `, suppressed=${this.skippedSendLogSuppressed}` : "";
|
|
12774
|
+
const detailSuffix = detail ? `, ${detail}` : "";
|
|
12775
|
+
this.opts.logger.warn(
|
|
12776
|
+
`Relay tunnel: \u25B6 ${kind} skipped, ws not open (readyState=${this.ws?.readyState ?? "null"}${detailSuffix}${suppressedSuffix})`
|
|
12777
|
+
);
|
|
12778
|
+
this.skippedSendLogLastAt = now;
|
|
12779
|
+
this.skippedSendLogSuppressed = 0;
|
|
12780
|
+
}
|
|
12703
12781
|
scheduleReconnect() {
|
|
12704
12782
|
if (this.aborted) return;
|
|
12705
12783
|
if (this.reconnectTimer) {
|
|
@@ -12727,36 +12805,6 @@ var RelayClient = class {
|
|
|
12727
12805
|
|
|
12728
12806
|
// src/tunnel/proxy.ts
|
|
12729
12807
|
var import_node_crypto5 = require("crypto");
|
|
12730
|
-
|
|
12731
|
-
// src/tunnel/utils.ts
|
|
12732
|
-
function previewText2(text, max = 200) {
|
|
12733
|
-
if (!text) return "";
|
|
12734
|
-
return text.length <= max ? text : `${text.substring(0, max)}\u2026`;
|
|
12735
|
-
}
|
|
12736
|
-
function findHeaderValue(headers, key) {
|
|
12737
|
-
if (!headers) return void 0;
|
|
12738
|
-
const lowerKey = key.toLowerCase();
|
|
12739
|
-
for (const [headerKey, headerValue] of Object.entries(headers)) {
|
|
12740
|
-
if (headerKey.toLowerCase() === lowerKey) {
|
|
12741
|
-
return headerValue;
|
|
12742
|
-
}
|
|
12743
|
-
}
|
|
12744
|
-
return void 0;
|
|
12745
|
-
}
|
|
12746
|
-
function summarizeRequestHeaders(headers) {
|
|
12747
|
-
const contentType = findHeaderValue(headers, "content-type");
|
|
12748
|
-
const requestId = findHeaderValue(headers, "x-request-id");
|
|
12749
|
-
const parts = [];
|
|
12750
|
-
if (contentType) {
|
|
12751
|
-
parts.push(`contentType=${contentType}`);
|
|
12752
|
-
}
|
|
12753
|
-
if (requestId) {
|
|
12754
|
-
parts.push(`xRequestId=${previewText2(requestId, 120)}`);
|
|
12755
|
-
}
|
|
12756
|
-
return parts.length ? `, ${parts.join(", ")}` : "";
|
|
12757
|
-
}
|
|
12758
|
-
|
|
12759
|
-
// src/tunnel/proxy.ts
|
|
12760
12808
|
init_host();
|
|
12761
12809
|
|
|
12762
12810
|
// src/tunnel/device-identity.ts
|
|
@@ -12985,18 +13033,17 @@ async function handleHttpRequest(opts, frame) {
|
|
|
12985
13033
|
const mappedPath = mapPath(frame.path);
|
|
12986
13034
|
const url = new URL(mappedPath, opts.gatewayBaseUrl);
|
|
12987
13035
|
const startedAtMs = Date.now();
|
|
12988
|
-
const trustedProxyHeaderLower = opts.gatewayTrustedProxyHeader?.trim().toLowerCase();
|
|
12989
13036
|
const localHeaders = {};
|
|
12990
13037
|
for (const [k, v] of Object.entries(frame.headers ?? {})) {
|
|
12991
13038
|
const lower = k.toLowerCase();
|
|
12992
|
-
if (lower
|
|
12993
|
-
|
|
12994
|
-
|
|
13039
|
+
if (lower !== "authorization" && lower !== "x-openclaw-password") {
|
|
13040
|
+
localHeaders[k] = v;
|
|
13041
|
+
}
|
|
12995
13042
|
}
|
|
12996
13043
|
localHeaders[RELAY_INTERNAL_HTTP_HEADER] = "1";
|
|
12997
13044
|
const authAttempts = buildLocalGatewayAuthAttempts(opts, localHeaders);
|
|
12998
13045
|
opts.logger.info(
|
|
12999
|
-
`TunnelProxy: HTTP id=${frame.id} ${frame.method} ${frame.path} \u2192 ${url.toString()}${summarizeRequestHeaders(frame.headers)}, authAttempts=${authAttempts.map((a) => a.label).join(" -> ")}, body=${
|
|
13046
|
+
`TunnelProxy: HTTP id=${frame.id} ${frame.method} ${frame.path} \u2192 ${url.toString()}${summarizeRequestHeaders(frame.headers)}, authAttempts=${authAttempts.map((a) => a.label).join(" -> ")}, body=${previewText(frame.body)}`
|
|
13000
13047
|
);
|
|
13001
13048
|
try {
|
|
13002
13049
|
for (let attemptIndex = 0; attemptIndex < authAttempts.length; attemptIndex++) {
|
|
@@ -13013,7 +13060,7 @@ async function handleHttpRequest(opts, frame) {
|
|
|
13013
13060
|
if (res.status === 401 && hasFallback) {
|
|
13014
13061
|
const body = await res.text();
|
|
13015
13062
|
opts.logger.warn(
|
|
13016
|
-
`TunnelProxy: HTTP id=${frame.id} local gateway auth via ${attempt.label} returned 401 after ${Date.now() - startedAtMs}ms, retrying next credential${body ? `, body=${
|
|
13063
|
+
`TunnelProxy: HTTP id=${frame.id} local gateway auth via ${attempt.label} returned 401 after ${Date.now() - startedAtMs}ms, retrying next credential${body ? `, body=${previewText(body)}` : ""}`
|
|
13017
13064
|
);
|
|
13018
13065
|
continue;
|
|
13019
13066
|
}
|
|
@@ -13054,7 +13101,7 @@ async function sendHttpResponse(opts, params) {
|
|
|
13054
13101
|
}
|
|
13055
13102
|
const body = await res.text();
|
|
13056
13103
|
opts.logger.info(
|
|
13057
|
-
`TunnelProxy: HTTP id=${frameId} response body=${
|
|
13104
|
+
`TunnelProxy: HTTP id=${frameId} response body=${previewText(body)}`
|
|
13058
13105
|
);
|
|
13059
13106
|
const headers = {};
|
|
13060
13107
|
res.headers.forEach((value, key) => {
|
|
@@ -13438,16 +13485,6 @@ var TunnelProxy = class {
|
|
|
13438
13485
|
`TunnelProxy: cleared stale stored device token after gateway mismatch (deviceId=${this.deviceIdentity.deviceId})`
|
|
13439
13486
|
);
|
|
13440
13487
|
}
|
|
13441
|
-
/**
|
|
13442
|
-
* 当 Gateway 处于 trusted-proxy 模式时,构造注入到本地连接的 user header。
|
|
13443
|
-
* 其他模式或参数未配齐时返回 undefined,本地用户保持原握手路径不受影响。
|
|
13444
|
-
*/
|
|
13445
|
-
buildTrustedProxyHeaders() {
|
|
13446
|
-
const headerName = this.opts.gatewayTrustedProxyHeader?.trim();
|
|
13447
|
-
const headerValue = this.opts.gatewayTrustedProxyUser?.trim();
|
|
13448
|
-
if (!headerName || !headerValue) return void 0;
|
|
13449
|
-
return { [headerName]: headerValue };
|
|
13450
|
-
}
|
|
13451
13488
|
async maybeAutoApproveGatewayPairing(frame) {
|
|
13452
13489
|
const errorCode = typeof frame?.error?.code === "string" ? frame.error.code : void 0;
|
|
13453
13490
|
const detailsCode = typeof frame?.error?.details?.code === "string" ? frame.error.details.code : void 0;
|
|
@@ -13618,12 +13655,10 @@ var TunnelProxy = class {
|
|
|
13618
13655
|
this.gatewayWsConnecting = true;
|
|
13619
13656
|
this.gatewayWsReady = false;
|
|
13620
13657
|
const wsUrl = this.opts.gatewayBaseUrl.replace(/^http/, "ws");
|
|
13621
|
-
const trustedProxyHeaders = this.buildTrustedProxyHeaders();
|
|
13622
|
-
const trustedProxyHint = trustedProxyHeaders ? `, trustedProxyHeader=${Object.keys(trustedProxyHeaders)[0]}` : "";
|
|
13623
13658
|
this.opts.logger.info(
|
|
13624
|
-
`TunnelProxy: RPC WS connecting to gateway ${wsUrl} (pending=${this.gatewayWsPending.length}
|
|
13659
|
+
`TunnelProxy: RPC WS connecting to gateway ${wsUrl} (pending=${this.gatewayWsPending.length})`
|
|
13625
13660
|
);
|
|
13626
|
-
const ws =
|
|
13661
|
+
const ws = new wrapper_default(wsUrl);
|
|
13627
13662
|
ws.on("open", () => {
|
|
13628
13663
|
this.gatewayWs = ws;
|
|
13629
13664
|
this.opts.logger.info(
|
|
@@ -13691,7 +13726,7 @@ var TunnelProxy = class {
|
|
|
13691
13726
|
return;
|
|
13692
13727
|
}
|
|
13693
13728
|
this.opts.logger.error(
|
|
13694
|
-
`TunnelProxy: RPC WS handshake failed (pending=${this.gatewayWsPending.length}): ${
|
|
13729
|
+
`TunnelProxy: RPC WS handshake failed (pending=${this.gatewayWsPending.length}): ${previewText(JSON.stringify(frame.error), 500)}`
|
|
13695
13730
|
);
|
|
13696
13731
|
ws.close();
|
|
13697
13732
|
return;
|
|
@@ -13867,7 +13902,7 @@ function createTunnelService(opts) {
|
|
|
13867
13902
|
JSON.stringify({
|
|
13868
13903
|
pid: process.pid,
|
|
13869
13904
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13870
|
-
tunnelUrl: opts.tunnelUrl
|
|
13905
|
+
tunnelUrl: redactUrlSecrets(opts.tunnelUrl)
|
|
13871
13906
|
}) + "\n"
|
|
13872
13907
|
);
|
|
13873
13908
|
lockFilePath = filePath;
|
|
@@ -13933,7 +13968,7 @@ function createTunnelService(opts) {
|
|
|
13933
13968
|
const { logger } = opts;
|
|
13934
13969
|
const baseStateDir = (0, import_node_path24.join)(ctx.stateDir, "plugins", "phone-notifications");
|
|
13935
13970
|
logger.info(
|
|
13936
|
-
`Relay tunnel: starting (pid=${process.pid}, url=${opts.tunnelUrl}, heartbeat=${opts.heartbeatSec ?? DEFAULT_HEARTBEAT_SEC}s, backoff=${opts.reconnectBackoffMs ?? DEFAULT_RECONNECT_BACKOFF_MS}ms, gateway=${opts.gatewayBaseUrl}, hasGatewayToken=${!!opts.gatewayToken}, hasGatewayPwd=${!!opts.gatewayPassword})`
|
|
13971
|
+
`Relay tunnel: starting (pid=${process.pid}, url=${redactUrlSecrets(opts.tunnelUrl)}, heartbeat=${opts.heartbeatSec ?? DEFAULT_HEARTBEAT_SEC}s, backoff=${opts.reconnectBackoffMs ?? DEFAULT_RECONNECT_BACKOFF_MS}ms, gateway=${opts.gatewayBaseUrl}, hasGatewayToken=${!!opts.gatewayToken}, hasGatewayPwd=${!!opts.gatewayPassword})`
|
|
13937
13972
|
);
|
|
13938
13973
|
const statusFilePath = (0, import_node_path24.join)(baseStateDir, "tunnel-status.json");
|
|
13939
13974
|
const lockPath = (0, import_node_path24.join)(baseStateDir, "relay-tunnel.lock");
|
|
@@ -13956,8 +13991,6 @@ function createTunnelService(opts) {
|
|
|
13956
13991
|
gatewayAuthMode: opts.gatewayAuthMode,
|
|
13957
13992
|
gatewayToken: opts.gatewayToken,
|
|
13958
13993
|
gatewayPassword: opts.gatewayPassword,
|
|
13959
|
-
gatewayTrustedProxyHeader: opts.gatewayTrustedProxyHeader,
|
|
13960
|
-
gatewayTrustedProxyUser: opts.gatewayTrustedProxyUser,
|
|
13961
13994
|
client,
|
|
13962
13995
|
logger
|
|
13963
13996
|
});
|
|
@@ -14070,14 +14103,9 @@ function readHostGatewayConfig(params) {
|
|
|
14070
14103
|
}
|
|
14071
14104
|
return configData;
|
|
14072
14105
|
}
|
|
14073
|
-
var DEFAULT_TRUSTED_PROXY_HEADER = "x-forwarded-user";
|
|
14074
|
-
var DEFAULT_TRUSTED_PROXY_USER = "openclaw";
|
|
14075
14106
|
function resolveLocalGatewayAuth(params) {
|
|
14076
14107
|
const envGatewayToken = trimToUndefined2(process.env.OPENCLAW_GATEWAY_TOKEN) ?? trimToUndefined2(process.env.QCLAW_GATEWAY_TOKEN);
|
|
14077
14108
|
const envGatewayPassword = trimToUndefined2(process.env.OPENCLAW_GATEWAY_PASSWORD) ?? trimToUndefined2(process.env.QCLAW_GATEWAY_PASSWORD);
|
|
14078
|
-
const envTrustedProxyUser = trimToUndefined2(
|
|
14079
|
-
process.env.OPENCLAW_GATEWAY_TRUSTED_PROXY_USER
|
|
14080
|
-
);
|
|
14081
14109
|
const configData = readHostGatewayConfig(params);
|
|
14082
14110
|
let configGatewayAuthMode;
|
|
14083
14111
|
const rawGatewayAuthMode = trimToUndefined2(configData?.gateway?.auth?.mode);
|
|
@@ -14086,18 +14114,10 @@ function resolveLocalGatewayAuth(params) {
|
|
|
14086
14114
|
}
|
|
14087
14115
|
const configGatewayToken = trimToUndefined2(configData?.gateway?.auth?.token);
|
|
14088
14116
|
const configGatewayPassword = trimToUndefined2(configData?.gateway?.auth?.password);
|
|
14089
|
-
let gatewayTrustedProxyHeader;
|
|
14090
|
-
let gatewayTrustedProxyUser;
|
|
14091
|
-
if (rawGatewayAuthMode === "trusted-proxy") {
|
|
14092
|
-
gatewayTrustedProxyHeader = trimToUndefined2(configData?.gateway?.auth?.trustedProxy?.userHeader) ?? DEFAULT_TRUSTED_PROXY_HEADER;
|
|
14093
|
-
gatewayTrustedProxyUser = envTrustedProxyUser ?? DEFAULT_TRUSTED_PROXY_USER;
|
|
14094
|
-
}
|
|
14095
14117
|
return {
|
|
14096
14118
|
gatewayAuthMode: configGatewayAuthMode,
|
|
14097
14119
|
gatewayToken: envGatewayToken ?? configGatewayToken,
|
|
14098
|
-
gatewayPassword: envGatewayPassword ?? configGatewayPassword
|
|
14099
|
-
gatewayTrustedProxyHeader,
|
|
14100
|
-
gatewayTrustedProxyUser
|
|
14120
|
+
gatewayPassword: envGatewayPassword ?? configGatewayPassword
|
|
14101
14121
|
};
|
|
14102
14122
|
}
|
|
14103
14123
|
function resolveExclusiveTunnelHint(params) {
|
|
@@ -14146,21 +14166,10 @@ function registerRelayTunnelLifecycle(deps) {
|
|
|
14146
14166
|
return null;
|
|
14147
14167
|
}
|
|
14148
14168
|
const gatewayPort = process.env.OPENCLAW_GATEWAY_PORT ?? process.env.QCLAW_GATEWAY_PORT ?? "18789";
|
|
14149
|
-
const {
|
|
14150
|
-
gatewayAuthMode,
|
|
14151
|
-
gatewayToken,
|
|
14152
|
-
gatewayPassword,
|
|
14153
|
-
gatewayTrustedProxyHeader,
|
|
14154
|
-
gatewayTrustedProxyUser
|
|
14155
|
-
} = resolveLocalGatewayAuth({
|
|
14169
|
+
const { gatewayAuthMode, gatewayToken, gatewayPassword } = resolveLocalGatewayAuth({
|
|
14156
14170
|
stateDir: openclawDir,
|
|
14157
14171
|
logger
|
|
14158
14172
|
});
|
|
14159
|
-
if (gatewayTrustedProxyHeader && gatewayTrustedProxyUser) {
|
|
14160
|
-
logger.info(
|
|
14161
|
-
`Relay tunnel: gateway in trusted-proxy mode, will inject ${gatewayTrustedProxyHeader} header on local connections`
|
|
14162
|
-
);
|
|
14163
|
-
}
|
|
14164
14173
|
const tunnelService = createTunnelService({
|
|
14165
14174
|
tunnelUrl,
|
|
14166
14175
|
heartbeatSec: config.relay?.heartbeatSec,
|
|
@@ -14169,8 +14178,6 @@ function registerRelayTunnelLifecycle(deps) {
|
|
|
14169
14178
|
gatewayAuthMode,
|
|
14170
14179
|
gatewayToken,
|
|
14171
14180
|
gatewayPassword,
|
|
14172
|
-
gatewayTrustedProxyHeader,
|
|
14173
|
-
gatewayTrustedProxyUser,
|
|
14174
14181
|
logger
|
|
14175
14182
|
});
|
|
14176
14183
|
api.registerService(tunnelService);
|