tesseract-agent 0.9.32 → 0.9.33
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-bundle/cli.js +435 -223
- package/package.json +1 -1
package/dist-bundle/cli.js
CHANGED
|
@@ -64867,7 +64867,7 @@ function compareUtf8(a, b) {
|
|
|
64867
64867
|
function canonicalStrs(items) {
|
|
64868
64868
|
return [...new Set(items)].sort(compareUtf8);
|
|
64869
64869
|
}
|
|
64870
|
-
var MeshCodecError,
|
|
64870
|
+
var MeshCodecError, fail, LIMITS, Writer, Reader;
|
|
64871
64871
|
var init_codec = __esm({
|
|
64872
64872
|
"../../packages/mesh-pki/dist/codec.js"() {
|
|
64873
64873
|
"use strict";
|
|
@@ -64879,7 +64879,7 @@ var init_codec = __esm({
|
|
|
64879
64879
|
this.reason = reason;
|
|
64880
64880
|
}
|
|
64881
64881
|
};
|
|
64882
|
-
|
|
64882
|
+
fail = (reason, detail) => {
|
|
64883
64883
|
throw new MeshCodecError(reason, detail);
|
|
64884
64884
|
};
|
|
64885
64885
|
LIMITS = {
|
|
@@ -64913,17 +64913,17 @@ var init_codec = __esm({
|
|
|
64913
64913
|
}
|
|
64914
64914
|
u8(v) {
|
|
64915
64915
|
if (!Number.isInteger(v) || v < 0 || v > 255)
|
|
64916
|
-
|
|
64916
|
+
fail("bad-value", `u8 ${v}`);
|
|
64917
64917
|
return this.#push(new Uint8Array([v]));
|
|
64918
64918
|
}
|
|
64919
64919
|
u16(v) {
|
|
64920
64920
|
if (!Number.isInteger(v) || v < 0 || v > 65535)
|
|
64921
|
-
|
|
64921
|
+
fail("bad-value", `u16 ${v}`);
|
|
64922
64922
|
return this.#push(new Uint8Array([v >>> 8 & 255, v & 255]));
|
|
64923
64923
|
}
|
|
64924
64924
|
u32(v) {
|
|
64925
64925
|
if (!Number.isInteger(v) || v < 0 || v > 4294967295)
|
|
64926
|
-
|
|
64926
|
+
fail("bad-value", `u32 ${v}`);
|
|
64927
64927
|
return this.#push(new Uint8Array([v >>> 24 & 255, v >>> 16 & 255, v >>> 8 & 255, v & 255]));
|
|
64928
64928
|
}
|
|
64929
64929
|
/** Milliseconds-since-epoch and similar. JS numbers are exact to 2^53, which is
|
|
@@ -64931,7 +64931,7 @@ var init_codec = __esm({
|
|
|
64931
64931
|
* than silently losing precision. */
|
|
64932
64932
|
u64(v) {
|
|
64933
64933
|
if (!Number.isInteger(v) || v < 0 || v > Number.MAX_SAFE_INTEGER)
|
|
64934
|
-
|
|
64934
|
+
fail("bad-value", `u64 ${v}`);
|
|
64935
64935
|
const hi = Math.floor(v / 4294967296);
|
|
64936
64936
|
const lo = v >>> 0;
|
|
64937
64937
|
return this.u32(hi).u32(lo);
|
|
@@ -64939,13 +64939,13 @@ var init_codec = __esm({
|
|
|
64939
64939
|
/** Fixed-width opaque bytes — no length prefix; the field's width is positional. */
|
|
64940
64940
|
fixed(b, width) {
|
|
64941
64941
|
if (b.length !== width)
|
|
64942
|
-
|
|
64942
|
+
fail("bad-value", `fixed expected ${width} got ${b.length}`);
|
|
64943
64943
|
return this.#push(b);
|
|
64944
64944
|
}
|
|
64945
64945
|
/** Length-prefixed opaque bytes. */
|
|
64946
64946
|
bytes(b, max = LIMITS.STR) {
|
|
64947
64947
|
if (b.length > max)
|
|
64948
|
-
|
|
64948
|
+
fail("too-long", `bytes ${b.length} > ${max}`);
|
|
64949
64949
|
return this.u16(b.length).#push(b);
|
|
64950
64950
|
}
|
|
64951
64951
|
/** Length-prefixed UTF-8 string. */
|
|
@@ -64958,13 +64958,13 @@ var init_codec = __esm({
|
|
|
64958
64958
|
*/
|
|
64959
64959
|
sortedStrs(items, max = LIMITS.VEC) {
|
|
64960
64960
|
if (items.length > max)
|
|
64961
|
-
|
|
64961
|
+
fail("too-long", `vec ${items.length} > ${max}`);
|
|
64962
64962
|
for (let i = 1; i < items.length; i++) {
|
|
64963
64963
|
const cmp = compareUtf8(items[i - 1], items[i]);
|
|
64964
64964
|
if (cmp === 0)
|
|
64965
|
-
|
|
64965
|
+
fail("duplicate", items[i]);
|
|
64966
64966
|
if (cmp > 0)
|
|
64967
|
-
|
|
64967
|
+
fail("not-sorted", `${items[i - 1]} > ${items[i]}`);
|
|
64968
64968
|
}
|
|
64969
64969
|
this.u16(items.length);
|
|
64970
64970
|
for (const s of items)
|
|
@@ -64974,7 +64974,7 @@ var init_codec = __esm({
|
|
|
64974
64974
|
/** A sequence whose order is meaningful (signatures, key lists). */
|
|
64975
64975
|
vec(items, each, max = LIMITS.VEC) {
|
|
64976
64976
|
if (items.length > max)
|
|
64977
|
-
|
|
64977
|
+
fail("too-long", `vec ${items.length} > ${max}`);
|
|
64978
64978
|
this.u16(items.length);
|
|
64979
64979
|
for (const it of items)
|
|
64980
64980
|
each(this, it);
|
|
@@ -65004,7 +65004,7 @@ var init_codec = __esm({
|
|
|
65004
65004
|
}
|
|
65005
65005
|
#need(n) {
|
|
65006
65006
|
if (n < 0 || this.#o + n > this.#b.length) {
|
|
65007
|
-
|
|
65007
|
+
fail("truncated", `need ${n} at ${this.#o}, have ${this.#b.length - this.#o}`);
|
|
65008
65008
|
}
|
|
65009
65009
|
}
|
|
65010
65010
|
u8() {
|
|
@@ -65028,7 +65028,7 @@ var init_codec = __esm({
|
|
|
65028
65028
|
const lo = this.u32();
|
|
65029
65029
|
const v = hi * 4294967296 + lo;
|
|
65030
65030
|
if (!Number.isSafeInteger(v))
|
|
65031
|
-
|
|
65031
|
+
fail("bad-value", "u64 exceeds 2^53");
|
|
65032
65032
|
return v;
|
|
65033
65033
|
}
|
|
65034
65034
|
fixed(width) {
|
|
@@ -65040,7 +65040,7 @@ var init_codec = __esm({
|
|
|
65040
65040
|
bytes(max = LIMITS.STR) {
|
|
65041
65041
|
const n = this.u16();
|
|
65042
65042
|
if (n > max)
|
|
65043
|
-
|
|
65043
|
+
fail("too-long", `bytes ${n} > ${max}`);
|
|
65044
65044
|
return this.fixed(n);
|
|
65045
65045
|
}
|
|
65046
65046
|
str(max = LIMITS.STR) {
|
|
@@ -65049,7 +65049,7 @@ var init_codec = __esm({
|
|
|
65049
65049
|
try {
|
|
65050
65050
|
s = new TextDecoder("utf-8", { fatal: true }).decode(raw);
|
|
65051
65051
|
} catch {
|
|
65052
|
-
return
|
|
65052
|
+
return fail("bad-utf8");
|
|
65053
65053
|
}
|
|
65054
65054
|
return s;
|
|
65055
65055
|
}
|
|
@@ -65057,16 +65057,16 @@ var init_codec = __esm({
|
|
|
65057
65057
|
sortedStrs(max = LIMITS.VEC) {
|
|
65058
65058
|
const n = this.u16();
|
|
65059
65059
|
if (n > max)
|
|
65060
|
-
|
|
65060
|
+
fail("too-long", `vec ${n} > ${max}`);
|
|
65061
65061
|
const out = [];
|
|
65062
65062
|
for (let i = 0; i < n; i++) {
|
|
65063
65063
|
const s = this.str();
|
|
65064
65064
|
if (i > 0) {
|
|
65065
65065
|
const cmp = compareUtf8(out[i - 1], s);
|
|
65066
65066
|
if (cmp === 0)
|
|
65067
|
-
|
|
65067
|
+
fail("duplicate", s);
|
|
65068
65068
|
if (cmp > 0)
|
|
65069
|
-
|
|
65069
|
+
fail("not-sorted", `${out[i - 1]} > ${s}`);
|
|
65070
65070
|
}
|
|
65071
65071
|
out.push(s);
|
|
65072
65072
|
}
|
|
@@ -65075,7 +65075,7 @@ var init_codec = __esm({
|
|
|
65075
65075
|
vec(each, max = LIMITS.VEC) {
|
|
65076
65076
|
const n = this.u16();
|
|
65077
65077
|
if (n > max)
|
|
65078
|
-
|
|
65078
|
+
fail("too-long", `vec ${n} > ${max}`);
|
|
65079
65079
|
const out = [];
|
|
65080
65080
|
for (let i = 0; i < n; i++)
|
|
65081
65081
|
out.push(each(this));
|
|
@@ -65084,7 +65084,7 @@ var init_codec = __esm({
|
|
|
65084
65084
|
/** Assert the value consumed the whole buffer. Trailing bytes are an error. */
|
|
65085
65085
|
finish() {
|
|
65086
65086
|
if (this.#o !== this.#b.length) {
|
|
65087
|
-
|
|
65087
|
+
fail("trailing", `${this.#b.length - this.#o} byte(s) after value`);
|
|
65088
65088
|
}
|
|
65089
65089
|
}
|
|
65090
65090
|
};
|
|
@@ -65473,18 +65473,18 @@ var init_blake2s = __esm({
|
|
|
65473
65473
|
});
|
|
65474
65474
|
|
|
65475
65475
|
// ../../packages/mesh-pki/dist/crypto.js
|
|
65476
|
-
function
|
|
65476
|
+
function randomBytes7(n) {
|
|
65477
65477
|
return globalThis.crypto.getRandomValues(new Uint8Array(n));
|
|
65478
65478
|
}
|
|
65479
65479
|
async function generateSigningKey(extractable = true) {
|
|
65480
|
-
const kp = await
|
|
65481
|
-
const publicRaw = new Uint8Array(await
|
|
65480
|
+
const kp = await subtle3.generateKey(ED25519, extractable, ["sign", "verify"]);
|
|
65481
|
+
const publicRaw = new Uint8Array(await subtle3.exportKey("raw", kp.publicKey));
|
|
65482
65482
|
return { privateKey: kp.privateKey, publicRaw };
|
|
65483
65483
|
}
|
|
65484
65484
|
async function importSigningPublic(raw) {
|
|
65485
65485
|
if (raw.length !== 32)
|
|
65486
65486
|
throw new Error(`Ed25519 public key must be 32 bytes, got ${raw.length}`);
|
|
65487
|
-
return
|
|
65487
|
+
return subtle3.importKey("raw", bs3(raw), ED25519, true, ["verify"]);
|
|
65488
65488
|
}
|
|
65489
65489
|
async function signingKeyFromSeed(seed) {
|
|
65490
65490
|
if (seed.length !== 32)
|
|
@@ -65508,14 +65508,14 @@ async function signingKeyFromSeed(seed) {
|
|
|
65508
65508
|
32
|
|
65509
65509
|
]);
|
|
65510
65510
|
const pkcs8 = concat2(prefix, seed);
|
|
65511
|
-
const privateKey = await
|
|
65512
|
-
const jwk = await
|
|
65511
|
+
const privateKey = await subtle3.importKey("pkcs8", bs3(pkcs8), ED25519, true, ["sign"]);
|
|
65512
|
+
const jwk = await subtle3.exportKey("jwk", privateKey);
|
|
65513
65513
|
if (typeof jwk.x !== "string")
|
|
65514
65514
|
throw new Error("Ed25519 JWK missing x");
|
|
65515
65515
|
return { privateKey, publicRaw: unb64u2(jwk.x) };
|
|
65516
65516
|
}
|
|
65517
65517
|
async function exportStaticPrivate(kp) {
|
|
65518
|
-
const jwk = await
|
|
65518
|
+
const jwk = await subtle3.exportKey("jwk", kp.privateKey);
|
|
65519
65519
|
if (typeof jwk.d !== "string")
|
|
65520
65520
|
throw new Error("X25519 JWK missing d");
|
|
65521
65521
|
const raw = unb64u2(jwk.d);
|
|
@@ -65524,34 +65524,34 @@ async function exportStaticPrivate(kp) {
|
|
|
65524
65524
|
return raw;
|
|
65525
65525
|
}
|
|
65526
65526
|
async function exportSigningPrivate(kp) {
|
|
65527
|
-
return
|
|
65527
|
+
return subtle3.exportKey("jwk", kp.privateKey);
|
|
65528
65528
|
}
|
|
65529
65529
|
async function importSigningPrivate(jwk) {
|
|
65530
|
-
const privateKey = await
|
|
65530
|
+
const privateKey = await subtle3.importKey("jwk", jwk, ED25519, true, ["sign"]);
|
|
65531
65531
|
if (typeof jwk.x !== "string")
|
|
65532
65532
|
throw new Error("Ed25519 JWK missing x");
|
|
65533
65533
|
return { privateKey, publicRaw: unb64u2(jwk.x) };
|
|
65534
65534
|
}
|
|
65535
65535
|
async function sign2(privateKey, message) {
|
|
65536
|
-
return new Uint8Array(await
|
|
65536
|
+
return new Uint8Array(await subtle3.sign(ED25519, privateKey, bs3(message)));
|
|
65537
65537
|
}
|
|
65538
65538
|
async function verify2(publicRaw, message, sig) {
|
|
65539
65539
|
if (sig.length !== 64 || publicRaw.length !== 32)
|
|
65540
65540
|
return false;
|
|
65541
65541
|
try {
|
|
65542
65542
|
const key2 = await importSigningPublic(publicRaw);
|
|
65543
|
-
return await
|
|
65543
|
+
return await subtle3.verify(ED25519, key2, bs3(sig), bs3(message));
|
|
65544
65544
|
} catch {
|
|
65545
65545
|
return false;
|
|
65546
65546
|
}
|
|
65547
65547
|
}
|
|
65548
65548
|
async function generateStaticKey(extractable = true) {
|
|
65549
|
-
const kp = await
|
|
65550
|
-
const publicRaw = new Uint8Array(await
|
|
65549
|
+
const kp = await subtle3.generateKey(X25519, extractable, ["deriveBits"]);
|
|
65550
|
+
const publicRaw = new Uint8Array(await subtle3.exportKey("raw", kp.publicKey));
|
|
65551
65551
|
return { privateKey: kp.privateKey, publicRaw };
|
|
65552
65552
|
}
|
|
65553
65553
|
async function sha2562(bytes2) {
|
|
65554
|
-
return new Uint8Array(await
|
|
65554
|
+
return new Uint8Array(await subtle3.digest("SHA-256", bs3(bytes2)));
|
|
65555
65555
|
}
|
|
65556
65556
|
function blake2s256(bytes2) {
|
|
65557
65557
|
return blake2s(bytes2, { dkLen: 32 });
|
|
@@ -65570,10 +65570,10 @@ function unb64u2(s) {
|
|
|
65570
65570
|
out[i] = b.charCodeAt(i);
|
|
65571
65571
|
return out;
|
|
65572
65572
|
}
|
|
65573
|
-
function
|
|
65573
|
+
function hex3(bytes2) {
|
|
65574
65574
|
return Array.from(bytes2, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
65575
65575
|
}
|
|
65576
|
-
function
|
|
65576
|
+
function utf82(s) {
|
|
65577
65577
|
return new TextEncoder().encode(s);
|
|
65578
65578
|
}
|
|
65579
65579
|
function concat2(...parts) {
|
|
@@ -65594,13 +65594,13 @@ function bytesEqual(a, b) {
|
|
|
65594
65594
|
diff |= a[i] ^ b[i];
|
|
65595
65595
|
return diff === 0;
|
|
65596
65596
|
}
|
|
65597
|
-
var
|
|
65597
|
+
var subtle3, bs3, ED25519, X25519;
|
|
65598
65598
|
var init_crypto = __esm({
|
|
65599
65599
|
"../../packages/mesh-pki/dist/crypto.js"() {
|
|
65600
65600
|
"use strict";
|
|
65601
65601
|
init_blake2s();
|
|
65602
|
-
|
|
65603
|
-
|
|
65602
|
+
subtle3 = globalThis.crypto.subtle;
|
|
65603
|
+
bs3 = (b) => b;
|
|
65604
65604
|
ED25519 = "Ed25519";
|
|
65605
65605
|
X25519 = "X25519";
|
|
65606
65606
|
}
|
|
@@ -65705,7 +65705,7 @@ async function genesisFingerprint(g) {
|
|
|
65705
65705
|
return sha2562(encodeGenesis(g));
|
|
65706
65706
|
}
|
|
65707
65707
|
function fingerprintShort(fp, groups = 12) {
|
|
65708
|
-
const h =
|
|
65708
|
+
const h = hex3(fp.subarray(0, Math.min(fp.length, groups * 2)));
|
|
65709
65709
|
return (h.match(/.{1,4}/g) ?? []).join(" ");
|
|
65710
65710
|
}
|
|
65711
65711
|
async function signGenesis(block2, signers) {
|
|
@@ -66066,8 +66066,8 @@ var init_addr = __esm({
|
|
|
66066
66066
|
init_crypto();
|
|
66067
66067
|
init_prefix();
|
|
66068
66068
|
init_codec();
|
|
66069
|
-
CTX_V6 =
|
|
66070
|
-
CTX_V4 =
|
|
66069
|
+
CTX_V6 = utf82("tsr-addr6-v1");
|
|
66070
|
+
CTX_V4 = utf82("tsr-addr4-v1");
|
|
66071
66071
|
}
|
|
66072
66072
|
});
|
|
66073
66073
|
|
|
@@ -68642,7 +68642,7 @@ var init_sas = __esm({
|
|
|
68642
68642
|
WORD_MASK = (1 << WORD_BITS) - 1;
|
|
68643
68643
|
SAS_WORDS = 6;
|
|
68644
68644
|
SAS_MIN_BITS = 64;
|
|
68645
|
-
CTX_ENROLL =
|
|
68645
|
+
CTX_ENROLL = utf82("tsr-enroll-sas-v1");
|
|
68646
68646
|
if (wordlist.length !== 1 << WORD_BITS) {
|
|
68647
68647
|
throw new Error(`BIP-39 wordlist must have ${1 << WORD_BITS} entries, got ${wordlist.length}`);
|
|
68648
68648
|
}
|
|
@@ -69061,7 +69061,7 @@ function alphabet(letters) {
|
|
|
69061
69061
|
};
|
|
69062
69062
|
}
|
|
69063
69063
|
// @__NO_SIDE_EFFECTS__
|
|
69064
|
-
function
|
|
69064
|
+
function join61(separator = "") {
|
|
69065
69065
|
astr("join", separator);
|
|
69066
69066
|
return {
|
|
69067
69067
|
encode: (from) => {
|
|
@@ -69266,7 +69266,7 @@ var init_esm = __esm({
|
|
|
69266
69266
|
convertRadix2,
|
|
69267
69267
|
radix,
|
|
69268
69268
|
radix2,
|
|
69269
|
-
join:
|
|
69269
|
+
join: join61,
|
|
69270
69270
|
padding
|
|
69271
69271
|
};
|
|
69272
69272
|
}
|
|
@@ -69337,7 +69337,7 @@ function validateKdf2(k) {
|
|
|
69337
69337
|
throw new MeshCodecError("bad-value", `unsupported KDF cost (m=${k.m} t=${k.t} p=${k.p})`);
|
|
69338
69338
|
}
|
|
69339
69339
|
function kdf(passphrase, salt, cost) {
|
|
69340
|
-
return argon2id(
|
|
69340
|
+
return argon2id(utf82(passphrase.normalize("NFKC")), salt, { ...cost, dkLen: KEY_LEN });
|
|
69341
69341
|
}
|
|
69342
69342
|
function header(version2, label, kdfCost, salt, nonce2) {
|
|
69343
69343
|
const w = new Writer();
|
|
@@ -69355,8 +69355,8 @@ async function sealCaKey(seed, passphrase, label = "mesh CA", cost = DEFAULT_KDF
|
|
|
69355
69355
|
if (label.length > MAX_LABEL)
|
|
69356
69356
|
throw new MeshCodecError("too-long", "label too long");
|
|
69357
69357
|
validateKdf2(cost);
|
|
69358
|
-
const salt =
|
|
69359
|
-
const nonce2 =
|
|
69358
|
+
const salt = randomBytes7(SALT_LEN);
|
|
69359
|
+
const nonce2 = randomBytes7(NONCE_LEN);
|
|
69360
69360
|
const aad = header(RECOVERY_VERSION, label, cost, salt, nonce2);
|
|
69361
69361
|
const key2 = await aesKey(kdf(passphrase, salt, cost));
|
|
69362
69362
|
const ct = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-GCM", iv: nonce2, additionalData: aad }, key2, seed));
|
|
@@ -69412,7 +69412,7 @@ function caKeyFromMnemonic(mnemonic) {
|
|
|
69412
69412
|
return mnemonicToEntropy(norm, wordlist);
|
|
69413
69413
|
}
|
|
69414
69414
|
async function newDisablement() {
|
|
69415
|
-
const secret =
|
|
69415
|
+
const secret = randomBytes7(SECRET_LEN);
|
|
69416
69416
|
return { secret, hash: await sha2562(secret) };
|
|
69417
69417
|
}
|
|
69418
69418
|
async function verifyDisablement(secret, committedHash) {
|
|
@@ -69442,7 +69442,7 @@ var init_recovery = __esm({
|
|
|
69442
69442
|
NONCE_LEN = 12;
|
|
69443
69443
|
KEY_LEN = 32;
|
|
69444
69444
|
MAX_LABEL = 128;
|
|
69445
|
-
DOMAIN =
|
|
69445
|
+
DOMAIN = utf82("tesseract-mesh-recovery-v1");
|
|
69446
69446
|
}
|
|
69447
69447
|
});
|
|
69448
69448
|
|
|
@@ -69452,7 +69452,7 @@ async function mintJoinTicket(opts) {
|
|
|
69452
69452
|
const ttl = opts.ttlMs ?? DEFAULT_TICKET_TTL_MS;
|
|
69453
69453
|
const details = {
|
|
69454
69454
|
version: 1,
|
|
69455
|
-
serial:
|
|
69455
|
+
serial: randomBytes7(16),
|
|
69456
69456
|
genesisFp,
|
|
69457
69457
|
nodeId: opts.nodeId,
|
|
69458
69458
|
name: opts.name,
|
|
@@ -69516,7 +69516,7 @@ async function redeemJoinTicket(opts) {
|
|
|
69516
69516
|
const genesisFp = await genesisFingerprint(ticket.genesis);
|
|
69517
69517
|
const details = {
|
|
69518
69518
|
version: 1,
|
|
69519
|
-
serial:
|
|
69519
|
+
serial: randomBytes7(16),
|
|
69520
69520
|
genesisFp,
|
|
69521
69521
|
nodeId: opts.nodeId ?? ca.nodeId,
|
|
69522
69522
|
name: opts.name ?? ca.name,
|
|
@@ -69661,7 +69661,7 @@ __export(dist_exports3, {
|
|
|
69661
69661
|
generateSigningKey: () => generateSigningKey,
|
|
69662
69662
|
generateStaticKey: () => generateStaticKey,
|
|
69663
69663
|
genesisFingerprint: () => genesisFingerprint,
|
|
69664
|
-
hex: () =>
|
|
69664
|
+
hex: () => hex3,
|
|
69665
69665
|
importSigningPrivate: () => importSigningPrivate,
|
|
69666
69666
|
importSigningPublic: () => importSigningPublic,
|
|
69667
69667
|
isCa: () => isCa,
|
|
@@ -69690,7 +69690,7 @@ __export(dist_exports3, {
|
|
|
69690
69690
|
prefixContains: () => prefixContains,
|
|
69691
69691
|
prefixContainsAddr: () => prefixContainsAddr,
|
|
69692
69692
|
prefixEqual: () => prefixEqual,
|
|
69693
|
-
randomBytes: () =>
|
|
69693
|
+
randomBytes: () => randomBytes7,
|
|
69694
69694
|
readPrefix: () => readPrefix,
|
|
69695
69695
|
readPrefixes: () => readPrefixes,
|
|
69696
69696
|
readRule: () => readRule,
|
|
@@ -69706,7 +69706,7 @@ __export(dist_exports3, {
|
|
|
69706
69706
|
signingKeyFromSeed: () => signingKeyFromSeed,
|
|
69707
69707
|
u32ToAddr: () => u32ToAddr,
|
|
69708
69708
|
unb64u: () => unb64u2,
|
|
69709
|
-
utf8: () =>
|
|
69709
|
+
utf8: () => utf82,
|
|
69710
69710
|
validateBundle: () => validateBundle,
|
|
69711
69711
|
validateDetails: () => validateDetails,
|
|
69712
69712
|
validateGenesis: () => validateGenesis,
|
|
@@ -70889,7 +70889,7 @@ async function netCaCommand(rest, flags) {
|
|
|
70889
70889
|
if (pass.length < 12) die("Use a passphrase of at least 12 characters \u2014 this key issues every identity on the mesh.");
|
|
70890
70890
|
const confirm2 = await readPassphrase("Confirm: ");
|
|
70891
70891
|
if (pass !== confirm2) die("Passphrases did not match.");
|
|
70892
|
-
const seed =
|
|
70892
|
+
const seed = randomBytes7(SEED_LEN);
|
|
70893
70893
|
const ca = await signingKeyFromSeed(seed);
|
|
70894
70894
|
const pol = ca;
|
|
70895
70895
|
const disable = await newDisablement();
|
|
@@ -70906,10 +70906,10 @@ async function netCaCommand(rest, flags) {
|
|
|
70906
70906
|
ensureDir(caDir);
|
|
70907
70907
|
writeFileSync42(join76(caDir, "genesis.bin"), genesisBytes);
|
|
70908
70908
|
writeSecretFile(join76(caDir, "ca.sealed"), encodeRecoveryBundle(await sealCaKey(seed, pass, `${org} mesh CA`)));
|
|
70909
|
-
writeSecretFile(join76(caDir, "disablement.secret"),
|
|
70909
|
+
writeSecretFile(join76(caDir, "disablement.secret"), hex3(disable.secret));
|
|
70910
70910
|
console.log(`
|
|
70911
70911
|
Mesh created for "${org}".`);
|
|
70912
|
-
console.log(` fingerprint: ${
|
|
70912
|
+
console.log(` fingerprint: ${hex3(fp)}`);
|
|
70913
70913
|
console.log(` CA directory: ${caDir}`);
|
|
70914
70914
|
console.log("\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
70915
70915
|
console.log("WRITE THESE DOWN NOW. They are not shown again.\n");
|
|
@@ -70918,7 +70918,7 @@ Mesh created for "${org}".`);
|
|
|
70918
70918
|
`);
|
|
70919
70919
|
console.log("Disablement secret (last resort if the CA AND the mnemonic are gone \u2014");
|
|
70920
70920
|
console.log("it drops every node back to relay-trusted mode, permanently):");
|
|
70921
|
-
console.log(` ${
|
|
70921
|
+
console.log(` ${hex3(disable.secret)}`);
|
|
70922
70922
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
70923
70923
|
console.log(`
|
|
70924
70924
|
A copy of the disablement secret is in ${join76(caDir, "disablement.secret")}.`);
|
|
@@ -70954,7 +70954,7 @@ Next, issue an identity for a machine (pick a free address in ${formatPrefix(gen
|
|
|
70954
70954
|
const cert = await issueCert(
|
|
70955
70955
|
{
|
|
70956
70956
|
version: 1,
|
|
70957
|
-
serial:
|
|
70957
|
+
serial: randomBytes7(16),
|
|
70958
70958
|
genesisFp: fp,
|
|
70959
70959
|
nodeId: name,
|
|
70960
70960
|
name,
|
|
@@ -92628,6 +92628,15 @@ function ownHostId() {
|
|
|
92628
92628
|
const mine = serverHosts.find((h) => h.hostId.endsWith(`:${deviceId}`));
|
|
92629
92629
|
return mine?.hostId ?? "local";
|
|
92630
92630
|
}
|
|
92631
|
+
var lastOwnHostLog = null;
|
|
92632
|
+
function logOwnHostVerdict() {
|
|
92633
|
+
const own2 = ownHostId();
|
|
92634
|
+
const verdict = own2 === "local" ? `NOT REGISTERED \u2014 the account lists ${serverHosts.length} host(s), none matching this deviceId=${deviceId.slice(0, 8)}; this machine is invisible to every client` : `registered as ${own2}`;
|
|
92635
|
+
if (verdict === lastOwnHostLog)
|
|
92636
|
+
return;
|
|
92637
|
+
lastOwnHostLog = verdict;
|
|
92638
|
+
console.log(`[control-link] own host: ${verdict}`);
|
|
92639
|
+
}
|
|
92631
92640
|
function presentedHosts() {
|
|
92632
92641
|
const out = serverHosts.slice();
|
|
92633
92642
|
if (!out.some((h) => h.hostId.endsWith(`:${deviceId}`))) {
|
|
@@ -93428,6 +93437,8 @@ function handleHostChannel(payload) {
|
|
|
93428
93437
|
entitlementDenied = true;
|
|
93429
93438
|
stopHeartbeat();
|
|
93430
93439
|
const message = typeof payload.message === "string" ? payload.message : "Running agents on your own machines requires a paid plan.";
|
|
93440
|
+
const d = payload;
|
|
93441
|
+
console.log(`[control-link] host:register DENIED reason=${String(d.reason ?? "?")} feature=${String(d.feature ?? "?")} limit=${String(d.limit ?? "?")} \u2014 ${message}`);
|
|
93431
93442
|
hooks?.notify({ type: "notify", level: "warning", message });
|
|
93432
93443
|
scheduleEntitlementRetry();
|
|
93433
93444
|
return;
|
|
@@ -93451,6 +93462,7 @@ function handleHostChannel(payload) {
|
|
|
93451
93462
|
setActiveLinkPeerOnline(l.linkId, true);
|
|
93452
93463
|
}
|
|
93453
93464
|
assertServerSelection();
|
|
93465
|
+
logOwnHostVerdict();
|
|
93454
93466
|
hooks?.ownHostResolved(ownHostId());
|
|
93455
93467
|
hooks?.pushHosts(presentedHosts());
|
|
93456
93468
|
resumeActiveLinks();
|
|
@@ -93472,6 +93484,7 @@ function registerAsHost() {
|
|
|
93472
93484
|
const upAdvert = upscaleAdvert();
|
|
93473
93485
|
if (upAdvert.gpu)
|
|
93474
93486
|
caps.push("gpu");
|
|
93487
|
+
console.log(`[control-link] host:register \u2192 deviceId=${deviceId.slice(0, 8)} machineId=${getMachinePublicId() ?? "none"} kind=${kind ?? "electron"} caps=${caps.join(",")}`);
|
|
93475
93488
|
send3("host", { type: "host:register", name, platform: process.platform, deviceId, publicMachineId: getMachinePublicId(), caps, ...kind ? { kind } : {}, ...staticMetrics(hostVersion), gpu: upAdvert.gpu, upscaleModels: upAdvert.upscaleModels, ...p2pAdvert ?? {} });
|
|
93476
93489
|
if (!heartbeat)
|
|
93477
93490
|
heartbeat = setInterval(() => send3("host", { type: "host:heartbeat", ...dynamicMetrics() }), 2e4);
|
|
@@ -93793,7 +93806,7 @@ function connect() {
|
|
|
93793
93806
|
} else if (rdSession && typeof p?.type === "string" && p.type.startsWith("rdesk:")) {
|
|
93794
93807
|
if (inbound) {
|
|
93795
93808
|
if (driving)
|
|
93796
|
-
hooks?.onRdesk?.(env.payload, clientId, rdSession);
|
|
93809
|
+
hooks?.onRdesk?.(env.payload, clientId, rdSession, env.viewerOwner === true);
|
|
93797
93810
|
} else
|
|
93798
93811
|
hooks?.deliverRdesk?.(env.payload, typeof env.hostId === "string" ? env.hostId : void 0, rdSession);
|
|
93799
93812
|
}
|
|
@@ -93806,7 +93819,7 @@ function connect() {
|
|
|
93806
93819
|
return;
|
|
93807
93820
|
if (inbound) {
|
|
93808
93821
|
if (driving)
|
|
93809
|
-
hooks?.onRdesk?.(p, clientId, sessionId);
|
|
93822
|
+
hooks?.onRdesk?.(p, clientId, sessionId, env.viewerOwner === true);
|
|
93810
93823
|
return;
|
|
93811
93824
|
}
|
|
93812
93825
|
hooks?.deliverRdesk?.(p, typeof env.hostId === "string" ? env.hostId : void 0, sessionId);
|
|
@@ -94038,6 +94051,32 @@ var RdeskSessionManager = class {
|
|
|
94038
94051
|
return 0;
|
|
94039
94052
|
return Math.min(PW_BACKOFF_BASE_MS * 2 ** (over - 1), PW_BACKOFF_MAX_MS);
|
|
94040
94053
|
}
|
|
94054
|
+
/** Tell the viewer that this host is (or is again) producing a picture.
|
|
94055
|
+
*
|
|
94056
|
+
* Sent by the HOST because only the host can know why: the OS reports a muted or ended
|
|
94057
|
+
* capture track as a fact, whereas a viewer sees an absence of frames and cannot tell a
|
|
94058
|
+
* slept display from a slow link from a genuinely black screen. Audited too, so "it just
|
|
94059
|
+
* showed black" is answerable after the fact. */
|
|
94060
|
+
reportCapture(sessionId, clientId, ok, message) {
|
|
94061
|
+
this.log(`capture ${ok ? "restored" : `lost \u2014 ${message}`} sessionId=${sessionId}`);
|
|
94062
|
+
this.audit({ event: "capture", sessionId, detail: ok ? "ok" : message });
|
|
94063
|
+
this.deps.sendControl(sessionId, clientId, { type: "rdesk:capture", ok, ...message ? { message } : {} });
|
|
94064
|
+
}
|
|
94065
|
+
/** Record which path a session's media actually took, once ICE has settled.
|
|
94066
|
+
*
|
|
94067
|
+
* Media is direct-first (no relay pinning); TURN exists only as a last resort for NATs
|
|
94068
|
+
* that never punch through. That makes relay usage a COST we pay, so it is written to
|
|
94069
|
+
* the audit trail rather than only logged — `path` events in rdesk-audit.jsonl answer
|
|
94070
|
+
* "what fraction of sessions actually relayed?" without grepping daemon logs. Candidate
|
|
94071
|
+
* types only: an audit file is not the place for peer addresses. */
|
|
94072
|
+
recordPath(sessionId, viewerUserId, path6, d) {
|
|
94073
|
+
this.audit({
|
|
94074
|
+
event: "path",
|
|
94075
|
+
sessionId,
|
|
94076
|
+
viewerUserId,
|
|
94077
|
+
detail: `${path6} local=${d.localType ?? "?"} remote=${d.remoteType ?? "?"}`
|
|
94078
|
+
});
|
|
94079
|
+
}
|
|
94041
94080
|
audit(e) {
|
|
94042
94081
|
this.deps.audit?.({ at: this.now(), ...e });
|
|
94043
94082
|
}
|
|
@@ -94062,10 +94101,10 @@ var RdeskSessionManager = class {
|
|
|
94062
94101
|
const viewer = viewerIn.name || !declared ? viewerIn : { ...viewerIn, name: declared };
|
|
94063
94102
|
const grant0 = grantOf(msg);
|
|
94064
94103
|
this.audit({ event: "connect", sessionId, viewerUserId: viewer.userId, viewerName: viewer.name, grant: grant0 });
|
|
94065
|
-
const deny = (reason) => {
|
|
94066
|
-
this.log(`connect denied sessionId=${sessionId} reason=${reason}`);
|
|
94067
|
-
this.audit({ event: "deny", sessionId, viewerUserId: viewer.userId, grant: grant0, detail: reason });
|
|
94068
|
-
this.deps.sendControl(sessionId, viewer.clientId, { type: "rdesk:denied", reason });
|
|
94104
|
+
const deny = (reason, message) => {
|
|
94105
|
+
this.log(`connect denied sessionId=${sessionId} reason=${reason}${message ? ` \u2014 ${message}` : ""}`);
|
|
94106
|
+
this.audit({ event: "deny", sessionId, viewerUserId: viewer.userId, grant: grant0, detail: message ? `${reason}: ${message}` : reason });
|
|
94107
|
+
this.deps.sendControl(sessionId, viewer.clientId, { type: "rdesk:denied", reason, ...message ? { message } : {} });
|
|
94069
94108
|
};
|
|
94070
94109
|
if (!this.deps.canServe())
|
|
94071
94110
|
return deny("entitlement");
|
|
@@ -94083,6 +94122,10 @@ var RdeskSessionManager = class {
|
|
|
94083
94122
|
return deny("busy");
|
|
94084
94123
|
}
|
|
94085
94124
|
const grant = grantOf(msg);
|
|
94125
|
+
if (grant === "registry" && viewer.sameAccount !== true) {
|
|
94126
|
+
this.log(`connect denied sessionId=${sessionId} \u2014 'registry' claimed by a viewer the relay does not consider the owner`);
|
|
94127
|
+
return deny("consent");
|
|
94128
|
+
}
|
|
94086
94129
|
if (grant === "password") {
|
|
94087
94130
|
if (this.now() < this.pwLockedUntil) {
|
|
94088
94131
|
this.log(`password attempt refused \u2014 locked for ${Math.ceil((this.pwLockedUntil - this.now()) / 1e3)}s`);
|
|
@@ -94123,7 +94166,9 @@ var RdeskSessionManager = class {
|
|
|
94123
94166
|
sendControl: (m) => this.deps.sendControl(sessionId, viewer.clientId, m),
|
|
94124
94167
|
sendData: (_m) => {
|
|
94125
94168
|
},
|
|
94126
|
-
log: (m) => this.log(`${sessionId}: ${m}`)
|
|
94169
|
+
log: (m) => this.log(`${sessionId}: ${m}`),
|
|
94170
|
+
onPath: (path6, d) => this.recordPath(sessionId, viewer.userId, path6, d),
|
|
94171
|
+
onCapture: (ok, message) => this.reportCapture(sessionId, viewer.clientId, ok, message)
|
|
94127
94172
|
};
|
|
94128
94173
|
let engine;
|
|
94129
94174
|
try {
|
|
@@ -94134,7 +94179,7 @@ var RdeskSessionManager = class {
|
|
|
94134
94179
|
const err2 = e instanceof Error ? e.message : String(e);
|
|
94135
94180
|
this.log(`engine start failed sessionId=${sessionId}: ${err2}`);
|
|
94136
94181
|
this.deps.onCaptureBlocked?.({ sessionId, viewerName: viewer.name, error: err2 });
|
|
94137
|
-
return deny("offline");
|
|
94182
|
+
return deny("offline", err2);
|
|
94138
94183
|
}
|
|
94139
94184
|
const monitors = await engine.listMonitors().catch(() => []);
|
|
94140
94185
|
const sources = await engine.listSources?.().catch(() => []) ?? [];
|
|
@@ -94203,7 +94248,9 @@ var RdeskSessionManager = class {
|
|
|
94203
94248
|
sendControl: (m) => this.deps.sendControl(s.sessionId, s.viewer.clientId, m),
|
|
94204
94249
|
sendData: () => {
|
|
94205
94250
|
},
|
|
94206
|
-
log: (m) => this.log(`${s.sessionId}: ${m}`)
|
|
94251
|
+
log: (m) => this.log(`${s.sessionId}: ${m}`),
|
|
94252
|
+
onPath: (path6, d) => this.recordPath(s.sessionId, s.viewer.userId, path6, d),
|
|
94253
|
+
onCapture: (ok, message) => this.reportCapture(s.sessionId, s.viewer.clientId, ok, message)
|
|
94207
94254
|
};
|
|
94208
94255
|
try {
|
|
94209
94256
|
s.engine = await this.deps.createEngine("tesseract", ctx2);
|
|
@@ -94378,6 +94425,93 @@ var RdeskSessionManager = class {
|
|
|
94378
94425
|
}
|
|
94379
94426
|
};
|
|
94380
94427
|
|
|
94428
|
+
// ../../packages/host-core/dist/daemon-identity-reload.js
|
|
94429
|
+
var reload = null;
|
|
94430
|
+
function setDaemonIdentityReload(fn) {
|
|
94431
|
+
reload = fn;
|
|
94432
|
+
}
|
|
94433
|
+
function nextDaemonIdentity(fresh, current) {
|
|
94434
|
+
if (!fresh?.accessToken)
|
|
94435
|
+
return { kind: "machine" };
|
|
94436
|
+
if (fresh.accessToken === current.accessToken && (fresh.userId ?? "") === current.userId)
|
|
94437
|
+
return { kind: "unchanged" };
|
|
94438
|
+
return { kind: "account" };
|
|
94439
|
+
}
|
|
94440
|
+
|
|
94441
|
+
// ../../packages/host-core/dist/rdesk/screen-permission.js
|
|
94442
|
+
function screenRecordingStatus() {
|
|
94443
|
+
if (process.platform !== "darwin")
|
|
94444
|
+
return "unsupported";
|
|
94445
|
+
try {
|
|
94446
|
+
const sp = electronModule()?.systemPreferences;
|
|
94447
|
+
const s = sp?.getMediaAccessStatus("screen");
|
|
94448
|
+
if (s === "granted" || s === "denied" || s === "restricted" || s === "not-determined")
|
|
94449
|
+
return s;
|
|
94450
|
+
return "not-determined";
|
|
94451
|
+
} catch {
|
|
94452
|
+
return "not-determined";
|
|
94453
|
+
}
|
|
94454
|
+
}
|
|
94455
|
+
function canCaptureScreen() {
|
|
94456
|
+
const s = screenRecordingStatus();
|
|
94457
|
+
return s === "granted" || s === "unsupported";
|
|
94458
|
+
}
|
|
94459
|
+
async function registerForScreenRecording() {
|
|
94460
|
+
try {
|
|
94461
|
+
const dc = electronModule()?.desktopCapturer;
|
|
94462
|
+
await dc?.getSources({ types: ["screen"], thumbnailSize: { width: 1, height: 1 } });
|
|
94463
|
+
} catch {
|
|
94464
|
+
}
|
|
94465
|
+
}
|
|
94466
|
+
async function openScreenRecordingSettings() {
|
|
94467
|
+
if (process.platform !== "darwin")
|
|
94468
|
+
return;
|
|
94469
|
+
await registerForScreenRecording();
|
|
94470
|
+
try {
|
|
94471
|
+
const shell = electronModule()?.shell;
|
|
94472
|
+
await shell?.openExternal("x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture");
|
|
94473
|
+
} catch {
|
|
94474
|
+
}
|
|
94475
|
+
}
|
|
94476
|
+
var PROMPT_COOLDOWN_MS = 6e4;
|
|
94477
|
+
var lastPromptAt = 0;
|
|
94478
|
+
async function promptForScreenRecording(opts = {}) {
|
|
94479
|
+
if (process.platform !== "darwin")
|
|
94480
|
+
return false;
|
|
94481
|
+
if (screenRecordingStatus() === "granted") {
|
|
94482
|
+
opts.log?.("capture failed although Screen Recording IS granted \u2014 the capture stack is wedged (seen after a GPU-process crash); restarting Tesseract clears it");
|
|
94483
|
+
return false;
|
|
94484
|
+
}
|
|
94485
|
+
const now2 = Date.now();
|
|
94486
|
+
if (now2 - lastPromptAt < PROMPT_COOLDOWN_MS)
|
|
94487
|
+
return false;
|
|
94488
|
+
lastPromptAt = now2;
|
|
94489
|
+
const el2 = electronModule();
|
|
94490
|
+
const who = opts.viewerName ? `${opts.viewerName} is` : "Someone is";
|
|
94491
|
+
opts.log?.(`screen recording not granted \u2014 prompting (${who} waiting)`);
|
|
94492
|
+
if (!el2?.dialog) {
|
|
94493
|
+
opts.log?.("no GUI to prompt with \u2014 grant Screen Recording in System Settings \u2192 Privacy & Security");
|
|
94494
|
+
return false;
|
|
94495
|
+
}
|
|
94496
|
+
try {
|
|
94497
|
+
const { response } = await el2.dialog.showMessageBox({
|
|
94498
|
+
type: "warning",
|
|
94499
|
+
buttons: ["Open System Settings", "Not Now"],
|
|
94500
|
+
defaultId: 0,
|
|
94501
|
+
cancelId: 1,
|
|
94502
|
+
message: "Allow screen sharing on this Mac?",
|
|
94503
|
+
detail: `${who} trying to connect to this computer, but macOS is blocking screen capture.
|
|
94504
|
+
|
|
94505
|
+
Open System Settings \u2192 Privacy & Security \u2192 Screen Recording and switch on Tesseract Remote Desktop, then ask them to connect again.`
|
|
94506
|
+
});
|
|
94507
|
+
if (response === 0)
|
|
94508
|
+
await openScreenRecordingSettings();
|
|
94509
|
+
return true;
|
|
94510
|
+
} catch {
|
|
94511
|
+
return false;
|
|
94512
|
+
}
|
|
94513
|
+
}
|
|
94514
|
+
|
|
94381
94515
|
// ../../packages/host-core/dist/rdesk/publisher-window.js
|
|
94382
94516
|
import { join as join54 } from "node:path";
|
|
94383
94517
|
var windows = /* @__PURE__ */ new Map();
|
|
@@ -94415,6 +94549,7 @@ function ensureIpc() {
|
|
|
94415
94549
|
el2.ipcMain.on("rdesk:pub:ready", (_e, p) => route2(p, (w) => w.handlers.onReady()));
|
|
94416
94550
|
el2.ipcMain.on("rdesk:pub:error", (_e, p) => route2(p, (w, x) => w.handlers.onError(String(x.error ?? "publisher error"))));
|
|
94417
94551
|
el2.ipcMain.on("rdesk:pub:path", (_e, p) => route2(p, (w, x) => w.handlers.onPath?.(String(x.path ?? "unknown"), { localType: x.localType ?? null, remoteType: x.remoteType ?? null })));
|
|
94552
|
+
el2.ipcMain.on("rdesk:pub:capture", (_e, p) => route2(p, (w, x) => w.handlers.onCapture?.(x.ok !== false, String(x.message ?? ""))));
|
|
94418
94553
|
el2.ipcMain.on("rdesk:pub:stopped", (_e, p) => route2(p, (w) => w.onStoppedAck()));
|
|
94419
94554
|
}
|
|
94420
94555
|
async function listPublisherMonitors() {
|
|
@@ -94461,21 +94596,41 @@ function displayBoundsById(monitorId) {
|
|
|
94461
94596
|
const d = el2.screen.getAllDisplays().find((x) => String(x.id) === monitorId) ?? el2.screen.getPrimaryDisplay();
|
|
94462
94597
|
return d ? { x: d.bounds.x, y: d.bounds.y, width: d.bounds.width, height: d.bounds.height } : null;
|
|
94463
94598
|
}
|
|
94464
|
-
async function
|
|
94599
|
+
async function wakeDisplay(log9) {
|
|
94600
|
+
if (process.platform !== "darwin")
|
|
94601
|
+
return;
|
|
94602
|
+
try {
|
|
94603
|
+
const { spawn: spawn17 } = await import("node:child_process");
|
|
94604
|
+
spawn17("caffeinate", ["-u", "-t", "5"], { detached: true, stdio: "ignore" }).unref();
|
|
94605
|
+
log9?.("display was asleep \u2014 declared user activity to wake it");
|
|
94606
|
+
await new Promise((r) => setTimeout(r, 1200));
|
|
94607
|
+
} catch {
|
|
94608
|
+
}
|
|
94609
|
+
}
|
|
94610
|
+
async function sourceIdForMonitor(monitorId, log9) {
|
|
94465
94611
|
const el2 = electronModule();
|
|
94466
94612
|
if (!el2?.desktopCapturer || !el2.screen)
|
|
94467
94613
|
throw new Error("Screen capture unavailable (Electron desktopCapturer/screen missing).");
|
|
94468
94614
|
const display = el2.screen.getAllDisplays().find((d) => String(d.id) === monitorId) ?? el2.screen.getPrimaryDisplay();
|
|
94469
|
-
const
|
|
94615
|
+
const list = async () => el2.desktopCapturer.getSources({ types: ["screen"], thumbnailSize: { width: 1, height: 1 } });
|
|
94616
|
+
let sources = await list();
|
|
94617
|
+
if (sources.length === 0) {
|
|
94618
|
+
await wakeDisplay(log9);
|
|
94619
|
+
sources = await list();
|
|
94620
|
+
}
|
|
94470
94621
|
const match = sources.find((s) => s.display_id === String(display.id)) ?? sources[0];
|
|
94471
|
-
if (!match)
|
|
94472
|
-
|
|
94622
|
+
if (!match) {
|
|
94623
|
+
const denied = !canCaptureScreen();
|
|
94624
|
+
throw new Error(denied ? "Screen capture failed: Screen Recording permission is not granted to this app." : "Screen capture failed: no screen source. Screen Recording IS granted, so this is usually a display that stayed asleep, or a Mac with no active display attached.");
|
|
94625
|
+
}
|
|
94473
94626
|
return match.id;
|
|
94474
94627
|
}
|
|
94475
94628
|
var PublisherWindow = class {
|
|
94476
94629
|
sessionId;
|
|
94477
94630
|
handlers;
|
|
94478
94631
|
win = null;
|
|
94632
|
+
/** powerSaveBlocker id held for the life of the session — see startDisplayHold(). */
|
|
94633
|
+
displayHold = null;
|
|
94479
94634
|
stopAck = null;
|
|
94480
94635
|
constructor(sessionId, handlers) {
|
|
94481
94636
|
this.sessionId = sessionId;
|
|
@@ -94493,6 +94648,7 @@ var PublisherWindow = class {
|
|
|
94493
94648
|
if (!el2?.BrowserWindow)
|
|
94494
94649
|
throw new Error("Publisher requires the daemon GUI shell (no BrowserWindow).");
|
|
94495
94650
|
ensureIpc();
|
|
94651
|
+
this.startDisplayHold();
|
|
94496
94652
|
const sourceId = opts.sourceId ?? await sourceIdForMonitor(opts.monitorId ?? await this.primaryMonitorId());
|
|
94497
94653
|
const win3 = new el2.BrowserWindow({
|
|
94498
94654
|
width: 320,
|
|
@@ -94606,7 +94762,36 @@ var PublisherWindow = class {
|
|
|
94606
94762
|
maxFps: opts.maxFps
|
|
94607
94763
|
});
|
|
94608
94764
|
}
|
|
94765
|
+
/** Hold the display awake for as long as this session lives.
|
|
94766
|
+
*
|
|
94767
|
+
* Waking it once at start is not enough: the idle timer keeps running, so an unattended
|
|
94768
|
+
* host would go dark again a few minutes into a session and capture would die with the
|
|
94769
|
+
* same empty source list it started with. Released in stop() — never leaked, or the host
|
|
94770
|
+
* can never sleep again. */
|
|
94771
|
+
startDisplayHold() {
|
|
94772
|
+
if (this.displayHold !== null)
|
|
94773
|
+
return;
|
|
94774
|
+
try {
|
|
94775
|
+
const psb = electronModule()?.powerSaveBlocker;
|
|
94776
|
+
if (psb)
|
|
94777
|
+
this.displayHold = psb.start("prevent-display-sleep");
|
|
94778
|
+
} catch {
|
|
94779
|
+
}
|
|
94780
|
+
}
|
|
94781
|
+
releaseDisplayHold() {
|
|
94782
|
+
const id = this.displayHold;
|
|
94783
|
+
this.displayHold = null;
|
|
94784
|
+
if (id === null)
|
|
94785
|
+
return;
|
|
94786
|
+
try {
|
|
94787
|
+
const psb = electronModule()?.powerSaveBlocker;
|
|
94788
|
+
if (psb?.isStarted(id))
|
|
94789
|
+
psb.stop(id);
|
|
94790
|
+
} catch {
|
|
94791
|
+
}
|
|
94792
|
+
}
|
|
94609
94793
|
async stop() {
|
|
94794
|
+
this.releaseDisplayHold();
|
|
94610
94795
|
const w = this.win;
|
|
94611
94796
|
this.win = null;
|
|
94612
94797
|
if (!w || w.isDestroyed()) {
|
|
@@ -94968,10 +95153,20 @@ var TesseractEngine = class {
|
|
|
94968
95153
|
}
|
|
94969
95154
|
},
|
|
94970
95155
|
onReady: () => this.ctx.log("publisher connected"),
|
|
94971
|
-
onError: (err2) =>
|
|
95156
|
+
onError: (err2) => {
|
|
95157
|
+
this.ctx.log(`publisher error: ${err2}`);
|
|
95158
|
+
this.ctx.sendControl({ type: "rdesk:closed", reason: "network" });
|
|
95159
|
+
},
|
|
94972
95160
|
// Media is direct-first; log which path actually won so a regression to relay
|
|
94973
95161
|
// (which costs real bandwidth) is visible instead of silent. Types only, no IPs.
|
|
94974
|
-
|
|
95162
|
+
onCapture: (ok, message) => {
|
|
95163
|
+
this.ctx.log(`capture ${ok ? "ok" : `LOST \u2014 ${message}`}`);
|
|
95164
|
+
this.ctx.onCapture?.(ok, message);
|
|
95165
|
+
},
|
|
95166
|
+
onPath: (path6, d) => {
|
|
95167
|
+
this.ctx.log(`media path=${path6} (local=${d.localType ?? "?"} remote=${d.remoteType ?? "?"})`);
|
|
95168
|
+
this.ctx.onPath?.(path6, d);
|
|
95169
|
+
}
|
|
94975
95170
|
});
|
|
94976
95171
|
this.pub = pub;
|
|
94977
95172
|
await pub.start({
|
|
@@ -97440,7 +97635,7 @@ async function startLocalServer(opts) {
|
|
|
97440
97635
|
const rd = opts.getRdesk?.();
|
|
97441
97636
|
if (rd && env.sessionId) {
|
|
97442
97637
|
rdeskSessions.add(env.sessionId);
|
|
97443
|
-
void rd.onClientMessage(env.sessionId, { clientId: loopbackOrigin, name: "This device" }, env.payload);
|
|
97638
|
+
void rd.onClientMessage(env.sessionId, { clientId: loopbackOrigin, name: "This device", sameAccount: true }, env.payload);
|
|
97444
97639
|
}
|
|
97445
97640
|
}
|
|
97446
97641
|
} else if (env.channel === "signal") {
|
|
@@ -98025,8 +98220,8 @@ async function startLocalServer(opts) {
|
|
|
98025
98220
|
init_base_paths();
|
|
98026
98221
|
import { readFileSync as readFileSync45, writeFileSync as writeFileSync38, existsSync as existsSync35, mkdirSync as mkdirSync37, unlinkSync as unlinkSync6, chmodSync as chmodSync7, statSync as statSync9 } from "node:fs";
|
|
98027
98222
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
98028
|
-
import { join as
|
|
98029
|
-
import { randomBytes as
|
|
98223
|
+
import { join as join70 } from "node:path";
|
|
98224
|
+
import { randomBytes as randomBytes10 } from "node:crypto";
|
|
98030
98225
|
import { hostname as hostname5 } from "node:os";
|
|
98031
98226
|
|
|
98032
98227
|
// ../../packages/shared/dist/daemon-registry.js
|
|
@@ -98855,9 +99050,54 @@ var MeshNode = class {
|
|
|
98855
99050
|
#relayed = /* @__PURE__ */ new Set();
|
|
98856
99051
|
/** staticPub hex → the Buffer, so events can be matched back to a peer. */
|
|
98857
99052
|
#peers = /* @__PURE__ */ new Map();
|
|
99053
|
+
/**
|
|
99054
|
+
* Peers whose CERTIFICATE says they are this network's way out, by display name.
|
|
99055
|
+
*
|
|
99056
|
+
* A hint for the UI, never an authorisation: the engine checks the same signed bit per
|
|
99057
|
+
* packet, alongside our own selection and a bundle capability. This exists so a person
|
|
99058
|
+
* can be offered a choice that has somewhere to go.
|
|
99059
|
+
*/
|
|
99060
|
+
#exitNodes = /* @__PURE__ */ new Map();
|
|
98858
99061
|
#lan = null;
|
|
98859
99062
|
#offRejoin = null;
|
|
98860
99063
|
#statusTimer = null;
|
|
99064
|
+
/**
|
|
99065
|
+
* Route this machine's non-mesh traffic through the network's exit node, or stop.
|
|
99066
|
+
*
|
|
99067
|
+
* GATE 1 OF THREE, and the only one that lives on this machine. `Engine::exit_allowed`
|
|
99068
|
+
* additionally requires that the CA marked the peer's certificate and that the signed
|
|
99069
|
+
* bundle grants CAP_EXIT_NODE, both checked per packet — so selecting a peer widens
|
|
99070
|
+
* nothing by itself, and selecting one that turns out not to qualify simply drops the
|
|
99071
|
+
* traffic rather than misrouting it.
|
|
99072
|
+
*
|
|
99073
|
+
* Without this call netd installs the routes and the engine refuses every packet that
|
|
99074
|
+
* arrives on them: a machine with its default route captured and nothing carrying it,
|
|
99075
|
+
* which is the worst of both states.
|
|
99076
|
+
*
|
|
99077
|
+
* Returns the name selected, or null when there is nobody to select.
|
|
99078
|
+
*/
|
|
99079
|
+
useExitNode(on) {
|
|
99080
|
+
const engine = this.#engine;
|
|
99081
|
+
if (!engine)
|
|
99082
|
+
return null;
|
|
99083
|
+
if (!on) {
|
|
99084
|
+
try {
|
|
99085
|
+
engine.setExitNode?.(null);
|
|
99086
|
+
} catch {
|
|
99087
|
+
}
|
|
99088
|
+
return null;
|
|
99089
|
+
}
|
|
99090
|
+
const first = [...this.#exitNodes.entries()][0];
|
|
99091
|
+
if (first === void 0)
|
|
99092
|
+
return null;
|
|
99093
|
+
const [hex6, name] = first;
|
|
99094
|
+
try {
|
|
99095
|
+
engine.setExitNode?.(Buffer.from(hex6, "hex"));
|
|
99096
|
+
} catch {
|
|
99097
|
+
return null;
|
|
99098
|
+
}
|
|
99099
|
+
return name;
|
|
99100
|
+
}
|
|
98861
99101
|
status() {
|
|
98862
99102
|
return {
|
|
98863
99103
|
available: meshCore.available,
|
|
@@ -98869,6 +99109,14 @@ var MeshNode = class {
|
|
|
98869
99109
|
peers: this.#engine?.peerCount() ?? 0,
|
|
98870
99110
|
established: [...this.#established],
|
|
98871
99111
|
relayed: [...this.#relayed],
|
|
99112
|
+
exitNodes: [...this.#exitNodes.values()],
|
|
99113
|
+
// Derived from the SAME sets the peer list is: an exit node with no established
|
|
99114
|
+
// session is one that cannot carry traffic yet, and saying "waiting" is different
|
|
99115
|
+
// from saying "none". Keyed by name so a caller never has to hold a key to read it.
|
|
99116
|
+
exitPaths: Object.fromEntries([...this.#exitNodes.entries()].map(([hex6, name]) => [
|
|
99117
|
+
name,
|
|
99118
|
+
this.#established.has(hex6) ? this.#relayed.has(hex6) ? "relay" : "direct" : "none"
|
|
99119
|
+
])),
|
|
98872
99120
|
meter: this.#engine?.meter() ?? null,
|
|
98873
99121
|
lastError: this.#lastError,
|
|
98874
99122
|
// Surfaced so `net status` can say "removed" rather than "not running". Those look
|
|
@@ -99137,6 +99385,8 @@ var MeshNode = class {
|
|
|
99137
99385
|
}
|
|
99138
99386
|
case "mesh:gone": {
|
|
99139
99387
|
const pk = Buffer.from(m.staticPub, "base64");
|
|
99388
|
+
if (pk.length === 32)
|
|
99389
|
+
this.#exitNodes.delete(pk.toString("hex"));
|
|
99140
99390
|
if (pk.length === 32) {
|
|
99141
99391
|
const hex6 = pk.toString("hex");
|
|
99142
99392
|
this.#peers.delete(hex6);
|
|
@@ -99166,6 +99416,18 @@ var MeshNode = class {
|
|
|
99166
99416
|
if (pk.length !== 32)
|
|
99167
99417
|
return;
|
|
99168
99418
|
const hex6 = pk.toString("hex");
|
|
99419
|
+
if (p.cert) {
|
|
99420
|
+
try {
|
|
99421
|
+
const bytes2 = Buffer.from(p.cert, "base64");
|
|
99422
|
+
const pki = (init_dist6(), __toCommonJS(dist_exports3));
|
|
99423
|
+
const details = pki.decodeCert(new Uint8Array(bytes2)).details;
|
|
99424
|
+
if (pki.isExitNode(details))
|
|
99425
|
+
this.#exitNodes.set(hex6, details.name);
|
|
99426
|
+
else
|
|
99427
|
+
this.#exitNodes.delete(hex6);
|
|
99428
|
+
} catch {
|
|
99429
|
+
}
|
|
99430
|
+
}
|
|
99169
99431
|
if (!this.#peers.has(hex6)) {
|
|
99170
99432
|
engine.addPeer(pk, 0, Buffer.alloc(16));
|
|
99171
99433
|
this.#peers.set(hex6, pk);
|
|
@@ -99364,7 +99626,7 @@ function netdEndpoint() {
|
|
|
99364
99626
|
function endpointOverride() {
|
|
99365
99627
|
return process.env.CCB_NETD_SOCKET ?? null;
|
|
99366
99628
|
}
|
|
99367
|
-
function
|
|
99629
|
+
function fail2(code, detail) {
|
|
99368
99630
|
return { ok: false, code, detail };
|
|
99369
99631
|
}
|
|
99370
99632
|
async function call(line) {
|
|
@@ -99385,28 +99647,28 @@ async function call(line) {
|
|
|
99385
99647
|
try {
|
|
99386
99648
|
sock = connect2(endpoint2);
|
|
99387
99649
|
} catch (e) {
|
|
99388
|
-
return resolve16(
|
|
99650
|
+
return resolve16(fail2("not-installed", e instanceof Error ? e.message : String(e)));
|
|
99389
99651
|
}
|
|
99390
99652
|
const timer2 = setTimeout(() => {
|
|
99391
|
-
done(
|
|
99653
|
+
done(fail2("timeout", `no answer from the network helper in ${TIMEOUT_MS2}ms`));
|
|
99392
99654
|
}, TIMEOUT_MS2);
|
|
99393
99655
|
timer2.unref?.();
|
|
99394
99656
|
sock.setTimeout(TIMEOUT_MS2);
|
|
99395
99657
|
sock.on("timeout", () => {
|
|
99396
99658
|
clearTimeout(timer2);
|
|
99397
|
-
done(
|
|
99659
|
+
done(fail2("timeout", "socket idle"));
|
|
99398
99660
|
});
|
|
99399
99661
|
sock.on("error", (e) => {
|
|
99400
99662
|
clearTimeout(timer2);
|
|
99401
99663
|
const absent = e.code === "ENOENT" || e.code === "ECONNREFUSED";
|
|
99402
|
-
done(
|
|
99664
|
+
done(fail2(absent ? "not-installed" : "io", e.message));
|
|
99403
99665
|
});
|
|
99404
99666
|
let buf = "";
|
|
99405
99667
|
sock.on("data", (chunk) => {
|
|
99406
99668
|
buf += chunk.toString("utf8");
|
|
99407
99669
|
if (buf.length > MAX_LINE) {
|
|
99408
99670
|
clearTimeout(timer2);
|
|
99409
|
-
done(
|
|
99671
|
+
done(fail2("protocol", "the helper sent an oversized line"));
|
|
99410
99672
|
return;
|
|
99411
99673
|
}
|
|
99412
99674
|
const nl = buf.indexOf("\n");
|
|
@@ -99417,7 +99679,7 @@ async function call(line) {
|
|
|
99417
99679
|
});
|
|
99418
99680
|
sock.on("close", () => {
|
|
99419
99681
|
clearTimeout(timer2);
|
|
99420
|
-
done(
|
|
99682
|
+
done(fail2("protocol", "the helper closed the connection without answering"));
|
|
99421
99683
|
});
|
|
99422
99684
|
sock.on("connect", () => {
|
|
99423
99685
|
sock.write(`${line}
|
|
@@ -99430,26 +99692,26 @@ function parse3(line) {
|
|
|
99430
99692
|
try {
|
|
99431
99693
|
body = JSON.parse(line);
|
|
99432
99694
|
} catch {
|
|
99433
|
-
return
|
|
99695
|
+
return fail2("protocol", "the helper sent something that is not JSON");
|
|
99434
99696
|
}
|
|
99435
99697
|
if (typeof body !== "object" || body === null) {
|
|
99436
|
-
return
|
|
99698
|
+
return fail2("protocol", "the helper sent something that is not an object");
|
|
99437
99699
|
}
|
|
99438
99700
|
const o = body;
|
|
99439
99701
|
if (o.ok === false) {
|
|
99440
99702
|
const code = typeof o.code === "string" ? o.code : "refused";
|
|
99441
99703
|
const detail = typeof o.detail === "string" ? o.detail : "the helper refused";
|
|
99442
|
-
return
|
|
99704
|
+
return fail2(code, detail);
|
|
99443
99705
|
}
|
|
99444
99706
|
if (o.ok !== true)
|
|
99445
|
-
return
|
|
99707
|
+
return fail2("protocol", "the helper did not say whether it succeeded");
|
|
99446
99708
|
return { ok: true, body: o };
|
|
99447
99709
|
}
|
|
99448
99710
|
async function request(line) {
|
|
99449
99711
|
const r = await call(line);
|
|
99450
99712
|
return r.ok ? parse3(r.line) : r;
|
|
99451
99713
|
}
|
|
99452
|
-
function
|
|
99714
|
+
function hex4(b) {
|
|
99453
99715
|
return Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
|
|
99454
99716
|
}
|
|
99455
99717
|
async function netdHello() {
|
|
@@ -99458,9 +99720,9 @@ async function netdHello() {
|
|
|
99458
99720
|
return r;
|
|
99459
99721
|
const v = r.body.wireVersion;
|
|
99460
99722
|
if (typeof v !== "number")
|
|
99461
|
-
return
|
|
99723
|
+
return fail2("protocol", "the helper did not report a wire version");
|
|
99462
99724
|
if (v !== NETD_WIRE_VERSION) {
|
|
99463
|
-
return
|
|
99725
|
+
return fail2("wire-version", `the helper speaks ${v}, this build speaks ${NETD_WIRE_VERSION}`);
|
|
99464
99726
|
}
|
|
99465
99727
|
return { ok: true, wireVersion: v };
|
|
99466
99728
|
}
|
|
@@ -99476,8 +99738,8 @@ async function netdUp(args) {
|
|
|
99476
99738
|
const r = await request(JSON.stringify({
|
|
99477
99739
|
op: "up",
|
|
99478
99740
|
meshId: args.meshId,
|
|
99479
|
-
genesis:
|
|
99480
|
-
cert:
|
|
99741
|
+
genesis: hex4(args.genesis),
|
|
99742
|
+
cert: hex4(args.cert),
|
|
99481
99743
|
fullTunnel: args.fullTunnel === true
|
|
99482
99744
|
}));
|
|
99483
99745
|
return r.ok ? { ok: true } : r;
|
|
@@ -99677,7 +99939,7 @@ import { basename as basename13 } from "node:path";
|
|
|
99677
99939
|
// ../../packages/host-core/dist/drops/paths.js
|
|
99678
99940
|
init_base_paths();
|
|
99679
99941
|
import { mkdir as mkdir12 } from "node:fs/promises";
|
|
99680
|
-
import { join as
|
|
99942
|
+
import { join as join62 } from "node:path";
|
|
99681
99943
|
|
|
99682
99944
|
// ../../packages/host-core/dist/drops/names.js
|
|
99683
99945
|
var WINDOWS_RESERVED = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/i;
|
|
@@ -99686,8 +99948,8 @@ var BIDI = /[\u200e\u200f\u202a-\u202e\u2066-\u2069]/g;
|
|
|
99686
99948
|
var MAX_NAME_BYTES = 200;
|
|
99687
99949
|
var MAX_EXT_BYTES = 32;
|
|
99688
99950
|
var MAX_DEPTH2 = 32;
|
|
99689
|
-
var
|
|
99690
|
-
var byteLen = (s) =>
|
|
99951
|
+
var utf83 = new TextEncoder();
|
|
99952
|
+
var byteLen = (s) => utf83.encode(s).length;
|
|
99691
99953
|
function capBytes(stem, ext, max) {
|
|
99692
99954
|
if (byteLen(stem + ext) <= max)
|
|
99693
99955
|
return stem + ext;
|
|
@@ -99766,7 +100028,7 @@ function basenameOf(p) {
|
|
|
99766
100028
|
function resolveDropsRoot() {
|
|
99767
100029
|
const root = resolveHostRoot();
|
|
99768
100030
|
const preferred = dropsDir();
|
|
99769
|
-
return isInsideRoot(preferred, root) ? preferred :
|
|
100031
|
+
return isInsideRoot(preferred, root) ? preferred : join62(root, "Drops");
|
|
99770
100032
|
}
|
|
99771
100033
|
async function ensureDropsRoot() {
|
|
99772
100034
|
const dir2 = resolveDropsRoot();
|
|
@@ -99782,7 +100044,7 @@ async function ensureDropDir(opts) {
|
|
|
99782
100044
|
parts.push(sanitizeDropName(opts.sender, "Unknown sender"));
|
|
99783
100045
|
if (!opts.singleItem && opts.label)
|
|
99784
100046
|
parts.push(sanitizeDropName(opts.label, "Files"));
|
|
99785
|
-
const dir2 =
|
|
100047
|
+
const dir2 = join62(...parts);
|
|
99786
100048
|
await mkdir12(dir2, { recursive: true });
|
|
99787
100049
|
return dir2;
|
|
99788
100050
|
}
|
|
@@ -99925,7 +100187,7 @@ function createDropHandler(deps) {
|
|
|
99925
100187
|
// ../../packages/host-core/dist/drops/blob-fetch.js
|
|
99926
100188
|
import { createWriteStream as createWriteStream2 } from "node:fs";
|
|
99927
100189
|
import { mkdir as mkdir13, rm as rm5, chmod as chmod3 } from "node:fs/promises";
|
|
99928
|
-
import { dirname as dirname26, join as
|
|
100190
|
+
import { dirname as dirname26, join as join63 } from "node:path";
|
|
99929
100191
|
import { Readable as Readable2 } from "node:stream";
|
|
99930
100192
|
import { pipeline } from "node:stream/promises";
|
|
99931
100193
|
|
|
@@ -99937,10 +100199,10 @@ var HEADER_BYTES = MAGIC2.length + NONCE_BYTES;
|
|
|
99937
100199
|
var FRAME_BYTES = 1024 * 1024;
|
|
99938
100200
|
var TAG_BYTES = 16;
|
|
99939
100201
|
var MAX_FRAME_CIPHERTEXT = FRAME_BYTES + TAG_BYTES + 1024;
|
|
99940
|
-
var
|
|
99941
|
-
var
|
|
100202
|
+
var subtle4 = () => globalThis.crypto.subtle;
|
|
100203
|
+
var bs4 = (b) => b;
|
|
99942
100204
|
async function importKey(raw) {
|
|
99943
|
-
return
|
|
100205
|
+
return subtle4().importKey("raw", bs4(raw), { name: "AES-GCM" }, false, ["encrypt", "decrypt"]);
|
|
99944
100206
|
}
|
|
99945
100207
|
function nonceFor(base, index) {
|
|
99946
100208
|
const n = Buffer.from(base);
|
|
@@ -100035,7 +100297,7 @@ function decryptStream(source, keyRaw) {
|
|
|
100035
100297
|
const frame = q.peek(4 + len);
|
|
100036
100298
|
if (!frame)
|
|
100037
100299
|
break;
|
|
100038
|
-
const plain = Buffer.from(await
|
|
100300
|
+
const plain = Buffer.from(await subtle4().decrypt({ name: "AES-GCM", iv: bs4(nonceFor(base, index)), additionalData: bs4(aadFor(index)) }, key2, bs4(frame.subarray(4))));
|
|
100039
100301
|
this.push(plain);
|
|
100040
100302
|
index += 1;
|
|
100041
100303
|
q.consume(4 + len);
|
|
@@ -100097,7 +100359,7 @@ async function fetchBlobDrop(opts) {
|
|
|
100097
100359
|
log7(`drop ${opts.dropId}: refusing directory "${item.rel}"`);
|
|
100098
100360
|
continue;
|
|
100099
100361
|
}
|
|
100100
|
-
const abs =
|
|
100362
|
+
const abs = join63(opts.destDir, rel);
|
|
100101
100363
|
if (!isInsideRoot(abs, opts.destDir)) {
|
|
100102
100364
|
log7(`drop ${opts.dropId}: refusing directory outside the destination`);
|
|
100103
100365
|
continue;
|
|
@@ -100118,7 +100380,7 @@ async function fetchBlobDrop(opts) {
|
|
|
100118
100380
|
log7(`drop ${opts.dropId}: refusing "${item.rel}"`);
|
|
100119
100381
|
continue;
|
|
100120
100382
|
}
|
|
100121
|
-
let abs =
|
|
100383
|
+
let abs = join63(opts.destDir, rel);
|
|
100122
100384
|
if (!isInsideRoot(abs, opts.destDir)) {
|
|
100123
100385
|
log7(`drop ${opts.dropId}: refusing a path outside the destination`);
|
|
100124
100386
|
continue;
|
|
@@ -100396,12 +100658,12 @@ var RdeskServerChannel = class {
|
|
|
100396
100658
|
|
|
100397
100659
|
// ../../packages/host-core/dist/rdesk/channel-client.js
|
|
100398
100660
|
import { readFileSync as readFileSync44 } from "node:fs";
|
|
100399
|
-
import { join as
|
|
100661
|
+
import { join as join64 } from "node:path";
|
|
100400
100662
|
var RECONNECT_MS = 2e3;
|
|
100401
100663
|
var CLAIM_RETRY_MS = 5e3;
|
|
100402
100664
|
function readEndpoint(dir2, selfPid) {
|
|
100403
100665
|
try {
|
|
100404
|
-
const s = JSON.parse(readFileSync44(
|
|
100666
|
+
const s = JSON.parse(readFileSync44(join64(dir2, "status.json"), "utf8"));
|
|
100405
100667
|
if (selfPid && s.pid === selfPid)
|
|
100406
100668
|
return null;
|
|
100407
100669
|
return s.localPort && s.localToken ? `ws://127.0.0.1:${s.localPort}/?token=${s.localToken}` : null;
|
|
@@ -100542,19 +100804,6 @@ function setRdeskServerAdmin(a) {
|
|
|
100542
100804
|
admin = a;
|
|
100543
100805
|
}
|
|
100544
100806
|
|
|
100545
|
-
// ../../packages/host-core/dist/daemon-identity-reload.js
|
|
100546
|
-
var reload = null;
|
|
100547
|
-
function setDaemonIdentityReload(fn) {
|
|
100548
|
-
reload = fn;
|
|
100549
|
-
}
|
|
100550
|
-
function nextDaemonIdentity(fresh, current) {
|
|
100551
|
-
if (!fresh?.accessToken)
|
|
100552
|
-
return { kind: "machine" };
|
|
100553
|
-
if (fresh.accessToken === current.accessToken && (fresh.userId ?? "") === current.userId)
|
|
100554
|
-
return { kind: "unchanged" };
|
|
100555
|
-
return { kind: "account" };
|
|
100556
|
-
}
|
|
100557
|
-
|
|
100558
100807
|
// ../../packages/host-core/dist/daemon-online-watch.js
|
|
100559
100808
|
var FIRST_DELAY_MS = 5e3;
|
|
100560
100809
|
var MAX_DELAY_MS = 3e4;
|
|
@@ -100847,10 +101096,10 @@ function registerRdpEngine() {
|
|
|
100847
101096
|
// ../../packages/host-core/dist/rdesk/audit.js
|
|
100848
101097
|
init_credentials();
|
|
100849
101098
|
import { appendFile, stat as stat8, rename as rename3 } from "node:fs/promises";
|
|
100850
|
-
import { join as
|
|
101099
|
+
import { join as join65 } from "node:path";
|
|
100851
101100
|
var MAX_BYTES = 2 * 1024 * 1024;
|
|
100852
101101
|
function rdeskAuditPath() {
|
|
100853
|
-
return
|
|
101102
|
+
return join65(daemonDir2(), "rdesk-audit.jsonl");
|
|
100854
101103
|
}
|
|
100855
101104
|
var queue = [];
|
|
100856
101105
|
var draining = false;
|
|
@@ -100890,81 +101139,13 @@ function appendRdeskAudit(e) {
|
|
|
100890
101139
|
}
|
|
100891
101140
|
}
|
|
100892
101141
|
|
|
100893
|
-
// ../../packages/host-core/dist/rdesk/screen-permission.js
|
|
100894
|
-
function screenRecordingStatus() {
|
|
100895
|
-
if (process.platform !== "darwin")
|
|
100896
|
-
return "unsupported";
|
|
100897
|
-
try {
|
|
100898
|
-
const sp = electronModule()?.systemPreferences;
|
|
100899
|
-
const s = sp?.getMediaAccessStatus("screen");
|
|
100900
|
-
if (s === "granted" || s === "denied" || s === "restricted" || s === "not-determined")
|
|
100901
|
-
return s;
|
|
100902
|
-
return "not-determined";
|
|
100903
|
-
} catch {
|
|
100904
|
-
return "not-determined";
|
|
100905
|
-
}
|
|
100906
|
-
}
|
|
100907
|
-
async function registerForScreenRecording() {
|
|
100908
|
-
try {
|
|
100909
|
-
const dc = electronModule()?.desktopCapturer;
|
|
100910
|
-
await dc?.getSources({ types: ["screen"], thumbnailSize: { width: 1, height: 1 } });
|
|
100911
|
-
} catch {
|
|
100912
|
-
}
|
|
100913
|
-
}
|
|
100914
|
-
async function openScreenRecordingSettings() {
|
|
100915
|
-
if (process.platform !== "darwin")
|
|
100916
|
-
return;
|
|
100917
|
-
await registerForScreenRecording();
|
|
100918
|
-
try {
|
|
100919
|
-
const shell = electronModule()?.shell;
|
|
100920
|
-
await shell?.openExternal("x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture");
|
|
100921
|
-
} catch {
|
|
100922
|
-
}
|
|
100923
|
-
}
|
|
100924
|
-
var PROMPT_COOLDOWN_MS = 6e4;
|
|
100925
|
-
var lastPromptAt = 0;
|
|
100926
|
-
async function promptForScreenRecording(opts = {}) {
|
|
100927
|
-
if (process.platform !== "darwin")
|
|
100928
|
-
return false;
|
|
100929
|
-
if (screenRecordingStatus() === "granted")
|
|
100930
|
-
return false;
|
|
100931
|
-
const now2 = Date.now();
|
|
100932
|
-
if (now2 - lastPromptAt < PROMPT_COOLDOWN_MS)
|
|
100933
|
-
return false;
|
|
100934
|
-
lastPromptAt = now2;
|
|
100935
|
-
const el2 = electronModule();
|
|
100936
|
-
const who = opts.viewerName ? `${opts.viewerName} is` : "Someone is";
|
|
100937
|
-
opts.log?.(`screen recording not granted \u2014 prompting (${who} waiting)`);
|
|
100938
|
-
if (!el2?.dialog) {
|
|
100939
|
-
opts.log?.("no GUI to prompt with \u2014 grant Screen Recording in System Settings \u2192 Privacy & Security");
|
|
100940
|
-
return false;
|
|
100941
|
-
}
|
|
100942
|
-
try {
|
|
100943
|
-
const { response } = await el2.dialog.showMessageBox({
|
|
100944
|
-
type: "warning",
|
|
100945
|
-
buttons: ["Open System Settings", "Not Now"],
|
|
100946
|
-
defaultId: 0,
|
|
100947
|
-
cancelId: 1,
|
|
100948
|
-
message: "Allow screen sharing on this Mac?",
|
|
100949
|
-
detail: `${who} trying to connect to this computer, but macOS is blocking screen capture.
|
|
100950
|
-
|
|
100951
|
-
Open System Settings \u2192 Privacy & Security \u2192 Screen Recording and switch on Tesseract Remote Desktop, then ask them to connect again.`
|
|
100952
|
-
});
|
|
100953
|
-
if (response === 0)
|
|
100954
|
-
await openScreenRecordingSettings();
|
|
100955
|
-
return true;
|
|
100956
|
-
} catch {
|
|
100957
|
-
return false;
|
|
100958
|
-
}
|
|
100959
|
-
}
|
|
100960
|
-
|
|
100961
101142
|
// ../../packages/host-core/dist/fileprovider-bridge.js
|
|
100962
101143
|
import { writeFileSync as writeFileSync34, mkdirSync as mkdirSync33, rmSync as rmSync8, existsSync as existsSync31 } from "node:fs";
|
|
100963
101144
|
import { homedir as homedir9 } from "node:os";
|
|
100964
|
-
import { join as
|
|
101145
|
+
import { join as join66 } from "node:path";
|
|
100965
101146
|
var APPEX_BUNDLE_ID = "dev.tesseract.FileProvider";
|
|
100966
101147
|
function appexBridgeInfoPath() {
|
|
100967
|
-
return
|
|
101148
|
+
return join66(homedir9(), "Library", "Containers", APPEX_BUNDLE_ID, "Data", "Library", "Application Support", "tesseract-bridge.json");
|
|
100968
101149
|
}
|
|
100969
101150
|
function clearBridgeInfo() {
|
|
100970
101151
|
if (process.platform !== "darwin")
|
|
@@ -101131,10 +101312,10 @@ function stopFileProviderBridge() {
|
|
|
101131
101312
|
}
|
|
101132
101313
|
|
|
101133
101314
|
// ../../packages/host-core/dist/vault/autofill-bridge.js
|
|
101134
|
-
import { randomBytes as
|
|
101315
|
+
import { randomBytes as randomBytes9 } from "node:crypto";
|
|
101135
101316
|
import { existsSync as existsSync32, mkdirSync as mkdirSync34, writeFileSync as writeFileSync35, rmSync as rmSync9 } from "node:fs";
|
|
101136
101317
|
import { homedir as homedir10 } from "node:os";
|
|
101137
|
-
import { join as
|
|
101318
|
+
import { join as join67 } from "node:path";
|
|
101138
101319
|
|
|
101139
101320
|
// ../../packages/host-core/dist/vault/peer-verify.js
|
|
101140
101321
|
import { execFile as execFile9 } from "node:child_process";
|
|
@@ -101196,10 +101377,10 @@ async function isTrustedAutofillPeer(remotePort) {
|
|
|
101196
101377
|
var APPEX_BUNDLE_ID2 = "dev.tesseract.AutoFill";
|
|
101197
101378
|
var BRIDGE_PORTS2 = [17872, 17873, 17874, 17875];
|
|
101198
101379
|
function appexContainerData() {
|
|
101199
|
-
return
|
|
101380
|
+
return join67(homedir10(), "Library", "Containers", APPEX_BUNDLE_ID2, "Data");
|
|
101200
101381
|
}
|
|
101201
101382
|
function bridgeInfoPath() {
|
|
101202
|
-
return
|
|
101383
|
+
return join67(appexContainerData(), "Library", "Application Support", "tesseract-autofill-bridge.json");
|
|
101203
101384
|
}
|
|
101204
101385
|
var infoLoggedOnce = false;
|
|
101205
101386
|
function writeBridgeInfo(port, token3, log9) {
|
|
@@ -101214,7 +101395,7 @@ function writeBridgeInfo(port, token3, log9) {
|
|
|
101214
101395
|
}
|
|
101215
101396
|
return;
|
|
101216
101397
|
}
|
|
101217
|
-
const dir2 =
|
|
101398
|
+
const dir2 = join67(containerData, "Library", "Application Support");
|
|
101218
101399
|
mkdirSync34(dir2, { recursive: true });
|
|
101219
101400
|
writeFileSync35(bridgeInfoPath(), JSON.stringify({ port, token: token3, pid: process.pid, ts: Date.now() }), { mode: 384 });
|
|
101220
101401
|
if (!infoLoggedOnce) {
|
|
@@ -101375,7 +101556,7 @@ function startAutofillBridge(log9 = () => {
|
|
|
101375
101556
|
if (process.platform !== "darwin" || wss2)
|
|
101376
101557
|
return;
|
|
101377
101558
|
stopping2 = false;
|
|
101378
|
-
token2 =
|
|
101559
|
+
token2 = randomBytes9(24).toString("base64url");
|
|
101379
101560
|
bind(0, log9);
|
|
101380
101561
|
}
|
|
101381
101562
|
function stopAutofillBridge() {
|
|
@@ -101460,7 +101641,7 @@ function createNodePowerController() {
|
|
|
101460
101641
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
101461
101642
|
import { chmodSync as chmodSync6, existsSync as existsSync33, mkdirSync as mkdirSync35, writeFileSync as writeFileSync36 } from "node:fs";
|
|
101462
101643
|
import { homedir as homedir11, platform as platform5 } from "node:os";
|
|
101463
|
-
import { dirname as dirname27, join as
|
|
101644
|
+
import { dirname as dirname27, join as join68, resolve as resolve12 } from "node:path";
|
|
101464
101645
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
101465
101646
|
var HOST_NAME = "com.tesseract.companion";
|
|
101466
101647
|
var EXTENSION_IDS = ["icpnghhpcmaonjckkpilpajblfehpplo", "giolfpookdhjfafcchaflhmigghaeffn"];
|
|
@@ -101469,18 +101650,18 @@ function browserProfileDirs() {
|
|
|
101469
101650
|
const home = homedir11();
|
|
101470
101651
|
const p = platform5();
|
|
101471
101652
|
if (p === "darwin") {
|
|
101472
|
-
const base =
|
|
101473
|
-
return ["Google/Chrome", "Google/Chrome Beta", "Google/Chrome Dev", "Google/Chrome Canary", "Chromium", "Microsoft Edge", "BraveSoftware/Brave-Browser", "Vivaldi", "Arc"].map((b) =>
|
|
101653
|
+
const base = join68(home, "Library/Application Support");
|
|
101654
|
+
return ["Google/Chrome", "Google/Chrome Beta", "Google/Chrome Dev", "Google/Chrome Canary", "Chromium", "Microsoft Edge", "BraveSoftware/Brave-Browser", "Vivaldi", "Arc"].map((b) => join68(base, b));
|
|
101474
101655
|
}
|
|
101475
101656
|
if (p === "win32")
|
|
101476
101657
|
return [];
|
|
101477
|
-
const cfg2 =
|
|
101478
|
-
return ["google-chrome", "google-chrome-beta", "chromium", "microsoft-edge", "BraveSoftware/Brave-Browser", "vivaldi"].map((b) =>
|
|
101658
|
+
const cfg2 = join68(home, ".config");
|
|
101659
|
+
return ["google-chrome", "google-chrome-beta", "chromium", "microsoft-edge", "BraveSoftware/Brave-Browser", "vivaldi"].map((b) => join68(cfg2, b));
|
|
101479
101660
|
}
|
|
101480
101661
|
function resolveBridge(log9) {
|
|
101481
101662
|
const candidates = [
|
|
101482
101663
|
process.env.CCB_COMPANION_HOST_JS,
|
|
101483
|
-
process.resourcesPath ?
|
|
101664
|
+
process.resourcesPath ? join68(process.resourcesPath, "companion-host", BRIDGE_BASENAME) : void 0
|
|
101484
101665
|
];
|
|
101485
101666
|
try {
|
|
101486
101667
|
const here = dirname27(fileURLToPath5(import.meta.url));
|
|
@@ -101496,7 +101677,7 @@ function resolveBridge(log9) {
|
|
|
101496
101677
|
}
|
|
101497
101678
|
function writeLauncher(daemonDir3, bridge, runtime) {
|
|
101498
101679
|
const isWin = platform5() === "win32";
|
|
101499
|
-
const launcher =
|
|
101680
|
+
const launcher = join68(daemonDir3, isWin ? "companion-host.cmd" : "companion-host.sh");
|
|
101500
101681
|
if (isWin) {
|
|
101501
101682
|
writeFileSync36(launcher, `@echo off\r
|
|
101502
101683
|
set ELECTRON_RUN_AS_NODE=1\r
|
|
@@ -101534,9 +101715,9 @@ function registerNativeHost(opts) {
|
|
|
101534
101715
|
if (!existsSync33(profile))
|
|
101535
101716
|
continue;
|
|
101536
101717
|
try {
|
|
101537
|
-
const dir2 =
|
|
101718
|
+
const dir2 = join68(profile, "NativeMessagingHosts");
|
|
101538
101719
|
mkdirSync35(dir2, { recursive: true });
|
|
101539
|
-
writeFileSync36(
|
|
101720
|
+
writeFileSync36(join68(dir2, `${HOST_NAME}.json`), manifestJson);
|
|
101540
101721
|
wrote++;
|
|
101541
101722
|
} catch {
|
|
101542
101723
|
}
|
|
@@ -101548,7 +101729,7 @@ function registerNativeHost(opts) {
|
|
|
101548
101729
|
}
|
|
101549
101730
|
function registerWindows(daemonDir3, manifestJson, log9) {
|
|
101550
101731
|
try {
|
|
101551
|
-
const manifestPath =
|
|
101732
|
+
const manifestPath = join68(daemonDir3, `${HOST_NAME}.json`);
|
|
101552
101733
|
writeFileSync36(manifestPath, manifestJson);
|
|
101553
101734
|
for (const root of ["Software\\Google\\Chrome", "Software\\Microsoft\\Edge", "Software\\BraveSoftware\\Brave-Browser"]) {
|
|
101554
101735
|
try {
|
|
@@ -101568,9 +101749,9 @@ init_daemon_settings();
|
|
|
101568
101749
|
// ../../packages/host-core/dist/activity/activity-tracker.js
|
|
101569
101750
|
init_credentials();
|
|
101570
101751
|
import { promises as fsp, writeFileSync as writeFileSync37, mkdirSync as mkdirSync36, existsSync as existsSync34 } from "node:fs";
|
|
101571
|
-
import { join as
|
|
101752
|
+
import { join as join69 } from "node:path";
|
|
101572
101753
|
function activityProfilePath() {
|
|
101573
|
-
return
|
|
101754
|
+
return join69(daemonDir2(), "activity-profile.json");
|
|
101574
101755
|
}
|
|
101575
101756
|
var MAX_APPS = 300;
|
|
101576
101757
|
var MAX_AGE_DAYS = 120;
|
|
@@ -101879,8 +102060,8 @@ async function runDaemon(opts = {}) {
|
|
|
101879
102060
|
log9("paths", JSON.stringify(sealBasePaths()));
|
|
101880
102061
|
const OUR_STARTED_AT = procStartedAt(process.pid);
|
|
101881
102062
|
let ownsMachine = false;
|
|
101882
|
-
const pidfile = () =>
|
|
101883
|
-
const statusFile = () =>
|
|
102063
|
+
const pidfile = () => join70(daemonDir2(), "daemon.lock");
|
|
102064
|
+
const statusFile = () => join70(daemonDir2(), "status.json");
|
|
101884
102065
|
const isAlive2 = (pid) => {
|
|
101885
102066
|
try {
|
|
101886
102067
|
process.kill(pid, 0);
|
|
@@ -102320,12 +102501,43 @@ async function runDaemon(opts = {}) {
|
|
|
102320
102501
|
} catch {
|
|
102321
102502
|
}
|
|
102322
102503
|
});
|
|
102323
|
-
|
|
102504
|
+
const renderRecoveries = [];
|
|
102505
|
+
const RECOVER_WINDOW_MS = 6e4, RECOVER_MAX = 4, RECOVER_DELAY_MS = 300;
|
|
102506
|
+
const recoverRenderer = (wc, reason) => {
|
|
102507
|
+
if (!mergedProcess || deliberateMergedQuit())
|
|
102508
|
+
return;
|
|
102509
|
+
if (reason && !["killed", "crashed", "abnormal-exit", "oom", "launch-failed", "integrity-failure"].includes(reason))
|
|
102510
|
+
return;
|
|
102511
|
+
const now2 = Date.now();
|
|
102512
|
+
while (renderRecoveries.length && now2 - renderRecoveries[0] > RECOVER_WINDOW_MS)
|
|
102513
|
+
renderRecoveries.shift();
|
|
102514
|
+
if (renderRecoveries.length >= RECOVER_MAX) {
|
|
102515
|
+
try {
|
|
102516
|
+
log9(`render-recover: ${RECOVER_MAX} reloads in <60s \u2014 backing off (page may be genuinely crashing)`);
|
|
102517
|
+
} catch {
|
|
102518
|
+
}
|
|
102519
|
+
return;
|
|
102520
|
+
}
|
|
102521
|
+
renderRecoveries.push(now2);
|
|
102522
|
+
const contents = wc;
|
|
102523
|
+
setTimeout(() => {
|
|
102524
|
+
try {
|
|
102525
|
+
if (!contents || contents.isDestroyed?.())
|
|
102526
|
+
return;
|
|
102527
|
+
log9(`render-recover: reloading window after '${reason ?? "unknown"}' (recovery #${renderRecoveries.length})`);
|
|
102528
|
+
contents.reload?.();
|
|
102529
|
+
} catch {
|
|
102530
|
+
}
|
|
102531
|
+
}, RECOVER_DELAY_MS).unref?.();
|
|
102532
|
+
};
|
|
102533
|
+
eapp.on("render-process-gone", (_e, wc, details) => {
|
|
102534
|
+
const reason = details?.reason;
|
|
102324
102535
|
try {
|
|
102325
|
-
log9(`render-process-gone (kept alive) uptime=${Date.now() - daemonStartedAt}ms: ${JSON.stringify(
|
|
102536
|
+
log9(`render-process-gone (kept alive) uptime=${Date.now() - daemonStartedAt}ms: ${JSON.stringify(details ?? {})}`);
|
|
102326
102537
|
snapshotProcs("render-gone");
|
|
102327
102538
|
} catch {
|
|
102328
102539
|
}
|
|
102540
|
+
recoverRenderer(wc, reason);
|
|
102329
102541
|
});
|
|
102330
102542
|
eapp.on("child-process-gone", (_e, d) => {
|
|
102331
102543
|
try {
|
|
@@ -102344,7 +102556,7 @@ async function runDaemon(opts = {}) {
|
|
|
102344
102556
|
}
|
|
102345
102557
|
if (ownsMachine)
|
|
102346
102558
|
setHostDaemonRole(true);
|
|
102347
|
-
const localToken =
|
|
102559
|
+
const localToken = randomBytes10(24).toString("hex");
|
|
102348
102560
|
const sendToViewer = (kind, sessionId, clientId, msg) => {
|
|
102349
102561
|
const lb = loopbackRdeskSend.get(clientId);
|
|
102350
102562
|
if (lb) {
|
|
@@ -102503,7 +102715,7 @@ async function runDaemon(opts = {}) {
|
|
|
102503
102715
|
if (r.status === 401) {
|
|
102504
102716
|
log9("device token no longer valid \u2014 dropping to local-only on restart");
|
|
102505
102717
|
try {
|
|
102506
|
-
unlinkSync6(
|
|
102718
|
+
unlinkSync6(join70(daemonDir2(), "credentials.json"));
|
|
102507
102719
|
} catch {
|
|
102508
102720
|
}
|
|
102509
102721
|
shutdown(0, "token-revoked-401");
|
|
@@ -102901,14 +103113,14 @@ async function runDaemon(opts = {}) {
|
|
|
102901
103113
|
// is on; with it off it is the standalone Remote Desktop app, and we forward rather than
|
|
102902
103114
|
// handle. `provider()` re-reads the setting every time, so switching it back on takes the
|
|
102903
103115
|
// channel away from the claimant mid-flight — there is never a moment with two servers.
|
|
102904
|
-
onRdesk: (payload, clientId, sessionId) => {
|
|
103116
|
+
onRdesk: (payload, clientId, sessionId, viewerOwner) => {
|
|
102905
103117
|
const p = rdeskChannel.provider();
|
|
102906
103118
|
if (p && clientId) {
|
|
102907
103119
|
p.control(sessionId, clientId, payload);
|
|
102908
103120
|
return;
|
|
102909
103121
|
}
|
|
102910
103122
|
if (rdesk && clientId)
|
|
102911
|
-
void rdesk.onClientMessage(sessionId, { clientId }, payload);
|
|
103123
|
+
void rdesk.onClientMessage(sessionId, { clientId, sameAccount: viewerOwner }, payload);
|
|
102912
103124
|
},
|
|
102913
103125
|
onRdeskSignal: (payload, clientId, sessionId) => {
|
|
102914
103126
|
const p = rdeskChannel.provider();
|
|
@@ -103001,7 +103213,7 @@ async function runDaemon(opts = {}) {
|
|
|
103001
103213
|
if (appPid > 0 && appPid !== process.pid) {
|
|
103002
103214
|
const quitMarker = () => {
|
|
103003
103215
|
try {
|
|
103004
|
-
return Number(readFileSync45(
|
|
103216
|
+
return Number(readFileSync45(join70(daemonDir2(), "app-quit.marker"), "utf-8").trim()) || 0;
|
|
103005
103217
|
} catch {
|
|
103006
103218
|
return 0;
|
|
103007
103219
|
}
|
|
@@ -103026,7 +103238,7 @@ async function runDaemon(opts = {}) {
|
|
|
103026
103238
|
log9(`desktop app (pid ${appPid}) is gone with NO clean-quit marker \u2014 reporting`);
|
|
103027
103239
|
const tail3 = (name) => {
|
|
103028
103240
|
try {
|
|
103029
|
-
const buf = readFileSync45(
|
|
103241
|
+
const buf = readFileSync45(join70(daemonDir2(), name), "utf-8");
|
|
103030
103242
|
return buf.length > 4096 ? buf.slice(-4096) : buf;
|
|
103031
103243
|
} catch {
|
|
103032
103244
|
return void 0;
|
|
@@ -103057,7 +103269,7 @@ async function runDaemon(opts = {}) {
|
|
|
103057
103269
|
}
|
|
103058
103270
|
try {
|
|
103059
103271
|
const DAEMON_LOG_CAP = 2 * 1024 * 1024;
|
|
103060
|
-
const daemonLogFile =
|
|
103272
|
+
const daemonLogFile = join70(daemonDir2(), "daemon.log");
|
|
103061
103273
|
const capTimer = setInterval(() => {
|
|
103062
103274
|
try {
|
|
103063
103275
|
if (existsSync35(daemonLogFile) && statSync9(daemonLogFile).size > DAEMON_LOG_CAP) {
|