openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
220 lines (219 loc) • 7.79 kB
JavaScript
import { i as formatErrorMessage } from "./errors-BXgSefBE.js";
import "./error-runtime-C8vbtAJt.js";
import { createRequire } from "node:module";
import fs from "node:fs";
import path from "node:path";
import { spawn } from "node:child_process";
//#region extensions/matrix/src/matrix/deps.ts
const REQUIRED_MATRIX_PACKAGES = [
"matrix-js-sdk",
"@matrix-org/matrix-sdk-crypto-nodejs",
"@matrix-org/matrix-sdk-crypto-wasm"
];
const MIN_MATRIX_CRYPTO_NATIVE_BINDING_BYTES = 1e6;
const MATRIX_COMMAND_OUTPUT_TAIL_BYTES = 64 * 1024;
function resolveMissingMatrixPackages(resolveFn) {
const resolve = resolveFn ?? defaultResolveFn;
return REQUIRED_MATRIX_PACKAGES.filter((pkg) => {
try {
resolve(pkg);
return false;
} catch {
return true;
}
});
}
function isMatrixSdkAvailable() {
return resolveMissingMatrixPackages().length === 0;
}
function buildMatrixDepsMissingMessage(missing) {
return [`Matrix plugin dependencies are missing: ${missing.join(", ")}.`, "Repair this plugin with `openclaw plugins update matrix` or run `openclaw doctor --fix`."].join(" ");
}
let defaultMatrixCryptoRuntimeEnsurePromise = null;
function appendBoundedOutputTail(current, chunk) {
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
if (chunkBuffer.byteLength >= 65536) return chunkBuffer.subarray(chunkBuffer.byteLength - MATRIX_COMMAND_OUTPUT_TAIL_BYTES).toString("utf8");
const currentBuffer = Buffer.from(current);
if (currentBuffer.byteLength + chunkBuffer.byteLength <= 65536) return `${current}${chunkBuffer.toString("utf8")}`;
const currentTailBytes = MATRIX_COMMAND_OUTPUT_TAIL_BYTES - chunkBuffer.byteLength;
const currentTail = currentBuffer.subarray(currentBuffer.byteLength - currentTailBytes);
return Buffer.concat([currentTail, chunkBuffer], MATRIX_COMMAND_OUTPUT_TAIL_BYTES).toString("utf8");
}
async function runFixedCommandWithTimeout(params) {
return await new Promise((resolve) => {
const [command, ...args] = params.argv;
if (!command) {
resolve({
code: 1,
stdout: "",
stderr: "command is required"
});
return;
}
const proc = spawn(command, args, {
cwd: params.cwd,
env: {
...process.env,
...params.env
},
stdio: [
"ignore",
"pipe",
"pipe"
]
});
let stdout = "";
let stderr = "";
let settled = false;
let timer = null;
const killChildOnExit = () => {
if (!settled && proc.exitCode === null) proc.kill("SIGTERM");
};
const finalize = (result) => {
if (settled) return;
settled = true;
if (timer) clearTimeout(timer);
process.off("exit", killChildOnExit);
resolve(result);
};
process.once("exit", killChildOnExit);
proc.stdout?.on("data", (chunk) => {
stdout = appendBoundedOutputTail(stdout, chunk);
});
proc.stderr?.on("data", (chunk) => {
stderr = appendBoundedOutputTail(stderr, chunk);
});
timer = setTimeout(() => {
proc.kill("SIGKILL");
finalize({
code: 124,
stdout,
stderr: stderr || `command timed out after ${params.timeoutMs}ms`
});
}, params.timeoutMs);
proc.on("error", (err) => {
finalize({
code: 1,
stdout,
stderr: err.message
});
});
proc.on("close", (code) => {
finalize({
code: code ?? 1,
stdout,
stderr
});
});
});
}
function defaultRequireFn(id) {
return createRequire(import.meta.url)(id);
}
function defaultResolveFn(id) {
return createRequire(import.meta.url).resolve(id);
}
function isMissingMatrixCryptoRuntimeError(error) {
const message = formatErrorMessage(error);
return message.includes("@matrix-org/matrix-sdk-crypto-nodejs-") || message.includes("matrix-sdk-crypto-nodejs") || message.includes("download-lib.js");
}
function isMuslRuntime() {
try {
return !(process.report?.getReport?.())?.header?.glibcVersionRuntime;
} catch {
return true;
}
}
function resolveMatrixCryptoNativeBindingFilename() {
switch (process.platform) {
case "darwin": return process.arch === "arm64" ? "matrix-sdk-crypto.darwin-arm64.node" : process.arch === "x64" ? "matrix-sdk-crypto.darwin-x64.node" : null;
case "linux":
if (process.arch === "x64") return isMuslRuntime() ? "matrix-sdk-crypto.linux-x64-musl.node" : "matrix-sdk-crypto.linux-x64-gnu.node";
if (process.arch === "arm64" && !isMuslRuntime()) return "matrix-sdk-crypto.linux-arm64-gnu.node";
if (process.arch === "arm") return "matrix-sdk-crypto.linux-arm-gnueabihf.node";
if (process.arch === "s390x") return "matrix-sdk-crypto.linux-s390x-gnu.node";
return null;
case "win32": return process.arch === "x64" ? "matrix-sdk-crypto.win32-x64-msvc.node" : process.arch === "ia32" ? "matrix-sdk-crypto.win32-ia32-msvc.node" : process.arch === "arm64" ? "matrix-sdk-crypto.win32-arm64-msvc.node" : null;
default: return null;
}
}
function resolveMatrixCryptoNativeBindingPath(resolveFn) {
const filename = resolveMatrixCryptoNativeBindingFilename();
if (!filename) return null;
try {
return path.join(path.dirname(resolveFn("@matrix-org/matrix-sdk-crypto-nodejs/download-lib.js")), filename);
} catch {
return null;
}
}
function removeIncompleteMatrixCryptoNativeBinding(params) {
const bindingPath = params.bindingPath;
if (!bindingPath) return;
try {
const stat = fs.statSync(bindingPath);
if (!stat.isFile() || stat.size >= MIN_MATRIX_CRYPTO_NATIVE_BINDING_BYTES) return;
fs.unlinkSync(bindingPath);
params.log?.(`matrix: removed incomplete native crypto runtime (${stat.size} bytes); it will be downloaded again`);
} catch (error) {
if (error.code !== "ENOENT") throw error;
}
}
async function ensureMatrixCryptoRuntime(params = {}) {
const usesDefaultRuntime = !params.requireFn && !params.runCommand && !params.resolveFn && !params.nodeExecutable;
if (usesDefaultRuntime && defaultMatrixCryptoRuntimeEnsurePromise) {
await defaultMatrixCryptoRuntimeEnsurePromise;
return;
}
const ensurePromise = ensureMatrixCryptoRuntimeOnce(params);
if (!usesDefaultRuntime) {
await ensurePromise;
return;
}
defaultMatrixCryptoRuntimeEnsurePromise = ensurePromise.catch((error) => {
defaultMatrixCryptoRuntimeEnsurePromise = null;
throw error;
});
await defaultMatrixCryptoRuntimeEnsurePromise;
}
async function ensureMatrixCryptoRuntimeOnce(params) {
const resolveFn = params.resolveFn ?? defaultResolveFn;
const nativeBindingPath = resolveMatrixCryptoNativeBindingPath(resolveFn);
removeIncompleteMatrixCryptoNativeBinding({
bindingPath: nativeBindingPath,
log: params.log
});
const requireFn = params.requireFn ?? defaultRequireFn;
try {
requireFn("@matrix-org/matrix-sdk-crypto-nodejs");
return;
} catch (err) {
if (!isMissingMatrixCryptoRuntimeError(err)) throw err;
}
const scriptPath = resolveFn("@matrix-org/matrix-sdk-crypto-nodejs/download-lib.js");
params.log?.("matrix: bootstrapping native crypto runtime");
const result = await (params.runCommand ?? runFixedCommandWithTimeout)({
argv: [params.nodeExecutable ?? process.execPath, scriptPath],
cwd: path.dirname(scriptPath),
timeoutMs: 3e5,
env: { COREPACK_ENABLE_DOWNLOAD_PROMPT: "0" }
});
if (result.code !== 0) {
removeIncompleteMatrixCryptoNativeBinding({
bindingPath: nativeBindingPath,
log: params.log
});
throw new Error(result.stderr.trim() || result.stdout.trim() || "Matrix crypto runtime bootstrap failed.");
}
removeIncompleteMatrixCryptoNativeBinding({
bindingPath: nativeBindingPath,
log: params.log
});
requireFn("@matrix-org/matrix-sdk-crypto-nodejs");
}
async function ensureMatrixSdkInstalled(params) {
const missing = resolveMissingMatrixPackages(params?.resolveFn);
if (missing.length === 0) return;
throw new Error(buildMatrixDepsMissingMessage(missing));
}
//#endregion
export { ensureMatrixSdkInstalled as n, isMatrixSdkAvailable as r, ensureMatrixCryptoRuntime as t };