@buzzni/saycode-cli 0.7.0 → 0.7.1
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/index.mjs +688 -519
- package/official-extensions/buzzni.discord-1.1.0.saycode-extension.base64 +1 -0
- package/official-extensions/buzzni.slack-1.1.0.saycode-extension.base64 +1 -0
- package/official-extensions/buzzni.telegram-1.1.0.saycode-extension.base64 +1 -0
- package/official-extensions/catalog.v1.json +26 -0
- package/package.json +2 -1
package/index.mjs
CHANGED
|
@@ -45,7 +45,7 @@ function _mergeNamespaces(n, m) {
|
|
|
45
45
|
}
|
|
46
46
|
return Object.freeze(Object.defineProperty(n, Symbol.toStringTag, { value: "Module" }));
|
|
47
47
|
}
|
|
48
|
-
const version$2 = "0.7.
|
|
48
|
+
const version$2 = "0.7.1";
|
|
49
49
|
const manifest = {
|
|
50
50
|
version: version$2
|
|
51
51
|
};
|
|
@@ -12696,7 +12696,7 @@ function normalizeConnectors(raw) {
|
|
|
12696
12696
|
}
|
|
12697
12697
|
return out;
|
|
12698
12698
|
}
|
|
12699
|
-
const PROVIDERS
|
|
12699
|
+
const PROVIDERS = ["claude", "codex"];
|
|
12700
12700
|
const ROTATION_STATES = [
|
|
12701
12701
|
"stopped",
|
|
12702
12702
|
"starting",
|
|
@@ -12734,7 +12734,7 @@ function nullableNum(value2) {
|
|
|
12734
12734
|
return typeof value2 === "number" && Number.isFinite(value2) ? value2 : null;
|
|
12735
12735
|
}
|
|
12736
12736
|
function provider(value2) {
|
|
12737
|
-
return PROVIDERS
|
|
12737
|
+
return PROVIDERS.includes(str$1(value2)) ? str$1(value2) : null;
|
|
12738
12738
|
}
|
|
12739
12739
|
function parseBundle(value2) {
|
|
12740
12740
|
const row2 = record$8(value2);
|
|
@@ -22621,9 +22621,9 @@ function resolvedProjectPreviewRelayUrl(input) {
|
|
|
22621
22621
|
}
|
|
22622
22622
|
return `${input.syncBaseUrl}/v1/preview/${encodeURIComponent(input.machineId)}/${input.port}/?ptoken=${encodeURIComponent(response.token)}`;
|
|
22623
22623
|
}
|
|
22624
|
-
const BASE64_PATTERN$
|
|
22624
|
+
const BASE64_PATTERN$3 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
22625
22625
|
function versionedAutomationBase64(value2, maxBytes, exactBytes) {
|
|
22626
|
-
if (typeof value2 !== "string" || !value2 || value2.length > Math.ceil(maxBytes / 3) * 4 || !BASE64_PATTERN$
|
|
22626
|
+
if (typeof value2 !== "string" || !value2 || value2.length > Math.ceil(maxBytes / 3) * 4 || !BASE64_PATTERN$3.test(value2)) {
|
|
22627
22627
|
throw new Error("automation-response-invalid");
|
|
22628
22628
|
}
|
|
22629
22629
|
const decoded = Buffer$1.from(value2, "base64");
|
|
@@ -32951,9 +32951,9 @@ function channelText(text2) {
|
|
|
32951
32951
|
}
|
|
32952
32952
|
const ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
|
32953
32953
|
const RAW_ED25519_PUBLIC_KEY_BYTES = 32;
|
|
32954
|
-
const BASE64_PATTERN$
|
|
32954
|
+
const BASE64_PATTERN$2 = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
32955
32955
|
function createExtensionCatalogVerifier(publicKeyBase64) {
|
|
32956
|
-
if (!publicKeyBase64 || !BASE64_PATTERN$
|
|
32956
|
+
if (!publicKeyBase64 || !BASE64_PATTERN$2.test(publicKeyBase64) || publicKeyBase64.length % 4 !== 0) {
|
|
32957
32957
|
throw new Error("extension catalog public key must be base64");
|
|
32958
32958
|
}
|
|
32959
32959
|
const raw = Buffer.from(publicKeyBase64, "base64");
|
|
@@ -32976,14 +32976,14 @@ function createExtensionCatalogVerifier(publicKeyBase64) {
|
|
|
32976
32976
|
const MAX_EXTENSION_CATALOG_PAYLOAD_BYTES = 256 * 1024;
|
|
32977
32977
|
const EXTENSION_CATALOG_SCHEMA_VERSION = 2;
|
|
32978
32978
|
const RELEASE_URL_PREFIX = "https://github.com/buzzni/saycode-extensions/releases/";
|
|
32979
|
-
const ID_PATTERN$
|
|
32980
|
-
const SEMVER_PATTERN$
|
|
32981
|
-
const SHA256_PATTERN = /^[a-f0-9]{64}$/;
|
|
32982
|
-
const BASE64_PATTERN = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
32979
|
+
const ID_PATTERN$4 = /^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/;
|
|
32980
|
+
const SEMVER_PATTERN$2 = /^\d+\.\d+\.\d+$/;
|
|
32981
|
+
const SHA256_PATTERN$1 = /^[a-f0-9]{64}$/;
|
|
32982
|
+
const BASE64_PATTERN$1 = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
32983
32983
|
const ISO_INSTANT_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/;
|
|
32984
32984
|
const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
32985
32985
|
function decodeBase64(value2, path) {
|
|
32986
|
-
if (!BASE64_PATTERN.test(value2) || value2.length % 4 !== 0) fail$7(path, "expected base64");
|
|
32986
|
+
if (!BASE64_PATTERN$1.test(value2) || value2.length % 4 !== 0) fail$7(path, "expected base64");
|
|
32987
32987
|
const padding = value2.endsWith("==") ? 2 : value2.endsWith("=") ? 1 : 0;
|
|
32988
32988
|
const bytes = new Uint8Array(value2.length / 4 * 3 - padding);
|
|
32989
32989
|
let offset = 0;
|
|
@@ -33022,16 +33022,16 @@ function releaseUrl(value2, path) {
|
|
|
33022
33022
|
}
|
|
33023
33023
|
return parsed2;
|
|
33024
33024
|
}
|
|
33025
|
-
function descriptor(value2, path) {
|
|
33025
|
+
function descriptor$1(value2, path) {
|
|
33026
33026
|
const record2 = objectWithExactKeys(value2, ["id", "version", "releaseUrl", "archiveUrl", "sha256"], path);
|
|
33027
|
-
const id2 = text$3(record2.id, `${path}.id`, ID_PATTERN$
|
|
33027
|
+
const id2 = text$3(record2.id, `${path}.id`, ID_PATTERN$4);
|
|
33028
33028
|
if (id2.includes("..")) fail$7(`${path}.id`, "malformed value");
|
|
33029
33029
|
return {
|
|
33030
33030
|
id: id2,
|
|
33031
|
-
version: text$3(record2.version, `${path}.version`, SEMVER_PATTERN$
|
|
33031
|
+
version: text$3(record2.version, `${path}.version`, SEMVER_PATTERN$2),
|
|
33032
33032
|
releaseUrl: releaseUrl(record2.releaseUrl, `${path}.releaseUrl`),
|
|
33033
33033
|
archiveUrl: releaseUrl(record2.archiveUrl, `${path}.archiveUrl`),
|
|
33034
|
-
sha256: text$3(record2.sha256, `${path}.sha256`, SHA256_PATTERN)
|
|
33034
|
+
sha256: text$3(record2.sha256, `${path}.sha256`, SHA256_PATTERN$1)
|
|
33035
33035
|
};
|
|
33036
33036
|
}
|
|
33037
33037
|
function revocation(value2, path) {
|
|
@@ -33039,13 +33039,13 @@ function revocation(value2, path) {
|
|
|
33039
33039
|
const record2 = value2;
|
|
33040
33040
|
const keys2 = Object.keys(record2).sort().join(",");
|
|
33041
33041
|
if (keys2 !== "id,version" && keys2 !== "id,reason,version") fail$7(path, "unexpected fields");
|
|
33042
|
-
const id2 = text$3(record2.id, `${path}.id`, ID_PATTERN$
|
|
33042
|
+
const id2 = text$3(record2.id, `${path}.id`, ID_PATTERN$4);
|
|
33043
33043
|
if (id2.includes("..")) fail$7(`${path}.id`, "malformed value");
|
|
33044
33044
|
return {
|
|
33045
33045
|
id: id2,
|
|
33046
33046
|
// Exact versions only: ADR-048 has no wildcard, so a mistaken entry costs one version,
|
|
33047
33047
|
// not an entire extension.
|
|
33048
|
-
version: text$3(record2.version, `${path}.version`, SEMVER_PATTERN$
|
|
33048
|
+
version: text$3(record2.version, `${path}.version`, SEMVER_PATTERN$2),
|
|
33049
33049
|
...record2.reason === void 0 ? {} : { reason: text$3(record2.reason, `${path}.reason`, /^.{1,200}$/s) }
|
|
33050
33050
|
};
|
|
33051
33051
|
}
|
|
@@ -33061,7 +33061,7 @@ function parsePayload(value2) {
|
|
|
33061
33061
|
if (record2.schemaVersion !== EXTENSION_CATALOG_SCHEMA_VERSION) {
|
|
33062
33062
|
fail$7("catalog.schemaVersion", `unsupported catalog schema ${String(record2.schemaVersion)}`);
|
|
33063
33063
|
}
|
|
33064
|
-
const extensions = array$2(record2.extensions, "catalog.extensions").map((entry, index) => descriptor(entry, `catalog.extensions[${index}]`));
|
|
33064
|
+
const extensions = array$2(record2.extensions, "catalog.extensions").map((entry, index) => descriptor$1(entry, `catalog.extensions[${index}]`));
|
|
33065
33065
|
if (new Set(extensions.map((entry) => entry.id)).size !== extensions.length) {
|
|
33066
33066
|
fail$7("catalog.extensions", "duplicate extension id");
|
|
33067
33067
|
}
|
|
@@ -33707,9 +33707,9 @@ async function reconcileOne(spec, deps) {
|
|
|
33707
33707
|
if (deps.isRevoked(spec.extensionId, spec.version)) return "revoked";
|
|
33708
33708
|
let current = deps.registry.get(spec.extensionId);
|
|
33709
33709
|
if (current?.installedVersion !== spec.version) {
|
|
33710
|
-
|
|
33711
|
-
|
|
33712
|
-
|
|
33710
|
+
if (await deps.official.versionOf(spec.extensionId) !== spec.version) return "unavailable";
|
|
33711
|
+
const installed = await deps.store.install(await deps.official.archive(spec.extensionId));
|
|
33712
|
+
if (installed.id !== spec.extensionId || installed.version !== spec.version) return "failed";
|
|
33713
33713
|
current = await deps.registry.apply(spec.extensionId, current ? { type: "update-installed", version: spec.version } : { type: "installed", version: spec.version });
|
|
33714
33714
|
}
|
|
33715
33715
|
if (!current) return "failed";
|
|
@@ -33740,474 +33740,9 @@ async function reconcileHostExtensions(desired, deps) {
|
|
|
33740
33740
|
}
|
|
33741
33741
|
return result;
|
|
33742
33742
|
}
|
|
33743
|
-
function describe(secretKey) {
|
|
33744
|
-
const { publicKey } = nacl.box.keyPair.fromSecretKey(secretKey);
|
|
33745
|
-
const digest = createHash("sha256").update(publicKey).digest("hex").slice(0, 16).toUpperCase();
|
|
33746
|
-
return {
|
|
33747
|
-
publicKey,
|
|
33748
|
-
secretKey,
|
|
33749
|
-
publicKeyBase64: Buffer.from(publicKey).toString("base64"),
|
|
33750
|
-
fingerprint: digest.match(/.{4}/g).join("-")
|
|
33751
|
-
};
|
|
33752
|
-
}
|
|
33753
|
-
async function openChannelHostKey(input) {
|
|
33754
|
-
if (!input.safeStorage.isEncryptionAvailable()) return null;
|
|
33755
|
-
const path = join(input.dir, "host-key.v1.json");
|
|
33756
|
-
let text2 = null;
|
|
33757
|
-
try {
|
|
33758
|
-
text2 = await readFile(path, "utf8");
|
|
33759
|
-
} catch (error) {
|
|
33760
|
-
if (error.code !== "ENOENT") throw error;
|
|
33761
|
-
}
|
|
33762
|
-
if (text2 !== null) {
|
|
33763
|
-
const parsed2 = JSON.parse(text2);
|
|
33764
|
-
if (parsed2.v !== 1 || typeof parsed2.sealed !== "string") throw new Error("channel host key file is unreadable");
|
|
33765
|
-
const secret = Buffer.from(input.safeStorage.decryptString(Buffer.from(parsed2.sealed, "base64")), "base64");
|
|
33766
|
-
if (secret.length !== nacl.box.secretKeyLength) throw new Error("channel host key file is unreadable");
|
|
33767
|
-
return describe(new Uint8Array(secret));
|
|
33768
|
-
}
|
|
33769
|
-
const { secretKey } = nacl.box.keyPair();
|
|
33770
|
-
await mkdir(input.dir, { recursive: true, mode: 448 });
|
|
33771
|
-
const sealed2 = input.safeStorage.encryptString(Buffer.from(secretKey).toString("base64")).toString("base64");
|
|
33772
|
-
const staging = `${path}.${process.pid}.tmp`;
|
|
33773
|
-
await writeFile(staging, JSON.stringify({ v: 1, sealed: sealed2 }), { mode: 384 });
|
|
33774
|
-
await rename(staging, path);
|
|
33775
|
-
return describe(secretKey);
|
|
33776
|
-
}
|
|
33777
|
-
function defaultIsAlive(pid) {
|
|
33778
|
-
try {
|
|
33779
|
-
process.kill(pid, 0);
|
|
33780
|
-
return true;
|
|
33781
|
-
} catch (error) {
|
|
33782
|
-
return error.code === "EPERM";
|
|
33783
|
-
}
|
|
33784
|
-
}
|
|
33785
|
-
async function acquireChannelHostLock(input) {
|
|
33786
|
-
const path = join(input.dir, "host.lock");
|
|
33787
|
-
const isAlive = input.isAlive ?? defaultIsAlive;
|
|
33788
|
-
for (let attempt2 = 0; attempt2 < 2; attempt2 += 1) {
|
|
33789
|
-
try {
|
|
33790
|
-
const handle = await open(path, "wx", 384);
|
|
33791
|
-
await handle.writeFile(JSON.stringify({ pid: process.pid, startedAt: Date.now() }));
|
|
33792
|
-
await handle.close();
|
|
33793
|
-
return {
|
|
33794
|
-
kind: "held",
|
|
33795
|
-
release: async () => {
|
|
33796
|
-
const current = await readFile(path, "utf8").then((text2) => JSON.parse(text2), () => null);
|
|
33797
|
-
if (current?.pid === process.pid) await rm(path, { force: true });
|
|
33798
|
-
}
|
|
33799
|
-
};
|
|
33800
|
-
} catch (error) {
|
|
33801
|
-
if (error.code !== "EEXIST") throw error;
|
|
33802
|
-
}
|
|
33803
|
-
let holder = null;
|
|
33804
|
-
try {
|
|
33805
|
-
const parsed2 = JSON.parse(await readFile(path, "utf8"));
|
|
33806
|
-
holder = typeof parsed2.pid === "number" && Number.isSafeInteger(parsed2.pid) ? parsed2.pid : null;
|
|
33807
|
-
} catch {
|
|
33808
|
-
holder = null;
|
|
33809
|
-
}
|
|
33810
|
-
if (holder === null || isAlive(holder)) return { kind: "refused" };
|
|
33811
|
-
await rm(path, { force: true });
|
|
33812
|
-
}
|
|
33813
|
-
return { kind: "refused" };
|
|
33814
|
-
}
|
|
33815
|
-
function isBytes(a) {
|
|
33816
|
-
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1;
|
|
33817
|
-
}
|
|
33818
|
-
function abytes(value2, length, title2 = "") {
|
|
33819
|
-
const bytes = isBytes(value2);
|
|
33820
|
-
const len = value2?.length;
|
|
33821
|
-
const needsLen = length !== void 0;
|
|
33822
|
-
if (!bytes || needsLen) {
|
|
33823
|
-
const prefix = title2 && `"${title2}" `;
|
|
33824
|
-
const ofLen = "";
|
|
33825
|
-
const got = bytes ? `length=${len}` : `type=${typeof value2}`;
|
|
33826
|
-
const message = prefix + "expected Uint8Array" + ofLen + ", got " + got;
|
|
33827
|
-
if (!bytes)
|
|
33828
|
-
throw new TypeError(message);
|
|
33829
|
-
throw new RangeError(message);
|
|
33830
|
-
}
|
|
33831
|
-
return value2;
|
|
33832
|
-
}
|
|
33833
|
-
function aexists(instance, checkFinished = true) {
|
|
33834
|
-
if (instance.destroyed)
|
|
33835
|
-
throw new Error("Hash instance has been destroyed");
|
|
33836
|
-
if (checkFinished && instance.finished)
|
|
33837
|
-
throw new Error("Hash#digest() has already been called");
|
|
33838
|
-
}
|
|
33839
|
-
function aoutput(out, instance) {
|
|
33840
|
-
abytes(out, void 0, "digestInto() output");
|
|
33841
|
-
const min = instance.outputLen;
|
|
33842
|
-
if (out.length < min) {
|
|
33843
|
-
throw new RangeError('"digestInto() output" expected to be of length >=' + min);
|
|
33844
|
-
}
|
|
33845
|
-
}
|
|
33846
|
-
function clean(...arrays) {
|
|
33847
|
-
for (let i = 0; i < arrays.length; i++) {
|
|
33848
|
-
arrays[i].fill(0);
|
|
33849
|
-
}
|
|
33850
|
-
}
|
|
33851
|
-
function createView(arr) {
|
|
33852
|
-
return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
33853
|
-
}
|
|
33854
|
-
function rotr(word, shift) {
|
|
33855
|
-
return word << 32 - shift | word >>> shift;
|
|
33856
|
-
}
|
|
33857
|
-
const hasHexBuiltin = /* @__PURE__ */ (() => (
|
|
33858
|
-
// @ts-ignore
|
|
33859
|
-
typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function"
|
|
33860
|
-
))();
|
|
33861
|
-
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
|
|
33862
|
-
function bytesToHex(bytes) {
|
|
33863
|
-
abytes(bytes);
|
|
33864
|
-
if (hasHexBuiltin)
|
|
33865
|
-
return bytes.toHex();
|
|
33866
|
-
let hex = "";
|
|
33867
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
33868
|
-
hex += hexes[bytes[i]];
|
|
33869
|
-
}
|
|
33870
|
-
return hex;
|
|
33871
|
-
}
|
|
33872
|
-
function createHasher(hashCons, info = {}) {
|
|
33873
|
-
const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
|
|
33874
|
-
const tmp = hashCons(void 0);
|
|
33875
|
-
hashC.outputLen = tmp.outputLen;
|
|
33876
|
-
hashC.blockLen = tmp.blockLen;
|
|
33877
|
-
hashC.canXOF = tmp.canXOF;
|
|
33878
|
-
hashC.create = (opts) => hashCons(opts);
|
|
33879
|
-
Object.assign(hashC, info);
|
|
33880
|
-
return Object.freeze(hashC);
|
|
33881
|
-
}
|
|
33882
|
-
const oidNist = (suffix) => ({
|
|
33883
|
-
// Current NIST hashAlgs suffixes used here fit in one DER subidentifier octet.
|
|
33884
|
-
// Larger suffix values would need base-128 OID encoding and a different length byte.
|
|
33885
|
-
oid: Uint8Array.from([6, 9, 96, 134, 72, 1, 101, 3, 4, 2, suffix])
|
|
33886
|
-
});
|
|
33887
|
-
function Chi(a, b, c) {
|
|
33888
|
-
return a & b ^ ~a & c;
|
|
33889
|
-
}
|
|
33890
|
-
function Maj(a, b, c) {
|
|
33891
|
-
return a & b ^ a & c ^ b & c;
|
|
33892
|
-
}
|
|
33893
|
-
class HashMD {
|
|
33894
|
-
blockLen;
|
|
33895
|
-
outputLen;
|
|
33896
|
-
canXOF = false;
|
|
33897
|
-
padOffset;
|
|
33898
|
-
isLE;
|
|
33899
|
-
// For partial updates less than block size
|
|
33900
|
-
buffer;
|
|
33901
|
-
view;
|
|
33902
|
-
finished = false;
|
|
33903
|
-
length = 0;
|
|
33904
|
-
pos = 0;
|
|
33905
|
-
destroyed = false;
|
|
33906
|
-
constructor(blockLen, outputLen, padOffset, isLE) {
|
|
33907
|
-
this.blockLen = blockLen;
|
|
33908
|
-
this.outputLen = outputLen;
|
|
33909
|
-
this.padOffset = padOffset;
|
|
33910
|
-
this.isLE = isLE;
|
|
33911
|
-
this.buffer = new Uint8Array(blockLen);
|
|
33912
|
-
this.view = createView(this.buffer);
|
|
33913
|
-
}
|
|
33914
|
-
update(data) {
|
|
33915
|
-
aexists(this);
|
|
33916
|
-
abytes(data);
|
|
33917
|
-
const { view, buffer, blockLen } = this;
|
|
33918
|
-
const len = data.length;
|
|
33919
|
-
for (let pos = 0; pos < len; ) {
|
|
33920
|
-
const take = Math.min(blockLen - this.pos, len - pos);
|
|
33921
|
-
if (take === blockLen) {
|
|
33922
|
-
const dataView = createView(data);
|
|
33923
|
-
for (; blockLen <= len - pos; pos += blockLen)
|
|
33924
|
-
this.process(dataView, pos);
|
|
33925
|
-
continue;
|
|
33926
|
-
}
|
|
33927
|
-
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
33928
|
-
this.pos += take;
|
|
33929
|
-
pos += take;
|
|
33930
|
-
if (this.pos === blockLen) {
|
|
33931
|
-
this.process(view, 0);
|
|
33932
|
-
this.pos = 0;
|
|
33933
|
-
}
|
|
33934
|
-
}
|
|
33935
|
-
this.length += data.length;
|
|
33936
|
-
this.roundClean();
|
|
33937
|
-
return this;
|
|
33938
|
-
}
|
|
33939
|
-
digestInto(out) {
|
|
33940
|
-
aexists(this);
|
|
33941
|
-
aoutput(out, this);
|
|
33942
|
-
this.finished = true;
|
|
33943
|
-
const { buffer, view, blockLen, isLE } = this;
|
|
33944
|
-
let { pos } = this;
|
|
33945
|
-
buffer[pos++] = 128;
|
|
33946
|
-
clean(this.buffer.subarray(pos));
|
|
33947
|
-
if (this.padOffset > blockLen - pos) {
|
|
33948
|
-
this.process(view, 0);
|
|
33949
|
-
pos = 0;
|
|
33950
|
-
}
|
|
33951
|
-
for (let i = pos; i < blockLen; i++)
|
|
33952
|
-
buffer[i] = 0;
|
|
33953
|
-
view.setBigUint64(blockLen - 8, BigInt(this.length * 8), isLE);
|
|
33954
|
-
this.process(view, 0);
|
|
33955
|
-
const oview = createView(out);
|
|
33956
|
-
const len = this.outputLen;
|
|
33957
|
-
if (len % 4)
|
|
33958
|
-
throw new Error("_sha2: outputLen must be aligned to 32bit");
|
|
33959
|
-
const outLen = len / 4;
|
|
33960
|
-
const state = this.get();
|
|
33961
|
-
if (outLen > state.length)
|
|
33962
|
-
throw new Error("_sha2: outputLen bigger than state");
|
|
33963
|
-
for (let i = 0; i < outLen; i++)
|
|
33964
|
-
oview.setUint32(4 * i, state[i], isLE);
|
|
33965
|
-
}
|
|
33966
|
-
digest() {
|
|
33967
|
-
const { buffer, outputLen } = this;
|
|
33968
|
-
this.digestInto(buffer);
|
|
33969
|
-
const res = buffer.slice(0, outputLen);
|
|
33970
|
-
this.destroy();
|
|
33971
|
-
return res;
|
|
33972
|
-
}
|
|
33973
|
-
_cloneInto(to) {
|
|
33974
|
-
to ||= new this.constructor();
|
|
33975
|
-
to.set(...this.get());
|
|
33976
|
-
const { blockLen, buffer, length, finished, destroyed, pos } = this;
|
|
33977
|
-
to.destroyed = destroyed;
|
|
33978
|
-
to.finished = finished;
|
|
33979
|
-
to.length = length;
|
|
33980
|
-
to.pos = pos;
|
|
33981
|
-
if (length % blockLen)
|
|
33982
|
-
to.buffer.set(buffer);
|
|
33983
|
-
return to;
|
|
33984
|
-
}
|
|
33985
|
-
clone() {
|
|
33986
|
-
return this._cloneInto();
|
|
33987
|
-
}
|
|
33988
|
-
}
|
|
33989
|
-
const SHA256_IV = /* @__PURE__ */ Uint32Array.from([
|
|
33990
|
-
1779033703,
|
|
33991
|
-
3144134277,
|
|
33992
|
-
1013904242,
|
|
33993
|
-
2773480762,
|
|
33994
|
-
1359893119,
|
|
33995
|
-
2600822924,
|
|
33996
|
-
528734635,
|
|
33997
|
-
1541459225
|
|
33998
|
-
]);
|
|
33999
|
-
const SHA256_K = /* @__PURE__ */ Uint32Array.from([
|
|
34000
|
-
1116352408,
|
|
34001
|
-
1899447441,
|
|
34002
|
-
3049323471,
|
|
34003
|
-
3921009573,
|
|
34004
|
-
961987163,
|
|
34005
|
-
1508970993,
|
|
34006
|
-
2453635748,
|
|
34007
|
-
2870763221,
|
|
34008
|
-
3624381080,
|
|
34009
|
-
310598401,
|
|
34010
|
-
607225278,
|
|
34011
|
-
1426881987,
|
|
34012
|
-
1925078388,
|
|
34013
|
-
2162078206,
|
|
34014
|
-
2614888103,
|
|
34015
|
-
3248222580,
|
|
34016
|
-
3835390401,
|
|
34017
|
-
4022224774,
|
|
34018
|
-
264347078,
|
|
34019
|
-
604807628,
|
|
34020
|
-
770255983,
|
|
34021
|
-
1249150122,
|
|
34022
|
-
1555081692,
|
|
34023
|
-
1996064986,
|
|
34024
|
-
2554220882,
|
|
34025
|
-
2821834349,
|
|
34026
|
-
2952996808,
|
|
34027
|
-
3210313671,
|
|
34028
|
-
3336571891,
|
|
34029
|
-
3584528711,
|
|
34030
|
-
113926993,
|
|
34031
|
-
338241895,
|
|
34032
|
-
666307205,
|
|
34033
|
-
773529912,
|
|
34034
|
-
1294757372,
|
|
34035
|
-
1396182291,
|
|
34036
|
-
1695183700,
|
|
34037
|
-
1986661051,
|
|
34038
|
-
2177026350,
|
|
34039
|
-
2456956037,
|
|
34040
|
-
2730485921,
|
|
34041
|
-
2820302411,
|
|
34042
|
-
3259730800,
|
|
34043
|
-
3345764771,
|
|
34044
|
-
3516065817,
|
|
34045
|
-
3600352804,
|
|
34046
|
-
4094571909,
|
|
34047
|
-
275423344,
|
|
34048
|
-
430227734,
|
|
34049
|
-
506948616,
|
|
34050
|
-
659060556,
|
|
34051
|
-
883997877,
|
|
34052
|
-
958139571,
|
|
34053
|
-
1322822218,
|
|
34054
|
-
1537002063,
|
|
34055
|
-
1747873779,
|
|
34056
|
-
1955562222,
|
|
34057
|
-
2024104815,
|
|
34058
|
-
2227730452,
|
|
34059
|
-
2361852424,
|
|
34060
|
-
2428436474,
|
|
34061
|
-
2756734187,
|
|
34062
|
-
3204031479,
|
|
34063
|
-
3329325298
|
|
34064
|
-
]);
|
|
34065
|
-
const SHA256_W = /* @__PURE__ */ new Uint32Array(64);
|
|
34066
|
-
class SHA2_32B extends HashMD {
|
|
34067
|
-
constructor(outputLen) {
|
|
34068
|
-
super(64, outputLen, 8, false);
|
|
34069
|
-
}
|
|
34070
|
-
get() {
|
|
34071
|
-
const { A, B, C, D, E, F, G, H } = this;
|
|
34072
|
-
return [A, B, C, D, E, F, G, H];
|
|
34073
|
-
}
|
|
34074
|
-
// prettier-ignore
|
|
34075
|
-
set(A, B, C, D, E, F, G, H) {
|
|
34076
|
-
this.A = A | 0;
|
|
34077
|
-
this.B = B | 0;
|
|
34078
|
-
this.C = C | 0;
|
|
34079
|
-
this.D = D | 0;
|
|
34080
|
-
this.E = E | 0;
|
|
34081
|
-
this.F = F | 0;
|
|
34082
|
-
this.G = G | 0;
|
|
34083
|
-
this.H = H | 0;
|
|
34084
|
-
}
|
|
34085
|
-
process(view, offset) {
|
|
34086
|
-
for (let i = 0; i < 16; i++, offset += 4)
|
|
34087
|
-
SHA256_W[i] = view.getUint32(offset, false);
|
|
34088
|
-
for (let i = 16; i < 64; i++) {
|
|
34089
|
-
const W15 = SHA256_W[i - 15];
|
|
34090
|
-
const W2 = SHA256_W[i - 2];
|
|
34091
|
-
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
|
|
34092
|
-
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
|
|
34093
|
-
SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
|
|
34094
|
-
}
|
|
34095
|
-
let { A, B, C, D, E, F, G, H } = this;
|
|
34096
|
-
for (let i = 0; i < 64; i++) {
|
|
34097
|
-
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
|
|
34098
|
-
const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i] | 0;
|
|
34099
|
-
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
|
|
34100
|
-
const T2 = sigma0 + Maj(A, B, C) | 0;
|
|
34101
|
-
H = G;
|
|
34102
|
-
G = F;
|
|
34103
|
-
F = E;
|
|
34104
|
-
E = D + T1 | 0;
|
|
34105
|
-
D = C;
|
|
34106
|
-
C = B;
|
|
34107
|
-
B = A;
|
|
34108
|
-
A = T1 + T2 | 0;
|
|
34109
|
-
}
|
|
34110
|
-
A = A + this.A | 0;
|
|
34111
|
-
B = B + this.B | 0;
|
|
34112
|
-
C = C + this.C | 0;
|
|
34113
|
-
D = D + this.D | 0;
|
|
34114
|
-
E = E + this.E | 0;
|
|
34115
|
-
F = F + this.F | 0;
|
|
34116
|
-
G = G + this.G | 0;
|
|
34117
|
-
H = H + this.H | 0;
|
|
34118
|
-
this.set(A, B, C, D, E, F, G, H);
|
|
34119
|
-
}
|
|
34120
|
-
roundClean() {
|
|
34121
|
-
clean(SHA256_W);
|
|
34122
|
-
}
|
|
34123
|
-
destroy() {
|
|
34124
|
-
this.destroyed = true;
|
|
34125
|
-
this.set(0, 0, 0, 0, 0, 0, 0, 0);
|
|
34126
|
-
clean(this.buffer);
|
|
34127
|
-
}
|
|
34128
|
-
}
|
|
34129
|
-
class _SHA256 extends SHA2_32B {
|
|
34130
|
-
// We cannot use array here since array allows indexing by variable
|
|
34131
|
-
// which means optimizer/compiler cannot use registers.
|
|
34132
|
-
A = SHA256_IV[0] | 0;
|
|
34133
|
-
B = SHA256_IV[1] | 0;
|
|
34134
|
-
C = SHA256_IV[2] | 0;
|
|
34135
|
-
D = SHA256_IV[3] | 0;
|
|
34136
|
-
E = SHA256_IV[4] | 0;
|
|
34137
|
-
F = SHA256_IV[5] | 0;
|
|
34138
|
-
G = SHA256_IV[6] | 0;
|
|
34139
|
-
H = SHA256_IV[7] | 0;
|
|
34140
|
-
constructor() {
|
|
34141
|
-
super(32);
|
|
34142
|
-
}
|
|
34143
|
-
}
|
|
34144
|
-
const sha256 = /* @__PURE__ */ createHasher(
|
|
34145
|
-
() => new _SHA256(),
|
|
34146
|
-
/* @__PURE__ */ oidNist(1)
|
|
34147
|
-
);
|
|
34148
|
-
function channelLeaseSubject(input) {
|
|
34149
|
-
const material = JSON.stringify([input.provider, input.installationId]);
|
|
34150
|
-
return bytesToHex(sha256(new TextEncoder().encode(material)));
|
|
34151
|
-
}
|
|
34152
|
-
const LEASE_OUTCOMES = /* @__PURE__ */ new Set([
|
|
34153
|
-
"claimed",
|
|
34154
|
-
"taken-over",
|
|
34155
|
-
"already-held",
|
|
34156
|
-
"renewed",
|
|
34157
|
-
"already-released",
|
|
34158
|
-
"released"
|
|
34159
|
-
]);
|
|
34160
|
-
const RELEASED_OUTCOMES = /* @__PURE__ */ new Set(["released", "already-released"]);
|
|
34161
|
-
const HELD_OUTCOMES = /* @__PURE__ */ new Set([
|
|
34162
|
-
"claimed",
|
|
34163
|
-
"taken-over",
|
|
34164
|
-
"renewed",
|
|
34165
|
-
"already-held"
|
|
34166
|
-
]);
|
|
34167
|
-
function nonNegativeInteger(value2) {
|
|
34168
|
-
return typeof value2 === "number" && Number.isSafeInteger(value2) && value2 >= 0;
|
|
34169
|
-
}
|
|
34170
|
-
function isLeaseResponse(value2) {
|
|
34171
|
-
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) return false;
|
|
34172
|
-
const body = value2;
|
|
34173
|
-
if (typeof body.held !== "boolean") return false;
|
|
34174
|
-
if (typeof body.outcome !== "string" || !LEASE_OUTCOMES.has(body.outcome)) return false;
|
|
34175
|
-
if (!nonNegativeInteger(body.ownerEpoch) || !nonNegativeInteger(body.version)) return false;
|
|
34176
|
-
if (!nonNegativeInteger(body.serverNow) || !nonNegativeInteger(body.leaseUntil)) return false;
|
|
34177
|
-
if (body.releasedAt !== null && !nonNegativeInteger(body.releasedAt)) return false;
|
|
34178
|
-
if (body.held && body.releasedAt !== null) return false;
|
|
34179
|
-
if (body.held && RELEASED_OUTCOMES.has(body.outcome)) return false;
|
|
34180
|
-
if (!body.held && HELD_OUTCOMES.has(body.outcome)) return false;
|
|
34181
|
-
return true;
|
|
34182
|
-
}
|
|
34183
|
-
function resolveChannelLease(input) {
|
|
34184
|
-
if (!isLeaseResponse(input.body)) return { kind: "unknown" };
|
|
34185
|
-
const body = input.body;
|
|
34186
|
-
if (!body.held) {
|
|
34187
|
-
return { kind: "lost", reason: body.releasedAt === null ? "conflict" : "released" };
|
|
34188
|
-
}
|
|
34189
|
-
const remaining = body.leaseUntil - body.serverNow;
|
|
34190
|
-
if (!Number.isFinite(remaining) || remaining <= 0) return { kind: "unknown" };
|
|
34191
|
-
return {
|
|
34192
|
-
kind: "held",
|
|
34193
|
-
hold: {
|
|
34194
|
-
ownerId: input.ownerId,
|
|
34195
|
-
ownerEpoch: body.ownerEpoch,
|
|
34196
|
-
version: body.version,
|
|
34197
|
-
deadlineMono: input.requestStartedMono + remaining
|
|
34198
|
-
}
|
|
34199
|
-
};
|
|
34200
|
-
}
|
|
34201
|
-
function channelLeaseStillHeld(hold, nowMono, options = {}) {
|
|
34202
|
-
if (!hold || options.suspectedSuspend === true) return false;
|
|
34203
|
-
return nowMono < hold.deadlineMono;
|
|
34204
|
-
}
|
|
34205
|
-
function channelLeaseAnswerIsCurrent(input) {
|
|
34206
|
-
return !input.stopped && input.attempt === input.currentAttempt;
|
|
34207
|
-
}
|
|
34208
33743
|
const EXTENSION_ARTIFACT_ACTION_OPERATIONS = ["publishPublic"];
|
|
34209
33744
|
const EXTENSION_ARTIFACT_SOURCE_TYPES = ["project-file", "personal-chat-file"];
|
|
34210
|
-
const ID_PATTERN$
|
|
33745
|
+
const ID_PATTERN$3 = /^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/;
|
|
34211
33746
|
const LOCALE_PATTERN$1 = /^[a-z]{2,3}(?:-[A-Z]{2})?$/;
|
|
34212
33747
|
const EXTENSION_PATTERN = /^[a-z0-9]+$/;
|
|
34213
33748
|
const MAX_ACTIONS = 32;
|
|
@@ -34283,7 +33818,7 @@ function parseExtensionArtifactActions(value2, path = "manifest.contributes.arti
|
|
|
34283
33818
|
const action = record$3(raw, actionPath);
|
|
34284
33819
|
exactKeys$2(action, ["id", "title", "operation", "when"], ["localizations"], actionPath);
|
|
34285
33820
|
const parsedId = text$2(action.id, `${actionPath}.id`);
|
|
34286
|
-
if (!ID_PATTERN$
|
|
33821
|
+
if (!ID_PATTERN$3.test(parsedId) || parsedId.includes("..")) fail$6(`${actionPath}.id`, "invalid stable identifier");
|
|
34287
33822
|
if (!EXTENSION_ARTIFACT_ACTION_OPERATIONS.includes(action.operation)) {
|
|
34288
33823
|
fail$6(`${actionPath}.operation`, "unsupported operation");
|
|
34289
33824
|
}
|
|
@@ -34618,7 +34153,7 @@ function parseOptions(value2, path, expected) {
|
|
|
34618
34153
|
}));
|
|
34619
34154
|
}
|
|
34620
34155
|
const MAX_CHANNEL_CONTRIBUTIONS = CHANNEL_PROVIDERS.length;
|
|
34621
|
-
const ID_PATTERN$
|
|
34156
|
+
const ID_PATTERN$2 = /^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/;
|
|
34622
34157
|
const ENTRY_KEYS = /* @__PURE__ */ new Set(["id", "provider", "commands"]);
|
|
34623
34158
|
function fail$3(path, detail) {
|
|
34624
34159
|
throw new Error(`${path}: ${detail}`);
|
|
@@ -34636,7 +34171,7 @@ function parseExtensionChannelContributions(value2) {
|
|
|
34636
34171
|
const extra = Object.keys(source2).find((key) => !ENTRY_KEYS.has(key));
|
|
34637
34172
|
if (extra !== void 0) fail$3(path, `unknown field ${extra}`);
|
|
34638
34173
|
const id2 = source2.id;
|
|
34639
|
-
if (typeof id2 !== "string" || !ID_PATTERN$
|
|
34174
|
+
if (typeof id2 !== "string" || !ID_PATTERN$2.test(id2) || id2.includes("..")) {
|
|
34640
34175
|
fail$3(`${path}.id`, "invalid identifier");
|
|
34641
34176
|
}
|
|
34642
34177
|
const provider2 = source2.provider;
|
|
@@ -34702,8 +34237,8 @@ class UnsupportedExtensionApiVersionError extends Error {
|
|
|
34702
34237
|
}
|
|
34703
34238
|
name = "UnsupportedExtensionApiVersionError";
|
|
34704
34239
|
}
|
|
34705
|
-
const ID_PATTERN = /^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/;
|
|
34706
|
-
const SEMVER_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
34240
|
+
const ID_PATTERN$1 = /^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/;
|
|
34241
|
+
const SEMVER_PATTERN$1 = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
34707
34242
|
const ENGINE_RANGE_PATTERN = /^(?:\^|~|>=|<=|>|<)?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
34708
34243
|
const ENTRYPOINT_PATTERN = /\.(?:cjs|mjs|js)$/;
|
|
34709
34244
|
const LOCALE_PATTERN = /^[a-z]{2,3}(?:-[A-Z]{2})?$/;
|
|
@@ -34792,7 +34327,7 @@ function string(value2, path) {
|
|
|
34792
34327
|
}
|
|
34793
34328
|
function id$1(value2, path) {
|
|
34794
34329
|
const parsed2 = string(value2, path);
|
|
34795
|
-
if (!ID_PATTERN.test(parsed2) || parsed2.includes("..")) fail$2(path, "invalid stable identifier");
|
|
34330
|
+
if (!ID_PATTERN$1.test(parsed2) || parsed2.includes("..")) fail$2(path, "invalid stable identifier");
|
|
34796
34331
|
return parsed2;
|
|
34797
34332
|
}
|
|
34798
34333
|
function relativePath(value2, path, requireScript = false) {
|
|
@@ -34968,7 +34503,7 @@ function parseExtensionManifest(value2, options) {
|
|
|
34968
34503
|
assertOnlyKeys(manifest2, TOP_LEVEL_KEYS, "manifest");
|
|
34969
34504
|
const parsedId = id$1(manifest2.id, "manifest.id");
|
|
34970
34505
|
const version2 = string(manifest2.version, "manifest.version");
|
|
34971
|
-
if (!SEMVER_PATTERN.test(version2)) fail$2("manifest.version", "expected semantic version");
|
|
34506
|
+
if (!SEMVER_PATTERN$1.test(version2)) fail$2("manifest.version", "expected semantic version");
|
|
34972
34507
|
const apiVersion = parseApiVersion(manifest2.apiVersion, options);
|
|
34973
34508
|
const channelApiVersion = parseChannelApiVersion(manifest2.channelApiVersion, apiVersion);
|
|
34974
34509
|
const engines = record$2(manifest2.engines, "manifest.engines");
|
|
@@ -35066,6 +34601,645 @@ function parseExtensionManifest(value2, options) {
|
|
|
35066
34601
|
contributes
|
|
35067
34602
|
};
|
|
35068
34603
|
}
|
|
34604
|
+
const ID_PATTERN = /^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/;
|
|
34605
|
+
const SEMVER_PATTERN = /^\d+\.\d+\.\d+$/;
|
|
34606
|
+
const SHA256_PATTERN = /^[a-f0-9]{64}$/;
|
|
34607
|
+
const BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
34608
|
+
function isNewerVersion(candidate, installed) {
|
|
34609
|
+
if (!SEMVER_PATTERN.test(installed)) return false;
|
|
34610
|
+
const left = candidate.split(".").map(Number);
|
|
34611
|
+
const right = installed.split(".").map(Number);
|
|
34612
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
34613
|
+
if (left[index] !== right[index]) return left[index] > right[index];
|
|
34614
|
+
}
|
|
34615
|
+
return false;
|
|
34616
|
+
}
|
|
34617
|
+
function descriptor(value2) {
|
|
34618
|
+
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) throw new Error("official extension descriptor is invalid");
|
|
34619
|
+
const item = value2;
|
|
34620
|
+
if (Object.keys(item).sort().join(",") !== "archive,id,releaseUrl,sha256,version" || typeof item.id !== "string" || !ID_PATTERN.test(item.id) || item.id.includes("..") || typeof item.version !== "string" || !SEMVER_PATTERN.test(item.version) || typeof item.releaseUrl !== "string" || !item.releaseUrl.startsWith("https://github.com/buzzni/saycode-extensions/releases/tag/") || typeof item.archive !== "string" || basename(item.archive) !== item.archive || typeof item.sha256 !== "string" || !SHA256_PATTERN.test(item.sha256)) throw new Error("official extension descriptor is invalid");
|
|
34621
|
+
return item;
|
|
34622
|
+
}
|
|
34623
|
+
function catalog(value2) {
|
|
34624
|
+
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) throw new Error("official extension catalog is invalid");
|
|
34625
|
+
const record2 = value2;
|
|
34626
|
+
if (Object.keys(record2).sort().join(",") !== "extensions,schemaVersion" || record2.schemaVersion !== 1 || !Array.isArray(record2.extensions)) throw new Error("official extension catalog is invalid");
|
|
34627
|
+
const extensions = record2.extensions.map(descriptor);
|
|
34628
|
+
if (new Set(extensions.map((item) => item.id)).size !== extensions.length) {
|
|
34629
|
+
throw new Error("official extension catalog contains duplicate ids");
|
|
34630
|
+
}
|
|
34631
|
+
return { schemaVersion: 1, extensions };
|
|
34632
|
+
}
|
|
34633
|
+
class OfficialExtensionInstaller {
|
|
34634
|
+
constructor(options) {
|
|
34635
|
+
this.options = options;
|
|
34636
|
+
}
|
|
34637
|
+
/**
|
|
34638
|
+
* What the user could install right now (specs/desktop-official-extension-install-list R1).
|
|
34639
|
+
*
|
|
34640
|
+
* `install(id)` has always taken any catalog id; nothing could ask which ids exist, so the only
|
|
34641
|
+
* way to offer one was a button written by hand per extension. This is that missing half.
|
|
34642
|
+
*
|
|
34643
|
+
* Already-installed ids are left out: the list is an offer, not an inventory — the installed
|
|
34644
|
+
* ones are the rest of the panel.
|
|
34645
|
+
*/
|
|
34646
|
+
async installable() {
|
|
34647
|
+
let bundled = [];
|
|
34648
|
+
try {
|
|
34649
|
+
bundled = (await this.readCatalog()).extensions;
|
|
34650
|
+
} catch {
|
|
34651
|
+
bundled = [];
|
|
34652
|
+
}
|
|
34653
|
+
const versions = /* @__PURE__ */ new Map();
|
|
34654
|
+
for (const entry of bundled) versions.set(entry.id, entry.version);
|
|
34655
|
+
for (const entry of this.options.remote?.descriptors() ?? []) versions.set(entry.id, entry.version);
|
|
34656
|
+
return [...versions].filter(([id2, version2]) => !this.options.registry.get(id2) && !this.options.revocations?.isRevoked(id2, version2)).map(([id2, version2]) => ({ id: id2, version: version2 }));
|
|
34657
|
+
}
|
|
34658
|
+
async install(id2) {
|
|
34659
|
+
if (this.options.registry.get(id2)) throw new Error(`extension is already installed: ${id2}`);
|
|
34660
|
+
const source2 = await this.resolveArtifact(id2);
|
|
34661
|
+
const installed = await this.options.store.install(source2.archive);
|
|
34662
|
+
if (installed.id !== source2.metadata.id || installed.version !== source2.metadata.version) {
|
|
34663
|
+
await this.options.store.removeVersion(installed.id, installed.version);
|
|
34664
|
+
throw new Error("official extension artifact does not match its provenance");
|
|
34665
|
+
}
|
|
34666
|
+
try {
|
|
34667
|
+
await this.options.registry.apply(installed.id, { type: "installed", version: installed.version });
|
|
34668
|
+
} catch (error) {
|
|
34669
|
+
await this.options.store.removeVersion(installed.id, installed.version);
|
|
34670
|
+
throw error;
|
|
34671
|
+
}
|
|
34672
|
+
return { id: installed.id, version: installed.version, releaseUrl: source2.metadata.releaseUrl };
|
|
34673
|
+
}
|
|
34674
|
+
async reconcileBundledCompatibility() {
|
|
34675
|
+
const installedEntries = this.options.registry.entries();
|
|
34676
|
+
if (installedEntries.length === 0) return;
|
|
34677
|
+
const bundled = (await this.readCatalog()).extensions;
|
|
34678
|
+
let firstError = null;
|
|
34679
|
+
for (const { id: id2, state } of installedEntries) {
|
|
34680
|
+
try {
|
|
34681
|
+
const metadata = bundled.find((item) => item.id === id2);
|
|
34682
|
+
if (!metadata || !isNewerVersion(metadata.version, state.installedVersion)) continue;
|
|
34683
|
+
try {
|
|
34684
|
+
await this.options.store.readInstalledManifest(id2, state.installedVersion);
|
|
34685
|
+
continue;
|
|
34686
|
+
} catch (error) {
|
|
34687
|
+
if (!(error instanceof UnsupportedExtensionApiVersionError) || typeof error.apiVersion !== "number" || error.apiVersion >= error.minimumSupportedApiVersion) throw error;
|
|
34688
|
+
}
|
|
34689
|
+
const archive = await this.readArchive(metadata);
|
|
34690
|
+
await this.options.store.removeVersion(id2, metadata.version);
|
|
34691
|
+
const migrated = await this.options.store.install(archive);
|
|
34692
|
+
if (migrated.id !== id2 || migrated.version !== metadata.version) {
|
|
34693
|
+
await this.options.store.removeVersion(migrated.id, migrated.version);
|
|
34694
|
+
throw new Error("bundled compatibility artifact does not match its provenance");
|
|
34695
|
+
}
|
|
34696
|
+
try {
|
|
34697
|
+
await this.options.registry.apply(id2, {
|
|
34698
|
+
type: "compatibility-update-installed",
|
|
34699
|
+
version: migrated.version
|
|
34700
|
+
});
|
|
34701
|
+
} catch (error) {
|
|
34702
|
+
await this.options.store.removeVersion(migrated.id, migrated.version);
|
|
34703
|
+
throw error;
|
|
34704
|
+
}
|
|
34705
|
+
await this.options.store.removeVersion(id2, state.installedVersion);
|
|
34706
|
+
} catch (error) {
|
|
34707
|
+
firstError ??= error;
|
|
34708
|
+
}
|
|
34709
|
+
}
|
|
34710
|
+
if (firstError) throw firstError;
|
|
34711
|
+
}
|
|
34712
|
+
/** Ids the official channel owns — bundled or signed-remote. A development build must never
|
|
34713
|
+
* be able to stand in for one (ADR-050). */
|
|
34714
|
+
async isOfficialId(id2) {
|
|
34715
|
+
if (this.options.remote?.descriptorFor(id2)) return true;
|
|
34716
|
+
try {
|
|
34717
|
+
return (await this.readCatalog()).extensions.some((item) => item.id === id2);
|
|
34718
|
+
} catch {
|
|
34719
|
+
return true;
|
|
34720
|
+
}
|
|
34721
|
+
}
|
|
34722
|
+
async resolveArtifact(id2) {
|
|
34723
|
+
const remote = this.options.remote?.descriptorFor(id2) ?? null;
|
|
34724
|
+
if (remote) {
|
|
34725
|
+
return { archive: await this.options.remote.downloadArchive(remote), metadata: remote };
|
|
34726
|
+
}
|
|
34727
|
+
const metadata = (await this.readCatalog()).extensions.find((item) => item.id === id2);
|
|
34728
|
+
if (!metadata) throw new Error(`official extension is unavailable: ${id2}`);
|
|
34729
|
+
return { archive: await this.readArchive(metadata), metadata };
|
|
34730
|
+
}
|
|
34731
|
+
async readCatalog() {
|
|
34732
|
+
try {
|
|
34733
|
+
return catalog(JSON.parse(await readFile(join(this.options.resourceRoot, "catalog.v1.json"), "utf8")));
|
|
34734
|
+
} catch (error) {
|
|
34735
|
+
throw new Error(`official extension catalog could not be loaded: ${error instanceof Error ? error.message : String(error)}`);
|
|
34736
|
+
}
|
|
34737
|
+
}
|
|
34738
|
+
async readArchive(metadata) {
|
|
34739
|
+
const encoded = (await readFile(join(this.options.resourceRoot, metadata.archive), "utf8")).trim();
|
|
34740
|
+
if (!BASE64_PATTERN.test(encoded) || encoded.length % 4 !== 0) {
|
|
34741
|
+
throw new Error("official extension archive encoding is invalid");
|
|
34742
|
+
}
|
|
34743
|
+
const archive = Buffer.from(encoded, "base64");
|
|
34744
|
+
const checksum2 = createHash("sha256").update(archive).digest("hex");
|
|
34745
|
+
if (checksum2 !== metadata.sha256) throw new Error("official extension checksum mismatch");
|
|
34746
|
+
return archive;
|
|
34747
|
+
}
|
|
34748
|
+
}
|
|
34749
|
+
const CHANNEL_ADAPTER_IDS = {
|
|
34750
|
+
telegram: "buzzni.telegram",
|
|
34751
|
+
slack: "buzzni.slack",
|
|
34752
|
+
discord: "buzzni.discord"
|
|
34753
|
+
};
|
|
34754
|
+
const ADAPTER_IDS = new Set(Object.values(CHANNEL_ADAPTER_IDS));
|
|
34755
|
+
function createHostOfficialAdapterSource(input) {
|
|
34756
|
+
const installer = new OfficialExtensionInstaller({
|
|
34757
|
+
resourceRoot: input.resourceRoot,
|
|
34758
|
+
store: null,
|
|
34759
|
+
registry: null,
|
|
34760
|
+
...input.remote ? { remote: input.remote } : {}
|
|
34761
|
+
});
|
|
34762
|
+
const resolve2 = (id2) => {
|
|
34763
|
+
if (!ADAPTER_IDS.has(id2)) return Promise.reject(new Error(`not a messenger adapter: ${id2}`));
|
|
34764
|
+
return installer.resolveArtifact(id2);
|
|
34765
|
+
};
|
|
34766
|
+
return {
|
|
34767
|
+
versionOf: (id2) => resolve2(id2).then((artifact) => artifact.metadata.version, () => null),
|
|
34768
|
+
archive: async (id2) => (await resolve2(id2)).archive
|
|
34769
|
+
};
|
|
34770
|
+
}
|
|
34771
|
+
async function offeredChannelProviders(source2) {
|
|
34772
|
+
const offered = [];
|
|
34773
|
+
for (const [provider2, id2] of Object.entries(CHANNEL_ADAPTER_IDS)) {
|
|
34774
|
+
if (await source2.versionOf(id2)) offered.push(provider2);
|
|
34775
|
+
}
|
|
34776
|
+
return offered;
|
|
34777
|
+
}
|
|
34778
|
+
function describe(secretKey) {
|
|
34779
|
+
const { publicKey } = nacl.box.keyPair.fromSecretKey(secretKey);
|
|
34780
|
+
const digest = createHash("sha256").update(publicKey).digest("hex").slice(0, 16).toUpperCase();
|
|
34781
|
+
return {
|
|
34782
|
+
publicKey,
|
|
34783
|
+
secretKey,
|
|
34784
|
+
publicKeyBase64: Buffer.from(publicKey).toString("base64"),
|
|
34785
|
+
fingerprint: digest.match(/.{4}/g).join("-")
|
|
34786
|
+
};
|
|
34787
|
+
}
|
|
34788
|
+
async function openChannelHostKey(input) {
|
|
34789
|
+
if (!input.safeStorage.isEncryptionAvailable()) return null;
|
|
34790
|
+
const path = join(input.dir, "host-key.v1.json");
|
|
34791
|
+
let text2 = null;
|
|
34792
|
+
try {
|
|
34793
|
+
text2 = await readFile(path, "utf8");
|
|
34794
|
+
} catch (error) {
|
|
34795
|
+
if (error.code !== "ENOENT") throw error;
|
|
34796
|
+
}
|
|
34797
|
+
if (text2 !== null) {
|
|
34798
|
+
const parsed2 = JSON.parse(text2);
|
|
34799
|
+
if (parsed2.v !== 1 || typeof parsed2.sealed !== "string") throw new Error("channel host key file is unreadable");
|
|
34800
|
+
const secret = Buffer.from(input.safeStorage.decryptString(Buffer.from(parsed2.sealed, "base64")), "base64");
|
|
34801
|
+
if (secret.length !== nacl.box.secretKeyLength) throw new Error("channel host key file is unreadable");
|
|
34802
|
+
return describe(new Uint8Array(secret));
|
|
34803
|
+
}
|
|
34804
|
+
const { secretKey } = nacl.box.keyPair();
|
|
34805
|
+
await mkdir(input.dir, { recursive: true, mode: 448 });
|
|
34806
|
+
const sealed2 = input.safeStorage.encryptString(Buffer.from(secretKey).toString("base64")).toString("base64");
|
|
34807
|
+
const staging = `${path}.${process.pid}.tmp`;
|
|
34808
|
+
await writeFile(staging, JSON.stringify({ v: 1, sealed: sealed2 }), { mode: 384 });
|
|
34809
|
+
await rename(staging, path);
|
|
34810
|
+
return describe(secretKey);
|
|
34811
|
+
}
|
|
34812
|
+
function defaultIsAlive(pid) {
|
|
34813
|
+
try {
|
|
34814
|
+
process.kill(pid, 0);
|
|
34815
|
+
return true;
|
|
34816
|
+
} catch (error) {
|
|
34817
|
+
return error.code === "EPERM";
|
|
34818
|
+
}
|
|
34819
|
+
}
|
|
34820
|
+
async function acquireChannelHostLock(input) {
|
|
34821
|
+
const path = join(input.dir, "host.lock");
|
|
34822
|
+
const isAlive = input.isAlive ?? defaultIsAlive;
|
|
34823
|
+
for (let attempt2 = 0; attempt2 < 2; attempt2 += 1) {
|
|
34824
|
+
try {
|
|
34825
|
+
const handle = await open(path, "wx", 384);
|
|
34826
|
+
await handle.writeFile(JSON.stringify({ pid: process.pid, startedAt: Date.now() }));
|
|
34827
|
+
await handle.close();
|
|
34828
|
+
return {
|
|
34829
|
+
kind: "held",
|
|
34830
|
+
release: async () => {
|
|
34831
|
+
const current = await readFile(path, "utf8").then((text2) => JSON.parse(text2), () => null);
|
|
34832
|
+
if (current?.pid === process.pid) await rm(path, { force: true });
|
|
34833
|
+
}
|
|
34834
|
+
};
|
|
34835
|
+
} catch (error) {
|
|
34836
|
+
if (error.code !== "EEXIST") throw error;
|
|
34837
|
+
}
|
|
34838
|
+
let holder = null;
|
|
34839
|
+
try {
|
|
34840
|
+
const parsed2 = JSON.parse(await readFile(path, "utf8"));
|
|
34841
|
+
holder = typeof parsed2.pid === "number" && Number.isSafeInteger(parsed2.pid) ? parsed2.pid : null;
|
|
34842
|
+
} catch {
|
|
34843
|
+
holder = null;
|
|
34844
|
+
}
|
|
34845
|
+
if (holder === null || isAlive(holder)) return { kind: "refused" };
|
|
34846
|
+
await rm(path, { force: true });
|
|
34847
|
+
}
|
|
34848
|
+
return { kind: "refused" };
|
|
34849
|
+
}
|
|
34850
|
+
function isBytes(a) {
|
|
34851
|
+
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1;
|
|
34852
|
+
}
|
|
34853
|
+
function abytes(value2, length, title2 = "") {
|
|
34854
|
+
const bytes = isBytes(value2);
|
|
34855
|
+
const len = value2?.length;
|
|
34856
|
+
const needsLen = length !== void 0;
|
|
34857
|
+
if (!bytes || needsLen) {
|
|
34858
|
+
const prefix = title2 && `"${title2}" `;
|
|
34859
|
+
const ofLen = "";
|
|
34860
|
+
const got = bytes ? `length=${len}` : `type=${typeof value2}`;
|
|
34861
|
+
const message = prefix + "expected Uint8Array" + ofLen + ", got " + got;
|
|
34862
|
+
if (!bytes)
|
|
34863
|
+
throw new TypeError(message);
|
|
34864
|
+
throw new RangeError(message);
|
|
34865
|
+
}
|
|
34866
|
+
return value2;
|
|
34867
|
+
}
|
|
34868
|
+
function aexists(instance, checkFinished = true) {
|
|
34869
|
+
if (instance.destroyed)
|
|
34870
|
+
throw new Error("Hash instance has been destroyed");
|
|
34871
|
+
if (checkFinished && instance.finished)
|
|
34872
|
+
throw new Error("Hash#digest() has already been called");
|
|
34873
|
+
}
|
|
34874
|
+
function aoutput(out, instance) {
|
|
34875
|
+
abytes(out, void 0, "digestInto() output");
|
|
34876
|
+
const min = instance.outputLen;
|
|
34877
|
+
if (out.length < min) {
|
|
34878
|
+
throw new RangeError('"digestInto() output" expected to be of length >=' + min);
|
|
34879
|
+
}
|
|
34880
|
+
}
|
|
34881
|
+
function clean(...arrays) {
|
|
34882
|
+
for (let i = 0; i < arrays.length; i++) {
|
|
34883
|
+
arrays[i].fill(0);
|
|
34884
|
+
}
|
|
34885
|
+
}
|
|
34886
|
+
function createView(arr) {
|
|
34887
|
+
return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
34888
|
+
}
|
|
34889
|
+
function rotr(word, shift) {
|
|
34890
|
+
return word << 32 - shift | word >>> shift;
|
|
34891
|
+
}
|
|
34892
|
+
const hasHexBuiltin = /* @__PURE__ */ (() => (
|
|
34893
|
+
// @ts-ignore
|
|
34894
|
+
typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function"
|
|
34895
|
+
))();
|
|
34896
|
+
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
|
|
34897
|
+
function bytesToHex(bytes) {
|
|
34898
|
+
abytes(bytes);
|
|
34899
|
+
if (hasHexBuiltin)
|
|
34900
|
+
return bytes.toHex();
|
|
34901
|
+
let hex = "";
|
|
34902
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
34903
|
+
hex += hexes[bytes[i]];
|
|
34904
|
+
}
|
|
34905
|
+
return hex;
|
|
34906
|
+
}
|
|
34907
|
+
function createHasher(hashCons, info = {}) {
|
|
34908
|
+
const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
|
|
34909
|
+
const tmp = hashCons(void 0);
|
|
34910
|
+
hashC.outputLen = tmp.outputLen;
|
|
34911
|
+
hashC.blockLen = tmp.blockLen;
|
|
34912
|
+
hashC.canXOF = tmp.canXOF;
|
|
34913
|
+
hashC.create = (opts) => hashCons(opts);
|
|
34914
|
+
Object.assign(hashC, info);
|
|
34915
|
+
return Object.freeze(hashC);
|
|
34916
|
+
}
|
|
34917
|
+
const oidNist = (suffix) => ({
|
|
34918
|
+
// Current NIST hashAlgs suffixes used here fit in one DER subidentifier octet.
|
|
34919
|
+
// Larger suffix values would need base-128 OID encoding and a different length byte.
|
|
34920
|
+
oid: Uint8Array.from([6, 9, 96, 134, 72, 1, 101, 3, 4, 2, suffix])
|
|
34921
|
+
});
|
|
34922
|
+
function Chi(a, b, c) {
|
|
34923
|
+
return a & b ^ ~a & c;
|
|
34924
|
+
}
|
|
34925
|
+
function Maj(a, b, c) {
|
|
34926
|
+
return a & b ^ a & c ^ b & c;
|
|
34927
|
+
}
|
|
34928
|
+
class HashMD {
|
|
34929
|
+
blockLen;
|
|
34930
|
+
outputLen;
|
|
34931
|
+
canXOF = false;
|
|
34932
|
+
padOffset;
|
|
34933
|
+
isLE;
|
|
34934
|
+
// For partial updates less than block size
|
|
34935
|
+
buffer;
|
|
34936
|
+
view;
|
|
34937
|
+
finished = false;
|
|
34938
|
+
length = 0;
|
|
34939
|
+
pos = 0;
|
|
34940
|
+
destroyed = false;
|
|
34941
|
+
constructor(blockLen, outputLen, padOffset, isLE) {
|
|
34942
|
+
this.blockLen = blockLen;
|
|
34943
|
+
this.outputLen = outputLen;
|
|
34944
|
+
this.padOffset = padOffset;
|
|
34945
|
+
this.isLE = isLE;
|
|
34946
|
+
this.buffer = new Uint8Array(blockLen);
|
|
34947
|
+
this.view = createView(this.buffer);
|
|
34948
|
+
}
|
|
34949
|
+
update(data) {
|
|
34950
|
+
aexists(this);
|
|
34951
|
+
abytes(data);
|
|
34952
|
+
const { view, buffer, blockLen } = this;
|
|
34953
|
+
const len = data.length;
|
|
34954
|
+
for (let pos = 0; pos < len; ) {
|
|
34955
|
+
const take = Math.min(blockLen - this.pos, len - pos);
|
|
34956
|
+
if (take === blockLen) {
|
|
34957
|
+
const dataView = createView(data);
|
|
34958
|
+
for (; blockLen <= len - pos; pos += blockLen)
|
|
34959
|
+
this.process(dataView, pos);
|
|
34960
|
+
continue;
|
|
34961
|
+
}
|
|
34962
|
+
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
34963
|
+
this.pos += take;
|
|
34964
|
+
pos += take;
|
|
34965
|
+
if (this.pos === blockLen) {
|
|
34966
|
+
this.process(view, 0);
|
|
34967
|
+
this.pos = 0;
|
|
34968
|
+
}
|
|
34969
|
+
}
|
|
34970
|
+
this.length += data.length;
|
|
34971
|
+
this.roundClean();
|
|
34972
|
+
return this;
|
|
34973
|
+
}
|
|
34974
|
+
digestInto(out) {
|
|
34975
|
+
aexists(this);
|
|
34976
|
+
aoutput(out, this);
|
|
34977
|
+
this.finished = true;
|
|
34978
|
+
const { buffer, view, blockLen, isLE } = this;
|
|
34979
|
+
let { pos } = this;
|
|
34980
|
+
buffer[pos++] = 128;
|
|
34981
|
+
clean(this.buffer.subarray(pos));
|
|
34982
|
+
if (this.padOffset > blockLen - pos) {
|
|
34983
|
+
this.process(view, 0);
|
|
34984
|
+
pos = 0;
|
|
34985
|
+
}
|
|
34986
|
+
for (let i = pos; i < blockLen; i++)
|
|
34987
|
+
buffer[i] = 0;
|
|
34988
|
+
view.setBigUint64(blockLen - 8, BigInt(this.length * 8), isLE);
|
|
34989
|
+
this.process(view, 0);
|
|
34990
|
+
const oview = createView(out);
|
|
34991
|
+
const len = this.outputLen;
|
|
34992
|
+
if (len % 4)
|
|
34993
|
+
throw new Error("_sha2: outputLen must be aligned to 32bit");
|
|
34994
|
+
const outLen = len / 4;
|
|
34995
|
+
const state = this.get();
|
|
34996
|
+
if (outLen > state.length)
|
|
34997
|
+
throw new Error("_sha2: outputLen bigger than state");
|
|
34998
|
+
for (let i = 0; i < outLen; i++)
|
|
34999
|
+
oview.setUint32(4 * i, state[i], isLE);
|
|
35000
|
+
}
|
|
35001
|
+
digest() {
|
|
35002
|
+
const { buffer, outputLen } = this;
|
|
35003
|
+
this.digestInto(buffer);
|
|
35004
|
+
const res = buffer.slice(0, outputLen);
|
|
35005
|
+
this.destroy();
|
|
35006
|
+
return res;
|
|
35007
|
+
}
|
|
35008
|
+
_cloneInto(to) {
|
|
35009
|
+
to ||= new this.constructor();
|
|
35010
|
+
to.set(...this.get());
|
|
35011
|
+
const { blockLen, buffer, length, finished, destroyed, pos } = this;
|
|
35012
|
+
to.destroyed = destroyed;
|
|
35013
|
+
to.finished = finished;
|
|
35014
|
+
to.length = length;
|
|
35015
|
+
to.pos = pos;
|
|
35016
|
+
if (length % blockLen)
|
|
35017
|
+
to.buffer.set(buffer);
|
|
35018
|
+
return to;
|
|
35019
|
+
}
|
|
35020
|
+
clone() {
|
|
35021
|
+
return this._cloneInto();
|
|
35022
|
+
}
|
|
35023
|
+
}
|
|
35024
|
+
const SHA256_IV = /* @__PURE__ */ Uint32Array.from([
|
|
35025
|
+
1779033703,
|
|
35026
|
+
3144134277,
|
|
35027
|
+
1013904242,
|
|
35028
|
+
2773480762,
|
|
35029
|
+
1359893119,
|
|
35030
|
+
2600822924,
|
|
35031
|
+
528734635,
|
|
35032
|
+
1541459225
|
|
35033
|
+
]);
|
|
35034
|
+
const SHA256_K = /* @__PURE__ */ Uint32Array.from([
|
|
35035
|
+
1116352408,
|
|
35036
|
+
1899447441,
|
|
35037
|
+
3049323471,
|
|
35038
|
+
3921009573,
|
|
35039
|
+
961987163,
|
|
35040
|
+
1508970993,
|
|
35041
|
+
2453635748,
|
|
35042
|
+
2870763221,
|
|
35043
|
+
3624381080,
|
|
35044
|
+
310598401,
|
|
35045
|
+
607225278,
|
|
35046
|
+
1426881987,
|
|
35047
|
+
1925078388,
|
|
35048
|
+
2162078206,
|
|
35049
|
+
2614888103,
|
|
35050
|
+
3248222580,
|
|
35051
|
+
3835390401,
|
|
35052
|
+
4022224774,
|
|
35053
|
+
264347078,
|
|
35054
|
+
604807628,
|
|
35055
|
+
770255983,
|
|
35056
|
+
1249150122,
|
|
35057
|
+
1555081692,
|
|
35058
|
+
1996064986,
|
|
35059
|
+
2554220882,
|
|
35060
|
+
2821834349,
|
|
35061
|
+
2952996808,
|
|
35062
|
+
3210313671,
|
|
35063
|
+
3336571891,
|
|
35064
|
+
3584528711,
|
|
35065
|
+
113926993,
|
|
35066
|
+
338241895,
|
|
35067
|
+
666307205,
|
|
35068
|
+
773529912,
|
|
35069
|
+
1294757372,
|
|
35070
|
+
1396182291,
|
|
35071
|
+
1695183700,
|
|
35072
|
+
1986661051,
|
|
35073
|
+
2177026350,
|
|
35074
|
+
2456956037,
|
|
35075
|
+
2730485921,
|
|
35076
|
+
2820302411,
|
|
35077
|
+
3259730800,
|
|
35078
|
+
3345764771,
|
|
35079
|
+
3516065817,
|
|
35080
|
+
3600352804,
|
|
35081
|
+
4094571909,
|
|
35082
|
+
275423344,
|
|
35083
|
+
430227734,
|
|
35084
|
+
506948616,
|
|
35085
|
+
659060556,
|
|
35086
|
+
883997877,
|
|
35087
|
+
958139571,
|
|
35088
|
+
1322822218,
|
|
35089
|
+
1537002063,
|
|
35090
|
+
1747873779,
|
|
35091
|
+
1955562222,
|
|
35092
|
+
2024104815,
|
|
35093
|
+
2227730452,
|
|
35094
|
+
2361852424,
|
|
35095
|
+
2428436474,
|
|
35096
|
+
2756734187,
|
|
35097
|
+
3204031479,
|
|
35098
|
+
3329325298
|
|
35099
|
+
]);
|
|
35100
|
+
const SHA256_W = /* @__PURE__ */ new Uint32Array(64);
|
|
35101
|
+
class SHA2_32B extends HashMD {
|
|
35102
|
+
constructor(outputLen) {
|
|
35103
|
+
super(64, outputLen, 8, false);
|
|
35104
|
+
}
|
|
35105
|
+
get() {
|
|
35106
|
+
const { A, B, C, D, E, F, G, H } = this;
|
|
35107
|
+
return [A, B, C, D, E, F, G, H];
|
|
35108
|
+
}
|
|
35109
|
+
// prettier-ignore
|
|
35110
|
+
set(A, B, C, D, E, F, G, H) {
|
|
35111
|
+
this.A = A | 0;
|
|
35112
|
+
this.B = B | 0;
|
|
35113
|
+
this.C = C | 0;
|
|
35114
|
+
this.D = D | 0;
|
|
35115
|
+
this.E = E | 0;
|
|
35116
|
+
this.F = F | 0;
|
|
35117
|
+
this.G = G | 0;
|
|
35118
|
+
this.H = H | 0;
|
|
35119
|
+
}
|
|
35120
|
+
process(view, offset) {
|
|
35121
|
+
for (let i = 0; i < 16; i++, offset += 4)
|
|
35122
|
+
SHA256_W[i] = view.getUint32(offset, false);
|
|
35123
|
+
for (let i = 16; i < 64; i++) {
|
|
35124
|
+
const W15 = SHA256_W[i - 15];
|
|
35125
|
+
const W2 = SHA256_W[i - 2];
|
|
35126
|
+
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
|
|
35127
|
+
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
|
|
35128
|
+
SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
|
|
35129
|
+
}
|
|
35130
|
+
let { A, B, C, D, E, F, G, H } = this;
|
|
35131
|
+
for (let i = 0; i < 64; i++) {
|
|
35132
|
+
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
|
|
35133
|
+
const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i] | 0;
|
|
35134
|
+
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
|
|
35135
|
+
const T2 = sigma0 + Maj(A, B, C) | 0;
|
|
35136
|
+
H = G;
|
|
35137
|
+
G = F;
|
|
35138
|
+
F = E;
|
|
35139
|
+
E = D + T1 | 0;
|
|
35140
|
+
D = C;
|
|
35141
|
+
C = B;
|
|
35142
|
+
B = A;
|
|
35143
|
+
A = T1 + T2 | 0;
|
|
35144
|
+
}
|
|
35145
|
+
A = A + this.A | 0;
|
|
35146
|
+
B = B + this.B | 0;
|
|
35147
|
+
C = C + this.C | 0;
|
|
35148
|
+
D = D + this.D | 0;
|
|
35149
|
+
E = E + this.E | 0;
|
|
35150
|
+
F = F + this.F | 0;
|
|
35151
|
+
G = G + this.G | 0;
|
|
35152
|
+
H = H + this.H | 0;
|
|
35153
|
+
this.set(A, B, C, D, E, F, G, H);
|
|
35154
|
+
}
|
|
35155
|
+
roundClean() {
|
|
35156
|
+
clean(SHA256_W);
|
|
35157
|
+
}
|
|
35158
|
+
destroy() {
|
|
35159
|
+
this.destroyed = true;
|
|
35160
|
+
this.set(0, 0, 0, 0, 0, 0, 0, 0);
|
|
35161
|
+
clean(this.buffer);
|
|
35162
|
+
}
|
|
35163
|
+
}
|
|
35164
|
+
class _SHA256 extends SHA2_32B {
|
|
35165
|
+
// We cannot use array here since array allows indexing by variable
|
|
35166
|
+
// which means optimizer/compiler cannot use registers.
|
|
35167
|
+
A = SHA256_IV[0] | 0;
|
|
35168
|
+
B = SHA256_IV[1] | 0;
|
|
35169
|
+
C = SHA256_IV[2] | 0;
|
|
35170
|
+
D = SHA256_IV[3] | 0;
|
|
35171
|
+
E = SHA256_IV[4] | 0;
|
|
35172
|
+
F = SHA256_IV[5] | 0;
|
|
35173
|
+
G = SHA256_IV[6] | 0;
|
|
35174
|
+
H = SHA256_IV[7] | 0;
|
|
35175
|
+
constructor() {
|
|
35176
|
+
super(32);
|
|
35177
|
+
}
|
|
35178
|
+
}
|
|
35179
|
+
const sha256 = /* @__PURE__ */ createHasher(
|
|
35180
|
+
() => new _SHA256(),
|
|
35181
|
+
/* @__PURE__ */ oidNist(1)
|
|
35182
|
+
);
|
|
35183
|
+
function channelLeaseSubject(input) {
|
|
35184
|
+
const material = JSON.stringify([input.provider, input.installationId]);
|
|
35185
|
+
return bytesToHex(sha256(new TextEncoder().encode(material)));
|
|
35186
|
+
}
|
|
35187
|
+
const LEASE_OUTCOMES = /* @__PURE__ */ new Set([
|
|
35188
|
+
"claimed",
|
|
35189
|
+
"taken-over",
|
|
35190
|
+
"already-held",
|
|
35191
|
+
"renewed",
|
|
35192
|
+
"already-released",
|
|
35193
|
+
"released"
|
|
35194
|
+
]);
|
|
35195
|
+
const RELEASED_OUTCOMES = /* @__PURE__ */ new Set(["released", "already-released"]);
|
|
35196
|
+
const HELD_OUTCOMES = /* @__PURE__ */ new Set([
|
|
35197
|
+
"claimed",
|
|
35198
|
+
"taken-over",
|
|
35199
|
+
"renewed",
|
|
35200
|
+
"already-held"
|
|
35201
|
+
]);
|
|
35202
|
+
function nonNegativeInteger(value2) {
|
|
35203
|
+
return typeof value2 === "number" && Number.isSafeInteger(value2) && value2 >= 0;
|
|
35204
|
+
}
|
|
35205
|
+
function isLeaseResponse(value2) {
|
|
35206
|
+
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) return false;
|
|
35207
|
+
const body = value2;
|
|
35208
|
+
if (typeof body.held !== "boolean") return false;
|
|
35209
|
+
if (typeof body.outcome !== "string" || !LEASE_OUTCOMES.has(body.outcome)) return false;
|
|
35210
|
+
if (!nonNegativeInteger(body.ownerEpoch) || !nonNegativeInteger(body.version)) return false;
|
|
35211
|
+
if (!nonNegativeInteger(body.serverNow) || !nonNegativeInteger(body.leaseUntil)) return false;
|
|
35212
|
+
if (body.releasedAt !== null && !nonNegativeInteger(body.releasedAt)) return false;
|
|
35213
|
+
if (body.held && body.releasedAt !== null) return false;
|
|
35214
|
+
if (body.held && RELEASED_OUTCOMES.has(body.outcome)) return false;
|
|
35215
|
+
if (!body.held && HELD_OUTCOMES.has(body.outcome)) return false;
|
|
35216
|
+
return true;
|
|
35217
|
+
}
|
|
35218
|
+
function resolveChannelLease(input) {
|
|
35219
|
+
if (!isLeaseResponse(input.body)) return { kind: "unknown" };
|
|
35220
|
+
const body = input.body;
|
|
35221
|
+
if (!body.held) {
|
|
35222
|
+
return { kind: "lost", reason: body.releasedAt === null ? "conflict" : "released" };
|
|
35223
|
+
}
|
|
35224
|
+
const remaining = body.leaseUntil - body.serverNow;
|
|
35225
|
+
if (!Number.isFinite(remaining) || remaining <= 0) return { kind: "unknown" };
|
|
35226
|
+
return {
|
|
35227
|
+
kind: "held",
|
|
35228
|
+
hold: {
|
|
35229
|
+
ownerId: input.ownerId,
|
|
35230
|
+
ownerEpoch: body.ownerEpoch,
|
|
35231
|
+
version: body.version,
|
|
35232
|
+
deadlineMono: input.requestStartedMono + remaining
|
|
35233
|
+
}
|
|
35234
|
+
};
|
|
35235
|
+
}
|
|
35236
|
+
function channelLeaseStillHeld(hold, nowMono, options = {}) {
|
|
35237
|
+
if (!hold || options.suspectedSuspend === true) return false;
|
|
35238
|
+
return nowMono < hold.deadlineMono;
|
|
35239
|
+
}
|
|
35240
|
+
function channelLeaseAnswerIsCurrent(input) {
|
|
35241
|
+
return !input.stopped && input.attempt === input.currentAttempt;
|
|
35242
|
+
}
|
|
35069
35243
|
function syncSocketTokens(auth) {
|
|
35070
35244
|
const primary = auth.syncToken || auth.token;
|
|
35071
35245
|
if (!primary) return [];
|
|
@@ -46893,12 +47067,12 @@ class ChannelSettingsService {
|
|
|
46893
47067
|
const { principalKey } = this.requirePrincipal();
|
|
46894
47068
|
const epoch = this.options.accountEpoch();
|
|
46895
47069
|
const record2 = await this.records(principalKey);
|
|
46896
|
-
const
|
|
47070
|
+
const catalog2 = await this.readCatalog(record2);
|
|
46897
47071
|
const after = this.requirePrincipal();
|
|
46898
47072
|
if (after.principalKey !== principalKey || this.options.accountEpoch() !== epoch) {
|
|
46899
47073
|
throw new ChannelSettingsError("STALE_SNAPSHOT", "the signed-in account changed");
|
|
46900
47074
|
}
|
|
46901
|
-
return this.buildSnapshot(record2,
|
|
47075
|
+
return this.buildSnapshot(record2, catalog2);
|
|
46902
47076
|
}
|
|
46903
47077
|
async get(provider2) {
|
|
46904
47078
|
const snapshot = await this.snapshot();
|
|
@@ -47083,22 +47257,22 @@ class ChannelSettingsService {
|
|
|
47083
47257
|
});
|
|
47084
47258
|
await this.options.persistence.save(principalKey, next);
|
|
47085
47259
|
this.cache.set(principalKey, next);
|
|
47086
|
-
const
|
|
47087
|
-
const snapshot = this.buildSnapshot(next,
|
|
47260
|
+
const catalog2 = await this.readCatalog(next);
|
|
47261
|
+
const snapshot = this.buildSnapshot(next, catalog2);
|
|
47088
47262
|
this.options.onChanged(snapshot);
|
|
47089
47263
|
await this.options.onCommitted?.(next).catch(() => void 0);
|
|
47090
|
-
const settled = this.buildSnapshot(next,
|
|
47264
|
+
const settled = this.buildSnapshot(next, catalog2);
|
|
47091
47265
|
const before = snapshot.connections[connection.provider];
|
|
47092
47266
|
const after = settled.connections[connection.provider];
|
|
47093
47267
|
const botFields = ["botCheck", "botUsername", "botName", "botAppRef", "botScopeRef", "status"];
|
|
47094
47268
|
if (botFields.some((field) => after[field] !== before[field])) this.options.onChanged(settled);
|
|
47095
47269
|
return after;
|
|
47096
47270
|
}
|
|
47097
|
-
buildSnapshot(record2,
|
|
47271
|
+
buildSnapshot(record2, catalog2) {
|
|
47098
47272
|
const { principalKey } = this.requirePrincipal();
|
|
47099
47273
|
return buildChannelSettingsSnapshot({
|
|
47100
47274
|
record: record2,
|
|
47101
|
-
catalog,
|
|
47275
|
+
catalog: catalog2,
|
|
47102
47276
|
accountScopeKey: principalKey,
|
|
47103
47277
|
epoch: this.options.accountEpoch(),
|
|
47104
47278
|
installed: this.options.installedAdapters(),
|
|
@@ -59934,7 +60108,6 @@ const runKeychainCommand = (command, args, stdin) => new Promise((resolve2, reje
|
|
|
59934
60108
|
}, reject2);
|
|
59935
60109
|
});
|
|
59936
60110
|
const TICK_MS = 3e4;
|
|
59937
|
-
const PROVIDERS = ["telegram", "slack", "discord"];
|
|
59938
60111
|
function report(code) {
|
|
59939
60112
|
process.stderr.write(`[channel-host] ${code}
|
|
59940
60113
|
`);
|
|
@@ -59988,8 +60161,9 @@ async function runChannelHost() {
|
|
|
59988
60161
|
if (!layout) report("CHANNEL_HOST_EXTENSIONS_DIR_DENIED");
|
|
59989
60162
|
const sandbox = layout ? await loadAdapterSandbox({ resolveFrom: import.meta.url, deniedReads: layout.deniedReads }) : null;
|
|
59990
60163
|
const bootstrapPath = join(dirname(fileURLToPath(import.meta.url)), "channel-extension-host.mjs");
|
|
60164
|
+
const officialRoot = join(dirname(fileURLToPath(import.meta.url)), "official-extensions");
|
|
59991
60165
|
let opened = null;
|
|
59992
|
-
let
|
|
60166
|
+
let catalog2 = null;
|
|
59993
60167
|
const store = createHostStateStore({ dir: init.dataDir, safeStorage });
|
|
59994
60168
|
const controller = createHostController({
|
|
59995
60169
|
machineId: init.machine.id,
|
|
@@ -59999,7 +60173,7 @@ async function runChannelHost() {
|
|
|
59999
60173
|
serverFor: (binding, token) => createHostServerClient({ apiBaseUrl: binding.apiBaseUrl, token }),
|
|
60000
60174
|
openRuntime: async ({ binding, token, isPaused }) => {
|
|
60001
60175
|
opened = await openHostRuntime({ init, binding, token, isPaused, safeStorage, bridge, sandbox, extensionRoot: layout?.extensionRoot ?? init.extensionsDir, bootstrapPath, report });
|
|
60002
|
-
|
|
60176
|
+
catalog2 = createRemoteExtensionCatalog({
|
|
60003
60177
|
cachePath: join(init.dataDir, "extension-catalog.v1.json"),
|
|
60004
60178
|
revocations: opened.extensions.revocations,
|
|
60005
60179
|
fetch: (url2) => fetch(url2, { signal: AbortSignal.timeout(3e4) }),
|
|
@@ -60008,14 +60182,16 @@ async function runChannelHost() {
|
|
|
60008
60182
|
return opened;
|
|
60009
60183
|
},
|
|
60010
60184
|
reconcileAdapters: async (specs) => {
|
|
60011
|
-
if (!opened
|
|
60012
|
-
|
|
60013
|
-
|
|
60185
|
+
if (!opened) throw Object.assign(new Error("NOT_READY"), { code: "CHANNEL_HOST_NOT_READY" });
|
|
60186
|
+
if (catalog2) {
|
|
60187
|
+
await catalog2.load();
|
|
60188
|
+
await catalog2.refresh().catch(() => report("CHANNEL_HOST_CATALOG_REFRESH_FAILED"));
|
|
60189
|
+
}
|
|
60014
60190
|
const { registry: registry2, store: extensionStore, revocations } = opened.extensions;
|
|
60015
60191
|
return reconcileHostExtensions(specs, {
|
|
60016
60192
|
registry: registry2,
|
|
60017
60193
|
store: extensionStore,
|
|
60018
|
-
|
|
60194
|
+
official: createHostOfficialAdapterSource({ resourceRoot: officialRoot, remote: catalog2 }),
|
|
60019
60195
|
isRevoked: (id2, version2) => revocations.isRevoked(id2, version2)
|
|
60020
60196
|
});
|
|
60021
60197
|
},
|
|
@@ -60027,22 +60203,15 @@ async function runChannelHost() {
|
|
|
60027
60203
|
void controller.handleSettings(wire).then((answer) => bridge.send({ t: "settings-result", id: id2, wire: answer })).catch(() => bridge.send({ t: "settings-result", id: id2, wire: { sealed: "", error: "HOST_CALL_FAILED" } }));
|
|
60028
60204
|
});
|
|
60029
60205
|
await controller.start().catch(() => report("CHANNEL_HOST_RESUME_FAILED"));
|
|
60030
|
-
const
|
|
60031
|
-
cachePath: join(init.dataDir, "extension-catalog.probe.json"),
|
|
60032
|
-
revocations: { record: async () => void 0 },
|
|
60033
|
-
fetch: async () => {
|
|
60034
|
-
throw new Error("probe");
|
|
60035
|
-
},
|
|
60036
|
-
onDiagnostic: () => void 0
|
|
60037
|
-
}) !== null;
|
|
60206
|
+
const offered = await offeredChannelProviders(createHostOfficialAdapterSource({ resourceRoot: officialRoot, remote: null }));
|
|
60038
60207
|
bridge.send({
|
|
60039
60208
|
t: "ready",
|
|
60040
60209
|
hostKey: key.publicKeyBase64,
|
|
60041
60210
|
fingerprint: key.fingerprint,
|
|
60042
60211
|
custody: "available",
|
|
60043
60212
|
isolation: sandbox ? "available" : "unavailable",
|
|
60044
|
-
// Without isolation
|
|
60045
|
-
providers: sandbox
|
|
60213
|
+
// Without isolation no adapter may run here, so nothing is offered.
|
|
60214
|
+
providers: sandbox ? offered : []
|
|
60046
60215
|
});
|
|
60047
60216
|
const tick = setInterval(() => {
|
|
60048
60217
|
void controller.tick().catch(() => report("CHANNEL_HOST_TICK_FAILED"));
|