mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:00:42 +00:00
perf(outbound): use read-only channel registry seam
This commit is contained in:
25
src/channels/plugins/registry-read.ts
Normal file
25
src/channels/plugins/registry-read.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import { getBundledChannelPlugin } from "./bundled.js";
|
||||
import { getLoadedChannelPluginById, listLoadedChannelPlugins } from "./registry-loaded.js";
|
||||
import type { ChannelPlugin } from "./types.plugin.js";
|
||||
import type { ChannelId } from "./types.public.js";
|
||||
|
||||
export function listChannelPluginsForRead(): ChannelPlugin[] {
|
||||
return listLoadedChannelPlugins() as ChannelPlugin[];
|
||||
}
|
||||
|
||||
export function getLoadedChannelPluginForRead(id: ChannelId): ChannelPlugin | undefined {
|
||||
const resolvedId = normalizeOptionalString(id) ?? "";
|
||||
if (!resolvedId) {
|
||||
return undefined;
|
||||
}
|
||||
return getLoadedChannelPluginById(resolvedId) as ChannelPlugin | undefined;
|
||||
}
|
||||
|
||||
export function getChannelPluginForRead(id: ChannelId): ChannelPlugin | undefined {
|
||||
const resolvedId = normalizeOptionalString(id) ?? "";
|
||||
if (!resolvedId) {
|
||||
return undefined;
|
||||
}
|
||||
return getLoadedChannelPluginForRead(resolvedId) ?? getBundledChannelPlugin(resolvedId);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getLoadedChannelPlugin } from "../../channels/plugins/index.js";
|
||||
import { getLoadedChannelPluginForRead } from "../../channels/plugins/registry-read.js";
|
||||
import type { ChannelId } from "../../channels/plugins/types.public.js";
|
||||
import { resolveAgentMainSessionKey } from "../../config/sessions/main-session.js";
|
||||
import { resolveStorePath } from "../../config/sessions/paths.js";
|
||||
@@ -177,7 +177,7 @@ export async function resolveDeliveryTarget(
|
||||
};
|
||||
}
|
||||
|
||||
const channelPlugin = getLoadedChannelPlugin(channel);
|
||||
const channelPlugin = getLoadedChannelPluginForRead(channel);
|
||||
const resolvedAccountId = normalizeAccountId(accountId);
|
||||
const configuredAllowFromRaw = channelPlugin?.config.resolveAllowFrom?.({
|
||||
cfg,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
|
||||
const normalizeChannelIdMock = vi.hoisted(() => vi.fn());
|
||||
const getChannelPluginMock = vi.hoisted(() => vi.fn());
|
||||
const getActivePluginChannelRegistryVersionMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
@@ -15,12 +14,8 @@ let resolveNormalizedTargetInput: TargetNormalizationModule["resolveNormalizedTa
|
||||
let normalizeTargetForProvider: TargetNormalizationModule["normalizeTargetForProvider"];
|
||||
let resetTargetNormalizerCacheForTests: TargetNormalizationModule["__testing"]["resetTargetNormalizerCacheForTests"];
|
||||
|
||||
vi.mock("../../channels/registry.js", () => ({
|
||||
normalizeAnyChannelId: (...args: unknown[]) => normalizeChannelIdMock(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../../channels/plugins/index.js", () => ({
|
||||
getChannelPlugin: (...args: unknown[]) => getChannelPluginMock(...args),
|
||||
vi.mock("../../channels/plugins/registry-read.js", () => ({
|
||||
getChannelPluginForRead: (...args: unknown[]) => getChannelPluginMock(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../../plugins/runtime.js", () => ({
|
||||
@@ -43,7 +38,6 @@ beforeAll(async () => {
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
normalizeChannelIdMock.mockReset();
|
||||
getChannelPluginMock.mockReset();
|
||||
getActivePluginChannelRegistryVersionMock.mockReset();
|
||||
resetTargetNormalizerCacheForTests();
|
||||
@@ -64,14 +58,13 @@ describe("normalizeTargetForProvider", () => {
|
||||
{
|
||||
provider: "unknown",
|
||||
setup: () => {
|
||||
normalizeChannelIdMock.mockReturnValueOnce(null);
|
||||
getChannelPluginMock.mockReturnValueOnce(undefined);
|
||||
},
|
||||
expected: "raw-id",
|
||||
},
|
||||
{
|
||||
provider: "telegram",
|
||||
setup: () => {
|
||||
normalizeChannelIdMock.mockReturnValueOnce("telegram");
|
||||
getActivePluginChannelRegistryVersionMock.mockReturnValueOnce(1);
|
||||
getChannelPluginMock.mockReturnValueOnce(undefined);
|
||||
},
|
||||
@@ -88,7 +81,6 @@ describe("normalizeTargetForProvider", () => {
|
||||
it("uses the cached target normalizer until the plugin registry version changes", () => {
|
||||
const firstNormalizer = vi.fn((raw: string) => raw.trim().toUpperCase());
|
||||
const secondNormalizer = vi.fn((raw: string) => `next:${raw.trim()}`);
|
||||
normalizeChannelIdMock.mockReturnValue("telegram");
|
||||
getActivePluginChannelRegistryVersionMock
|
||||
.mockReturnValueOnce(10)
|
||||
.mockReturnValueOnce(10)
|
||||
@@ -111,7 +103,6 @@ describe("normalizeTargetForProvider", () => {
|
||||
});
|
||||
|
||||
it("returns undefined when the provider normalizer resolves to an empty value", () => {
|
||||
normalizeChannelIdMock.mockReturnValueOnce("telegram");
|
||||
getActivePluginChannelRegistryVersionMock.mockReturnValueOnce(20);
|
||||
getChannelPluginMock.mockReturnValueOnce({
|
||||
messaging: {
|
||||
@@ -129,7 +120,6 @@ describe("resolveNormalizedTargetInput", () => {
|
||||
});
|
||||
|
||||
it("returns raw and normalized values", () => {
|
||||
normalizeChannelIdMock.mockReturnValueOnce("telegram");
|
||||
getActivePluginChannelRegistryVersionMock.mockReturnValueOnce(1);
|
||||
getChannelPluginMock.mockReturnValueOnce({
|
||||
messaging: {
|
||||
@@ -198,7 +188,6 @@ describe("maybeResolvePluginMessagingTarget", () => {
|
||||
});
|
||||
|
||||
it("invokes the plugin resolver with normalized input and defaults source", async () => {
|
||||
normalizeChannelIdMock.mockReturnValueOnce("slack");
|
||||
getActivePluginChannelRegistryVersionMock.mockReturnValueOnce(1);
|
||||
const resolveTarget = vi.fn().mockResolvedValue({
|
||||
to: "channel:C123ABC",
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { getChannelPlugin } from "../../channels/plugins/index.js";
|
||||
import { getChannelPluginForRead } from "../../channels/plugins/registry-read.js";
|
||||
import type { ChannelDirectoryEntryKind, ChannelId } from "../../channels/plugins/types.public.js";
|
||||
import { normalizeAnyChannelId } from "../../channels/registry.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { getActivePluginChannelRegistryVersion } from "../../plugins/runtime.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
} from "../../shared/string-coerce.js";
|
||||
|
||||
export function normalizeChannelTargetInput(raw: string): string {
|
||||
return raw.trim();
|
||||
@@ -28,10 +30,10 @@ export const __testing = {
|
||||
function resolveTargetNormalizer(channelId: ChannelId): TargetNormalizer {
|
||||
const version = getActivePluginChannelRegistryVersion();
|
||||
const cached = targetNormalizerCacheByChannelId.get(channelId);
|
||||
if (cached?.version === version) {
|
||||
if (cached && cached.version === version) {
|
||||
return cached.normalizer;
|
||||
}
|
||||
const plugin = getChannelPlugin(channelId);
|
||||
const plugin = getChannelPluginForRead(channelId);
|
||||
const normalizer = plugin?.messaging?.normalizeTarget;
|
||||
targetNormalizerCacheByChannelId.set(channelId, {
|
||||
version,
|
||||
@@ -48,7 +50,7 @@ export function normalizeTargetForProvider(provider: string, raw?: string): stri
|
||||
if (!fallback) {
|
||||
return undefined;
|
||||
}
|
||||
const providerId = normalizeAnyChannelId(provider);
|
||||
const providerId = normalizeOptionalLowercaseString(provider);
|
||||
const normalizer = providerId ? resolveTargetNormalizer(providerId) : undefined;
|
||||
return normalizeOptionalString(normalizer?.(raw) ?? fallback);
|
||||
}
|
||||
@@ -83,7 +85,7 @@ export function looksLikeTargetId(params: {
|
||||
}): boolean {
|
||||
const normalizedInput =
|
||||
params.normalized ?? normalizeTargetForProvider(params.channel, params.raw);
|
||||
const lookup = getChannelPlugin(params.channel)?.messaging?.targetResolver?.looksLikeId;
|
||||
const lookup = getChannelPluginForRead(params.channel)?.messaging?.targetResolver?.looksLikeId;
|
||||
if (lookup) {
|
||||
return lookup(params.raw, normalizedInput ?? params.raw);
|
||||
}
|
||||
@@ -114,7 +116,7 @@ export async function maybeResolvePluginMessagingTarget(params: {
|
||||
if (!normalizedInput) {
|
||||
return undefined;
|
||||
}
|
||||
const resolver = getChannelPlugin(params.channel)?.messaging?.targetResolver;
|
||||
const resolver = getChannelPluginForRead(params.channel)?.messaging?.targetResolver;
|
||||
if (!resolver?.resolveTarget) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -147,7 +149,7 @@ export async function maybeResolvePluginMessagingTarget(params: {
|
||||
}
|
||||
|
||||
export function buildTargetResolverSignature(channel: ChannelId): string {
|
||||
const plugin = getChannelPlugin(channel);
|
||||
const plugin = getChannelPluginForRead(channel);
|
||||
const resolver = plugin?.messaging?.targetResolver;
|
||||
const hint = resolver?.hint ?? "";
|
||||
const looksLike = resolver?.looksLikeId;
|
||||
|
||||
@@ -6,8 +6,8 @@ const mocks = vi.hoisted(() => ({
|
||||
getLoadedChannelPlugin: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../../channels/plugins/index.js", () => ({
|
||||
getLoadedChannelPlugin: mocks.getLoadedChannelPlugin,
|
||||
vi.mock("../../channels/plugins/registry-read.js", () => ({
|
||||
getLoadedChannelPluginForRead: mocks.getLoadedChannelPlugin,
|
||||
}));
|
||||
|
||||
describe("tryResolveLoadedOutboundTarget", () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getLoadedChannelPlugin } from "../../channels/plugins/index.js";
|
||||
import { getLoadedChannelPluginForRead } from "../../channels/plugins/registry-read.js";
|
||||
import type { ChannelPlugin } from "../../channels/plugins/types.plugin.js";
|
||||
import type { ChannelOutboundTargetMode } from "../../channels/plugins/types.public.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
@@ -18,7 +18,7 @@ function resolveLoadedOutboundChannelPlugin(channel: string): ChannelPlugin | un
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return getLoadedChannelPlugin(normalized);
|
||||
return getLoadedChannelPluginForRead(normalized);
|
||||
}
|
||||
|
||||
export function tryResolveLoadedOutboundTarget(params: {
|
||||
|
||||
Reference in New Issue
Block a user