mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-09 15:35:17 +00:00
matrix: bootstrap crypto runtime when npm scripts are skipped
This commit is contained in:
committed by
Peter Steinberger
parent
dbbd41a2ed
commit
66c1da45d4
@@ -1,6 +1,6 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
|
||||
import { matrixPlugin } from "./src/channel.js";
|
||||
import { ensureMatrixCryptoRuntime } from "./src/matrix/deps.js";
|
||||
import { setMatrixRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
@@ -8,8 +8,10 @@ const plugin = {
|
||||
name: "Matrix",
|
||||
description: "Matrix channel plugin (matrix-js-sdk)",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
async register(api: OpenClawPluginApi) {
|
||||
setMatrixRuntime(api.runtime);
|
||||
await ensureMatrixCryptoRuntime();
|
||||
const { matrixPlugin } = await import("./src/channel.js");
|
||||
api.registerChannel({ plugin: matrixPlugin });
|
||||
},
|
||||
};
|
||||
|
||||
74
extensions/matrix/src/matrix/deps.test.ts
Normal file
74
extensions/matrix/src/matrix/deps.test.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { ensureMatrixCryptoRuntime } from "./deps.js";
|
||||
|
||||
const logStub = vi.fn();
|
||||
|
||||
describe("ensureMatrixCryptoRuntime", () => {
|
||||
it("returns immediately when matrix SDK loads", async () => {
|
||||
const runCommand = vi.fn();
|
||||
const requireFn = vi.fn(() => ({}));
|
||||
|
||||
await ensureMatrixCryptoRuntime({
|
||||
log: logStub,
|
||||
requireFn,
|
||||
runCommand,
|
||||
resolveFn: () => "/tmp/download-lib.js",
|
||||
nodeExecutable: "/usr/bin/node",
|
||||
});
|
||||
|
||||
expect(requireFn).toHaveBeenCalledTimes(1);
|
||||
expect(runCommand).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("bootstraps missing crypto runtime and retries matrix SDK load", async () => {
|
||||
let bootstrapped = false;
|
||||
const requireFn = vi.fn(() => {
|
||||
if (!bootstrapped) {
|
||||
throw new Error(
|
||||
"Cannot find module '@matrix-org/matrix-sdk-crypto-nodejs-linux-x64-gnu' (required by matrix sdk)",
|
||||
);
|
||||
}
|
||||
return {};
|
||||
});
|
||||
const runCommand = vi.fn(async () => {
|
||||
bootstrapped = true;
|
||||
return { code: 0, stdout: "", stderr: "" };
|
||||
});
|
||||
|
||||
await ensureMatrixCryptoRuntime({
|
||||
log: logStub,
|
||||
requireFn,
|
||||
runCommand,
|
||||
resolveFn: () => "/tmp/download-lib.js",
|
||||
nodeExecutable: "/usr/bin/node",
|
||||
});
|
||||
|
||||
expect(runCommand).toHaveBeenCalledWith({
|
||||
argv: ["/usr/bin/node", "/tmp/download-lib.js"],
|
||||
cwd: "/tmp",
|
||||
timeoutMs: 300_000,
|
||||
env: { COREPACK_ENABLE_DOWNLOAD_PROMPT: "0" },
|
||||
});
|
||||
expect(requireFn).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("rethrows non-crypto module errors without bootstrapping", async () => {
|
||||
const runCommand = vi.fn();
|
||||
const requireFn = vi.fn(() => {
|
||||
throw new Error("Cannot find module '@vector-im/matrix-bot-sdk'");
|
||||
});
|
||||
|
||||
await expect(
|
||||
ensureMatrixCryptoRuntime({
|
||||
log: logStub,
|
||||
requireFn,
|
||||
runCommand,
|
||||
resolveFn: () => "/tmp/download-lib.js",
|
||||
nodeExecutable: "/usr/bin/node",
|
||||
}),
|
||||
).rejects.toThrow("Cannot find module '@vector-im/matrix-bot-sdk'");
|
||||
|
||||
expect(runCommand).not.toHaveBeenCalled();
|
||||
expect(requireFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@@ -5,6 +5,27 @@ import { fileURLToPath } from "node:url";
|
||||
import { runPluginCommandWithTimeout, type RuntimeEnv } from "openclaw/plugin-sdk";
|
||||
|
||||
const MATRIX_SDK_PACKAGE = "@vector-im/matrix-bot-sdk";
|
||||
const MATRIX_CRYPTO_DOWNLOAD_HELPER = "@matrix-org/matrix-sdk-crypto-nodejs/download-lib.js";
|
||||
|
||||
function formatCommandError(result: { stderr: string; stdout: string }): string {
|
||||
const stderr = result.stderr.trim();
|
||||
if (stderr) {
|
||||
return stderr;
|
||||
}
|
||||
const stdout = result.stdout.trim();
|
||||
if (stdout) {
|
||||
return stdout;
|
||||
}
|
||||
return "unknown error";
|
||||
}
|
||||
|
||||
function isMissingMatrixCryptoRuntimeError(err: unknown): boolean {
|
||||
const message = err instanceof Error ? err.message : String(err ?? "");
|
||||
return (
|
||||
message.includes("Cannot find module") &&
|
||||
message.includes("@matrix-org/matrix-sdk-crypto-nodejs-")
|
||||
);
|
||||
}
|
||||
|
||||
export function isMatrixSdkAvailable(): boolean {
|
||||
try {
|
||||
@@ -21,6 +42,51 @@ function resolvePluginRoot(): string {
|
||||
return path.resolve(currentDir, "..", "..");
|
||||
}
|
||||
|
||||
export async function ensureMatrixCryptoRuntime(
|
||||
params: {
|
||||
log?: (message: string) => void;
|
||||
requireFn?: (id: string) => unknown;
|
||||
resolveFn?: (id: string) => string;
|
||||
runCommand?: typeof runPluginCommandWithTimeout;
|
||||
nodeExecutable?: string;
|
||||
} = {},
|
||||
): Promise<void> {
|
||||
const req = createRequire(import.meta.url);
|
||||
const requireFn = params.requireFn ?? ((id: string) => req(id));
|
||||
const resolveFn = params.resolveFn ?? ((id: string) => req.resolve(id));
|
||||
const runCommand = params.runCommand ?? runPluginCommandWithTimeout;
|
||||
const nodeExecutable = params.nodeExecutable ?? process.execPath;
|
||||
|
||||
try {
|
||||
requireFn(MATRIX_SDK_PACKAGE);
|
||||
return;
|
||||
} catch (err) {
|
||||
if (!isMissingMatrixCryptoRuntimeError(err)) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
const scriptPath = resolveFn(MATRIX_CRYPTO_DOWNLOAD_HELPER);
|
||||
params.log?.("matrix: crypto runtime missing; downloading platform library…");
|
||||
const result = await runCommand({
|
||||
argv: [nodeExecutable, scriptPath],
|
||||
cwd: path.dirname(scriptPath),
|
||||
timeoutMs: 300_000,
|
||||
env: { COREPACK_ENABLE_DOWNLOAD_PROMPT: "0" },
|
||||
});
|
||||
if (result.code !== 0) {
|
||||
throw new Error(`Matrix crypto runtime bootstrap failed: ${formatCommandError(result)}`);
|
||||
}
|
||||
|
||||
try {
|
||||
requireFn(MATRIX_SDK_PACKAGE);
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`Matrix crypto runtime remains unavailable after bootstrap: ${err instanceof Error ? err.message : String(err)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function ensureMatrixSdkInstalled(params: {
|
||||
runtime: RuntimeEnv;
|
||||
confirm?: (message: string) => Promise<boolean>;
|
||||
|
||||
Reference in New Issue
Block a user