mirror of
https://github.com/farcasclaudiu/openclaw.git
synced 2026-06-29 13:02:10 +03:00
fix: harden matrix multi-account routing (#7286) (thanks @emonty)
This commit is contained in:
+1
-1
@@ -239,7 +239,7 @@ Docs: https://docs.openclaw.ai
|
|||||||
- Doctor/State dir: suppress repeated legacy migration warnings only for valid symlink mirrors, while keeping warnings for empty or invalid legacy trees. (#11709) Thanks @gumadeiras.
|
- Doctor/State dir: suppress repeated legacy migration warnings only for valid symlink mirrors, while keeping warnings for empty or invalid legacy trees. (#11709) Thanks @gumadeiras.
|
||||||
- Tests: harden flaky hotspots by removing timer sleeps, consolidating onboarding provider-auth coverage, and improving memory test realism. (#11598) Thanks @gumadeiras.
|
- Tests: harden flaky hotspots by removing timer sleeps, consolidating onboarding provider-auth coverage, and improving memory test realism. (#11598) Thanks @gumadeiras.
|
||||||
- macOS: honor Nix-managed defaults suite (`ai.openclaw.mac`) for nixMode to prevent onboarding from reappearing after bundle-id churn. (#12205) Thanks @joshp123.
|
- macOS: honor Nix-managed defaults suite (`ai.openclaw.mac`) for nixMode to prevent onboarding from reappearing after bundle-id churn. (#12205) Thanks @joshp123.
|
||||||
- Matrix: add multi-account support via `channels.matrix.accounts`; use per-account config for dm policy, allowFrom, groups, and other settings; serialize account startup to avoid race condition. (#3165, #3085) Thanks @emonty.
|
- Matrix: add multi-account support via `channels.matrix.accounts`; use per-account config for dm policy, allowFrom, groups, and other settings; serialize account startup to avoid race condition. (#7286, #3165, #3085) Thanks @emonty.
|
||||||
|
|
||||||
## 2026.2.6
|
## 2026.2.6
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,28 @@
|
|||||||
import type { PluginRuntime } from "openclaw/plugin-sdk";
|
import type { PluginRuntime } from "openclaw/plugin-sdk";
|
||||||
import { beforeEach, describe, expect, it } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import type { CoreConfig } from "./types.js";
|
import type { CoreConfig } from "./types.js";
|
||||||
import { matrixPlugin } from "./channel.js";
|
import { matrixPlugin } from "./channel.js";
|
||||||
import { setMatrixRuntime } from "./runtime.js";
|
import { setMatrixRuntime } from "./runtime.js";
|
||||||
|
|
||||||
|
vi.mock("@vector-im/matrix-bot-sdk", () => ({
|
||||||
|
ConsoleLogger: class {
|
||||||
|
trace = vi.fn();
|
||||||
|
debug = vi.fn();
|
||||||
|
info = vi.fn();
|
||||||
|
warn = vi.fn();
|
||||||
|
error = vi.fn();
|
||||||
|
},
|
||||||
|
MatrixClient: class {},
|
||||||
|
LogService: {
|
||||||
|
setLogger: vi.fn(),
|
||||||
|
warn: vi.fn(),
|
||||||
|
info: vi.fn(),
|
||||||
|
debug: vi.fn(),
|
||||||
|
},
|
||||||
|
SimpleFsStorageProvider: class {},
|
||||||
|
RustSdkCryptoStorageProvider: class {},
|
||||||
|
}));
|
||||||
|
|
||||||
describe("matrix directory", () => {
|
describe("matrix directory", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
setMatrixRuntime({
|
setMatrixRuntime({
|
||||||
@@ -61,4 +80,65 @@ describe("matrix directory", () => {
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("resolves replyToMode from account config", () => {
|
||||||
|
const cfg = {
|
||||||
|
channels: {
|
||||||
|
matrix: {
|
||||||
|
replyToMode: "off",
|
||||||
|
accounts: {
|
||||||
|
Assistant: {
|
||||||
|
replyToMode: "all",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as unknown as CoreConfig;
|
||||||
|
|
||||||
|
expect(matrixPlugin.threading?.resolveReplyToMode).toBeTruthy();
|
||||||
|
expect(
|
||||||
|
matrixPlugin.threading?.resolveReplyToMode?.({
|
||||||
|
cfg,
|
||||||
|
accountId: "assistant",
|
||||||
|
chatType: "direct",
|
||||||
|
}),
|
||||||
|
).toBe("all");
|
||||||
|
expect(
|
||||||
|
matrixPlugin.threading?.resolveReplyToMode?.({
|
||||||
|
cfg,
|
||||||
|
accountId: "default",
|
||||||
|
chatType: "direct",
|
||||||
|
}),
|
||||||
|
).toBe("off");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("resolves group mention policy from account config", () => {
|
||||||
|
const cfg = {
|
||||||
|
channels: {
|
||||||
|
matrix: {
|
||||||
|
groups: {
|
||||||
|
"!room:example.org": { requireMention: true },
|
||||||
|
},
|
||||||
|
accounts: {
|
||||||
|
Assistant: {
|
||||||
|
groups: {
|
||||||
|
"!room:example.org": { requireMention: false },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as unknown as CoreConfig;
|
||||||
|
|
||||||
|
expect(matrixPlugin.groups.resolveRequireMention({ cfg, groupId: "!room:example.org" })).toBe(
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
matrixPlugin.groups.resolveRequireMention({
|
||||||
|
cfg,
|
||||||
|
accountId: "assistant",
|
||||||
|
groupId: "!room:example.org",
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
} from "./group-mentions.js";
|
} from "./group-mentions.js";
|
||||||
import {
|
import {
|
||||||
listMatrixAccountIds,
|
listMatrixAccountIds,
|
||||||
|
resolveMatrixAccountConfig,
|
||||||
resolveDefaultMatrixAccountId,
|
resolveDefaultMatrixAccountId,
|
||||||
resolveMatrixAccount,
|
resolveMatrixAccount,
|
||||||
type ResolvedMatrixAccount,
|
type ResolvedMatrixAccount,
|
||||||
@@ -146,8 +147,8 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|||||||
baseUrl: account.homeserver,
|
baseUrl: account.homeserver,
|
||||||
}),
|
}),
|
||||||
resolveAllowFrom: ({ cfg, accountId }) => {
|
resolveAllowFrom: ({ cfg, accountId }) => {
|
||||||
const account = resolveMatrixAccount({ cfg: cfg as CoreConfig, accountId });
|
const matrixConfig = resolveMatrixAccountConfig({ cfg: cfg as CoreConfig, accountId });
|
||||||
return (account.config.dm?.allowFrom ?? []).map((entry: string | number) => String(entry));
|
return (matrixConfig.dm?.allowFrom ?? []).map((entry: string | number) => String(entry));
|
||||||
},
|
},
|
||||||
formatAllowFrom: ({ allowFrom }) => normalizeMatrixAllowList(allowFrom),
|
formatAllowFrom: ({ allowFrom }) => normalizeMatrixAllowList(allowFrom),
|
||||||
},
|
},
|
||||||
@@ -183,7 +184,8 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|||||||
resolveToolPolicy: resolveMatrixGroupToolPolicy,
|
resolveToolPolicy: resolveMatrixGroupToolPolicy,
|
||||||
},
|
},
|
||||||
threading: {
|
threading: {
|
||||||
resolveReplyToMode: ({ cfg }) => (cfg as CoreConfig).channels?.matrix?.replyToMode ?? "off",
|
resolveReplyToMode: ({ cfg, accountId }) =>
|
||||||
|
resolveMatrixAccountConfig({ cfg: cfg as CoreConfig, accountId }).replyToMode ?? "off",
|
||||||
buildToolContext: ({ context, hasRepliedRef }) => {
|
buildToolContext: ({ context, hasRepliedRef }) => {
|
||||||
const currentTarget = context.To;
|
const currentTarget = context.To;
|
||||||
return {
|
return {
|
||||||
@@ -290,10 +292,10 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|||||||
.map((id) => ({ kind: "group", id }) as const);
|
.map((id) => ({ kind: "group", id }) as const);
|
||||||
return ids;
|
return ids;
|
||||||
},
|
},
|
||||||
listPeersLive: async ({ cfg, query, limit }) =>
|
listPeersLive: async ({ cfg, accountId, query, limit }) =>
|
||||||
listMatrixDirectoryPeersLive({ cfg, query, limit }),
|
listMatrixDirectoryPeersLive({ cfg, accountId, query, limit }),
|
||||||
listGroupsLive: async ({ cfg, query, limit }) =>
|
listGroupsLive: async ({ cfg, accountId, query, limit }) =>
|
||||||
listMatrixDirectoryGroupsLive({ cfg, query, limit }),
|
listMatrixDirectoryGroupsLive({ cfg, accountId, query, limit }),
|
||||||
},
|
},
|
||||||
resolver: {
|
resolver: {
|
||||||
resolveTargets: async ({ cfg, inputs, kind, runtime }) =>
|
resolveTargets: async ({ cfg, inputs, kind, runtime }) =>
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
import { listMatrixDirectoryGroupsLive, listMatrixDirectoryPeersLive } from "./directory-live.js";
|
||||||
|
import { resolveMatrixAuth } from "./matrix/client.js";
|
||||||
|
|
||||||
|
vi.mock("./matrix/client.js", () => ({
|
||||||
|
resolveMatrixAuth: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe("matrix directory live", () => {
|
||||||
|
const cfg = { channels: { matrix: {} } };
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.mocked(resolveMatrixAuth).mockReset();
|
||||||
|
vi.mocked(resolveMatrixAuth).mockResolvedValue({
|
||||||
|
homeserver: "https://matrix.example.org",
|
||||||
|
userId: "@bot:example.org",
|
||||||
|
accessToken: "test-token",
|
||||||
|
});
|
||||||
|
vi.stubGlobal(
|
||||||
|
"fetch",
|
||||||
|
vi.fn().mockResolvedValue({
|
||||||
|
ok: true,
|
||||||
|
json: async () => ({ results: [] }),
|
||||||
|
text: async () => "",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.unstubAllGlobals();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("passes accountId to peer directory auth resolution", async () => {
|
||||||
|
await listMatrixDirectoryPeersLive({
|
||||||
|
cfg,
|
||||||
|
accountId: "assistant",
|
||||||
|
query: "alice",
|
||||||
|
limit: 10,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(resolveMatrixAuth).toHaveBeenCalledWith({ cfg, accountId: "assistant" });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("passes accountId to group directory auth resolution", async () => {
|
||||||
|
await listMatrixDirectoryGroupsLive({
|
||||||
|
cfg,
|
||||||
|
accountId: "assistant",
|
||||||
|
query: "!room:example.org",
|
||||||
|
limit: 10,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(resolveMatrixAuth).toHaveBeenCalledWith({ cfg, accountId: "assistant" });
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -50,6 +50,7 @@ function normalizeQuery(value?: string | null): string {
|
|||||||
|
|
||||||
export async function listMatrixDirectoryPeersLive(params: {
|
export async function listMatrixDirectoryPeersLive(params: {
|
||||||
cfg: unknown;
|
cfg: unknown;
|
||||||
|
accountId?: string | null;
|
||||||
query?: string | null;
|
query?: string | null;
|
||||||
limit?: number | null;
|
limit?: number | null;
|
||||||
}): Promise<ChannelDirectoryEntry[]> {
|
}): Promise<ChannelDirectoryEntry[]> {
|
||||||
@@ -57,7 +58,7 @@ export async function listMatrixDirectoryPeersLive(params: {
|
|||||||
if (!query) {
|
if (!query) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const auth = await resolveMatrixAuth({ cfg: params.cfg as never });
|
const auth = await resolveMatrixAuth({ cfg: params.cfg as never, accountId: params.accountId });
|
||||||
const res = await fetchMatrixJson<MatrixUserDirectoryResponse>({
|
const res = await fetchMatrixJson<MatrixUserDirectoryResponse>({
|
||||||
homeserver: auth.homeserver,
|
homeserver: auth.homeserver,
|
||||||
accessToken: auth.accessToken,
|
accessToken: auth.accessToken,
|
||||||
@@ -122,6 +123,7 @@ async function fetchMatrixRoomName(
|
|||||||
|
|
||||||
export async function listMatrixDirectoryGroupsLive(params: {
|
export async function listMatrixDirectoryGroupsLive(params: {
|
||||||
cfg: unknown;
|
cfg: unknown;
|
||||||
|
accountId?: string | null;
|
||||||
query?: string | null;
|
query?: string | null;
|
||||||
limit?: number | null;
|
limit?: number | null;
|
||||||
}): Promise<ChannelDirectoryEntry[]> {
|
}): Promise<ChannelDirectoryEntry[]> {
|
||||||
@@ -129,7 +131,7 @@ export async function listMatrixDirectoryGroupsLive(params: {
|
|||||||
if (!query) {
|
if (!query) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const auth = await resolveMatrixAuth({ cfg: params.cfg as never });
|
const auth = await resolveMatrixAuth({ cfg: params.cfg as never, accountId: params.accountId });
|
||||||
const limit = typeof params.limit === "number" && params.limit > 0 ? params.limit : 20;
|
const limit = typeof params.limit === "number" && params.limit > 0 ? params.limit : 20;
|
||||||
|
|
||||||
if (query.startsWith("#")) {
|
if (query.startsWith("#")) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { ChannelGroupContext, GroupToolPolicyConfig } from "openclaw/plugin-sdk";
|
import type { ChannelGroupContext, GroupToolPolicyConfig } from "openclaw/plugin-sdk";
|
||||||
import type { CoreConfig } from "./types.js";
|
import type { CoreConfig } from "./types.js";
|
||||||
|
import { resolveMatrixAccountConfig } from "./matrix/accounts.js";
|
||||||
import { resolveMatrixRoomConfig } from "./matrix/monitor/rooms.js";
|
import { resolveMatrixRoomConfig } from "./matrix/monitor/rooms.js";
|
||||||
|
|
||||||
export function resolveMatrixGroupRequireMention(params: ChannelGroupContext): boolean {
|
export function resolveMatrixGroupRequireMention(params: ChannelGroupContext): boolean {
|
||||||
@@ -18,8 +19,9 @@ export function resolveMatrixGroupRequireMention(params: ChannelGroupContext): b
|
|||||||
const groupChannel = params.groupChannel?.trim() ?? "";
|
const groupChannel = params.groupChannel?.trim() ?? "";
|
||||||
const aliases = groupChannel ? [groupChannel] : [];
|
const aliases = groupChannel ? [groupChannel] : [];
|
||||||
const cfg = params.cfg as CoreConfig;
|
const cfg = params.cfg as CoreConfig;
|
||||||
|
const matrixConfig = resolveMatrixAccountConfig({ cfg, accountId: params.accountId });
|
||||||
const resolved = resolveMatrixRoomConfig({
|
const resolved = resolveMatrixRoomConfig({
|
||||||
rooms: cfg.channels?.matrix?.groups ?? cfg.channels?.matrix?.rooms,
|
rooms: matrixConfig.groups ?? matrixConfig.rooms,
|
||||||
roomId,
|
roomId,
|
||||||
aliases,
|
aliases,
|
||||||
name: groupChannel || undefined,
|
name: groupChannel || undefined,
|
||||||
@@ -56,8 +58,9 @@ export function resolveMatrixGroupToolPolicy(
|
|||||||
const groupChannel = params.groupChannel?.trim() ?? "";
|
const groupChannel = params.groupChannel?.trim() ?? "";
|
||||||
const aliases = groupChannel ? [groupChannel] : [];
|
const aliases = groupChannel ? [groupChannel] : [];
|
||||||
const cfg = params.cfg as CoreConfig;
|
const cfg = params.cfg as CoreConfig;
|
||||||
|
const matrixConfig = resolveMatrixAccountConfig({ cfg, accountId: params.accountId });
|
||||||
const resolved = resolveMatrixRoomConfig({
|
const resolved = resolveMatrixRoomConfig({
|
||||||
rooms: cfg.channels?.matrix?.groups ?? cfg.channels?.matrix?.rooms,
|
rooms: matrixConfig.groups ?? matrixConfig.rooms,
|
||||||
roomId,
|
roomId,
|
||||||
aliases,
|
aliases,
|
||||||
name: groupChannel || undefined,
|
name: groupChannel || undefined,
|
||||||
|
|||||||
@@ -86,16 +86,7 @@ export function resolveMatrixAccount(params: {
|
|||||||
}): ResolvedMatrixAccount {
|
}): ResolvedMatrixAccount {
|
||||||
const accountId = normalizeAccountId(params.accountId);
|
const accountId = normalizeAccountId(params.accountId);
|
||||||
const matrixBase = params.cfg.channels?.matrix ?? {};
|
const matrixBase = params.cfg.channels?.matrix ?? {};
|
||||||
|
const base = resolveMatrixAccountConfig({ cfg: params.cfg, accountId });
|
||||||
// Check if this account exists in accounts structure
|
|
||||||
const accountConfig = resolveAccountConfig(params.cfg, accountId);
|
|
||||||
|
|
||||||
// Merge account-specific config with top-level defaults so settings like
|
|
||||||
// blockStreaming, groupPolicy, etc. inherit from channels.matrix when not
|
|
||||||
// overridden per account.
|
|
||||||
const base: MatrixConfig = accountConfig
|
|
||||||
? mergeAccountConfig(matrixBase, accountConfig)
|
|
||||||
: matrixBase;
|
|
||||||
const enabled = base.enabled !== false && matrixBase.enabled !== false;
|
const enabled = base.enabled !== false && matrixBase.enabled !== false;
|
||||||
|
|
||||||
const resolved = resolveMatrixConfigForAccount(params.cfg, accountId, process.env);
|
const resolved = resolveMatrixConfigForAccount(params.cfg, accountId, process.env);
|
||||||
@@ -124,6 +115,21 @@ export function resolveMatrixAccount(params: {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function resolveMatrixAccountConfig(params: {
|
||||||
|
cfg: CoreConfig;
|
||||||
|
accountId?: string | null;
|
||||||
|
}): MatrixConfig {
|
||||||
|
const accountId = normalizeAccountId(params.accountId);
|
||||||
|
const matrixBase = params.cfg.channels?.matrix ?? {};
|
||||||
|
const accountConfig = resolveAccountConfig(params.cfg, accountId);
|
||||||
|
if (!accountConfig) {
|
||||||
|
return matrixBase;
|
||||||
|
}
|
||||||
|
// Merge account-specific config with top-level defaults so settings like
|
||||||
|
// groupPolicy and blockStreaming inherit when not overridden.
|
||||||
|
return mergeAccountConfig(matrixBase, accountConfig);
|
||||||
|
}
|
||||||
|
|
||||||
export function listEnabledMatrixAccounts(cfg: CoreConfig): ResolvedMatrixAccount[] {
|
export function listEnabledMatrixAccounts(cfg: CoreConfig): ResolvedMatrixAccount[] {
|
||||||
return listMatrixAccountIds(cfg)
|
return listMatrixAccountIds(cfg)
|
||||||
.map((accountId) => resolveMatrixAccount({ cfg, accountId }))
|
.map((accountId) => resolveMatrixAccount({ cfg, accountId }))
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { MatrixClient } from "@vector-im/matrix-bot-sdk";
|
import type { MatrixClient } from "@vector-im/matrix-bot-sdk";
|
||||||
import { LogService } from "@vector-im/matrix-bot-sdk";
|
import { LogService } from "@vector-im/matrix-bot-sdk";
|
||||||
|
import { normalizeAccountId } from "openclaw/plugin-sdk";
|
||||||
import type { CoreConfig } from "../../types.js";
|
import type { CoreConfig } from "../../types.js";
|
||||||
import type { MatrixAuth } from "./types.js";
|
import type { MatrixAuth } from "./types.js";
|
||||||
import { resolveMatrixAuth } from "./config.js";
|
import { resolveMatrixAuth } from "./config.js";
|
||||||
@@ -19,12 +20,13 @@ const sharedClientPromises = new Map<string, Promise<SharedMatrixClientState>>()
|
|||||||
const sharedClientStartPromises = new Map<string, Promise<void>>();
|
const sharedClientStartPromises = new Map<string, Promise<void>>();
|
||||||
|
|
||||||
function buildSharedClientKey(auth: MatrixAuth, accountId?: string | null): string {
|
function buildSharedClientKey(auth: MatrixAuth, accountId?: string | null): string {
|
||||||
|
const normalizedAccountId = normalizeAccountId(accountId);
|
||||||
return [
|
return [
|
||||||
auth.homeserver,
|
auth.homeserver,
|
||||||
auth.userId,
|
auth.userId,
|
||||||
auth.accessToken,
|
auth.accessToken,
|
||||||
auth.encryption ? "e2ee" : "plain",
|
auth.encryption ? "e2ee" : "plain",
|
||||||
accountId ?? DEFAULT_ACCOUNT_KEY,
|
normalizedAccountId || DEFAULT_ACCOUNT_KEY,
|
||||||
].join("|");
|
].join("|");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,10 +105,10 @@ export async function resolveSharedMatrixClient(
|
|||||||
accountId?: string | null;
|
accountId?: string | null;
|
||||||
} = {},
|
} = {},
|
||||||
): Promise<MatrixClient> {
|
): Promise<MatrixClient> {
|
||||||
|
const accountId = normalizeAccountId(params.accountId);
|
||||||
const auth =
|
const auth =
|
||||||
params.auth ??
|
params.auth ?? (await resolveMatrixAuth({ cfg: params.cfg, env: params.env, accountId }));
|
||||||
(await resolveMatrixAuth({ cfg: params.cfg, env: params.env, accountId: params.accountId }));
|
const key = buildSharedClientKey(auth, accountId);
|
||||||
const key = buildSharedClientKey(auth, params.accountId);
|
|
||||||
const shouldStart = params.startClient !== false;
|
const shouldStart = params.startClient !== false;
|
||||||
|
|
||||||
// Check if we already have a client for this key
|
// Check if we already have a client for this key
|
||||||
@@ -142,7 +144,7 @@ export async function resolveSharedMatrixClient(
|
|||||||
const createPromise = createSharedMatrixClient({
|
const createPromise = createSharedMatrixClient({
|
||||||
auth,
|
auth,
|
||||||
timeoutMs: params.timeoutMs,
|
timeoutMs: params.timeoutMs,
|
||||||
accountId: params.accountId,
|
accountId,
|
||||||
});
|
});
|
||||||
sharedClientPromises.set(key, createPromise);
|
sharedClientPromises.set(key, createPromise);
|
||||||
try {
|
try {
|
||||||
@@ -194,6 +196,6 @@ export function stopSharedClient(key?: string): void {
|
|||||||
* to avoid stopping all accounts.
|
* to avoid stopping all accounts.
|
||||||
*/
|
*/
|
||||||
export function stopSharedClientForAccount(auth: MatrixAuth, accountId?: string | null): void {
|
export function stopSharedClientForAccount(auth: MatrixAuth, accountId?: string | null): void {
|
||||||
const key = buildSharedClientKey(auth, accountId);
|
const key = buildSharedClientKey(auth, normalizeAccountId(accountId));
|
||||||
stopSharedClient(key);
|
stopSharedClient(key);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ export async function monitorMatrixProvider(opts: MonitorMatrixOpts = {}): Promi
|
|||||||
...cfg.channels?.matrix?.dm,
|
...cfg.channels?.matrix?.dm,
|
||||||
allowFrom,
|
allowFrom,
|
||||||
},
|
},
|
||||||
...(groupAllowFrom.length > 0 ? { groupAllowFrom } : {}),
|
groupAllowFrom,
|
||||||
...(roomsConfig ? { groups: roomsConfig } : {}),
|
...(roomsConfig ? { groups: roomsConfig } : {}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -62,14 +62,18 @@ export async function resolveMatrixClient(opts: {
|
|||||||
if (opts.client) {
|
if (opts.client) {
|
||||||
return { client: opts.client, stopOnDone: false };
|
return { client: opts.client, stopOnDone: false };
|
||||||
}
|
}
|
||||||
|
const accountId =
|
||||||
|
typeof opts.accountId === "string" && opts.accountId.trim().length > 0
|
||||||
|
? normalizeAccountId(opts.accountId)
|
||||||
|
: undefined;
|
||||||
// Try to get the client for the specific account
|
// Try to get the client for the specific account
|
||||||
const active = getActiveMatrixClient(opts.accountId);
|
const active = getActiveMatrixClient(accountId);
|
||||||
if (active) {
|
if (active) {
|
||||||
return { client: active, stopOnDone: false };
|
return { client: active, stopOnDone: false };
|
||||||
}
|
}
|
||||||
// When no account is specified, try the default account first; only fall back to
|
// When no account is specified, try the default account first; only fall back to
|
||||||
// any active client as a last resort (prevents sending from an arbitrary account).
|
// any active client as a last resort (prevents sending from an arbitrary account).
|
||||||
if (!opts.accountId) {
|
if (!accountId) {
|
||||||
const defaultClient = getActiveMatrixClient(DEFAULT_ACCOUNT_ID);
|
const defaultClient = getActiveMatrixClient(DEFAULT_ACCOUNT_ID);
|
||||||
if (defaultClient) {
|
if (defaultClient) {
|
||||||
return { client: defaultClient, stopOnDone: false };
|
return { client: defaultClient, stopOnDone: false };
|
||||||
@@ -83,18 +87,18 @@ export async function resolveMatrixClient(opts: {
|
|||||||
if (shouldShareClient) {
|
if (shouldShareClient) {
|
||||||
const client = await resolveSharedMatrixClient({
|
const client = await resolveSharedMatrixClient({
|
||||||
timeoutMs: opts.timeoutMs,
|
timeoutMs: opts.timeoutMs,
|
||||||
accountId: opts.accountId,
|
accountId,
|
||||||
});
|
});
|
||||||
return { client, stopOnDone: false };
|
return { client, stopOnDone: false };
|
||||||
}
|
}
|
||||||
const auth = await resolveMatrixAuth({ accountId: opts.accountId });
|
const auth = await resolveMatrixAuth({ accountId });
|
||||||
const client = await createMatrixClient({
|
const client = await createMatrixClient({
|
||||||
homeserver: auth.homeserver,
|
homeserver: auth.homeserver,
|
||||||
userId: auth.userId,
|
userId: auth.userId,
|
||||||
accessToken: auth.accessToken,
|
accessToken: auth.accessToken,
|
||||||
encryption: auth.encryption,
|
encryption: auth.encryption,
|
||||||
localTimeoutMs: opts.timeoutMs,
|
localTimeoutMs: opts.timeoutMs,
|
||||||
accountId: opts.accountId,
|
accountId,
|
||||||
});
|
});
|
||||||
if (auth.encryption && client.crypto) {
|
if (auth.encryption && client.crypto) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user