perf: defer bundled channel presence lookups

This commit is contained in:
Peter Steinberger
2026-04-11 05:42:01 +01:00
parent 70c0a64595
commit 2d6519dcb9
5 changed files with 39 additions and 25 deletions

View File

@@ -1,7 +1,7 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { afterEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../config/config.js";
import {
hasMeaningfulChannelConfig,
@@ -9,6 +9,21 @@ import {
listPotentialConfiguredChannelIds,
} from "./config-presence.js";
vi.mock("./plugins/bundled-ids.js", () => ({
listBundledChannelPluginIds: () => ["matrix"],
}));
vi.mock("../channels/plugins/persisted-auth-state.js", () => ({
listBundledChannelIdsWithPersistedAuthState: () => ["matrix"],
hasBundledChannelPersistedAuthState: ({
channelId,
env,
}: {
channelId: string;
env?: NodeJS.ProcessEnv;
}) => channelId === "matrix" && env?.OPENCLAW_STATE_DIR?.includes("persisted-matrix"),
}));
const tempDirs: string[] = [];
function makeTempStateDir() {
@@ -45,8 +60,7 @@ describe("config presence", () => {
});
it("ignores enabled-only matrix config when listing configured channels", () => {
const stateDir = makeTempStateDir();
const env = { OPENCLAW_STATE_DIR: stateDir } as NodeJS.ProcessEnv;
const env = {} as NodeJS.ProcessEnv;
const cfg = { channels: { matrix: { enabled: false } } };
expectPotentialConfiguredChannelCase({
@@ -58,9 +72,7 @@ describe("config presence", () => {
});
it("detects env-only channel config", () => {
const stateDir = makeTempStateDir();
const env = {
OPENCLAW_STATE_DIR: stateDir,
MATRIX_ACCESS_TOKEN: "token",
} as NodeJS.ProcessEnv;
@@ -73,17 +85,12 @@ describe("config presence", () => {
});
it("detects persisted Matrix credentials without config or env", () => {
const stateDir = makeTempStateDir();
fs.mkdirSync(path.join(stateDir, "credentials", "matrix"), { recursive: true });
fs.writeFileSync(
path.join(stateDir, "credentials", "matrix", "credentials.json"),
JSON.stringify({
homeserver: "https://matrix.example.org",
userId: "@bot:example.org",
accessToken: "token",
}),
"utf8",
const stateDir = makeTempStateDir().replace(
"openclaw-channel-config-presence-",
"persisted-matrix-",
);
fs.mkdirSync(stateDir, { recursive: true });
tempDirs.push(stateDir);
const env = { OPENCLAW_STATE_DIR: stateDir } as NodeJS.ProcessEnv;
expectPotentialConfiguredChannelCase({

View File

@@ -36,7 +36,12 @@ function hasPersistedChannelState(env: NodeJS.ProcessEnv): boolean {
return fs.existsSync(resolveStateDir(env, os.homedir));
}
const PERSISTED_AUTH_STATE_CHANNEL_IDS = listBundledChannelIdsWithPersistedAuthState();
let persistedAuthStateChannelIds: string[] | null = null;
function getPersistedAuthStateChannelIds(): string[] {
persistedAuthStateChannelIds ??= listBundledChannelIdsWithPersistedAuthState();
return persistedAuthStateChannelIds;
}
export function listPotentialConfiguredChannelIds(
cfg: OpenClawConfig,
@@ -70,7 +75,7 @@ export function listPotentialConfiguredChannelIds(
}
if (options.includePersistedAuthState !== false && hasPersistedChannelState(env)) {
for (const channelId of PERSISTED_AUTH_STATE_CHANNEL_IDS) {
for (const channelId of getPersistedAuthStateChannelIds()) {
if (hasBundledChannelPersistedAuthState({ channelId, cfg, env })) {
configuredChannelIds.add(channelId);
}
@@ -98,7 +103,7 @@ function hasEnvConfiguredChannel(
if (options.includePersistedAuthState === false || !hasPersistedChannelState(env)) {
return false;
}
return PERSISTED_AUTH_STATE_CHANNEL_IDS.some((channelId) =>
return getPersistedAuthStateChannelIds().some((channelId) =>
hasBundledChannelPersistedAuthState({ channelId, cfg, env }),
);
}

View File

@@ -1,9 +1,10 @@
import { listChannelCatalogEntries } from "../../plugins/channel-catalog-registry.js";
export const BUNDLED_CHANNEL_PLUGIN_IDS = listChannelCatalogEntries({ origin: "bundled" })
.map((entry) => entry.pluginId)
.toSorted((left, right) => left.localeCompare(right));
let bundledChannelPluginIds: string[] | null = null;
export function listBundledChannelPluginIds(): string[] {
return [...BUNDLED_CHANNEL_PLUGIN_IDS];
bundledChannelPluginIds ??= listChannelCatalogEntries({ origin: "bundled" })
.map((entry) => entry.pluginId)
.toSorted((left, right) => left.localeCompare(right));
return [...bundledChannelPluginIds];
}

View File

@@ -12,6 +12,9 @@ export function isChannelConfigured(
channelId: string,
env: NodeJS.ProcessEnv = process.env,
): boolean {
if (hasMeaningfulChannelConfigShallow(resolveChannelConfigRecord(cfg, channelId))) {
return true;
}
if (hasBundledChannelConfiguredState({ channelId, cfg, env })) {
return true;
}
@@ -19,9 +22,6 @@ export function isChannelConfigured(
if (pluginPersistedAuthState) {
return true;
}
if (hasMeaningfulChannelConfigShallow(resolveChannelConfigRecord(cfg, channelId))) {
return true;
}
const plugin = getBootstrapChannelPlugin(channelId);
return Boolean(plugin?.config?.hasConfiguredState?.({ cfg, env }));
}

View File

@@ -81,6 +81,7 @@ describe("applyPluginAutoEnable channels", () => {
env: {
...makeIsolatedEnv(),
OPENCLAW_STATE_DIR: stateDir,
OPENCLAW_BUNDLED_PLUGINS_DIR: "/nonexistent/bundled/plugins",
},
manifestRegistry: makeRegistry([]),
});