perf(outbound): isolate id-like target resolution

This commit is contained in:
Vincent Koc
2026-04-13 17:17:18 +01:00
parent 8628d05ecd
commit 6eb04c8aab
5 changed files with 39 additions and 20 deletions

View File

@@ -23,7 +23,7 @@ vi.mock("../../infra/outbound/channel-selection.runtime.js", () => ({
.mockResolvedValue({ channel: "telegram", configured: ["telegram"] }),
}));
vi.mock("../../infra/outbound/target-resolver.js", () => ({
vi.mock("../../infra/outbound/target-id-resolution.js", () => ({
maybeResolveIdLikeTarget: vi.fn(),
}));
@@ -40,13 +40,13 @@ const mockedModuleIds = [
"../../config/sessions/store-load.js",
"../../infra/outbound/channel-selection.runtime.js",
"../../infra/outbound/targets.runtime.js",
"../../infra/outbound/target-resolver.js",
"../../infra/outbound/target-id-resolution.js",
"../../pairing/pairing-store.js",
];
import { loadSessionStore } from "../../config/sessions/store-load.js";
import { resolveMessageChannelSelection } from "../../infra/outbound/channel-selection.runtime.js";
import { maybeResolveIdLikeTarget } from "../../infra/outbound/target-resolver.js";
import { maybeResolveIdLikeTarget } from "../../infra/outbound/target-id-resolution.js";
import { resolveOutboundTarget } from "../../infra/outbound/targets.runtime.js";
import { readChannelAllowFromStoreSync } from "../../pairing/pairing-store.js";
import { resolveDeliveryTarget } from "./delivery-target.js";

View File

@@ -5,7 +5,7 @@ import { resolveStorePath } from "../../config/sessions/paths.js";
import { loadSessionStore } from "../../config/sessions/store-load.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { formatErrorMessage } from "../../infra/errors.js";
import { maybeResolveIdLikeTarget } from "../../infra/outbound/target-resolver.js";
import { maybeResolveIdLikeTarget } from "../../infra/outbound/target-id-resolution.js";
import { tryResolveLoadedOutboundTarget } from "../../infra/outbound/targets-loaded.js";
import { resolveSessionDeliveryTarget } from "../../infra/outbound/targets-session.js";
import type { OutboundChannel } from "../../infra/outbound/targets.js";

View File

@@ -0,0 +1,27 @@
import type { ChannelDirectoryEntryKind, ChannelId } from "../../channels/plugins/types.public.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { maybeResolvePluginMessagingTarget } from "./target-normalization.js";
export type ResolvedIdLikeTarget = {
to: string;
kind: ChannelDirectoryEntryKind | "channel";
display?: string;
source: "normalized" | "directory";
};
export async function maybeResolveIdLikeTarget(params: {
cfg: OpenClawConfig;
channel: ChannelId;
input: string;
accountId?: string | null;
preferredKind?: ChannelDirectoryEntryKind | "channel";
}): Promise<ResolvedIdLikeTarget | undefined> {
const target = await maybeResolvePluginMessagingTarget({
...params,
requireIdLike: true,
});
if (!target) {
return undefined;
}
return target;
}

View File

@@ -22,6 +22,10 @@ vi.mock("../../channels/plugins/index.js", () => ({
normalizeChannelId: (value: string) => value,
}));
vi.mock("../../channels/plugins/registry-loaded-read.js", () => ({
getLoadedChannelPluginForRead: (...args: unknown[]) => mocks.getChannelPlugin(...args),
}));
vi.mock("../../plugins/runtime.js", () => ({
getActivePluginChannelRegistry: () => null,
getActivePluginRegistry: () => null,

View File

@@ -9,6 +9,7 @@ import { defaultRuntime, type RuntimeEnv } from "../../runtime.js";
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
import { buildDirectoryCacheKey, DirectoryCache } from "./directory-cache.js";
import { ambiguousTargetError, unknownTargetError } from "./target-errors.js";
import { maybeResolveIdLikeTarget, type ResolvedIdLikeTarget } from "./target-id-resolution.js";
import {
buildTargetResolverSignature,
looksLikeTargetId,
@@ -34,11 +35,13 @@ export type ResolveMessagingTargetResult =
| { ok: false; error: Error; candidates?: ChannelDirectoryEntry[] };
function asResolvedMessagingTarget(
target: Awaited<ReturnType<typeof maybeResolvePluginMessagingTarget>>,
target: Awaited<ReturnType<typeof maybeResolvePluginMessagingTarget>> | ResolvedIdLikeTarget,
): ResolvedMessagingTarget | undefined {
return target;
}
export { maybeResolveIdLikeTarget } from "./target-id-resolution.js";
export async function resolveChannelTarget(params: {
cfg: OpenClawConfig;
channel: ChannelId;
@@ -50,21 +53,6 @@ export async function resolveChannelTarget(params: {
return resolveMessagingTarget(params);
}
export async function maybeResolveIdLikeTarget(params: {
cfg: OpenClawConfig;
channel: ChannelId;
input: string;
accountId?: string | null;
preferredKind?: TargetResolveKind;
}): Promise<ResolvedMessagingTarget | undefined> {
return asResolvedMessagingTarget(
await maybeResolvePluginMessagingTarget({
...params,
requireIdLike: true,
}),
);
}
const CACHE_TTL_MS = 30 * 60 * 1000;
const directoryCache = new DirectoryCache<ChannelDirectoryEntry[]>(CACHE_TTL_MS);