TypeScript: add extensions to tsconfig and fix type errors (#12781)

* TypeScript: add extensions to tsconfig and fix type errors

- Add extensions/**/* to tsconfig.json includes
- Export ProviderAuthResult, AnyAgentTool from plugin-sdk
- Fix optional chaining for messageActions across channels
- Add missing type imports (MSTeamsConfig, GroupPolicy, etc.)
- Add type annotations for provider auth handlers
- Fix undici/fetch type compatibility in zalo proxy
- Correct ChannelAccountSnapshot property usage
- Add type casts for tool registrations
- Extract usage view styles and types to separate files

* TypeScript: fix optional debug calls and handleAction guards
This commit is contained in:
max
2026-02-09 10:05:38 -08:00
committed by GitHub
parent 2e4334c32c
commit 40b11db80e
87 changed files with 2947 additions and 2706 deletions

View File

@@ -78,7 +78,7 @@ export const matrixMessageActions: ChannelMessageActionAdapter = {
replyToId: replyTo ?? undefined,
threadId: threadId ?? undefined,
},
cfg,
cfg as CoreConfig,
);
}
@@ -94,7 +94,7 @@ export const matrixMessageActions: ChannelMessageActionAdapter = {
emoji,
remove,
},
cfg,
cfg as CoreConfig,
);
}
@@ -108,7 +108,7 @@ export const matrixMessageActions: ChannelMessageActionAdapter = {
messageId,
limit,
},
cfg,
cfg as CoreConfig,
);
}
@@ -122,7 +122,7 @@ export const matrixMessageActions: ChannelMessageActionAdapter = {
before: readStringParam(params, "before"),
after: readStringParam(params, "after"),
},
cfg,
cfg as CoreConfig,
);
}
@@ -136,7 +136,7 @@ export const matrixMessageActions: ChannelMessageActionAdapter = {
messageId,
content,
},
cfg,
cfg as CoreConfig,
);
}
@@ -148,7 +148,7 @@ export const matrixMessageActions: ChannelMessageActionAdapter = {
roomId: resolveRoomId(),
messageId,
},
cfg,
cfg as CoreConfig,
);
}
@@ -164,7 +164,7 @@ export const matrixMessageActions: ChannelMessageActionAdapter = {
roomId: resolveRoomId(),
messageId,
},
cfg,
cfg as CoreConfig,
);
}
@@ -176,7 +176,7 @@ export const matrixMessageActions: ChannelMessageActionAdapter = {
userId,
roomId: readStringParam(params, "roomId") ?? readStringParam(params, "channelId"),
},
cfg,
cfg as CoreConfig,
);
}
@@ -186,7 +186,7 @@ export const matrixMessageActions: ChannelMessageActionAdapter = {
action: "channelInfo",
roomId: resolveRoomId(),
},
cfg,
cfg as CoreConfig,
);
}

View File

@@ -1,4 +1,4 @@
import type { CoreConfig } from "../types.js";
import type { CoreConfig } from "../../types.js";
import type { MatrixActionClient, MatrixActionClientOpts } from "./types.js";
import { getMatrixRuntime } from "../../runtime.js";
import { getActiveMatrixClient } from "../active-client.js";
@@ -47,7 +47,9 @@ export async function resolveActionClient(
if (auth.encryption && client.crypto) {
try {
const joinedRooms = await client.getJoinedRooms();
await client.crypto.prepare(joinedRooms);
await (client.crypto as { prepare: (rooms?: string[]) => Promise<void> }).prepare(
joinedRooms,
);
} catch {
// Ignore crypto prep failures for one-off actions.
}

View File

@@ -63,7 +63,7 @@ export async function fetchEventSummary(
eventId: string,
): Promise<MatrixMessageSummary | null> {
try {
const raw = (await client.getEvent(roomId, eventId)) as MatrixRawEvent;
const raw = (await client.getEvent(roomId, eventId)) as unknown as MatrixRawEvent;
if (raw.unsigned?.redacted_because) {
return null;
}

View File

@@ -1,5 +1,5 @@
import { MatrixClient } from "@vector-im/matrix-bot-sdk";
import type { CoreConfig } from "../types.js";
import type { CoreConfig } from "../../types.js";
import type { MatrixAuth, MatrixResolvedConfig } from "./types.js";
import { getMatrixRuntime } from "../../runtime.js";
import { ensureMatrixSdkLoggingConfigured } from "./logging.js";

View File

@@ -1,6 +1,6 @@
import type { MatrixClient } from "@vector-im/matrix-bot-sdk";
import { LogService } from "@vector-im/matrix-bot-sdk";
import type { CoreConfig } from "../types.js";
import type { CoreConfig } from "../../types.js";
import type { MatrixAuth } from "./types.js";
import { resolveMatrixAuth } from "./config.js";
import { createMatrixClient } from "./create-client.js";
@@ -69,7 +69,9 @@ async function ensureSharedClientStarted(params: {
try {
const joinedRooms = await client.getJoinedRooms();
if (client.crypto) {
await client.crypto.prepare(joinedRooms);
await (client.crypto as { prepare: (rooms?: string[]) => Promise<void> }).prepare(
joinedRooms,
);
params.state.cryptoReady = true;
}
} catch (err) {

View File

@@ -1,5 +1,5 @@
import type { MatrixClient } from "@vector-im/matrix-bot-sdk";
import type { PluginRuntime } from "openclaw/plugin-sdk";
import type { PluginRuntime, RuntimeLogger } from "openclaw/plugin-sdk";
import type { MatrixAuth } from "../client.js";
import type { MatrixRawEvent } from "./types.js";
import { EventType } from "./types.js";
@@ -10,7 +10,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 {
@@ -42,10 +42,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}`,
);
@@ -76,7 +77,7 @@ export function registerMatrixMonitorEvents(params: {
warnedEncryptedRooms.add(roomId);
const warning =
"matrix: encrypted event received without encryption enabled; set channels.matrix.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);
@@ -86,7 +87,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

@@ -6,9 +6,11 @@ import {
logInboundDrop,
logTypingFailure,
resolveControlCommandGate,
type PluginRuntime,
type RuntimeEnv,
type RuntimeLogger,
} from "openclaw/plugin-sdk";
import type { CoreConfig, ReplyToMode } from "../../types.js";
import type { CoreConfig, MatrixRoomConfig, ReplyToMode } from "../../types.js";
import type { MatrixRawEvent, RoomMessageEventContent } from "./types.js";
import {
formatPollAsText,
@@ -37,34 +39,14 @@ import { EventType, RelationType } from "./types.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> | undefined;
mentionRegexes: ReturnType<PluginRuntime["channel"]["mentions"]["buildMentionRegexes"]>;
groupPolicy: "open" | "allowlist" | "disabled";
replyToMode: ReplyToMode;
threadReplies: "off" | "inbound" | "always";
@@ -121,7 +103,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
}
const isPollEvent = isPollStartType(eventType);
const locationContent = event.content as LocationMessageEventContent;
const locationContent = event.content as unknown as LocationMessageEventContent;
const isLocationEvent =
eventType === EventType.Location ||
(eventType === EventType.RoomMessage && locationContent.msgtype === EventType.Location);
@@ -159,9 +141,9 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
const roomName = roomInfo.name;
const roomAliases = [roomInfo.canonicalAlias ?? "", ...roomInfo.altAliases].filter(Boolean);
let content = event.content as RoomMessageEventContent;
let content = event.content as unknown as RoomMessageEventContent;
if (isPollEvent) {
const pollStartContent = event.content as PollStartContent;
const pollStartContent = event.content as unknown as PollStartContent;
const pollSummary = parsePollStartContent(pollStartContent);
if (pollSummary) {
pollSummary.eventId = event.event_id ?? "";
@@ -435,7 +417,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;
}
@@ -523,14 +505,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,
});
},
});

View File

@@ -55,7 +55,7 @@ export async function monitorMatrixProvider(opts: MonitorMatrixOpts = {}): Promi
if (!core.logging.shouldLogVerbose()) {
return;
}
logger.debug(message);
logger.debug?.(message);
};
const normalizeUserEntry = (raw: string) =>
@@ -75,13 +75,13 @@ export async function monitorMatrixProvider(opts: MonitorMatrixOpts = {}): Promi
): Promise<string[]> => {
let allowList = list ?? [];
if (allowList.length === 0) {
return allowList;
return allowList.map(String);
}
const entries = allowList
.map((entry) => normalizeUserEntry(String(entry)))
.filter((entry) => entry && entry !== "*");
if (entries.length === 0) {
return allowList;
return allowList.map(String);
}
const mapping: string[] = [];
const unresolved: string[] = [];
@@ -118,12 +118,12 @@ export async function monitorMatrixProvider(opts: MonitorMatrixOpts = {}): Promi
`${label} entries must be full Matrix IDs (example: @user:server). Unresolved entries are ignored.`,
);
}
return allowList;
return allowList.map(String);
};
const allowlistOnly = cfg.channels?.matrix?.allowlistOnly === true;
let allowFrom = cfg.channels?.matrix?.dm?.allowFrom ?? [];
let groupAllowFrom = cfg.channels?.matrix?.groupAllowFrom ?? [];
let allowFrom: string[] = (cfg.channels?.matrix?.dm?.allowFrom ?? []).map(String);
let groupAllowFrom: string[] = (cfg.channels?.matrix?.groupAllowFrom ?? []).map(String);
let roomsConfig = cfg.channels?.matrix?.groups ?? cfg.channels?.matrix?.rooms;
allowFrom = await resolveUserAllowlist("matrix dm allowlist", allowFrom);
@@ -307,15 +307,16 @@ export async function monitorMatrixProvider(opts: MonitorMatrixOpts = {}): Promi
if (auth.encryption && client.crypto) {
try {
// Request verification from other sessions
const verificationRequest = await client.crypto.requestOwnUserVerification();
const verificationRequest = await (
client.crypto as { requestOwnUserVerification?: () => Promise<unknown> }
).requestOwnUserVerification?.();
if (verificationRequest) {
logger.info("matrix: device verification requested - please verify in another client");
}
} catch (err) {
logger.debug(
{ error: String(err) },
"Device verification request failed (may already be verified)",
);
logger.debug?.("Device verification request failed (may already be verified)", {
error: String(err),
});
}
}

View File

@@ -29,7 +29,8 @@ async function fetchMatrixMediaBuffer(params: {
// Use the client's download method which handles auth
try {
const buffer = await params.client.downloadContent(params.mxcUrl);
const result = await params.client.downloadContent(params.mxcUrl);
const buffer = result.data;
if (buffer.byteLength > params.maxBytes) {
throw new Error("Matrix media exceeds configured size limit");
}
@@ -53,7 +54,9 @@ async function fetchEncryptedMediaBuffer(params: {
}
// decryptMedia handles downloading and decrypting the encrypted content internally
const decrypted = await params.client.crypto.decryptMedia(params.file);
const decrypted = await params.client.crypto.decryptMedia(
params.file as Parameters<typeof params.client.crypto.decryptMedia>[0],
);
if (decrypted.byteLength > params.maxBytes) {
throw new Error("Matrix media exceeds configured size limit");

View File

@@ -73,7 +73,7 @@ export type PollSummary = {
};
export function isPollStartType(eventType: string): boolean {
return POLL_START_TYPES.includes(eventType);
return (POLL_START_TYPES as readonly string[]).includes(eventType);
}
export function getTextContent(text?: TextContent): string {
@@ -147,7 +147,8 @@ export function buildPollStartContent(poll: PollInput): PollStartContent {
...buildTextContent(option),
}));
const maxSelections = poll.multiple ? Math.max(1, answers.length) : 1;
const isMultiple = (poll.maxSelections ?? 1) > 1;
const maxSelections = isMultiple ? Math.max(1, answers.length) : 1;
const fallbackText = buildPollFallbackText(
question,
answers.map((answer) => getTextContent(answer)),
@@ -156,7 +157,7 @@ export function buildPollStartContent(poll: PollInput): PollStartContent {
return {
[M_POLL_START]: {
question: buildTextContent(question),
kind: poll.multiple ? "m.poll.undisclosed" : "m.poll.disclosed",
kind: isMultiple ? "m.poll.undisclosed" : "m.poll.disclosed",
max_selections: maxSelections,
answers,
},

View File

@@ -1,5 +1,5 @@
import type { MatrixClient } from "@vector-im/matrix-bot-sdk";
import type { CoreConfig } from "../types.js";
import type { CoreConfig } from "../../types.js";
import { getMatrixRuntime } from "../../runtime.js";
import { getActiveMatrixClient } from "../active-client.js";
import {
@@ -55,7 +55,9 @@ export async function resolveMatrixClient(opts: {
if (auth.encryption && client.crypto) {
try {
const joinedRooms = await client.getJoinedRooms();
await client.crypto.prepare(joinedRooms);
await (client.crypto as { prepare: (rooms?: string[]) => Promise<void> }).prepare(
joinedRooms,
);
} catch {
// Ignore crypto prep failures for one-off sends; normal sync will retry.
}

View File

@@ -70,9 +70,12 @@ async function resolveDirectRoomId(client: MatrixClient, userId: string): Promis
// 1) Fast path: use account data (m.direct) for *this* logged-in user (the bot).
try {
const directContent = await client.getAccountData(EventType.Direct);
const directContent = (await client.getAccountData(EventType.Direct)) as Record<
string,
string[] | undefined
>;
const list = Array.isArray(directContent?.[trimmed]) ? directContent[trimmed] : [];
if (list.length > 0) {
if (list && list.length > 0) {
setDirectRoomCached(trimmed, list[0]);
return list[0];
}

View File

@@ -1,4 +1,5 @@
export type { DmPolicy, GroupPolicy } from "openclaw/plugin-sdk";
import type { DmPolicy, GroupPolicy } from "openclaw/plugin-sdk";
export type { DmPolicy, GroupPolicy };
export type ReplyToMode = "off" | "first" | "all";
@@ -92,6 +93,19 @@ export type MatrixConfig = {
export type CoreConfig = {
channels?: {
matrix?: MatrixConfig;
defaults?: {
groupPolicy?: "open" | "allowlist" | "disabled";
};
};
commands?: {
useAccessGroups?: boolean;
};
session?: {
store?: string;
};
messages?: {
ackReaction?: string;
ackReactionScope?: "group-mentions" | "group-all" | "direct" | "all";
};
[key: string]: unknown;
};