mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 12:50:42 +00:00
perf: optimize Matrix test boundaries
This commit is contained in:
@@ -11,7 +11,7 @@ import {
|
||||
} from "openclaw/plugin-sdk/account-id";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { hasConfiguredSecretInput } from "openclaw/plugin-sdk/secret-input";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import {
|
||||
resolveMatrixAccountStringValues,
|
||||
type MatrixResolvedStringField,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { extractToolSend } from "openclaw/plugin-sdk/tool-send";
|
||||
import { requiresExplicitMatrixDefaultAccount } from "./account-selection.js";
|
||||
import { resolveDefaultMatrixAccountId, resolveMatrixAccount } from "./matrix/accounts.js";
|
||||
|
||||
@@ -14,7 +14,7 @@ import type { ExecApprovalRequest, PluginApprovalRequest } from "openclaw/plugin
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalStringifiedId,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
} from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { getMatrixApprovalAuthApprovers, matrixApprovalAuth } from "./approval-auth.js";
|
||||
import { normalizeMatrixApproverId } from "./approval-ids.js";
|
||||
import {
|
||||
|
||||
@@ -24,11 +24,11 @@ import {
|
||||
createComputedAccountStatusAdapter,
|
||||
createDefaultChannelRuntimeState,
|
||||
} from "openclaw/plugin-sdk/status-helpers";
|
||||
import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
} from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
|
||||
import { matrixMessageActions } from "./actions.js";
|
||||
import { matrixApprovalCapability } from "./approval-native.js";
|
||||
import { createMatrixPairingText, createMatrixProbeAccount } from "./channel-account-paths.js";
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { Command } from "commander";
|
||||
import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
||||
import { formatZonedTimestamp } from "openclaw/plugin-sdk/matrix-runtime-shared";
|
||||
import type { ChannelSetupInput } from "openclaw/plugin-sdk/setup";
|
||||
import { resolveMatrixAccount, resolveMatrixAccountConfig } from "./matrix/accounts.js";
|
||||
import { withResolvedActionClient, withStartedActionClient } from "./matrix/actions/client.js";
|
||||
import { listMatrixOwnDevices, pruneMatrixStaleGatewayDevices } from "./matrix/actions/devices.js";
|
||||
import { updateMatrixOwnProfile } from "./matrix/actions/profile.js";
|
||||
import {
|
||||
@@ -16,14 +18,9 @@ import { resolveMatrixAuthContext } from "./matrix/client.js";
|
||||
import { setMatrixSdkConsoleLogging, setMatrixSdkLogMode } from "./matrix/client/logging.js";
|
||||
import { resolveMatrixConfigPath, updateMatrixAccountConfig } from "./matrix/config-update.js";
|
||||
import { isOpenClawManagedMatrixDevice } from "./matrix/device-health.js";
|
||||
import {
|
||||
inspectMatrixDirectRooms,
|
||||
repairMatrixDirectRooms,
|
||||
type MatrixDirectRoomCandidate,
|
||||
} from "./matrix/direct-management.js";
|
||||
import type { MatrixDirectRoomCandidate } from "./matrix/direct-management.js";
|
||||
import { formatMatrixErrorMessage } from "./matrix/errors.js";
|
||||
import { applyMatrixProfileUpdate, type MatrixProfileUpdateResult } from "./profile-update.js";
|
||||
import { formatZonedTimestamp, normalizeAccountId, type ChannelSetupInput } from "./runtime-api.js";
|
||||
import { getMatrixRuntime } from "./runtime.js";
|
||||
import { matrixSetupAdapter } from "./setup-core.js";
|
||||
import type { CoreConfig } from "./types.js";
|
||||
@@ -334,6 +331,10 @@ async function inspectMatrixDirectRoom(params: {
|
||||
accountId: string;
|
||||
userId: string;
|
||||
}): Promise<MatrixCliDirectRoomInspection> {
|
||||
const [{ withResolvedActionClient }, { inspectMatrixDirectRooms }] = await Promise.all([
|
||||
import("./matrix/actions/client.js"),
|
||||
import("./matrix/direct-management.js"),
|
||||
]);
|
||||
return await withResolvedActionClient(
|
||||
{ accountId: params.accountId },
|
||||
async (client) => {
|
||||
@@ -361,6 +362,10 @@ async function repairMatrixDirectRoom(params: {
|
||||
}): Promise<MatrixCliDirectRoomRepair> {
|
||||
const cfg = getMatrixRuntime().config.loadConfig() as CoreConfig;
|
||||
const account = resolveMatrixAccount({ cfg, accountId: params.accountId });
|
||||
const [{ withStartedActionClient }, { repairMatrixDirectRooms }] = await Promise.all([
|
||||
import("./matrix/actions/client.js"),
|
||||
import("./matrix/direct-management.js"),
|
||||
]);
|
||||
return await withStartedActionClient({ accountId: params.accountId }, async (client) => {
|
||||
const repaired = await repairMatrixDirectRooms({
|
||||
client,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
} from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { resolveMatrixAuth } from "./matrix/client.js";
|
||||
import { MatrixAuthedHttpClient } from "./matrix/sdk/http-client.js";
|
||||
import { isMatrixQualifiedUserId, normalizeMatrixMessagingTarget } from "./matrix/target-ids.js";
|
||||
|
||||
@@ -11,7 +11,7 @@ import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import type { ExecApprovalRequest, PluginApprovalRequest } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { getMatrixApprovalAuthApprovers } from "./approval-auth.js";
|
||||
import { normalizeMatrixApproverId } from "./approval-ids.js";
|
||||
import { listMatrixAccountIds, resolveMatrixAccount } from "./matrix/accounts.js";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
||||
import { hasConfiguredSecretInput } from "openclaw/plugin-sdk/secret-input";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import {
|
||||
resolveConfiguredMatrixAccountIds,
|
||||
resolveMatrixDefaultOrOnlyAccountId,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { fetchMatrixPollMessageSummary, resolveMatrixPollRootEventId } from "../poll-summary.js";
|
||||
import { isPollEventType } from "../poll-types.js";
|
||||
import { editMessageMatrix, sendMessageMatrix } from "../send.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { getMatrixRuntime } from "../../runtime.js";
|
||||
import type { CoreConfig } from "../../types.js";
|
||||
import { formatMatrixEncryptionUnavailableError } from "../encryption-guidance.js";
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { formatErrorMessage, type PinnedDispatcherPolicy } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { coerceSecretRef } from "openclaw/plugin-sdk/provider-auth";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { retryAsync } from "openclaw/plugin-sdk/retry-runtime";
|
||||
import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
||||
import {
|
||||
coerceSecretRef,
|
||||
normalizeResolvedSecretInputString,
|
||||
} from "openclaw/plugin-sdk/secret-input";
|
||||
import type { PinnedDispatcherPolicy } from "openclaw/plugin-sdk/ssrf-dispatcher";
|
||||
import {
|
||||
requiresExplicitMatrixDefaultAccount,
|
||||
resolveMatrixDefaultOrOnlyAccountId,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import fs from "node:fs";
|
||||
import type { PinnedDispatcherPolicy } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import type { PinnedDispatcherPolicy } from "openclaw/plugin-sdk/ssrf-dispatcher";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import type { SsrFPolicy } from "../../runtime-api.js";
|
||||
import type { MatrixClient } from "../sdk.js";
|
||||
import { resolveValidatedMatrixHomeserverUrl } from "./config.js";
|
||||
|
||||
@@ -1,6 +1,95 @@
|
||||
export {
|
||||
hasReadyMatrixEnvAuth,
|
||||
resolveGlobalMatrixEnvConfig,
|
||||
resolveMatrixEnvAuthReadiness,
|
||||
resolveScopedMatrixEnvConfig,
|
||||
} from "./config.js";
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
||||
import { getMatrixScopedEnvVarNames } from "../../env-vars.js";
|
||||
|
||||
type MatrixEnvConfig = {
|
||||
homeserver: string;
|
||||
userId: string;
|
||||
accessToken?: string;
|
||||
password?: string;
|
||||
deviceId?: string;
|
||||
deviceName?: string;
|
||||
};
|
||||
|
||||
function cleanEnv(value: unknown): string {
|
||||
return typeof value === "string" ? value.trim() : "";
|
||||
}
|
||||
|
||||
export function resolveGlobalMatrixEnvConfig(env: NodeJS.ProcessEnv): MatrixEnvConfig {
|
||||
return {
|
||||
homeserver: cleanEnv(env.MATRIX_HOMESERVER),
|
||||
userId: cleanEnv(env.MATRIX_USER_ID),
|
||||
accessToken: cleanEnv(env.MATRIX_ACCESS_TOKEN) || undefined,
|
||||
password: cleanEnv(env.MATRIX_PASSWORD) || undefined,
|
||||
deviceId: cleanEnv(env.MATRIX_DEVICE_ID) || undefined,
|
||||
deviceName: cleanEnv(env.MATRIX_DEVICE_NAME) || undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function hasReadyMatrixEnvAuth(config: {
|
||||
homeserver?: string;
|
||||
userId?: string;
|
||||
accessToken?: string;
|
||||
password?: string;
|
||||
}): boolean {
|
||||
const homeserver = cleanEnv(config.homeserver);
|
||||
const userId = cleanEnv(config.userId);
|
||||
const accessToken = cleanEnv(config.accessToken);
|
||||
const password = cleanEnv(config.password);
|
||||
return Boolean(homeserver && (accessToken || (userId && password)));
|
||||
}
|
||||
|
||||
export function resolveScopedMatrixEnvConfig(
|
||||
accountId: string,
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): MatrixEnvConfig {
|
||||
const keys = getMatrixScopedEnvVarNames(accountId);
|
||||
return {
|
||||
homeserver: cleanEnv(env[keys.homeserver]),
|
||||
userId: cleanEnv(env[keys.userId]),
|
||||
accessToken: cleanEnv(env[keys.accessToken]) || undefined,
|
||||
password: cleanEnv(env[keys.password]) || undefined,
|
||||
deviceId: cleanEnv(env[keys.deviceId]) || undefined,
|
||||
deviceName: cleanEnv(env[keys.deviceName]) || undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function resolveMatrixEnvAuthReadiness(
|
||||
accountId: string,
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): {
|
||||
ready: boolean;
|
||||
homeserver?: string;
|
||||
userId?: string;
|
||||
sourceHint: string;
|
||||
missingMessage: string;
|
||||
} {
|
||||
const normalizedAccountId = normalizeAccountId(accountId);
|
||||
const scoped = resolveScopedMatrixEnvConfig(normalizedAccountId, env);
|
||||
const scopedReady = hasReadyMatrixEnvAuth(scoped);
|
||||
if (normalizedAccountId !== DEFAULT_ACCOUNT_ID) {
|
||||
const keys = getMatrixScopedEnvVarNames(normalizedAccountId);
|
||||
return {
|
||||
ready: scopedReady,
|
||||
homeserver: scoped.homeserver || undefined,
|
||||
userId: scoped.userId || undefined,
|
||||
sourceHint: `${keys.homeserver} (+ auth vars)`,
|
||||
missingMessage: `Set per-account env vars for "${normalizedAccountId}" (for example ${keys.homeserver} + ${keys.accessToken} or ${keys.userId} + ${keys.password}).`,
|
||||
};
|
||||
}
|
||||
|
||||
const defaultScoped = resolveScopedMatrixEnvConfig(DEFAULT_ACCOUNT_ID, env);
|
||||
const global = resolveGlobalMatrixEnvConfig(env);
|
||||
const defaultScopedReady = hasReadyMatrixEnvAuth(defaultScoped);
|
||||
const globalReady = hasReadyMatrixEnvAuth(global);
|
||||
const defaultKeys = getMatrixScopedEnvVarNames(DEFAULT_ACCOUNT_ID);
|
||||
return {
|
||||
ready: defaultScopedReady || globalReady,
|
||||
homeserver: defaultScoped.homeserver || global.homeserver || undefined,
|
||||
userId: defaultScoped.userId || global.userId || undefined,
|
||||
sourceHint: "MATRIX_* or MATRIX_DEFAULT_*",
|
||||
missingMessage:
|
||||
`Set Matrix env vars for the default account ` +
|
||||
`(for example MATRIX_HOMESERVER + MATRIX_ACCESS_TOKEN, MATRIX_USER_ID + MATRIX_PASSWORD, ` +
|
||||
`or ${defaultKeys.homeserver} + ${defaultKeys.accessToken}).`,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import net from "node:net";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
|
||||
function normalizeHost(host: string): string {
|
||||
const normalized = normalizeLowercaseStringOrEmpty(host).replace(/\.+$/, "");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { PinnedDispatcherPolicy } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import type { PinnedDispatcherPolicy } from "openclaw/plugin-sdk/ssrf-dispatcher";
|
||||
import type { SsrFPolicy } from "../../runtime-api.js";
|
||||
|
||||
export type MatrixResolvedConfig = {
|
||||
|
||||
76
extensions/matrix/src/matrix/client/url-validation.ts
Normal file
76
extensions/matrix/src/matrix/client/url-validation.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import {
|
||||
assertHttpUrlTargetsPrivateNetwork,
|
||||
type LookupFn,
|
||||
} from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
import { isPrivateOrLoopbackHost } from "./private-network-host.js";
|
||||
|
||||
const MATRIX_HTTP_HOMESERVER_ERROR =
|
||||
"Matrix homeserver must use https:// unless it targets a private or loopback host";
|
||||
|
||||
function cleanString(value: unknown, requiredMessage: string): string {
|
||||
const trimmed = typeof value === "string" ? value.trim() : "";
|
||||
if (!trimmed) {
|
||||
throw new Error(requiredMessage);
|
||||
}
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
export function validateMatrixHomeserverUrl(
|
||||
homeserver: string,
|
||||
opts?: { allowPrivateNetwork?: boolean },
|
||||
): string {
|
||||
const trimmed = cleanString(homeserver, "Matrix homeserver is required (matrix.homeserver)");
|
||||
|
||||
let parsed: URL;
|
||||
try {
|
||||
parsed = new URL(trimmed);
|
||||
} catch {
|
||||
throw new Error("Matrix homeserver must be a valid http(s) URL");
|
||||
}
|
||||
|
||||
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
||||
throw new Error("Matrix homeserver must use http:// or https://");
|
||||
}
|
||||
if (!parsed.hostname) {
|
||||
throw new Error("Matrix homeserver must include a hostname");
|
||||
}
|
||||
if (parsed.username || parsed.password) {
|
||||
throw new Error("Matrix homeserver URL must not include embedded credentials");
|
||||
}
|
||||
if (parsed.search || parsed.hash) {
|
||||
throw new Error("Matrix homeserver URL must not include query strings or fragments");
|
||||
}
|
||||
if (
|
||||
parsed.protocol === "http:" &&
|
||||
opts?.allowPrivateNetwork !== true &&
|
||||
!isPrivateOrLoopbackHost(parsed.hostname)
|
||||
) {
|
||||
throw new Error(MATRIX_HTTP_HOMESERVER_ERROR);
|
||||
}
|
||||
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
export async function resolveValidatedMatrixHomeserverUrl(
|
||||
homeserver: string,
|
||||
opts?: {
|
||||
dangerouslyAllowPrivateNetwork?: boolean;
|
||||
allowPrivateNetwork?: boolean;
|
||||
lookupFn?: LookupFn;
|
||||
},
|
||||
): Promise<string> {
|
||||
const allowPrivateNetwork =
|
||||
typeof opts?.dangerouslyAllowPrivateNetwork === "boolean"
|
||||
? opts.dangerouslyAllowPrivateNetwork
|
||||
: opts?.allowPrivateNetwork;
|
||||
const normalized = validateMatrixHomeserverUrl(homeserver, {
|
||||
allowPrivateNetwork,
|
||||
});
|
||||
await assertHttpUrlTargetsPrivateNetwork(normalized, {
|
||||
dangerouslyAllowPrivateNetwork: opts?.dangerouslyAllowPrivateNetwork,
|
||||
allowPrivateNetwork,
|
||||
lookupFn: opts?.lookupFn,
|
||||
errorMessage: MATRIX_HTTP_HOMESERVER_ERROR,
|
||||
});
|
||||
return normalized;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
||||
import { coerceSecretRef } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { coerceSecretRef } from "openclaw/plugin-sdk/secret-ref-runtime";
|
||||
import { normalizeSecretInputString } from "openclaw/plugin-sdk/setup";
|
||||
import type { CoreConfig, MatrixConfig } from "../types.js";
|
||||
import { findMatrixAccountConfig } from "./account-config.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { writeJsonFileAtomically } from "../runtime-api.js";
|
||||
import { writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
|
||||
import { createAsyncLock, type AsyncLock } from "./async-lock.js";
|
||||
import { loadMatrixCredentials, resolveMatrixCredentialsPath } from "./credentials-read.js";
|
||||
import type { MatrixStoredCredentials } from "./credentials-read.js";
|
||||
|
||||
@@ -4,7 +4,7 @@ import { createRequire } from "node:module";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import type { RuntimeEnv } from "../runtime-api.js";
|
||||
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime";
|
||||
|
||||
const REQUIRED_MATRIX_PACKAGES = [
|
||||
"matrix-js-sdk",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { inspectMatrixDirectRoomEvidence } from "./direct-room.js";
|
||||
import type { MatrixClient } from "./sdk.js";
|
||||
import { EventType, type MatrixDirectAccountData } from "./send/types.js";
|
||||
|
||||
@@ -1,15 +1,134 @@
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { PluginRuntime } from "../runtime-api.js";
|
||||
|
||||
const loadConfigMock = vi.fn(() => ({}));
|
||||
const resolveTextChunkLimitMock = vi.fn<
|
||||
(cfg: unknown, channel: unknown, accountId?: unknown) => number
|
||||
>(() => 4000);
|
||||
const resolveChunkModeMock = vi.fn<(cfg: unknown, channel: unknown, accountId?: unknown) => string>(
|
||||
() => "length",
|
||||
);
|
||||
const chunkMarkdownTextWithModeMock = vi.fn((text: string) => (text ? [text] : []));
|
||||
const convertMarkdownTablesMock = vi.fn((text: string) => text);
|
||||
const sendModuleMocks = vi.hoisted(() => {
|
||||
const loadConfigMock = vi.fn(() => ({}));
|
||||
const resolveTextChunkLimitMock = vi.fn<
|
||||
(cfg: unknown, channel: unknown, accountId?: unknown) => number
|
||||
>(() => 4000);
|
||||
const resolveChunkModeMock = vi.fn<
|
||||
(cfg: unknown, channel: unknown, accountId?: unknown) => string
|
||||
>(() => "length");
|
||||
const chunkMarkdownTextWithModeMock = vi.fn((text: string) => (text ? [text] : []));
|
||||
const convertMarkdownTablesMock = vi.fn((text: string) => text);
|
||||
const prepareMatrixSingleText = vi.fn(
|
||||
(text: string, opts: { cfg?: unknown; accountId?: string } = {}) => {
|
||||
const trimmedText = text.trim();
|
||||
const convertedText = convertMarkdownTablesMock(trimmedText);
|
||||
const singleEventLimit = Math.min(
|
||||
resolveTextChunkLimitMock(opts.cfg ?? {}, "matrix", opts.accountId),
|
||||
4000,
|
||||
);
|
||||
return {
|
||||
trimmedText,
|
||||
convertedText,
|
||||
singleEventLimit,
|
||||
fitsInSingleEvent: convertedText.length <= singleEventLimit,
|
||||
};
|
||||
},
|
||||
);
|
||||
const sendSingleTextMessageMatrix = vi.fn(
|
||||
async (
|
||||
roomId: string,
|
||||
text: string,
|
||||
opts: {
|
||||
client?: {
|
||||
sendMessage: (roomId: string, content: Record<string, unknown>) => Promise<string>;
|
||||
};
|
||||
cfg?: unknown;
|
||||
accountId?: string;
|
||||
msgtype?: string;
|
||||
includeMentions?: boolean;
|
||||
live?: boolean;
|
||||
} = {},
|
||||
) => {
|
||||
const prepared = prepareMatrixSingleText(text, {
|
||||
cfg: opts.cfg,
|
||||
accountId: opts.accountId,
|
||||
});
|
||||
if (!prepared.trimmedText) {
|
||||
throw new Error("Matrix single-message send requires text");
|
||||
}
|
||||
if (!prepared.fitsInSingleEvent) {
|
||||
throw new Error("Matrix single-message text exceeds limit");
|
||||
}
|
||||
const content: Record<string, unknown> = {
|
||||
msgtype: opts.msgtype ?? "m.text",
|
||||
body: prepared.convertedText,
|
||||
};
|
||||
if (opts.live) {
|
||||
content["org.matrix.msc4357.live"] = {};
|
||||
}
|
||||
const eventId = await opts.client?.sendMessage(roomId, content);
|
||||
return {
|
||||
messageId: eventId ?? "unknown",
|
||||
roomId,
|
||||
primaryMessageId: eventId ?? "unknown",
|
||||
messageIds: eventId ? [eventId] : [],
|
||||
};
|
||||
},
|
||||
);
|
||||
const editMessageMatrix = vi.fn(
|
||||
async (
|
||||
roomId: string,
|
||||
originalEventId: string,
|
||||
newText: string,
|
||||
opts: {
|
||||
client?: {
|
||||
sendMessage: (roomId: string, content: Record<string, unknown>) => Promise<string>;
|
||||
};
|
||||
msgtype?: string;
|
||||
live?: boolean;
|
||||
} = {},
|
||||
) => {
|
||||
const convertedText = convertMarkdownTablesMock(newText);
|
||||
const newContent: Record<string, unknown> = {
|
||||
msgtype: opts.msgtype ?? "m.text",
|
||||
body: convertedText,
|
||||
};
|
||||
if (opts.live) {
|
||||
newContent["org.matrix.msc4357.live"] = {};
|
||||
}
|
||||
const content: Record<string, unknown> = {
|
||||
...newContent,
|
||||
body: `* ${convertedText}`,
|
||||
"m.new_content": newContent,
|
||||
"m.relates_to": {
|
||||
rel_type: "m.replace",
|
||||
event_id: originalEventId,
|
||||
},
|
||||
};
|
||||
if (opts.live) {
|
||||
content["org.matrix.msc4357.live"] = {};
|
||||
}
|
||||
return (await opts.client?.sendMessage(roomId, content)) ?? "";
|
||||
},
|
||||
);
|
||||
return {
|
||||
chunkMarkdownTextWithModeMock,
|
||||
convertMarkdownTablesMock,
|
||||
editMessageMatrix,
|
||||
loadConfigMock,
|
||||
prepareMatrixSingleText,
|
||||
resolveChunkModeMock,
|
||||
resolveTextChunkLimitMock,
|
||||
sendSingleTextMessageMatrix,
|
||||
};
|
||||
});
|
||||
|
||||
const {
|
||||
chunkMarkdownTextWithModeMock,
|
||||
convertMarkdownTablesMock,
|
||||
loadConfigMock,
|
||||
resolveChunkModeMock,
|
||||
resolveTextChunkLimitMock,
|
||||
} = sendModuleMocks;
|
||||
|
||||
vi.mock("./send.js", () => ({
|
||||
editMessageMatrix: sendModuleMocks.editMessageMatrix,
|
||||
prepareMatrixSingleText: sendModuleMocks.prepareMatrixSingleText,
|
||||
sendSingleTextMessageMatrix: sendModuleMocks.sendSingleTextMessageMatrix,
|
||||
}));
|
||||
const runtimeStub = {
|
||||
config: { loadConfig: () => loadConfigMock() },
|
||||
channel: {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
|
||||
export function formatMatrixErrorMessage(err: unknown): string {
|
||||
return formatErrorMessage(err);
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import MarkdownIt from "markdown-it";
|
||||
import {
|
||||
isAutoLinkedFileRef,
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { isAutoLinkedFileRef } from "openclaw/plugin-sdk/text-autolink-runtime";
|
||||
import type { MatrixClient } from "./sdk.js";
|
||||
import { isMatrixQualifiedUserId } from "./target-ids.js";
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { resolveAckReaction } from "openclaw/plugin-sdk/channel-feedback";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import type { CoreConfig } from "../../types.js";
|
||||
import { resolveMatrixAccountConfig } from "../account-config.js";
|
||||
import { resolveAckReaction, type OpenClawConfig } from "./runtime-api.js";
|
||||
|
||||
type MatrixAckReactionScope = "group-mentions" | "group-all" | "direct" | "all" | "none" | "off";
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ import {
|
||||
resolveAllowlistMatchByCandidates,
|
||||
type AllowlistMatch,
|
||||
} from "openclaw/plugin-sdk/allow-from";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { normalizeStringEntries } from "openclaw/plugin-sdk/string-normalization-runtime";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
|
||||
function normalizeAllowList(list?: Array<string | number>) {
|
||||
return normalizeStringEntries(list);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { normalizeStringifiedOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeStringifiedOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { getMatrixRuntime } from "../../runtime.js";
|
||||
import type { MatrixConfig } from "../../types.js";
|
||||
import type { MatrixClient } from "../sdk.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import type { PluginRuntime, RuntimeLogger } from "../../runtime-api.js";
|
||||
import type { CoreConfig } from "../../types.js";
|
||||
import type { MatrixAuth } from "../client.js";
|
||||
|
||||
@@ -25,6 +25,35 @@ import {
|
||||
} from "./handler.test-helpers.js";
|
||||
import { type MatrixRawEvent } from "./types.js";
|
||||
|
||||
const deliverMatrixRepliesMock = vi.hoisted(() => vi.fn(async () => true));
|
||||
|
||||
vi.mock("./replies.js", () => ({
|
||||
deliverMatrixReplies: deliverMatrixRepliesMock,
|
||||
}));
|
||||
|
||||
vi.mock("./route.js", () => ({
|
||||
resolveMatrixInboundRoute: (params: {
|
||||
resolveAgentRoute: (input: unknown) => unknown;
|
||||
cfg: unknown;
|
||||
accountId: string;
|
||||
roomId: string;
|
||||
senderId: string;
|
||||
isDirectMessage: boolean;
|
||||
}) => ({
|
||||
route: params.resolveAgentRoute({
|
||||
cfg: params.cfg,
|
||||
channel: "matrix",
|
||||
accountId: params.accountId,
|
||||
peer: {
|
||||
kind: params.isDirectMessage ? "direct" : "channel",
|
||||
id: params.isDirectMessage ? params.senderId : params.roomId,
|
||||
},
|
||||
}),
|
||||
configuredBinding: null,
|
||||
runtimeBindingId: null,
|
||||
}),
|
||||
}));
|
||||
|
||||
const DEFAULT_ROOM = "!room:example.org";
|
||||
|
||||
function makeRoomTriggerEvent(params: { eventId: string; body: string; ts?: number }) {
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import { resolveControlCommandGate } from "openclaw/plugin-sdk/command-auth";
|
||||
import { resolveControlCommandGate } from "openclaw/plugin-sdk/command-gating";
|
||||
import {
|
||||
evaluateSupplementalContextVisibility,
|
||||
resolveChannelContextVisibilityMode,
|
||||
} from "openclaw/plugin-sdk/context-visibility-runtime";
|
||||
import {
|
||||
loadSessionStore,
|
||||
resolveChannelContextVisibilityMode,
|
||||
resolveSessionStoreEntry,
|
||||
} from "openclaw/plugin-sdk/config-runtime";
|
||||
import { getSessionBindingService } from "openclaw/plugin-sdk/conversation-runtime";
|
||||
import { evaluateSupplementalContextVisibility } from "openclaw/plugin-sdk/security-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
} from "openclaw/plugin-sdk/session-store-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import type {
|
||||
CoreConfig,
|
||||
MatrixRoomConfig,
|
||||
MatrixStreamingMode,
|
||||
ReplyToMode,
|
||||
} from "../../types.js";
|
||||
import { createMatrixDraftStream } from "../draft-stream.js";
|
||||
import { formatMatrixErrorMessage } from "../errors.js";
|
||||
import { isMatrixMediaSizeLimitError } from "../media-errors.js";
|
||||
import {
|
||||
@@ -31,13 +31,6 @@ import {
|
||||
parsePollStartContent,
|
||||
} from "../poll-types.js";
|
||||
import type { LocationMessageEventContent, MatrixClient } from "../sdk.js";
|
||||
import {
|
||||
editMessageMatrix,
|
||||
reactMatrixMessage,
|
||||
sendMessageMatrix,
|
||||
sendReadReceiptMatrix,
|
||||
sendTypingMatrix,
|
||||
} from "../send.js";
|
||||
import { MATRIX_OPENCLAW_FINALIZED_PREVIEW_KEY } from "../send/types.js";
|
||||
import { resolveMatrixStoredSessionMeta } from "../session-store-metadata.js";
|
||||
import { resolveMatrixMonitorAccessState } from "./access-state.js";
|
||||
@@ -47,7 +40,6 @@ import type { MatrixInboundEventDeduper } from "./inbound-dedupe.js";
|
||||
import { resolveMatrixLocation, type MatrixLocationPayload } from "./location.js";
|
||||
import { downloadMatrixMedia } from "./media.js";
|
||||
import { resolveMentions } from "./mentions.js";
|
||||
import { handleInboundMatrixReaction } from "./reaction-events.js";
|
||||
import { deliverMatrixReplies } from "./replies.js";
|
||||
import { createMatrixReplyContextResolver } from "./reply-context.js";
|
||||
import { createRoomHistoryTracker } from "./room-history.js";
|
||||
@@ -57,7 +49,6 @@ import { resolveMatrixInboundRoute } from "./route.js";
|
||||
import {
|
||||
createReplyPrefixOptions,
|
||||
createTypingCallbacks,
|
||||
ensureConfiguredAcpBindingReady,
|
||||
formatAllowlistMatchMeta,
|
||||
getAgentScopedMediaLocalRoots,
|
||||
logInboundDrop,
|
||||
@@ -80,9 +71,44 @@ import { isMatrixVerificationRoomMessage } from "./verification-utils.js";
|
||||
|
||||
const ALLOW_FROM_STORE_CACHE_TTL_MS = 30_000;
|
||||
const PAIRING_REPLY_COOLDOWN_MS = 5 * 60_000;
|
||||
let matrixSendModulePromise: Promise<typeof import("../send.js")> | undefined;
|
||||
let acpBindingRuntimePromise:
|
||||
| Promise<typeof import("openclaw/plugin-sdk/acp-binding-runtime")>
|
||||
| undefined;
|
||||
let sessionBindingRuntimePromise:
|
||||
| Promise<typeof import("openclaw/plugin-sdk/session-binding-runtime")>
|
||||
| undefined;
|
||||
|
||||
function loadMatrixSendModule(): Promise<typeof import("../send.js")> {
|
||||
matrixSendModulePromise ??= import("../send.js");
|
||||
return matrixSendModulePromise;
|
||||
}
|
||||
|
||||
function loadAcpBindingRuntime(): Promise<
|
||||
typeof import("openclaw/plugin-sdk/acp-binding-runtime")
|
||||
> {
|
||||
acpBindingRuntimePromise ??= import("openclaw/plugin-sdk/acp-binding-runtime");
|
||||
return acpBindingRuntimePromise;
|
||||
}
|
||||
|
||||
function loadSessionBindingRuntime(): Promise<
|
||||
typeof import("openclaw/plugin-sdk/session-binding-runtime")
|
||||
> {
|
||||
sessionBindingRuntimePromise ??= import("openclaw/plugin-sdk/session-binding-runtime");
|
||||
return sessionBindingRuntimePromise;
|
||||
}
|
||||
const MAX_TRACKED_PAIRING_REPLY_SENDERS = 512;
|
||||
const MAX_TRACKED_SHARED_DM_CONTEXT_NOTICES = 512;
|
||||
type MatrixAllowBotsMode = "off" | "mentions" | "all";
|
||||
type MatrixDraftStreamHandle = {
|
||||
update: (text: string) => void;
|
||||
stop: () => Promise<string | undefined>;
|
||||
eventId: () => string | undefined;
|
||||
mustDeliverFinalNormally: () => boolean;
|
||||
matchesPreparedText: (text: string) => boolean;
|
||||
finalizeLive: () => Promise<boolean>;
|
||||
reset: () => void;
|
||||
};
|
||||
|
||||
export class MatrixRetryableInboundError extends Error {
|
||||
constructor(message: string, options?: ErrorOptions) {
|
||||
@@ -426,7 +452,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
return async (roomId: string, event: MatrixRawEvent) => {
|
||||
const eventId = typeof event.event_id === "string" ? event.event_id.trim() : "";
|
||||
let claimedInboundEvent = false;
|
||||
let draftStreamRef: ReturnType<typeof createMatrixDraftStream> | undefined;
|
||||
let draftStreamRef: MatrixDraftStreamHandle | undefined;
|
||||
let draftConsumed = false;
|
||||
try {
|
||||
const eventType = event.type;
|
||||
@@ -645,6 +671,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
: `matrix pairing reminder sender=${senderId} name=${senderName ?? "unknown"} (${allowMatchMeta})`,
|
||||
);
|
||||
try {
|
||||
const { sendMessageMatrix } = await loadMatrixSendModule();
|
||||
await sendMessageMatrix(
|
||||
`room:${roomId}`,
|
||||
created
|
||||
@@ -712,6 +739,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
|
||||
if (isReactionEvent) {
|
||||
const senderName = await getSenderName();
|
||||
const { handleInboundMatrixReaction } = await import("./reaction-events.js");
|
||||
await handleInboundMatrixReaction({
|
||||
client,
|
||||
core,
|
||||
@@ -957,6 +985,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
}
|
||||
const senderName = await getSenderName();
|
||||
if (_configuredBinding) {
|
||||
const { ensureConfiguredAcpBindingReady } = await loadAcpBindingRuntime();
|
||||
const ensured = await ensureConfiguredAcpBindingReady({
|
||||
cfg,
|
||||
configuredBinding: _configuredBinding,
|
||||
@@ -972,6 +1001,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
}
|
||||
}
|
||||
if (_runtimeBindingId) {
|
||||
const { getSessionBindingService } = await loadSessionBindingRuntime();
|
||||
getSessionBindingService().touch(_runtimeBindingId, eventTs ?? undefined);
|
||||
}
|
||||
const preparedTrigger =
|
||||
@@ -1270,17 +1300,23 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
}),
|
||||
);
|
||||
if (shouldAckReaction() && _messageId) {
|
||||
reactMatrixMessage(roomId, _messageId, ackReaction, client).catch((err) => {
|
||||
logVerboseMessage(`matrix react failed for room ${roomId}: ${String(err)}`);
|
||||
});
|
||||
loadMatrixSendModule()
|
||||
.then(({ reactMatrixMessage }) =>
|
||||
reactMatrixMessage(roomId, _messageId, ackReaction, client),
|
||||
)
|
||||
.catch((err) => {
|
||||
logVerboseMessage(`matrix react failed for room ${roomId}: ${String(err)}`);
|
||||
});
|
||||
}
|
||||
|
||||
if (_messageId) {
|
||||
sendReadReceiptMatrix(roomId, _messageId, client).catch((err) => {
|
||||
logVerboseMessage(
|
||||
`matrix: read receipt failed room=${roomId} id=${_messageId}: ${String(err)}`,
|
||||
);
|
||||
});
|
||||
loadMatrixSendModule()
|
||||
.then(({ sendReadReceiptMatrix }) => sendReadReceiptMatrix(roomId, _messageId, client))
|
||||
.catch((err) => {
|
||||
logVerboseMessage(
|
||||
`matrix: read receipt failed room=${roomId} id=${_messageId}: ${String(err)}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
const tableMode = core.channel.text.resolveMarkdownTableMode({
|
||||
@@ -1299,8 +1335,14 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
accountId: _route.accountId,
|
||||
});
|
||||
const typingCallbacks = createTypingCallbacks({
|
||||
start: () => sendTypingMatrix(roomId, true, undefined, client),
|
||||
stop: () => sendTypingMatrix(roomId, false, undefined, client),
|
||||
start: async () => {
|
||||
const { sendTypingMatrix } = await loadMatrixSendModule();
|
||||
await sendTypingMatrix(roomId, true, undefined, client);
|
||||
},
|
||||
stop: async () => {
|
||||
const { sendTypingMatrix } = await loadMatrixSendModule();
|
||||
await sendTypingMatrix(roomId, false, undefined, client);
|
||||
},
|
||||
onStartError: (err) => {
|
||||
logTypingFailure({
|
||||
log: logVerboseMessage,
|
||||
@@ -1323,18 +1365,20 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
const draftStreamingEnabled = streaming !== "off";
|
||||
const quietDraftStreaming = streaming === "quiet";
|
||||
const draftReplyToId = replyToMode !== "off" && !threadTarget ? _messageId : undefined;
|
||||
const draftStream = draftStreamingEnabled
|
||||
? createMatrixDraftStream({
|
||||
roomId,
|
||||
client,
|
||||
cfg,
|
||||
mode: quietDraftStreaming ? "quiet" : "partial",
|
||||
threadId: threadTarget,
|
||||
replyToId: draftReplyToId,
|
||||
preserveReplyId: replyToMode === "all",
|
||||
accountId: _route.accountId,
|
||||
log: logVerboseMessage,
|
||||
})
|
||||
const draftStream: MatrixDraftStreamHandle | undefined = draftStreamingEnabled
|
||||
? await import("../draft-stream.js").then(({ createMatrixDraftStream }) =>
|
||||
createMatrixDraftStream({
|
||||
roomId,
|
||||
client,
|
||||
cfg,
|
||||
mode: quietDraftStreaming ? "quiet" : "partial",
|
||||
threadId: threadTarget,
|
||||
replyToId: draftReplyToId,
|
||||
preserveReplyId: replyToMode === "all",
|
||||
accountId: _route.accountId,
|
||||
log: logVerboseMessage,
|
||||
}),
|
||||
)
|
||||
: undefined;
|
||||
draftStreamRef = draftStream;
|
||||
type PendingDraftBoundary = {
|
||||
@@ -1458,6 +1502,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
const requiresFinalEdit =
|
||||
quietDraftStreaming || !draftStream.matchesPreparedText(payload.text);
|
||||
if (requiresFinalEdit) {
|
||||
const { editMessageMatrix } = await loadMatrixSendModule();
|
||||
await editMessageMatrix(roomId, draftEventId, payload.text, {
|
||||
client,
|
||||
cfg,
|
||||
@@ -1500,6 +1545,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
quietDraftStreaming ||
|
||||
(typeof payloadText === "string" && !payloadTextMatchesDraft);
|
||||
if (textEditOk && payloadText && requiresFinalTextEdit) {
|
||||
const { editMessageMatrix } = await loadMatrixSendModule();
|
||||
textEditOk = await editMessageMatrix(roomId, draftEventId, payloadText, {
|
||||
client,
|
||||
cfg,
|
||||
@@ -1568,6 +1614,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
|
||||
// Re-assert typing so the user still sees the indicator while
|
||||
// the next block generates.
|
||||
const { sendTypingMatrix } = await loadMatrixSendModule();
|
||||
await sendTypingMatrix(roomId, true, undefined, client).catch(() => {});
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
} from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import type { LocationMessageEventContent } from "../sdk.js";
|
||||
import { formatLocationText, toLocationContext, type NormalizedLocation } from "./runtime-api.js";
|
||||
import { EventType } from "./types.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { getMatrixRuntime } from "../../runtime.js";
|
||||
import type { RoomMessageEventContent } from "./types.js";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getSessionBindingService } from "openclaw/plugin-sdk/conversation-runtime";
|
||||
import { getSessionBindingService } from "openclaw/plugin-sdk/session-binding-runtime";
|
||||
import { matrixApprovalCapability } from "../../approval-native.js";
|
||||
import {
|
||||
resolveMatrixApprovalReactionTarget,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { getMatrixRuntime } from "../../runtime.js";
|
||||
import type { MatrixClient } from "../sdk.js";
|
||||
import { chunkMatrixText, sendMessageMatrix } from "../send.js";
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { buildAgentSessionKey, deriveLastRoutePolicy } from "openclaw/plugin-sdk/routing";
|
||||
import { resolveConfiguredAcpBindingRecord } from "openclaw/plugin-sdk/acp-binding-resolve-runtime";
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk/plugin-runtime";
|
||||
import {
|
||||
getSessionBindingService,
|
||||
buildAgentSessionKey,
|
||||
deriveLastRoutePolicy,
|
||||
resolveAgentIdFromSessionKey,
|
||||
resolveConfiguredAcpBindingRecord,
|
||||
type PluginRuntime,
|
||||
} from "../../runtime-api.js";
|
||||
} from "openclaw/plugin-sdk/routing";
|
||||
import { getSessionBindingService } from "openclaw/plugin-sdk/session-binding-runtime";
|
||||
import type { CoreConfig } from "../../types.js";
|
||||
import { resolveMatrixThreadSessionKeys } from "./threads.js";
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
// Keep monitor internals off the broad package runtime-api barrel so monitor
|
||||
// tests and shared workers do not pull unrelated Matrix helper surfaces.
|
||||
|
||||
export { ensureConfiguredAcpBindingReady } from "openclaw/plugin-sdk/acp-binding-runtime";
|
||||
export type { NormalizedLocation } from "openclaw/plugin-sdk/channel-inbound";
|
||||
export type { NormalizedLocation } from "openclaw/plugin-sdk/channel-location";
|
||||
export type { PluginRuntime, RuntimeLogger } from "openclaw/plugin-sdk/plugin-runtime";
|
||||
export type { BlockReplyContext, ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
|
||||
export type { MarkdownTableMode, OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
@@ -18,13 +17,10 @@ export {
|
||||
} from "openclaw/plugin-sdk/allow-from";
|
||||
export { createReplyPrefixOptions } from "openclaw/plugin-sdk/channel-reply-pipeline";
|
||||
export { createTypingCallbacks } from "openclaw/plugin-sdk/channel-reply-pipeline";
|
||||
export {
|
||||
formatLocationText,
|
||||
logInboundDrop,
|
||||
toLocationContext,
|
||||
} from "openclaw/plugin-sdk/channel-inbound";
|
||||
export { formatLocationText, toLocationContext } from "openclaw/plugin-sdk/channel-location";
|
||||
export { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/agent-media-payload";
|
||||
export { logTypingFailure, resolveAckReaction } from "openclaw/plugin-sdk/channel-feedback";
|
||||
export { logInboundDrop, logTypingFailure } from "openclaw/plugin-sdk/channel-logging";
|
||||
export { resolveAckReaction } from "openclaw/plugin-sdk/channel-feedback";
|
||||
export {
|
||||
buildChannelKeyCandidates,
|
||||
resolveChannelEntryMatch,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
|
||||
const VERIFICATION_EVENT_PREFIX = "m.key.verification.";
|
||||
const VERIFICATION_REQUEST_MSGTYPE = "m.key.verification.request";
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { loadOutboundMediaFromUrl } from "../runtime-api.js";
|
||||
export { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media";
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
* - m.poll.end - Closes a poll
|
||||
*/
|
||||
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizePollInput, type PollInput } from "../runtime-api.js";
|
||||
import { normalizePollInput, type PollInput } from "openclaw/plugin-sdk/poll-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
|
||||
export const M_POLL_START = "m.poll.start" as const;
|
||||
export const M_POLL_RESPONSE = "m.poll.response" as const;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { formatErrorMessage, type PinnedDispatcherPolicy } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import type { SsrFPolicy } from "../runtime-api.js";
|
||||
import type { BaseProbeResult } from "../runtime-api.js";
|
||||
import { isBunRuntime } from "./client/runtime.js";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
} from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import type { MatrixClient } from "./sdk.js";
|
||||
|
||||
export const MATRIX_PROFILE_AVATAR_MAX_BYTES = 10 * 1024 * 1024;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
|
||||
export const MATRIX_ANNOTATION_RELATION_TYPE = "m.annotation";
|
||||
export const MATRIX_REACTION_EVENT_TYPE = "m.reaction";
|
||||
|
||||
@@ -10,9 +10,9 @@ import {
|
||||
type MatrixEvent,
|
||||
} from "matrix-js-sdk/lib/matrix.js";
|
||||
import { VerificationMethod } from "matrix-js-sdk/lib/types.js";
|
||||
import type { PinnedDispatcherPolicy } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
|
||||
import { normalizeNullableString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import type { PinnedDispatcherPolicy } from "openclaw/plugin-sdk/ssrf-dispatcher";
|
||||
import { normalizeNullableString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import type { SsrFPolicy } from "../runtime-api.js";
|
||||
import { resolveMatrixRoomKeyBackupReadinessError } from "./backup-health.js";
|
||||
import { FileBackedMatrixSyncStore } from "./client/file-sync-store.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { PinnedDispatcherPolicy } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import type { PinnedDispatcherPolicy } from "openclaw/plugin-sdk/ssrf-dispatcher";
|
||||
import type { SsrFPolicy } from "../../runtime-api.js";
|
||||
import { buildHttpError } from "./event-helpers.js";
|
||||
import { type HttpMethod, type QueryParams, performMatrixRequest } from "./transport.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { FileLockOptions } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import type { FileLockOptions } from "openclaw/plugin-sdk/file-lock";
|
||||
|
||||
export const MATRIX_IDB_PERSIST_INTERVAL_MS = 60_000;
|
||||
|
||||
|
||||
@@ -15,9 +15,9 @@ const { withFileLockMock } = vi.hoisted(() => ({
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/infra-runtime", async () => {
|
||||
const actual = await vi.importActual<typeof import("openclaw/plugin-sdk/infra-runtime")>(
|
||||
"openclaw/plugin-sdk/infra-runtime",
|
||||
vi.mock("openclaw/plugin-sdk/file-lock", async () => {
|
||||
const actual = await vi.importActual<typeof import("openclaw/plugin-sdk/file-lock")>(
|
||||
"openclaw/plugin-sdk/file-lock",
|
||||
);
|
||||
return {
|
||||
...actual,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { indexedDB as fakeIndexedDB } from "fake-indexeddb";
|
||||
import { withFileLock } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { withFileLock } from "openclaw/plugin-sdk/file-lock";
|
||||
import { MATRIX_IDB_SNAPSHOT_LOCK_OPTIONS } from "./idb-persistence-lock.js";
|
||||
import { LogService } from "./logger.js";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { readResponseWithLimit as readSharedResponseWithLimit } from "openclaw/plugin-sdk/media-runtime";
|
||||
import { readResponseWithLimit as readSharedResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
|
||||
|
||||
export async function readResponseWithLimit(
|
||||
res: Response,
|
||||
|
||||
49
extensions/matrix/src/matrix/sdk/transport-runtime-api.ts
Normal file
49
extensions/matrix/src/matrix/sdk/transport-runtime-api.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { fetchWithRuntimeDispatcher } from "openclaw/plugin-sdk/runtime-fetch";
|
||||
import {
|
||||
closeDispatcher,
|
||||
createPinnedDispatcher,
|
||||
resolvePinnedHostnameWithPolicy,
|
||||
type PinnedDispatcherPolicy,
|
||||
type SsrFPolicy,
|
||||
} from "openclaw/plugin-sdk/ssrf-dispatcher";
|
||||
|
||||
export {
|
||||
closeDispatcher,
|
||||
createPinnedDispatcher,
|
||||
fetchWithRuntimeDispatcher,
|
||||
resolvePinnedHostnameWithPolicy,
|
||||
type PinnedDispatcherPolicy,
|
||||
type SsrFPolicy,
|
||||
};
|
||||
|
||||
export function buildTimeoutAbortSignal(params: { timeoutMs?: number; signal?: AbortSignal }): {
|
||||
signal?: AbortSignal;
|
||||
cleanup: () => void;
|
||||
} {
|
||||
const { timeoutMs, signal } = params;
|
||||
if (!timeoutMs && !signal) {
|
||||
return { signal: undefined, cleanup: () => {} };
|
||||
}
|
||||
if (!timeoutMs) {
|
||||
return { signal, cleanup: () => {} };
|
||||
}
|
||||
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(controller.abort.bind(controller), timeoutMs);
|
||||
const onAbort = () => controller.abort();
|
||||
if (signal) {
|
||||
if (signal.aborted) {
|
||||
controller.abort();
|
||||
} else {
|
||||
signal.addEventListener("abort", onAbort, { once: true });
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
signal: controller.signal,
|
||||
cleanup: () => {
|
||||
clearTimeout(timeoutId);
|
||||
signal?.removeEventListener("abort", onAbort);
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1,16 +1,14 @@
|
||||
import {
|
||||
fetchWithRuntimeDispatcher,
|
||||
type PinnedDispatcherPolicy,
|
||||
} from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { MatrixMediaSizeLimitError } from "../media-errors.js";
|
||||
import { readResponseWithLimit } from "./read-response-with-limit.js";
|
||||
import {
|
||||
buildTimeoutAbortSignal,
|
||||
closeDispatcher,
|
||||
createPinnedDispatcher,
|
||||
resolvePinnedHostnameWithPolicy,
|
||||
type SsrFPolicy,
|
||||
} from "../../runtime-api.js";
|
||||
import { MatrixMediaSizeLimitError } from "../media-errors.js";
|
||||
import { readResponseWithLimit } from "./read-response-with-limit.js";
|
||||
fetchWithRuntimeDispatcher,
|
||||
type PinnedDispatcherPolicy,
|
||||
} from "./transport-runtime-api.js";
|
||||
|
||||
export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalStringifiedId,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
} from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { inspectMatrixDirectRooms, persistMatrixDirectRoomMapping } from "../direct-management.js";
|
||||
import { isStrictDirectRoom } from "../direct-room.js";
|
||||
import type { MatrixClient } from "../sdk.js";
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
type SessionBindingRecord,
|
||||
} from "openclaw/plugin-sdk/conversation-binding-runtime";
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { findMatrixAccountConfig, resolveMatrixBaseConfig } from "./account-config.js";
|
||||
import { resolveMatrixTargetIdentity } from "./target-ids.js";
|
||||
import {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
|
||||
type MatrixTarget = { kind: "room"; id: string } | { kind: "user"; id: string };
|
||||
const MATRIX_PREFIX = "matrix:";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import path from "node:path";
|
||||
import { readJsonFileWithFallback, writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
|
||||
import { resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/routing";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import {
|
||||
registerSessionBindingAdapter,
|
||||
resolveThreadBindingFarewellText,
|
||||
|
||||
@@ -3,7 +3,7 @@ import os from "node:os";
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import {
|
||||
findMatrixAccountEntry,
|
||||
requiresExplicitMatrixDefaultAccount,
|
||||
|
||||
@@ -2,8 +2,7 @@ import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
|
||||
import { resolveRequiredHomeDir } from "openclaw/plugin-sdk/provider-auth";
|
||||
import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
|
||||
import { resolveRequiredHomeDir, resolveStateDir } from "openclaw/plugin-sdk/state-paths";
|
||||
|
||||
const MATRIX_MIGRATION_SNAPSHOT_DIRNAME = "openclaw-migrations";
|
||||
|
||||
|
||||
@@ -1,44 +1,40 @@
|
||||
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
|
||||
import type { DmPolicy } from "openclaw/plugin-sdk/config-runtime";
|
||||
import type { WizardPrompter } from "openclaw/plugin-sdk/matrix-runtime-shared";
|
||||
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime";
|
||||
import {
|
||||
type ChannelSetupDmPolicy,
|
||||
type ChannelSetupWizardAdapter,
|
||||
addWildcardAllowFrom,
|
||||
formatDocsLink,
|
||||
hasConfiguredSecretInput,
|
||||
mergeAllowFromEntries,
|
||||
normalizeAccountId,
|
||||
promptAccountId,
|
||||
promptChannelAccessConfig,
|
||||
splitSetupEntries,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import { isPrivateNetworkOptInEnabled } from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
import { isPrivateNetworkOptInEnabled } from "openclaw/plugin-sdk/ssrf-policy";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
normalizeStringifiedOptionalString,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
} from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { requiresExplicitMatrixDefaultAccount } from "./account-selection.js";
|
||||
import { listMatrixDirectoryGroupsLive } from "./directory-live.js";
|
||||
import {
|
||||
listMatrixAccountIds,
|
||||
resolveDefaultMatrixAccountId,
|
||||
resolveMatrixAccount,
|
||||
resolveMatrixAccountConfig,
|
||||
} from "./matrix/accounts.js";
|
||||
import { resolveMatrixEnvAuthReadiness } from "./matrix/client/env-auth.js";
|
||||
import { isPrivateOrLoopbackHost } from "./matrix/client/private-network-host.js";
|
||||
import {
|
||||
resolveValidatedMatrixHomeserverUrl,
|
||||
validateMatrixHomeserverUrl,
|
||||
} from "./matrix/client.js";
|
||||
import { resolveMatrixEnvAuthReadiness } from "./matrix/client/env-auth.js";
|
||||
} from "./matrix/client/url-validation.js";
|
||||
import { resolveMatrixConfigFieldPath, updateMatrixAccountConfig } from "./matrix/config-update.js";
|
||||
import { ensureMatrixSdkInstalled, isMatrixSdkAvailable } from "./matrix/deps.js";
|
||||
import { resolveMatrixTargets } from "./resolve-targets.js";
|
||||
import type { DmPolicy } from "./runtime-api.js";
|
||||
import {
|
||||
addWildcardAllowFrom,
|
||||
formatDocsLink,
|
||||
hasConfiguredSecretInput,
|
||||
isPrivateOrLoopbackHost,
|
||||
mergeAllowFromEntries,
|
||||
normalizeAccountId,
|
||||
promptAccountId,
|
||||
promptChannelAccessConfig,
|
||||
splitSetupEntries,
|
||||
type RuntimeEnv,
|
||||
type WizardPrompter,
|
||||
} from "./runtime-api.js";
|
||||
import { moveSingleMatrixAccountConfigToNamedAccount } from "./setup-config.js";
|
||||
import type { CoreConfig, MatrixConfig } from "./types.js";
|
||||
|
||||
@@ -161,6 +157,7 @@ async function promptMatrixAllowFrom(params: {
|
||||
}
|
||||
|
||||
if (pending.length > 0) {
|
||||
const { resolveMatrixTargets } = await import("./resolve-targets.js");
|
||||
const results = await resolveMatrixTargets({
|
||||
cfg,
|
||||
accountId,
|
||||
@@ -362,6 +359,7 @@ async function configureMatrixAccessPrompts(params: {
|
||||
resolvedIds.push(cleaned);
|
||||
continue;
|
||||
}
|
||||
const { listMatrixDirectoryGroupsLive } = await import("./directory-live.js");
|
||||
const matches = await listMatrixDirectoryGroupsLive({
|
||||
cfg: next,
|
||||
accountId: params.accountId,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { GatewayRequestHandlerOptions } from "openclaw/plugin-sdk/gateway-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { formatMatrixErrorMessage } from "./matrix/errors.js";
|
||||
|
||||
function sendError(respond: (ok: boolean, payload?: unknown) => void, err: unknown) {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { isRecord } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
|
||||
export { isRecord };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { listMatrixDirectoryGroupsLive, listMatrixDirectoryPeersLive } from "./directory-live.js";
|
||||
import { isMatrixQualifiedUserId, normalizeMatrixMessagingTarget } from "./matrix/target-ids.js";
|
||||
import type {
|
||||
|
||||
@@ -29,11 +29,11 @@ export type {
|
||||
} from "openclaw/plugin-sdk/channel-contract";
|
||||
export {
|
||||
formatLocationText,
|
||||
logInboundDrop,
|
||||
toLocationContext,
|
||||
type NormalizedLocation,
|
||||
} from "openclaw/plugin-sdk/channel-inbound";
|
||||
export { resolveAckReaction, logTypingFailure } from "openclaw/plugin-sdk/channel-feedback";
|
||||
} from "openclaw/plugin-sdk/channel-location";
|
||||
export { logInboundDrop, logTypingFailure } from "openclaw/plugin-sdk/channel-logging";
|
||||
export { resolveAckReaction } from "openclaw/plugin-sdk/channel-feedback";
|
||||
export type { ChannelSetupInput } from "openclaw/plugin-sdk/setup";
|
||||
export type {
|
||||
OpenClawConfig,
|
||||
@@ -92,7 +92,7 @@ export { resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/routing";
|
||||
export { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
|
||||
export { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pipeline";
|
||||
export { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media";
|
||||
export { normalizePollInput, type PollInput } from "openclaw/plugin-sdk/media-runtime";
|
||||
export { normalizePollInput, type PollInput } from "openclaw/plugin-sdk/poll-runtime";
|
||||
export { writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
|
||||
export {
|
||||
buildChannelKeyCandidates,
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
normalizeSecretInputString,
|
||||
type ChannelSetupInput,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { resolveMatrixEnvAuthReadiness } from "./matrix/client/env-auth.js";
|
||||
import { updateMatrixAccountConfig } from "./matrix/config-update.js";
|
||||
import { isSupportedMatrixAvatarSource } from "./matrix/profile.js";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import crypto from "node:crypto";
|
||||
import path from "node:path";
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
|
||||
export function sanitizeMatrixPathSegment(value: string): string {
|
||||
const cleaned = normalizeLowercaseStringOrEmpty(value)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
implicitMentionKindWhen,
|
||||
resolveInboundMentionDecision,
|
||||
} from "openclaw/plugin-sdk/channel-inbound";
|
||||
} from "openclaw/plugin-sdk/channel-mention-gating";
|
||||
import { vi } from "vitest";
|
||||
import type { PluginRuntime } from "./runtime-api.js";
|
||||
import { setMatrixRuntime } from "./runtime.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { resolveMatrixTargetIdentity } from "./matrix/target-ids.js";
|
||||
|
||||
export const defaultTopLevelPlacement = "child" as const;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { AgentToolResult } from "@mariozechner/pi-agent-core";
|
||||
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { resolveMatrixAccountConfig } from "./matrix/accounts.js";
|
||||
import {
|
||||
bootstrapMatrixVerification,
|
||||
|
||||
Reference in New Issue
Block a user