import { resolveChannelDefaultAccountId } from "../channels/plugins/helpers.js" ;
import type { ChannelPlugin } from "../channels/plugins/types.plugin.js" ;
import { inspectReadOnlyChannelAccount } from "../channels/read-only-account-inspect.js" ;
import type { OpenClawConfig } from "../config/types.openclaw.js" ;
import { formatErrorMessage } from "../infra/errors.js" ;
import { isRecord } from "../utils.js" ;
export type ChannelDefaultAccountContext = {
accountIds: string[];
defaultAccountId: string;
account: unknown;
enabled: boolean ;
configured: boolean ;
diagnostics: string[];
/**
* Indicates read - only resolution was used instead of strict full - account resolution .
* This is expected for read_only mode and does not necessarily mean an error occurred .
*/
degraded: boolean ;
};
export type ChannelAccountContextMode = "strict" | "read_only" ;
function getBooleanField(value: unknown, key: string): boolean | undefined {
const record = isRecord(value) ? value : null ;
if (!record) {
return undefined;
}
return typeof record[key] === "boolean" ? record[key] : undefined;
}
function formatContextDiagnostic(params: {
commandName?: string;
pluginId: string;
accountId: string;
message: string;
}): string {
const prefix = params.commandName ? `${params.commandName}: ` : "" ;
return `${prefix}channels.${params.pluginId}.accounts.${params.accountId}: ${params.message}`;
}
export async function resolveDefaultChannelAccountContext(
plugin: ChannelPlugin,
cfg: OpenClawConfig,
options?: { mode?: ChannelAccountContextMode; commandName?: string },
): Promise<ChannelDefaultAccountContext> {
const mode = options?.mode ?? "strict" ;
const accountIds = plugin.config.listAccountIds(cfg);
const defaultAccountId = resolveChannelDefaultAccountId({
plugin,
cfg,
accountIds,
});
if (mode === "strict" ) {
const account = plugin.config.resolveAccount(cfg, defaultAccountId);
const enabled = plugin.config.isEnabled ? plugin.config.isEnabled(account, cfg) : true ;
const configured = plugin.config.isConfigured
? await plugin.config.isConfigured(account, cfg)
: true ;
return {
accountIds,
defaultAccountId,
account,
enabled,
configured,
diagnostics: [],
degraded: false ,
};
}
const diagnostics: string[] = [];
let degraded = false ;
const inspected =
plugin.config.inspectAccount?.(cfg, defaultAccountId) ??
(await inspectReadOnlyChannelAccount({
channelId: plugin.id,
cfg,
accountId: defaultAccountId,
}));
let account = inspected;
if (!account) {
try {
account = plugin.config.resolveAccount(cfg, defaultAccountId);
} catch (error) {
degraded = true ;
diagnostics.push(
formatContextDiagnostic({
commandName: options?.commandName,
pluginId: plugin.id,
accountId: defaultAccountId,
message: `failed to resolve account (${formatErrorMessage(error)}); skipping read-only checks.`,
}),
);
return {
accountIds,
defaultAccountId,
account: {},
enabled: false ,
configured: false ,
diagnostics,
degraded,
};
}
} else {
degraded = true ;
}
const inspectEnabled = getBooleanField(account, "enabled" );
let enabled = inspectEnabled ?? true ;
if (inspectEnabled === undefined && plugin.config.isEnabled) {
try {
enabled = plugin.config.isEnabled(account, cfg);
} catch (error) {
degraded = true ;
enabled = false ;
diagnostics.push(
formatContextDiagnostic({
commandName: options?.commandName,
pluginId: plugin.id,
accountId: defaultAccountId,
message: `failed to evaluate enabled state (${formatErrorMessage(error)}); treating as disabled.`,
}),
);
}
}
const inspectConfigured = getBooleanField(account, "configured" );
let configured = inspectConfigured ?? true ;
if (inspectConfigured === undefined && plugin.config.isConfigured) {
try {
configured = await plugin.config.isConfigured(account, cfg);
} catch (error) {
degraded = true ;
configured = false ;
diagnostics.push(
formatContextDiagnostic({
commandName: options?.commandName,
pluginId: plugin.id,
accountId: defaultAccountId,
message: `failed to evaluate configured state (${formatErrorMessage(error)}); treating as unconfigured.`,
}),
);
}
}
return {
accountIds,
defaultAccountId,
account,
enabled,
configured,
diagnostics,
degraded,
};
}
Messung V0.5 in Prozent C=100 H=100 G=100
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland