perf(runtime): reduce hot-path config and routing overhead

This commit is contained in:
Peter Steinberger
2026-03-03 00:20:16 +00:00
parent 051b380d38
commit 6bf84ac28c
3 changed files with 88 additions and 15 deletions

View File

@@ -229,8 +229,8 @@ function validateConfigObjectWithPluginsBase(
type RegistryInfo = { type RegistryInfo = {
registry: ReturnType<typeof loadPluginManifestRegistry>; registry: ReturnType<typeof loadPluginManifestRegistry>;
knownIds: Set<string>; knownIds?: Set<string>;
normalizedPlugins: ReturnType<typeof normalizePluginsConfig>; normalizedPlugins?: ReturnType<typeof normalizePluginsConfig>;
}; };
let registryInfo: RegistryInfo | null = null; let registryInfo: RegistryInfo | null = null;
@@ -245,8 +245,6 @@ function validateConfigObjectWithPluginsBase(
config, config,
workspaceDir: workspaceDir ?? undefined, workspaceDir: workspaceDir ?? undefined,
}); });
const knownIds = new Set(registry.plugins.map((record) => record.id));
const normalizedPlugins = normalizePluginsConfig(config.plugins);
for (const diag of registry.diagnostics) { for (const diag of registry.diagnostics) {
let path = diag.pluginId ? `plugins.entries.${diag.pluginId}` : "plugins"; let path = diag.pluginId ? `plugins.entries.${diag.pluginId}` : "plugins";
@@ -262,10 +260,26 @@ function validateConfigObjectWithPluginsBase(
} }
} }
registryInfo = { registry, knownIds, normalizedPlugins }; registryInfo = { registry };
return registryInfo; return registryInfo;
}; };
const ensureKnownIds = (): Set<string> => {
const info = ensureRegistry();
if (!info.knownIds) {
info.knownIds = new Set(info.registry.plugins.map((record) => record.id));
}
return info.knownIds;
};
const ensureNormalizedPlugins = (): ReturnType<typeof normalizePluginsConfig> => {
const info = ensureRegistry();
if (!info.normalizedPlugins) {
info.normalizedPlugins = normalizePluginsConfig(config.plugins);
}
return info.normalizedPlugins;
};
const allowedChannels = new Set<string>(["defaults", "modelByChannel", ...CHANNEL_IDS]); const allowedChannels = new Set<string>(["defaults", "modelByChannel", ...CHANNEL_IDS]);
if (config.channels && isRecord(config.channels)) { if (config.channels && isRecord(config.channels)) {
@@ -346,7 +360,9 @@ function validateConfigObjectWithPluginsBase(
return { ok: true, config, warnings }; return { ok: true, config, warnings };
} }
const { registry, knownIds, normalizedPlugins } = ensureRegistry(); const { registry } = ensureRegistry();
const knownIds = ensureKnownIds();
const normalizedPlugins = ensureNormalizedPlugins();
const pushMissingPluginIssue = ( const pushMissingPluginIssue = (
path: string, path: string,
pluginId: string, pluginId: string,

View File

@@ -1,17 +1,45 @@
import { getChannelPlugin, normalizeChannelId } from "../../channels/plugins/index.js"; import { getChannelPlugin, normalizeChannelId } from "../../channels/plugins/index.js";
import type { ChannelId } from "../../channels/plugins/types.js"; import type { ChannelId } from "../../channels/plugins/types.js";
import { getActivePluginRegistryVersion } from "../../plugins/runtime.js";
export function normalizeChannelTargetInput(raw: string): string { export function normalizeChannelTargetInput(raw: string): string {
return raw.trim(); return raw.trim();
} }
type TargetNormalizer = ((raw: string) => string | undefined) | undefined;
type TargetNormalizerCacheEntry = {
version: number;
normalizer: TargetNormalizer;
};
const targetNormalizerCacheByChannelId = new Map<string, TargetNormalizerCacheEntry>();
function resolveTargetNormalizer(channelId: ChannelId): TargetNormalizer {
const version = getActivePluginRegistryVersion();
const cached = targetNormalizerCacheByChannelId.get(channelId);
if (cached?.version === version) {
return cached.normalizer;
}
const plugin = getChannelPlugin(channelId);
const normalizer = plugin?.messaging?.normalizeTarget;
targetNormalizerCacheByChannelId.set(channelId, {
version,
normalizer,
});
return normalizer;
}
export function normalizeTargetForProvider(provider: string, raw?: string): string | undefined { export function normalizeTargetForProvider(provider: string, raw?: string): string | undefined {
if (!raw) { if (!raw) {
return undefined; return undefined;
} }
const fallback = raw.trim() || undefined;
if (!fallback) {
return undefined;
}
const providerId = normalizeChannelId(provider); const providerId = normalizeChannelId(provider);
const plugin = providerId ? getChannelPlugin(providerId) : undefined; const normalizer = providerId ? resolveTargetNormalizer(providerId) : undefined;
const normalized = plugin?.messaging?.normalizeTarget?.(raw) ?? (raw.trim() || undefined); const normalized = normalizer?.(raw) ?? fallback;
return normalized || undefined; return normalized || undefined;
} }

View File

@@ -448,6 +448,35 @@ function formatRouteCachePeer(peer: RoutePeer | null): string {
return `${peer.kind}:${peer.id}`; return `${peer.kind}:${peer.id}`;
} }
function formatRoleIdsCacheKey(roleIds: string[]): string {
const count = roleIds.length;
if (count === 0) {
return "-";
}
if (count === 1) {
return roleIds[0] ?? "-";
}
if (count === 2) {
const first = roleIds[0] ?? "";
const second = roleIds[1] ?? "";
return first <= second ? `${first},${second}` : `${second},${first}`;
}
return roleIds.toSorted().join(",");
}
function buildResolvedRouteCacheKey(params: {
channel: string;
accountId: string;
peer: RoutePeer | null;
parentPeer: RoutePeer | null;
guildId: string;
teamId: string;
memberRoleIds: string[];
dmScope: string;
}): string {
return `${params.channel}\t${params.accountId}\t${formatRouteCachePeer(params.peer)}\t${formatRouteCachePeer(params.parentPeer)}\t${params.guildId || "-"}\t${params.teamId || "-"}\t${formatRoleIdsCacheKey(params.memberRoleIds)}\t${params.dmScope}`;
}
function hasGuildConstraint(match: NormalizedBindingMatch): boolean { function hasGuildConstraint(match: NormalizedBindingMatch): boolean {
return Boolean(match.guildId); return Boolean(match.guildId);
} }
@@ -524,16 +553,16 @@ export function resolveAgentRoute(input: ResolveAgentRouteInput): ResolvedAgentR
const routeCache = const routeCache =
!shouldLogDebug && !identityLinks ? resolveRouteCacheForConfig(input.cfg) : null; !shouldLogDebug && !identityLinks ? resolveRouteCacheForConfig(input.cfg) : null;
const routeCacheKey = routeCache const routeCacheKey = routeCache
? [ ? buildResolvedRouteCacheKey({
channel, channel,
accountId, accountId,
formatRouteCachePeer(peer), peer,
formatRouteCachePeer(parentPeer), parentPeer,
guildId || "-", guildId,
teamId || "-", teamId,
memberRoleIds.length > 0 ? memberRoleIds.toSorted().join(",") : "-", memberRoleIds,
dmScope, dmScope,
].join("\t") })
: ""; : "";
if (routeCache && routeCacheKey) { if (routeCache && routeCacheKey) {
const cachedRoute = routeCache.get(routeCacheKey); const cachedRoute = routeCache.get(routeCacheKey);