Status: lazy-load read-only account inspectors

This commit is contained in:
Vincent Koc
2026-03-15 20:10:43 -07:00
parent 986b772a89
commit f71f44576a
10 changed files with 79 additions and 49 deletions

View File

@@ -41,17 +41,17 @@ async function buildSnapshotFromAccount<ResolvedAccount>(params: {
};
}
function inspectChannelAccount<ResolvedAccount>(params: {
async function inspectChannelAccount<ResolvedAccount>(params: {
plugin: ChannelPlugin<ResolvedAccount>;
cfg: OpenClawConfig;
accountId: string;
}): ResolvedAccount | null {
}): Promise<ResolvedAccount | null> {
return (params.plugin.config.inspectAccount?.(params.cfg, params.accountId) ??
inspectReadOnlyChannelAccount({
(await inspectReadOnlyChannelAccount({
channelId: params.plugin.id,
cfg: params.cfg,
accountId: params.accountId,
})) as ResolvedAccount | null;
}))) as ResolvedAccount | null;
}
export async function buildReadOnlySourceChannelAccountSnapshot<ResolvedAccount>(params: {
@@ -62,7 +62,7 @@ export async function buildReadOnlySourceChannelAccountSnapshot<ResolvedAccount>
probe?: unknown;
audit?: unknown;
}): Promise<ChannelAccountSnapshot | null> {
const inspectedAccount = inspectChannelAccount(params);
const inspectedAccount = await inspectChannelAccount(params);
if (!inspectedAccount) {
return null;
}
@@ -80,7 +80,7 @@ export async function buildChannelAccountSnapshot<ResolvedAccount>(params: {
probe?: unknown;
audit?: unknown;
}): Promise<ChannelAccountSnapshot> {
const inspectedAccount = inspectChannelAccount(params);
const inspectedAccount = await inspectChannelAccount(params);
const account =
inspectedAccount ?? params.plugin.config.resolveAccount(params.cfg, params.accountId);
return await buildSnapshotFromAccount({

View File

@@ -0,0 +1,4 @@
export {
inspectDiscordAccount,
type InspectedDiscordAccount,
} from "../../extensions/discord/src/account-inspect.js";

View File

@@ -0,0 +1,4 @@
export {
inspectSlackAccount,
type InspectedSlackAccount,
} from "../../extensions/slack/src/account-inspect.js";

View File

@@ -0,0 +1,4 @@
export {
inspectTelegramAccount,
type InspectedTelegramAccount,
} from "../../extensions/telegram/src/account-inspect.js";

View File

@@ -1,41 +1,55 @@
import {
inspectDiscordAccount,
type InspectedDiscordAccount,
} from "../../extensions/discord/src/account-inspect.js";
import {
inspectSlackAccount,
type InspectedSlackAccount,
} from "../../extensions/slack/src/account-inspect.js";
import {
inspectTelegramAccount,
type InspectedTelegramAccount,
} from "../../extensions/telegram/src/account-inspect.js";
import type { OpenClawConfig } from "../config/config.js";
import type { ChannelId } from "./plugins/types.js";
export type ReadOnlyInspectedAccount =
| InspectedDiscordAccount
| InspectedSlackAccount
| InspectedTelegramAccount;
type DiscordInspectModule = typeof import("./read-only-account-inspect.discord.runtime.js");
type SlackInspectModule = typeof import("./read-only-account-inspect.slack.runtime.js");
type TelegramInspectModule = typeof import("./read-only-account-inspect.telegram.runtime.js");
export function inspectReadOnlyChannelAccount(params: {
let discordInspectModulePromise: Promise<DiscordInspectModule> | undefined;
let slackInspectModulePromise: Promise<SlackInspectModule> | undefined;
let telegramInspectModulePromise: Promise<TelegramInspectModule> | undefined;
function loadDiscordInspectModule() {
discordInspectModulePromise ??= import("./read-only-account-inspect.discord.runtime.js");
return discordInspectModulePromise;
}
function loadSlackInspectModule() {
slackInspectModulePromise ??= import("./read-only-account-inspect.slack.runtime.js");
return slackInspectModulePromise;
}
function loadTelegramInspectModule() {
telegramInspectModulePromise ??= import("./read-only-account-inspect.telegram.runtime.js");
return telegramInspectModulePromise;
}
export type ReadOnlyInspectedAccount =
| Awaited<ReturnType<DiscordInspectModule["inspectDiscordAccount"]>>
| Awaited<ReturnType<SlackInspectModule["inspectSlackAccount"]>>
| Awaited<ReturnType<TelegramInspectModule["inspectTelegramAccount"]>>;
export async function inspectReadOnlyChannelAccount(params: {
channelId: ChannelId;
cfg: OpenClawConfig;
accountId?: string | null;
}): ReadOnlyInspectedAccount | null {
}): Promise<ReadOnlyInspectedAccount | null> {
if (params.channelId === "discord") {
const { inspectDiscordAccount } = await loadDiscordInspectModule();
return inspectDiscordAccount({
cfg: params.cfg,
accountId: params.accountId,
});
}
if (params.channelId === "slack") {
const { inspectSlackAccount } = await loadSlackInspectModule();
return inspectSlackAccount({
cfg: params.cfg,
accountId: params.accountId,
});
}
if (params.channelId === "telegram") {
const { inspectTelegramAccount } = await loadTelegramInspectModule();
return inspectTelegramAccount({
cfg: params.cfg,
accountId: params.accountId,

View File

@@ -79,11 +79,11 @@ export async function resolveDefaultChannelAccountContext(
const inspected =
plugin.config.inspectAccount?.(cfg, defaultAccountId) ??
inspectReadOnlyChannelAccount({
(await inspectReadOnlyChannelAccount({
channelId: plugin.id,
cfg,
accountId: defaultAccountId,
});
}));
let account = inspected;
if (!account) {

View File

@@ -165,18 +165,14 @@ const buildSessionSummary = (storePath: string) => {
const asRecord = (value: unknown): Record<string, unknown> | null =>
value && typeof value === "object" ? (value as Record<string, unknown>) : null;
function inspectHealthAccount(
plugin: ChannelPlugin,
cfg: OpenClawConfig,
accountId: string,
): unknown {
async function inspectHealthAccount(plugin: ChannelPlugin, cfg: OpenClawConfig, accountId: string) {
return (
plugin.config.inspectAccount?.(cfg, accountId) ??
inspectReadOnlyChannelAccount({
(await inspectReadOnlyChannelAccount({
channelId: plugin.id,
cfg,
accountId,
})
}))
);
}
@@ -206,7 +202,7 @@ async function resolveHealthAccountContext(params: {
diagnostics.push(
`${params.plugin.id}:${params.accountId}: failed to resolve account (${formatErrorMessage(error)}).`,
);
account = inspectHealthAccount(params.plugin, params.cfg, params.accountId);
account = await inspectHealthAccount(params.plugin, params.cfg, params.accountId);
}
if (!account) {

View File

@@ -91,14 +91,18 @@ function formatTokenHint(token: string, opts: { showSecrets: boolean }): string
return `${head}${tail} · len ${t.length}`;
}
function inspectChannelAccount(plugin: ChannelPlugin, cfg: OpenClawConfig, accountId: string) {
async function inspectChannelAccount(
plugin: ChannelPlugin,
cfg: OpenClawConfig,
accountId: string,
) {
return (
plugin.config.inspectAccount?.(cfg, accountId) ??
inspectReadOnlyChannelAccount({
(await inspectReadOnlyChannelAccount({
channelId: plugin.id,
cfg,
accountId,
})
}))
);
}
@@ -106,8 +110,8 @@ async function resolveChannelAccountRow(
params: ResolvedChannelAccountRowParams,
): Promise<ChannelAccountRow> {
const { plugin, cfg, sourceConfig, accountId } = params;
const sourceInspectedAccount = inspectChannelAccount(plugin, sourceConfig, accountId);
const resolvedInspectedAccount = inspectChannelAccount(plugin, cfg, accountId);
const sourceInspectedAccount = await inspectChannelAccount(plugin, sourceConfig, accountId);
const resolvedInspectedAccount = await inspectChannelAccount(plugin, cfg, accountId);
const resolvedInspection = resolvedInspectedAccount as {
enabled?: boolean;
configured?: boolean;

View File

@@ -105,14 +105,18 @@ const buildAccountDetails = (params: {
return details;
};
function inspectChannelAccount(plugin: ChannelPlugin, cfg: OpenClawConfig, accountId: string) {
async function inspectChannelAccount(
plugin: ChannelPlugin,
cfg: OpenClawConfig,
accountId: string,
) {
return (
plugin.config.inspectAccount?.(cfg, accountId) ??
inspectReadOnlyChannelAccount({
(await inspectReadOnlyChannelAccount({
channelId: plugin.id,
cfg,
accountId,
})
}))
);
}
@@ -135,8 +139,8 @@ export async function buildChannelSummary(
const entries: ChannelAccountEntry[] = [];
for (const accountId of resolvedAccountIds) {
const sourceInspectedAccount = inspectChannelAccount(plugin, sourceConfig, accountId);
const resolvedInspectedAccount = inspectChannelAccount(plugin, effective, accountId);
const sourceInspectedAccount = await inspectChannelAccount(plugin, sourceConfig, accountId);
const resolvedInspectedAccount = await inspectChannelAccount(plugin, effective, accountId);
const resolvedInspection = resolvedInspectedAccount as {
enabled?: boolean;
configured?: boolean;

View File

@@ -144,17 +144,17 @@ export async function collectChannelSecurityFindings(params: {
const findings: SecurityAuditFinding[] = [];
const sourceConfig = params.sourceConfig ?? params.cfg;
const inspectChannelAccount = (
const inspectChannelAccount = async (
plugin: (typeof params.plugins)[number],
cfg: OpenClawConfig,
accountId: string,
) =>
plugin.config.inspectAccount?.(cfg, accountId) ??
inspectReadOnlyChannelAccount({
(await inspectReadOnlyChannelAccount({
channelId: plugin.id,
cfg,
accountId,
});
}));
const asAccountRecord = (value: unknown): Record<string, unknown> | null =>
value && typeof value === "object" && !Array.isArray(value)
@@ -166,8 +166,8 @@ export async function collectChannelSecurityFindings(params: {
accountId: string,
) => {
const diagnostics: string[] = [];
const sourceInspectedAccount = inspectChannelAccount(plugin, sourceConfig, accountId);
const resolvedInspectedAccount = inspectChannelAccount(plugin, params.cfg, accountId);
const sourceInspectedAccount = await inspectChannelAccount(plugin, sourceConfig, accountId);
const resolvedInspectedAccount = await inspectChannelAccount(plugin, params.cfg, accountId);
const sourceInspection = sourceInspectedAccount as {
enabled?: boolean;
configured?: boolean;