@skylandnpm/octopus-proxy 0.1.51 → 0.1.52
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/{chunk-55TEBVWY.js → chunk-3KIA6HF6.js} +86 -17
- package/dist/cli.js +1 -1
- package/dist/main.js +1 -1
- package/package.json +1 -1
- package/proxy.example.json +0 -1
|
@@ -3321,8 +3321,8 @@ var require_utils = __commonJS({
|
|
|
3321
3321
|
var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
|
|
3322
3322
|
var HOST_DELIM_RE = /[@/?#:]/g;
|
|
3323
3323
|
var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
|
|
3324
|
-
function reescapeHostDelimiters(host,
|
|
3325
|
-
const re =
|
|
3324
|
+
function reescapeHostDelimiters(host, isIP2) {
|
|
3325
|
+
const re = isIP2 ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
|
|
3326
3326
|
re.lastIndex = 0;
|
|
3327
3327
|
return host.replace(re, (ch) => HOST_DELIMS[ch]);
|
|
3328
3328
|
}
|
|
@@ -4011,8 +4011,8 @@ var require_fast_uri = __commonJS({
|
|
|
4011
4011
|
const host = matches[4];
|
|
4012
4012
|
return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
|
|
4013
4013
|
}
|
|
4014
|
-
function canonicalizeHost(parsed, options, schemeHandler,
|
|
4015
|
-
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) &&
|
|
4014
|
+
function canonicalizeHost(parsed, options, schemeHandler, isIP2) {
|
|
4015
|
+
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP2 === false && nonSimpleDomain(parsed.host)) {
|
|
4016
4016
|
try {
|
|
4017
4017
|
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
4018
4018
|
} catch (e) {
|
|
@@ -4039,7 +4039,7 @@ var require_fast_uri = __commonJS({
|
|
|
4039
4039
|
let malformedHost = false;
|
|
4040
4040
|
let malformedIPLiteral = false;
|
|
4041
4041
|
let malformedScheme = false;
|
|
4042
|
-
let
|
|
4042
|
+
let isIP2 = false;
|
|
4043
4043
|
if (options.reference === "suffix") {
|
|
4044
4044
|
if (options.scheme) {
|
|
4045
4045
|
uri = options.scheme + ":" + uri;
|
|
@@ -4102,15 +4102,15 @@ var require_fast_uri = __commonJS({
|
|
|
4102
4102
|
const bracketedIPLiteral = isIPLiteral(parsed.host);
|
|
4103
4103
|
const hasIPLiteralBracket = parsed.host.indexOf("[") !== -1 || parsed.host.indexOf("]") !== -1;
|
|
4104
4104
|
const ipv6result = normalizeIPv6(parsed.host);
|
|
4105
|
-
|
|
4105
|
+
isIP2 = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
|
|
4106
4106
|
malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
|
|
4107
|
-
parsed.host =
|
|
4107
|
+
parsed.host = isIP2 ? ipv6result.host : ipv6result.host.toLowerCase();
|
|
4108
4108
|
if (malformedIPLiteral) {
|
|
4109
4109
|
parsed.error = parsed.error || "URI host is malformed.";
|
|
4110
4110
|
malformedAuthorityOrPort = true;
|
|
4111
4111
|
}
|
|
4112
4112
|
} else {
|
|
4113
|
-
|
|
4113
|
+
isIP2 = true;
|
|
4114
4114
|
}
|
|
4115
4115
|
}
|
|
4116
4116
|
if (parsed.scheme === void 0 && parsed.userinfo === void 0 && parsed.host === void 0 && parsed.port === void 0 && parsed.query === void 0 && !parsed.path) {
|
|
@@ -4127,14 +4127,14 @@ var require_fast_uri = __commonJS({
|
|
|
4127
4127
|
}
|
|
4128
4128
|
const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
|
|
4129
4129
|
if (!malformedIPLiteral) {
|
|
4130
|
-
malformedHost = canonicalizeHost(parsed, options, schemeHandler,
|
|
4130
|
+
malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP2);
|
|
4131
4131
|
}
|
|
4132
4132
|
if (uri.indexOf("%") !== -1 && parsed.host !== void 0 && !malformedIPLiteral) {
|
|
4133
|
-
let host =
|
|
4134
|
-
if (!
|
|
4133
|
+
let host = isIP2 ? parsed.host : normalizePercentEncoding(parsed.host, true);
|
|
4134
|
+
if (!isIP2) {
|
|
4135
4135
|
host = normalizePercentEncoding(host.toLowerCase());
|
|
4136
4136
|
}
|
|
4137
|
-
parsed.host = reescapeHostDelimiters(host,
|
|
4137
|
+
parsed.host = reescapeHostDelimiters(host, isIP2);
|
|
4138
4138
|
}
|
|
4139
4139
|
if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
|
|
4140
4140
|
if (parsed.path) {
|
|
@@ -13335,6 +13335,71 @@ var PlatformDesktopSession = class {
|
|
|
13335
13335
|
import { fork } from "node:child_process";
|
|
13336
13336
|
import { randomBytes as randomBytes2, randomUUID as randomUUID16 } from "node:crypto";
|
|
13337
13337
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
13338
|
+
|
|
13339
|
+
// src/remote-stun.ts
|
|
13340
|
+
import { Resolver } from "node:dns/promises";
|
|
13341
|
+
import { isIP } from "node:net";
|
|
13342
|
+
var publicStunHost = "stun.cloudflare.com";
|
|
13343
|
+
var dnsJsonEndpoints = ["https://dns.alidns.com/resolve", "https://cloudflare-dns.com/dns-query"];
|
|
13344
|
+
var STUN_DNS_TIMEOUT = 1500;
|
|
13345
|
+
function defaultRemoteStunUrls(hubUrl) {
|
|
13346
|
+
return [.../* @__PURE__ */ new Set([`stun:${new URL(hubUrl).hostname}:3478`, `stun:${publicStunHost}:3478`])];
|
|
13347
|
+
}
|
|
13348
|
+
function publicAddress(address, family) {
|
|
13349
|
+
if (isIP(address) !== family) return false;
|
|
13350
|
+
if (family === 6) return /^[23][\da-f]{0,3}:/i.test(address);
|
|
13351
|
+
const [a, b] = address.split(".").map(Number);
|
|
13352
|
+
return a !== 0 && a !== 10 && a !== 127 && a < 224 && !(a === 100 && b >= 64 && b <= 127) && !(a === 169 && b === 254) && !(a === 172 && b >= 16 && b <= 31) && !(a === 192 && b === 168) && !(a === 198 && (b === 18 || b === 19));
|
|
13353
|
+
}
|
|
13354
|
+
async function systemLookup(family) {
|
|
13355
|
+
const resolver = new Resolver({ timeout: 500, tries: 1 });
|
|
13356
|
+
try {
|
|
13357
|
+
return await (family === 6 ? resolver.resolve6(publicStunHost) : resolver.resolve4(publicStunHost));
|
|
13358
|
+
} finally {
|
|
13359
|
+
resolver.cancel();
|
|
13360
|
+
}
|
|
13361
|
+
}
|
|
13362
|
+
async function queryDnsJson(endpoint, family, signal) {
|
|
13363
|
+
const type = family === 6 ? 28 : 1;
|
|
13364
|
+
const url = new URL(endpoint);
|
|
13365
|
+
url.searchParams.set("name", publicStunHost);
|
|
13366
|
+
url.searchParams.set("type", String(type));
|
|
13367
|
+
const response = await fetch(url, { headers: { accept: "application/dns-json" }, signal, redirect: "error" });
|
|
13368
|
+
if (!response.ok) throw new Error("STUN DNS request failed");
|
|
13369
|
+
const text = await response.text();
|
|
13370
|
+
if (text.length > 16384) throw new Error("STUN DNS response too large");
|
|
13371
|
+
const body = JSON.parse(text);
|
|
13372
|
+
if (body.Status !== 0 || !Array.isArray(body.Answer)) throw new Error("STUN DNS answer unavailable");
|
|
13373
|
+
return body.Answer.filter((record2) => record2.type === type && typeof record2.data === "string").map((record2) => record2.data);
|
|
13374
|
+
}
|
|
13375
|
+
async function resolvePublicStunAddresses(lookup = systemLookup, query = queryDnsJson) {
|
|
13376
|
+
const families = await Promise.all([6, 4].map(async (family) => {
|
|
13377
|
+
const valid = (addresses) => addresses.filter((address) => publicAddress(address, family)).slice(0, 1);
|
|
13378
|
+
const native = valid(await lookup(family).catch(() => []));
|
|
13379
|
+
if (native.length) return native;
|
|
13380
|
+
const controller = new AbortController();
|
|
13381
|
+
const timer = setTimeout(() => controller.abort(), STUN_DNS_TIMEOUT);
|
|
13382
|
+
try {
|
|
13383
|
+
return await Promise.any(dnsJsonEndpoints.map(async (endpoint) => {
|
|
13384
|
+
const addresses = valid(await query(endpoint, family, controller.signal));
|
|
13385
|
+
if (!addresses.length) throw new Error("No public STUN address");
|
|
13386
|
+
return addresses;
|
|
13387
|
+
})).catch(() => []);
|
|
13388
|
+
} finally {
|
|
13389
|
+
clearTimeout(timer);
|
|
13390
|
+
controller.abort();
|
|
13391
|
+
}
|
|
13392
|
+
}));
|
|
13393
|
+
return families.flat();
|
|
13394
|
+
}
|
|
13395
|
+
async function discoverRemoteStunUrls(hubUrl, configured, resolve5 = resolvePublicStunAddresses) {
|
|
13396
|
+
if (configured) return [...configured];
|
|
13397
|
+
const addresses = await resolve5().catch(() => []);
|
|
13398
|
+
const numeric = addresses.map((address) => `stun:${isIP(address) === 6 ? `[${address}]` : address}:3478`);
|
|
13399
|
+
return [.../* @__PURE__ */ new Set([...numeric, ...defaultRemoteStunUrls(hubUrl)])].slice(0, 4);
|
|
13400
|
+
}
|
|
13401
|
+
|
|
13402
|
+
// src/remote-manager.ts
|
|
13338
13403
|
function spawnWorker(message) {
|
|
13339
13404
|
const worker = fileURLToPath4(new URL(import.meta.url.endsWith(".ts") ? "./remote-worker.ts" : "./remote-worker.js", import.meta.url));
|
|
13340
13405
|
const child = fork(worker, [], { stdio: ["ignore", "ignore", "ignore", "ipc"], execArgv: import.meta.url.endsWith(".ts") ? ["--import", "tsx"] : [] });
|
|
@@ -13342,7 +13407,7 @@ function spawnWorker(message) {
|
|
|
13342
13407
|
return child;
|
|
13343
13408
|
}
|
|
13344
13409
|
var RemoteManager = class {
|
|
13345
|
-
constructor(host, desktop, desktopSession, send, touch, workerFactory = spawnWorker, probe = probeRemote) {
|
|
13410
|
+
constructor(host, desktop, desktopSession, send, touch, workerFactory = spawnWorker, probe = probeRemote, discoverStun = discoverRemoteStunUrls) {
|
|
13346
13411
|
this.host = host;
|
|
13347
13412
|
this.desktop = desktop;
|
|
13348
13413
|
this.desktopSession = desktopSession;
|
|
@@ -13350,13 +13415,14 @@ var RemoteManager = class {
|
|
|
13350
13415
|
this.touch = touch;
|
|
13351
13416
|
this.workerFactory = workerFactory;
|
|
13352
13417
|
this.probe = probe;
|
|
13418
|
+
this.discoverStun = discoverStun;
|
|
13353
13419
|
this.config = RemoteConfigSchema.parse(host.desktopRemote ?? {});
|
|
13354
13420
|
}
|
|
13355
13421
|
current;
|
|
13356
13422
|
stopping = false;
|
|
13357
13423
|
config;
|
|
13358
13424
|
stunUrls() {
|
|
13359
|
-
return this.config.stunUrls ??
|
|
13425
|
+
return this.config.stunUrls ?? defaultRemoteStunUrls(this.host.hubUrl);
|
|
13360
13426
|
}
|
|
13361
13427
|
async status() {
|
|
13362
13428
|
const base = { qualityModes: RemoteQualitySchema.options, platform: process.platform, passwordInput: process.platform === "darwin", enabled: this.config.enabled, busy: !!this.current, stunUrls: this.stunUrls(), budget: { ...REMOTE_DEFAULTS, totalBitrate: this.config.totalBitrate, videoMaxBitrate: this.config.videoMaxBitrate } };
|
|
@@ -13404,7 +13470,10 @@ var RemoteManager = class {
|
|
|
13404
13470
|
const session = { remoteId: randomUUID16(), owner, closed: false, signaling: Promise.resolve(), signals: 0, signalWindow: Date.now(), candidates: 0 };
|
|
13405
13471
|
this.current = session;
|
|
13406
13472
|
try {
|
|
13407
|
-
const permissions = await
|
|
13473
|
+
const [permissions, stunUrls] = await Promise.all([
|
|
13474
|
+
this.probe(this.host.stateDirectory, this.config),
|
|
13475
|
+
this.discoverStun(this.host.hubUrl, this.config.stunUrls)
|
|
13476
|
+
]);
|
|
13408
13477
|
if (!permissions.session || !permissions.capture || !permissions.input) throw new Error("\u8FDC\u63A7\u9700\u8981\u4E3B\u673A\u56FE\u5F62\u4F1A\u8BDD\u3001\u5C4F\u5E55\u5F55\u5236\u53CA\u8F85\u52A9\u529F\u80FD\u6743\u9650");
|
|
13409
13478
|
if (permissions.locked === true && permissions.lockCapture === false) throw new Error("\u9501\u5C4F\u8FDC\u63A7\u9700\u8981 macOS 14 \u53CA\u4EE5\u4E0A\u53CA\u65B0\u7248 Xcode Command Line Tools\uFF1B\u5F53\u524D\u4E3B\u673A\u8BF7\u5148\u672C\u5730\u89E3\u9501");
|
|
13410
13479
|
const identity = await this.desktopSession.sessionIdentity();
|
|
@@ -13413,7 +13482,7 @@ var RemoteManager = class {
|
|
|
13413
13482
|
const layout = await this.desktop.layoutIdentity?.(display.id);
|
|
13414
13483
|
if (session.closed || this.current !== session) throw new Error("\u5DE5\u4F5C\u533A\u8FDE\u63A5\u5DF2\u5173\u95ED\uFF0C\u8FDC\u63A7\u5DF2\u53D6\u6D88");
|
|
13415
13484
|
const bindToken = randomBytes2(32).toString("base64url"), expiresAt = Date.now() + 2e4;
|
|
13416
|
-
const child = this.workerFactory({ remoteId: session.remoteId, bindToken, expiresAt, display, helper: permissions.helper, quality, legacy: payload.quality === void 0, config: this.config, stunUrls
|
|
13485
|
+
const child = this.workerFactory({ remoteId: session.remoteId, bindToken, expiresAt, display, helper: permissions.helper, quality, legacy: payload.quality === void 0, config: this.config, stunUrls });
|
|
13417
13486
|
session.child = child;
|
|
13418
13487
|
child.on("message", (message) => {
|
|
13419
13488
|
if (this.current !== session || session.closed || !message || typeof message !== "object") return;
|
|
@@ -13447,7 +13516,7 @@ var RemoteManager = class {
|
|
|
13447
13516
|
}
|
|
13448
13517
|
}, 1e3);
|
|
13449
13518
|
session.monitor.unref();
|
|
13450
|
-
return { remoteId: session.remoteId, bindToken, expiresAt: new Date(expiresAt).toISOString(), display, revision: 1, stunUrls
|
|
13519
|
+
return { remoteId: session.remoteId, bindToken, expiresAt: new Date(expiresAt).toISOString(), display, revision: 1, stunUrls, budget, quality, qualityModes: RemoteQualitySchema.options, protocolVersion: 1, heartbeatAck: true };
|
|
13451
13520
|
} catch (error) {
|
|
13452
13521
|
this.finish(session);
|
|
13453
13522
|
throw error;
|
package/dist/cli.js
CHANGED
package/dist/main.js
CHANGED
package/package.json
CHANGED
package/proxy.example.json
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
"tool": { "kind": "opencode", "command": "/Users/luhuili/.opencode/bin/opencode", "baseUrl": "http://127.0.0.1:4096", "mode": "external", "password": "replace-with-a-random-secret-at-least-20-characters" },
|
|
8
8
|
"desktopRemote": {
|
|
9
9
|
"enabled": true,
|
|
10
|
-
"stunUrls": ["stun:hub.example.com:3478"],
|
|
11
10
|
"totalBitrate": 22000000,
|
|
12
11
|
"videoMaxBitrate": 16000000
|
|
13
12
|
}
|