refactor(matrix): dedupe directory/target match helpers

This commit is contained in:
Peter Steinberger
2026-02-18 16:20:12 +00:00
parent e5f13db13d
commit eb4f1e765c
2 changed files with 71 additions and 62 deletions

View File

@@ -22,6 +22,15 @@ type MatrixAliasLookup = {
room_id?: string;
};
type MatrixDirectoryLiveParams = {
cfg: unknown;
accountId?: string | null;
query?: string | null;
limit?: number | null;
};
type MatrixResolvedAuth = Awaited<ReturnType<typeof resolveMatrixAuth>>;
async function fetchMatrixJson<T>(params: {
homeserver: string;
path: string;
@@ -48,17 +57,42 @@ function normalizeQuery(value?: string | null): string {
return value?.trim().toLowerCase() ?? "";
}
export async function listMatrixDirectoryPeersLive(params: {
cfg: unknown;
accountId?: string | null;
query?: string | null;
limit?: number | null;
}): Promise<ChannelDirectoryEntry[]> {
function resolveMatrixDirectoryLimit(limit?: number | null): number {
return typeof limit === "number" && limit > 0 ? limit : 20;
}
async function resolveMatrixDirectoryContext(
params: MatrixDirectoryLiveParams,
): Promise<{ query: string; auth: MatrixResolvedAuth } | null> {
const query = normalizeQuery(params.query);
if (!query) {
return [];
return null;
}
const auth = await resolveMatrixAuth({ cfg: params.cfg as never, accountId: params.accountId });
return { query, auth };
}
function createGroupDirectoryEntry(params: {
id: string;
name: string;
handle?: string;
}): ChannelDirectoryEntry {
return {
kind: "group",
id: params.id,
name: params.name,
handle: params.handle,
} satisfies ChannelDirectoryEntry;
}
export async function listMatrixDirectoryPeersLive(
params: MatrixDirectoryLiveParams,
): Promise<ChannelDirectoryEntry[]> {
const context = await resolveMatrixDirectoryContext(params);
if (!context) {
return [];
}
const { query, auth } = context;
const res = await fetchMatrixJson<MatrixUserDirectoryResponse>({
homeserver: auth.homeserver,
accessToken: auth.accessToken,
@@ -66,7 +100,7 @@ export async function listMatrixDirectoryPeersLive(params: {
method: "POST",
body: {
search_term: query,
limit: typeof params.limit === "number" && params.limit > 0 ? params.limit : 20,
limit: resolveMatrixDirectoryLimit(params.limit),
},
});
const results = res.results ?? [];
@@ -121,42 +155,26 @@ async function fetchMatrixRoomName(
}
}
export async function listMatrixDirectoryGroupsLive(params: {
cfg: unknown;
accountId?: string | null;
query?: string | null;
limit?: number | null;
}): Promise<ChannelDirectoryEntry[]> {
const query = normalizeQuery(params.query);
if (!query) {
export async function listMatrixDirectoryGroupsLive(
params: MatrixDirectoryLiveParams,
): Promise<ChannelDirectoryEntry[]> {
const context = await resolveMatrixDirectoryContext(params);
if (!context) {
return [];
}
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 { query, auth } = context;
const limit = resolveMatrixDirectoryLimit(params.limit);
if (query.startsWith("#")) {
const roomId = await resolveMatrixRoomAlias(auth.homeserver, auth.accessToken, query);
if (!roomId) {
return [];
}
return [
{
kind: "group",
id: roomId,
name: query,
handle: query,
} satisfies ChannelDirectoryEntry,
];
return [createGroupDirectoryEntry({ id: roomId, name: query, handle: query })];
}
if (query.startsWith("!")) {
return [
{
kind: "group",
id: query,
name: query,
} satisfies ChannelDirectoryEntry,
];
return [createGroupDirectoryEntry({ id: query, name: query })];
}
const joined = await fetchMatrixJson<MatrixJoinedRoomsResponse>({

View File

@@ -6,6 +6,22 @@ import type {
} from "openclaw/plugin-sdk";
import { listMatrixDirectoryGroupsLive, listMatrixDirectoryPeersLive } from "./directory-live.js";
function findExactDirectoryMatches(
matches: ChannelDirectoryEntry[],
query: string,
): ChannelDirectoryEntry[] {
const normalized = query.trim().toLowerCase();
if (!normalized) {
return [];
}
return matches.filter((match) => {
const id = match.id.trim().toLowerCase();
const name = match.name?.trim().toLowerCase();
const handle = match.handle?.trim().toLowerCase();
return normalized === id || normalized === name || normalized === handle;
});
}
function pickBestGroupMatch(
matches: ChannelDirectoryEntry[],
query: string,
@@ -13,19 +29,8 @@ function pickBestGroupMatch(
if (matches.length === 0) {
return undefined;
}
const normalized = query.trim().toLowerCase();
if (normalized) {
const exact = matches.find((match) => {
const name = match.name?.trim().toLowerCase();
const handle = match.handle?.trim().toLowerCase();
const id = match.id.trim().toLowerCase();
return name === normalized || handle === normalized || id === normalized;
});
if (exact) {
return exact;
}
}
return matches[0];
const [exact] = findExactDirectoryMatches(matches, query);
return exact ?? matches[0];
}
function pickBestUserMatch(
@@ -35,16 +40,7 @@ function pickBestUserMatch(
if (matches.length === 0) {
return undefined;
}
const normalized = query.trim().toLowerCase();
if (!normalized) {
return undefined;
}
const exact = matches.filter((match) => {
const id = match.id.trim().toLowerCase();
const name = match.name?.trim().toLowerCase();
const handle = match.handle?.trim().toLowerCase();
return normalized === id || normalized === name || normalized === handle;
});
const exact = findExactDirectoryMatches(matches, query);
if (exact.length === 1) {
return exact[0];
}
@@ -59,12 +55,7 @@ function describeUserMatchFailure(matches: ChannelDirectoryEntry[], query: strin
if (!normalized) {
return "empty input";
}
const exact = matches.filter((match) => {
const id = match.id.trim().toLowerCase();
const name = match.name?.trim().toLowerCase();
const handle = match.handle?.trim().toLowerCase();
return normalized === id || normalized === name || normalized === handle;
});
const exact = findExactDirectoryMatches(matches, normalized);
if (exact.length === 0) {
return "no exact match; use full Matrix ID";
}