Matrix-js: fix pnpm check typing regressions

This commit is contained in:
Gustavo Madeira Santana
2026-02-25 17:22:09 -05:00
parent 78354f14a5
commit 3c52124ca7
24 changed files with 123 additions and 117 deletions

View File

@@ -2,14 +2,6 @@ import { readMatrixMessages } from "../src/matrix/actions.js";
import { createMatrixClient, resolveMatrixAuth } from "../src/matrix/client.js";
import { installLiveHarnessRuntime, resolveLiveHarnessConfig } from "./live-common.js";
function toMessageText(msg: {
text: string | null;
body?: string | null;
fallbackBody?: string | null;
}): string {
return msg.text ?? msg.body ?? msg.fallbackBody ?? "";
}
async function main() {
const roomId = process.argv[2]?.trim();
if (!roomId) {
@@ -34,10 +26,10 @@ async function main() {
try {
const result = await readMatrixMessages(roomId, { client, limit });
const compact = result.messages.map((msg) => ({
id: msg.id,
id: msg.eventId,
sender: msg.sender,
ts: msg.timestamp,
text: toMessageText(msg),
text: msg.body ?? "",
}));
process.stdout.write(

View File

@@ -10,19 +10,19 @@ const resolveMatrixAuthMock = vi.fn();
vi.mock("../../runtime.js", () => ({
getMatrixRuntime: () => ({
config: {
loadConfig: (...args: unknown[]) => loadConfigMock(...args),
loadConfig: loadConfigMock,
},
}),
}));
vi.mock("../active-client.js", () => ({
getActiveMatrixClient: (...args: unknown[]) => getActiveMatrixClientMock(...args),
getActiveMatrixClient: getActiveMatrixClientMock,
}));
vi.mock("../client.js", () => ({
createMatrixClient: (...args: unknown[]) => createMatrixClientMock(...args),
createMatrixClient: createMatrixClientMock,
isBunRuntime: () => isBunRuntimeMock(),
resolveMatrixAuth: (...args: unknown[]) => resolveMatrixAuthMock(...args),
resolveMatrixAuth: resolveMatrixAuthMock,
}));
let resolveActionClient: typeof import("./client.js").resolveActionClient;

View File

@@ -1,7 +1,7 @@
import { getMatrixRuntime } from "../../runtime.js";
import type { CoreConfig } from "../../types.js";
import { getActiveMatrixClient } from "../active-client.js";
import { createMatrixClient, isBunRuntime, resolveMatrixAuth } from "../client.js";
import type { CoreConfig } from "../types.js";
import type { MatrixActionClient, MatrixActionClientOpts } from "./types.js";
export function ensureNodeRuntime() {

View File

@@ -1,4 +1,5 @@
import type { MatrixClient, MatrixRawEvent, MessageEventContent } from "../sdk.js";
import type { MatrixClient, MessageEventContent } from "../sdk.js";
export type { MatrixRawEvent } from "../sdk.js";
export const MsgType = {
Text: "m.text",

View File

@@ -10,15 +10,14 @@ const finalizeMatrixRegisterConfigAfterSuccessMock = vi.fn(async () => false);
vi.mock("./credentials.js", () => ({
loadMatrixCredentials: vi.fn(() => null),
saveMatrixCredentials: (...args: unknown[]) => saveMatrixCredentialsMock(...args),
saveMatrixCredentials: saveMatrixCredentialsMock,
credentialsMatchConfig: vi.fn(() => false),
touchMatrixCredentials: vi.fn(),
}));
vi.mock("./client/register-mode.js", () => ({
prepareMatrixRegisterMode: (...args: unknown[]) => prepareMatrixRegisterModeMock(...args),
finalizeMatrixRegisterConfigAfterSuccess: (...args: unknown[]) =>
finalizeMatrixRegisterConfigAfterSuccessMock(...args),
prepareMatrixRegisterMode: prepareMatrixRegisterModeMock,
finalizeMatrixRegisterConfigAfterSuccess: finalizeMatrixRegisterConfigAfterSuccessMock,
resetPreparedMatrixRegisterModesForTests: vi.fn(),
}));

View File

@@ -1,7 +1,7 @@
import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
import { getMatrixRuntime } from "../../runtime.js";
import type { CoreConfig } from "../../types.js";
import { MatrixClient } from "../sdk.js";
import type { CoreConfig } from "../types.js";
import { ensureMatrixSdkLoggingConfigured } from "./logging.js";
import {
finalizeMatrixRegisterConfigAfterSuccess,

View File

@@ -91,7 +91,8 @@ describe("matrix register mode helpers", () => {
}),
}),
);
const written = writeConfigFile.mock.calls[0]?.[0] as CoreConfig;
const firstCall = (writeConfigFile.mock.calls as unknown[][])[0];
const written = (firstCall?.[0] ?? {}) as CoreConfig;
expect(written.channels?.["matrix-js"]?.accessToken).toBeUndefined();
});
});

View File

@@ -112,7 +112,7 @@ export async function finalizeMatrixRegisterConfigAfterSuccess(params: {
...cfg,
channels: {
...(cfg.channels ?? {}),
"matrix-js": nextMatrix as CoreConfig["channels"]["matrix-js"],
"matrix-js": nextMatrix as NonNullable<CoreConfig["channels"]>["matrix-js"],
},
};

View File

@@ -1,6 +1,6 @@
import type { CoreConfig } from "../../types.js";
import type { MatrixClient } from "../sdk.js";
import { LogService } from "../sdk/logger.js";
import type { CoreConfig } from "../types.js";
import { resolveMatrixAuth } from "./config.js";
import { createMatrixClient } from "./create-client.js";
import { DEFAULT_ACCOUNT_KEY } from "./storage.js";

View File

@@ -7,6 +7,12 @@ import { EventType } from "./types.js";
type RoomEventListener = (roomId: string, event: MatrixRawEvent) => void;
function getSentNoticeBody(sendMessage: ReturnType<typeof vi.fn>, index = 0): string {
const calls = sendMessage.mock.calls as unknown[][];
const payload = (calls[index]?.[1] ?? {}) as { body?: string };
return payload.body ?? "";
}
function createHarness(params?: {
verifications?: Array<{
id: string;
@@ -43,7 +49,7 @@ function createHarness(params?: {
logVerboseMessage: vi.fn(),
warnedEncryptedRooms: new Set<string>(),
warnedCryptoMissingRooms: new Set<string>(),
logger: { warn: vi.fn() },
logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn() },
formatNativeDependencyHint: vi.fn(() => "install hint"),
onRoomMessage,
});
@@ -83,7 +89,7 @@ describe("registerMatrixMonitorEvents verification routing", () => {
expect(sendMessage).toHaveBeenCalledTimes(1);
});
expect(onRoomMessage).not.toHaveBeenCalled();
const body = (sendMessage.mock.calls[0]?.[1] as { body?: string } | undefined)?.body ?? "";
const body = getSentNoticeBody(sendMessage, 0);
expect(body).toContain("Matrix verification request received from @alice:example.org.");
expect(body).toContain('Open "Verify by emoji"');
});
@@ -103,7 +109,7 @@ describe("registerMatrixMonitorEvents verification routing", () => {
await vi.waitFor(() => {
expect(sendMessage).toHaveBeenCalledTimes(1);
});
const body = (sendMessage.mock.calls[0]?.[1] as { body?: string } | undefined)?.body ?? "";
const body = getSentNoticeBody(sendMessage, 0);
expect(body).toContain("Matrix verification is ready with @alice:example.org.");
expect(body).toContain('Choose "Verify by emoji"');
});
@@ -140,8 +146,8 @@ describe("registerMatrixMonitorEvents verification routing", () => {
});
await vi.waitFor(() => {
const bodies = sendMessage.mock.calls.map((call) =>
((call[1] as { body?: string } | undefined)?.body ?? "").toString(),
const bodies = (sendMessage.mock.calls as unknown[][]).map((call) =>
String((call[1] as { body?: string } | undefined)?.body ?? ""),
);
expect(bodies.some((body) => body.includes("SAS emoji:"))).toBe(true);
expect(bodies.some((body) => body.includes("SAS decimal: 6158 1986 3513"))).toBe(true);
@@ -193,7 +199,7 @@ describe("registerMatrixMonitorEvents verification routing", () => {
await new Promise((resolve) => setTimeout(resolve, 20));
const sasBodies = sendMessage.mock.calls
.map((call) => ((call[1] as { body?: string } | undefined)?.body ?? "").toString())
.map((call) => String(((call as unknown[])[1] as { body?: string } | undefined)?.body ?? ""))
.filter((body) => body.includes("SAS emoji:"));
expect(sasBodies).toHaveLength(1);
});

View File

@@ -1,4 +1,4 @@
import type { PluginRuntime } from "openclaw/plugin-sdk";
import type { PluginRuntime, RuntimeLogger } from "openclaw/plugin-sdk";
import type { MatrixAuth } from "../client.js";
import type { MatrixClient } from "../sdk.js";
import type { MatrixRawEvent } from "./types.js";
@@ -240,7 +240,7 @@ export function registerMatrixMonitorEvents(params: {
logVerboseMessage: (message: string) => void;
warnedEncryptedRooms: Set<string>;
warnedCryptoMissingRooms: Set<string>;
logger: { warn: (meta: Record<string, unknown>, message: string) => void };
logger: RuntimeLogger;
formatNativeDependencyHint: PluginRuntime["system"]["formatNativeDependencyHint"];
onRoomMessage: (roomId: string, event: MatrixRawEvent) => void | Promise<void>;
}): void {
@@ -334,10 +334,11 @@ export function registerMatrixMonitorEvents(params: {
client.on(
"room.failed_decryption",
async (roomId: string, event: MatrixRawEvent, error: Error) => {
logger.warn(
{ roomId, eventId: event.event_id, error: error.message },
"Failed to decrypt message",
);
logger.warn("Failed to decrypt message", {
roomId,
eventId: event.event_id,
error: error.message,
});
logVerboseMessage(
`matrix: failed decrypt room=${roomId} id=${event.event_id ?? "unknown"} error=${error.message}`,
);
@@ -368,7 +369,7 @@ export function registerMatrixMonitorEvents(params: {
warnedEncryptedRooms.add(roomId);
const warning =
"matrix: encrypted event received without encryption enabled; set channels.matrix-js.encryption=true and verify the device to decrypt";
logger.warn({ roomId }, warning);
logger.warn(warning, { roomId });
}
if (auth.encryption === true && !client.crypto && !warnedCryptoMissingRooms.has(roomId)) {
warnedCryptoMissingRooms.add(roomId);
@@ -378,7 +379,7 @@ export function registerMatrixMonitorEvents(params: {
downloadCommand: "node node_modules/@matrix-org/matrix-sdk-crypto-nodejs/download-lib.js",
});
const warning = `matrix: encryption enabled but crypto is unavailable; ${hint}`;
logger.warn({ roomId }, warning);
logger.warn(warning, { roomId });
}
return;
}

View File

@@ -5,9 +5,12 @@ import {
logInboundDrop,
logTypingFailure,
resolveControlCommandGate,
type PluginRuntime,
type ReplyPayload,
type RuntimeEnv,
type RuntimeLogger,
} from "openclaw/plugin-sdk";
import type { CoreConfig, ReplyToMode } from "../../types.js";
import type { CoreConfig, MatrixRoomConfig, ReplyToMode } from "../../types.js";
import {
formatPollAsText,
isPollStartType,
@@ -38,34 +41,14 @@ import { isMatrixVerificationRoomMessage } from "./verification-utils.js";
export type MatrixMonitorHandlerParams = {
client: MatrixClient;
core: {
logging: {
shouldLogVerbose: () => boolean;
};
channel: (typeof import("openclaw/plugin-sdk"))["channel"];
system: {
enqueueSystemEvent: (
text: string,
meta: { sessionKey?: string | null; contextKey?: string | null },
) => void;
};
};
core: PluginRuntime;
cfg: CoreConfig;
runtime: RuntimeEnv;
logger: {
info: (message: string | Record<string, unknown>, ...meta: unknown[]) => void;
warn: (meta: Record<string, unknown>, message: string) => void;
};
logger: RuntimeLogger;
logVerboseMessage: (message: string) => void;
allowFrom: string[];
roomsConfig: CoreConfig["channels"] extends { matrix?: infer MatrixConfig }
? MatrixConfig extends { groups?: infer Groups }
? Groups
: Record<string, unknown> | undefined
: Record<string, unknown> | undefined;
mentionRegexes: ReturnType<
(typeof import("openclaw/plugin-sdk"))["channel"]["mentions"]["buildMentionRegexes"]
>;
roomsConfig?: Record<string, MatrixRoomConfig>;
mentionRegexes: ReturnType<PluginRuntime["channel"]["mentions"]["buildMentionRegexes"]>;
groupPolicy: "open" | "allowlist" | "disabled";
replyToMode: ReplyToMode;
threadReplies: "off" | "inbound" | "always";
@@ -447,7 +430,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
hasControlCommandInMessage;
const canDetectMention = mentionRegexes.length > 0 || hasExplicitMention;
if (isRoom && shouldRequireMention && !wasMentioned && !shouldBypassMention) {
logger.info({ roomId, reason: "no-mention" }, "skipping room message");
logger.info("skipping room message", { roomId, reason: "no-mention" });
return;
}
@@ -465,7 +448,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
cfg,
channel: "matrix-js",
peer: {
kind: isDirectMessage ? "dm" : "channel",
kind: isDirectMessage ? "direct" : "channel",
id: isDirectMessage ? senderId : roomId,
},
});
@@ -535,14 +518,11 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
}
: undefined,
onRecordError: (err) => {
logger.warn(
{
error: String(err),
storePath,
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
},
"failed updating session meta",
);
logger.warn("failed updating session meta", {
error: String(err),
storePath,
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
});
},
});
@@ -623,7 +603,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
core.channel.reply.createReplyDispatcherWithTyping({
...prefixOptions,
humanDelay: core.channel.reply.resolveHumanDelayConfig(cfg, route.agentId),
deliver: async (payload) => {
deliver: async (payload: ReplyPayload) => {
await deliverMatrixReplies({
replies: [payload],
roomId,
@@ -637,7 +617,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
});
didSendReply = true;
},
onError: (err, info) => {
onError: (err: unknown, info: { kind: "tool" | "block" | "final" }) => {
runtime.error?.(`matrix ${info.kind} reply failed: ${String(err)}`);
},
onReplyStart: typingCallbacks.onReplyStart,

View File

@@ -304,7 +304,6 @@ export async function monitorMatrixProvider(opts: MonitorMatrixOpts = {}): Promi
directTracker,
getRoomInfo,
getMemberDisplayName,
accountId: opts.accountId,
});
registerMatrixMonitorEvents({

View File

@@ -20,7 +20,7 @@ async function fetchMatrixMediaBuffer(params: {
client: MatrixClient;
mxcUrl: string;
maxBytes: number;
}): Promise<{ buffer: Buffer; headerType?: string } | null> {
}): Promise<{ buffer: Buffer } | null> {
// The client wrapper exposes mxcToHttp for Matrix media URIs.
const url = params.client.mxcToHttp(params.mxcUrl);
if (!url) {
@@ -29,14 +29,13 @@ async function fetchMatrixMediaBuffer(params: {
// Use the client's download method which handles auth
try {
const result = await params.client.downloadContent(params.mxcUrl);
const raw = result.data ?? result;
const raw = await params.client.downloadContent(params.mxcUrl);
const buffer = Buffer.isBuffer(raw) ? raw : Buffer.from(raw);
if (buffer.byteLength > params.maxBytes) {
throw new Error("Matrix media exceeds configured size limit");
}
return { buffer, headerType: result.contentType };
return { buffer };
} catch (err) {
throw new Error(`Matrix media download failed: ${String(err)}`, { cause: err });
}
@@ -103,7 +102,7 @@ export async function downloadMatrixMedia(params: {
if (!fetched) {
return null;
}
const headerType = fetched.headerType ?? params.contentType ?? undefined;
const headerType = params.contentType ?? undefined;
const saved = await getMatrixRuntime().channel.media.saveMediaBuffer(
fetched.buffer,
headerType,

View File

@@ -1,14 +1,12 @@
import { getMatrixRuntime } from "../../runtime.js";
// Type for room message content with mentions
type MessageContentWithMentions = {
msgtype: string;
body: string;
formatted_body?: string;
"m.mentions"?: {
user_ids?: string[];
room?: boolean;
};
[key: string]: unknown;
};
/**

View File

@@ -19,7 +19,9 @@ export function createMatrixRoomInfoResolver(client: MatrixClient) {
let altAliases: string[] = [];
try {
const nameState = await client.getRoomStateEvent(roomId, "m.room.name", "").catch(() => null);
name = nameState?.name;
if (nameState && typeof nameState.name === "string") {
name = nameState.name;
}
} catch {
// ignore
}
@@ -27,8 +29,13 @@ export function createMatrixRoomInfoResolver(client: MatrixClient) {
const aliasState = await client
.getRoomStateEvent(roomId, "m.room.canonical_alias", "")
.catch(() => null);
canonicalAlias = aliasState?.alias;
altAliases = aliasState?.alt_aliases ?? [];
if (aliasState && typeof aliasState.alias === "string") {
canonicalAlias = aliasState.alias;
}
const rawAliases = aliasState?.alt_aliases;
if (Array.isArray(rawAliases)) {
altAliases = rawAliases.filter((entry): entry is string => typeof entry === "string");
}
} catch {
// ignore
}
@@ -42,7 +49,10 @@ export function createMatrixRoomInfoResolver(client: MatrixClient) {
const memberState = await client
.getRoomStateEvent(roomId, "m.room.member", userId)
.catch(() => null);
return memberState?.displayname ?? userId;
if (memberState && typeof memberState.displayname === "string") {
return memberState.displayname;
}
return userId;
} catch {
return userId;
}

View File

@@ -8,8 +8,6 @@ type MatrixRawEvent = {
};
type RoomMessageEventContent = {
msgtype: string;
body: string;
"m.relates_to"?: {
rel_type?: string;
event_id?: string;

View File

@@ -1,4 +1,5 @@
import type { EncryptedFile, MatrixRawEvent, MessageEventContent } from "../sdk.js";
import type { EncryptedFile, MessageEventContent } from "../sdk.js";
export type { MatrixRawEvent } from "../sdk.js";
export const EventType = {
RoomMessage: "m.room.message",

View File

@@ -549,11 +549,11 @@ describe("MatrixClient event bridge", () => {
},
});
let releaseRetry: (() => void) | null = null;
const releaseRetryRef: { current?: () => void } = {};
matrixJsClient.decryptEventIfNeeded = vi.fn(
async () =>
await new Promise<void>((resolve) => {
releaseRetry = () => {
releaseRetryRef.current = () => {
encrypted.emit("decrypted", decrypted);
resolve();
};
@@ -571,7 +571,7 @@ describe("MatrixClient event bridge", () => {
await Promise.resolve();
expect(matrixJsClient.decryptEventIfNeeded).toHaveBeenCalledTimes(1);
releaseRetry?.();
releaseRetryRef.current?.();
await Promise.resolve();
expect(delivered).toEqual(["m.room.message"]);
});
@@ -1227,11 +1227,12 @@ describe("MatrixClient crypto bootstrapping", () => {
expect(result.success).toBe(true);
expect(result.verification.backupVersion).toBe("9");
expect(
bootstrapSecretStorage.mock.calls.some(([opts]) =>
Boolean((opts as { setupNewKeyBackup?: boolean } | undefined)?.setupNewKeyBackup),
),
).toBe(false);
const bootstrapSecretStorageCalls = bootstrapSecretStorage.mock.calls as Array<
[{ setupNewKeyBackup?: boolean }?]
>;
expect(bootstrapSecretStorageCalls.some((call) => Boolean(call[0]?.setupNewKeyBackup))).toBe(
false,
);
});
it("does not report bootstrap errors when final verification state is healthy", async () => {

View File

@@ -38,6 +38,7 @@ export type {
export type {
EncryptedFile,
LocationMessageEventContent,
MatrixRawEvent,
MessageEventContent,
TextualMessageEventContent,
} from "./sdk/types.js";
@@ -187,7 +188,7 @@ export class MatrixClient {
deviceId: opts.deviceId,
logger: createMatrixJsSdkClientLogger("MatrixClient"),
localTimeoutMs: this.localTimeoutMs,
cryptoCallbacks,
cryptoCallbacks: cryptoCallbacks as never,
verificationMethods: [
VerificationMethod.Sas,
VerificationMethod.ShowQrCode,
@@ -421,7 +422,7 @@ export class MatrixClient {
}
async getAccountData(eventType: string): Promise<Record<string, unknown> | undefined> {
const event = this.client.getAccountData(eventType);
const event = this.client.getAccountData(eventType as never);
return (event?.getContent() as Record<string, unknown> | undefined) ?? undefined;
}
@@ -529,7 +530,7 @@ export class MatrixClient {
}
async uploadContent(file: Buffer, contentType?: string, filename?: string): Promise<string> {
const uploaded = await this.client.uploadContent(file, {
const uploaded = await this.client.uploadContent(new Uint8Array(file), {
type: contentType || "application/octet-stream",
name: filename,
includeFilename: Boolean(filename),
@@ -1053,8 +1054,8 @@ export class MatrixClient {
return;
}
const raw: MatrixRawEvent = {
event_id: `$membership-${roomId}-${Date.now()}`,
type: "m.room.member",
room_id: roomId,
sender: selfUserId,
state_key: selfUserId,
content: { membership },

View File

@@ -135,15 +135,21 @@ describe("MatrixCryptoBootstrapper", () => {
await bootstrapper.bootstrap(crypto);
const firstCall = bootstrapCrossSigning.mock.calls[0]?.[0] as {
authUploadDeviceSigningKeys?: <T>(
makeRequest: (authData: Record<string, unknown> | null) => Promise<T>,
) => Promise<T>;
};
expect(firstCall.authUploadDeviceSigningKeys).toBeTypeOf("function");
const bootstrapCrossSigningCalls = bootstrapCrossSigning.mock.calls as Array<
[
{
authUploadDeviceSigningKeys?: <T>(
makeRequest: (authData: Record<string, unknown> | null) => Promise<T>,
) => Promise<T>;
}?,
]
>;
const authUploadDeviceSigningKeys =
bootstrapCrossSigningCalls[0]?.[0]?.authUploadDeviceSigningKeys;
expect(authUploadDeviceSigningKeys).toBeTypeOf("function");
const seenAuthStages: Array<Record<string, unknown> | null> = [];
const result = await firstCall.authUploadDeviceSigningKeys?.(async (authData) => {
const result = await authUploadDeviceSigningKeys?.(async (authData) => {
seenAuthStages.push(authData);
if (authData === null) {
throw new Error("need auth");

View File

@@ -145,7 +145,7 @@ export class MatrixRecoveryKeyStore {
);
let generatedRecoveryKey = false;
const storedRecovery = this.loadStoredRecoveryKey();
let recoveryKey = storedRecovery
let recoveryKey: MatrixGeneratedSecretStorageKey | null = storedRecovery
? {
keyInfo: storedRecovery.keyInfo,
privateKey: new Uint8Array(Buffer.from(storedRecovery.privateKeyBase64, "base64")),

View File

@@ -1,8 +1,9 @@
import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
import { getMatrixRuntime } from "../../runtime.js";
import type { CoreConfig } from "../../types.js";
import { getActiveMatrixClient } from "../active-client.js";
import { createMatrixClient, isBunRuntime, resolveMatrixAuth } from "../client.js";
import type { MatrixClient } from "../sdk.js";
import type { CoreConfig } from "../types.js";
const getCore = () => getMatrixRuntime();
@@ -12,10 +13,20 @@ export function ensureNodeRuntime() {
}
}
export function resolveMediaMaxBytes(): number | undefined {
export function resolveMediaMaxBytes(accountId?: string | null): number | undefined {
const cfg = getCore().config.loadConfig() as CoreConfig;
if (typeof cfg.channels?.["matrix-js"]?.mediaMaxMb === "number") {
return cfg.channels["matrix-js"].mediaMaxMb * 1024 * 1024;
const matrixCfg = cfg.channels?.["matrix-js"];
const accountCfg = accountId
? (matrixCfg?.accounts?.[accountId] ?? matrixCfg?.accounts?.[normalizeAccountId(accountId)])
: undefined;
const mediaMaxMb =
typeof accountCfg?.mediaMaxMb === "number"
? accountCfg.mediaMaxMb
: typeof matrixCfg?.mediaMaxMb === "number"
? matrixCfg.mediaMaxMb
: undefined;
if (typeof mediaMaxMb === "number") {
return mediaMaxMb * 1024 * 1024;
}
return undefined;
}

View File

@@ -35,9 +35,11 @@ async function persistDirectRoom(
userId: string,
roomId: string,
): Promise<void> {
let directContent: MatrixDirectAccountData | null = null;
let directContent: MatrixDirectAccountData | undefined;
try {
directContent = await client.getAccountData(EventType.Direct);
directContent = (await client.getAccountData(EventType.Direct)) as
| MatrixDirectAccountData
| undefined;
} catch {
// Ignore fetch errors and fall back to an empty map.
}