mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 15:40:44 +00:00
fix: avoid channel runtime in format summaries
This commit is contained in:
@@ -11,6 +11,7 @@ import type { AgentSummary } from "./agents.config.js";
|
|||||||
import { buildAgentSummaries } from "./agents.config.js";
|
import { buildAgentSummaries } from "./agents.config.js";
|
||||||
import {
|
import {
|
||||||
buildProviderStatusIndex,
|
buildProviderStatusIndex,
|
||||||
|
buildProviderSummaryMetadataIndex,
|
||||||
listProvidersForAgent,
|
listProvidersForAgent,
|
||||||
summarizeBindings,
|
summarizeBindings,
|
||||||
} from "./agents.providers.js";
|
} from "./agents.providers.js";
|
||||||
@@ -107,11 +108,12 @@ export async function agentsListCommand(
|
|||||||
// catalog entry, this keeps `agents list --json` on the config-only path.
|
// catalog entry, this keeps `agents list --json` on the config-only path.
|
||||||
const includeProviderDetails = !opts.json || opts.bindings === true;
|
const includeProviderDetails = !opts.json || opts.bindings === true;
|
||||||
const providerStatus = includeProviderDetails ? await buildProviderStatusIndex(cfg) : null;
|
const providerStatus = includeProviderDetails ? await buildProviderStatusIndex(cfg) : null;
|
||||||
|
const providerMetadata = includeProviderDetails ? buildProviderSummaryMetadataIndex(cfg) : null;
|
||||||
|
|
||||||
for (const summary of summaries) {
|
for (const summary of summaries) {
|
||||||
const bindings = bindingMap.get(summary.id) ?? [];
|
const bindings = bindingMap.get(summary.id) ?? [];
|
||||||
if (includeProviderDetails && providerStatus) {
|
if (includeProviderDetails && providerStatus && providerMetadata) {
|
||||||
const routes = summarizeBindings(cfg, bindings);
|
const routes = summarizeBindings(cfg, bindings, providerMetadata);
|
||||||
if (routes.length > 0) {
|
if (routes.length > 0) {
|
||||||
summary.routes = routes;
|
summary.routes = routes;
|
||||||
} else if (summary.isDefault) {
|
} else if (summary.isDefault) {
|
||||||
@@ -123,6 +125,7 @@ export async function agentsListCommand(
|
|||||||
cfg,
|
cfg,
|
||||||
bindings,
|
bindings,
|
||||||
providerStatus,
|
providerStatus,
|
||||||
|
providerMetadata,
|
||||||
});
|
});
|
||||||
if (providerLines.length > 0) {
|
if (providerLines.length > 0) {
|
||||||
summary.providers = providerLines;
|
summary.providers = providerLines;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { isChannelVisibleInConfiguredLists } from "../channels/plugins/exposure.js";
|
import { isChannelVisibleInConfiguredLists } from "../channels/plugins/exposure.js";
|
||||||
import { resolveChannelDefaultAccountId } from "../channels/plugins/helpers.js";
|
import { resolveChannelDefaultAccountId } from "../channels/plugins/helpers.js";
|
||||||
import { getChannelPlugin, normalizeChannelId } from "../channels/plugins/index.js";
|
import { normalizeChannelId } from "../channels/plugins/index.js";
|
||||||
import { listReadOnlyChannelPluginsForConfig } from "../channels/plugins/read-only.js";
|
import { listReadOnlyChannelPluginsForConfig } from "../channels/plugins/read-only.js";
|
||||||
import type { ChannelPlugin } from "../channels/plugins/types.plugin.js";
|
import type { ChannelPlugin } from "../channels/plugins/types.plugin.js";
|
||||||
import type { ChannelId } from "../channels/plugins/types.public.js";
|
import type { ChannelId } from "../channels/plugins/types.public.js";
|
||||||
@@ -19,10 +19,37 @@ type ProviderAccountStatus = {
|
|||||||
visibleInConfiguredLists?: boolean;
|
visibleInConfiguredLists?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ProviderSummaryMetadata = {
|
||||||
|
label: string;
|
||||||
|
defaultAccountId: string;
|
||||||
|
visibleInConfiguredLists: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
function providerAccountKey(provider: ChannelId, accountId?: string) {
|
function providerAccountKey(provider: ChannelId, accountId?: string) {
|
||||||
return `${provider}:${accountId ?? DEFAULT_ACCOUNT_ID}`;
|
return `${provider}:${accountId ?? DEFAULT_ACCOUNT_ID}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildProviderSummaryMetadataIndex(
|
||||||
|
cfg: OpenClawConfig,
|
||||||
|
): Map<ChannelId, ProviderSummaryMetadata> {
|
||||||
|
return new Map(
|
||||||
|
listReadOnlyChannelPluginsForConfig(cfg, {
|
||||||
|
includeSetupRuntimeFallback: false,
|
||||||
|
}).map((plugin) => [
|
||||||
|
plugin.id,
|
||||||
|
{
|
||||||
|
label: plugin.meta.label,
|
||||||
|
defaultAccountId: resolveChannelDefaultAccountId({
|
||||||
|
plugin,
|
||||||
|
cfg,
|
||||||
|
accountIds: plugin.config.listAccountIds(cfg),
|
||||||
|
}),
|
||||||
|
visibleInConfiguredLists: isChannelVisibleInConfiguredLists(plugin.meta),
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function isUnresolvedSecretRefResolutionError(error: unknown): boolean {
|
function isUnresolvedSecretRefResolutionError(error: unknown): boolean {
|
||||||
return (
|
return (
|
||||||
error instanceof Error &&
|
error instanceof Error &&
|
||||||
@@ -37,8 +64,7 @@ function formatChannelAccountLabel(params: {
|
|||||||
accountId: string;
|
accountId: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
}): string {
|
}): string {
|
||||||
const label =
|
const label = params.providerLabel ?? params.provider;
|
||||||
params.providerLabel ?? getChannelPlugin(params.provider)?.meta.label ?? params.provider;
|
|
||||||
const account = params.name?.trim()
|
const account = params.name?.trim()
|
||||||
? `${params.accountId} (${params.name.trim()})`
|
? `${params.accountId} (${params.name.trim()})`
|
||||||
: params.accountId;
|
: params.accountId;
|
||||||
@@ -134,31 +160,26 @@ export async function buildProviderStatusIndex(
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveDefaultAccountId(cfg: OpenClawConfig, provider: ChannelId): string {
|
function resolveDefaultAccountId(
|
||||||
const plugin = getChannelPlugin(provider);
|
provider: ChannelId,
|
||||||
if (!plugin) {
|
metadataByProvider: ReadonlyMap<ChannelId, ProviderSummaryMetadata>,
|
||||||
return DEFAULT_ACCOUNT_ID;
|
): string {
|
||||||
}
|
return metadataByProvider.get(provider)?.defaultAccountId ?? DEFAULT_ACCOUNT_ID;
|
||||||
return resolveChannelDefaultAccountId({ plugin, cfg });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldShowProviderEntry(entry: ProviderAccountStatus, cfg: OpenClawConfig): boolean {
|
function shouldShowProviderEntry(params: {
|
||||||
if (entry.visibleInConfiguredLists !== undefined) {
|
entry: ProviderAccountStatus;
|
||||||
if (!entry.visibleInConfiguredLists) {
|
cfg: OpenClawConfig;
|
||||||
const providerConfig = (cfg as Record<string, unknown>)[entry.provider];
|
metadataByProvider: ReadonlyMap<ChannelId, ProviderSummaryMetadata>;
|
||||||
return Boolean(entry.configured) || Boolean(providerConfig);
|
}): boolean {
|
||||||
}
|
const visibleInConfiguredLists =
|
||||||
return Boolean(entry.configured);
|
params.entry.visibleInConfiguredLists ??
|
||||||
|
params.metadataByProvider.get(params.entry.provider)?.visibleInConfiguredLists;
|
||||||
|
if (visibleInConfiguredLists === false) {
|
||||||
|
const providerConfig = (params.cfg as Record<string, unknown>)[params.entry.provider];
|
||||||
|
return Boolean(params.entry.configured) || Boolean(providerConfig);
|
||||||
}
|
}
|
||||||
const plugin = getChannelPlugin(entry.provider);
|
return Boolean(params.entry.configured);
|
||||||
if (!plugin) {
|
|
||||||
return Boolean(entry.configured);
|
|
||||||
}
|
|
||||||
if (!isChannelVisibleInConfiguredLists(plugin.meta)) {
|
|
||||||
const providerConfig = (cfg as Record<string, unknown>)[plugin.id];
|
|
||||||
return Boolean(entry.configured) || Boolean(providerConfig);
|
|
||||||
}
|
|
||||||
return Boolean(entry.configured);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatProviderEntry(entry: ProviderAccountStatus): string {
|
function formatProviderEntry(entry: ProviderAccountStatus): string {
|
||||||
@@ -171,7 +192,11 @@ function formatProviderEntry(entry: ProviderAccountStatus): string {
|
|||||||
return `${label}: ${formatProviderState(entry)}`;
|
return `${label}: ${formatProviderState(entry)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function summarizeBindings(cfg: OpenClawConfig, bindings: AgentBinding[]): string[] {
|
export function summarizeBindings(
|
||||||
|
cfg: OpenClawConfig,
|
||||||
|
bindings: AgentBinding[],
|
||||||
|
metadataByProvider = buildProviderSummaryMetadataIndex(cfg),
|
||||||
|
): string[] {
|
||||||
if (bindings.length === 0) {
|
if (bindings.length === 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -181,11 +206,13 @@ export function summarizeBindings(cfg: OpenClawConfig, bindings: AgentBinding[])
|
|||||||
if (!channel) {
|
if (!channel) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const accountId = binding.match.accountId ?? resolveDefaultAccountId(cfg, channel);
|
const accountId =
|
||||||
|
binding.match.accountId ?? resolveDefaultAccountId(channel, metadataByProvider);
|
||||||
const key = providerAccountKey(channel, accountId);
|
const key = providerAccountKey(channel, accountId);
|
||||||
if (!seen.has(key)) {
|
if (!seen.has(key)) {
|
||||||
const label = formatChannelAccountLabel({
|
const label = formatChannelAccountLabel({
|
||||||
provider: channel,
|
provider: channel,
|
||||||
|
providerLabel: metadataByProvider.get(channel)?.label,
|
||||||
accountId,
|
accountId,
|
||||||
});
|
});
|
||||||
seen.set(key, label);
|
seen.set(key, label);
|
||||||
@@ -199,9 +226,12 @@ export function listProvidersForAgent(params: {
|
|||||||
cfg: OpenClawConfig;
|
cfg: OpenClawConfig;
|
||||||
bindings: AgentBinding[];
|
bindings: AgentBinding[];
|
||||||
providerStatus: Map<string, ProviderAccountStatus>;
|
providerStatus: Map<string, ProviderAccountStatus>;
|
||||||
|
providerMetadata?: ReadonlyMap<ChannelId, ProviderSummaryMetadata>;
|
||||||
}): string[] {
|
}): string[] {
|
||||||
const allProviderEntries = [...params.providerStatus.values()];
|
const allProviderEntries = [...params.providerStatus.values()];
|
||||||
const providerLines: string[] = [];
|
const providerLines: string[] = [];
|
||||||
|
const metadataByProvider =
|
||||||
|
params.providerMetadata ?? buildProviderSummaryMetadataIndex(params.cfg);
|
||||||
if (params.bindings.length > 0) {
|
if (params.bindings.length > 0) {
|
||||||
const seen = new Set<string>();
|
const seen = new Set<string>();
|
||||||
for (const binding of params.bindings) {
|
for (const binding of params.bindings) {
|
||||||
@@ -209,7 +239,8 @@ export function listProvidersForAgent(params: {
|
|||||||
if (!channel) {
|
if (!channel) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const accountId = binding.match.accountId ?? resolveDefaultAccountId(params.cfg, channel);
|
const accountId =
|
||||||
|
binding.match.accountId ?? resolveDefaultAccountId(channel, metadataByProvider);
|
||||||
const key = providerAccountKey(channel, accountId);
|
const key = providerAccountKey(channel, accountId);
|
||||||
if (seen.has(key)) {
|
if (seen.has(key)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -220,7 +251,11 @@ export function listProvidersForAgent(params: {
|
|||||||
providerLines.push(formatProviderEntry(status));
|
providerLines.push(formatProviderEntry(status));
|
||||||
} else {
|
} else {
|
||||||
providerLines.push(
|
providerLines.push(
|
||||||
`${formatChannelAccountLabel({ provider: channel, accountId })}: unknown`,
|
`${formatChannelAccountLabel({
|
||||||
|
provider: channel,
|
||||||
|
providerLabel: metadataByProvider.get(channel)?.label,
|
||||||
|
accountId,
|
||||||
|
})}: unknown`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -229,7 +264,7 @@ export function listProvidersForAgent(params: {
|
|||||||
|
|
||||||
if (params.summaryIsDefault) {
|
if (params.summaryIsDefault) {
|
||||||
for (const entry of allProviderEntries) {
|
for (const entry of allProviderEntries) {
|
||||||
if (shouldShowProviderEntry(entry, params.cfg)) {
|
if (shouldShowProviderEntry({ entry, cfg: params.cfg, metadataByProvider })) {
|
||||||
providerLines.push(formatProviderEntry(entry));
|
providerLines.push(formatProviderEntry(entry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getChannelPlugin } from "../channels/plugins/index.js";
|
|
||||||
import { formatChannelStatusState } from "../channels/plugins/status-state.js";
|
import { formatChannelStatusState } from "../channels/plugins/status-state.js";
|
||||||
import { asNullableRecord } from "../shared/record-coerce.js";
|
import { asNullableRecord } from "../shared/record-coerce.js";
|
||||||
import { colorize, isRich, theme } from "../terminal/theme.js";
|
import { colorize, isRich, theme } from "../terminal/theme.js";
|
||||||
@@ -147,8 +146,7 @@ export const formatHealthChannelLines = (
|
|||||||
if (!channelSummary) {
|
if (!channelSummary) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const plugin = getChannelPlugin(channelId as never);
|
const label = summary.channelLabels?.[channelId] ?? channelId;
|
||||||
const label = summary.channelLabels?.[channelId] ?? plugin?.meta.label ?? channelId;
|
|
||||||
const accountSummaries = channelSummary.accounts ?? {};
|
const accountSummaries = channelSummary.accounts ?? {};
|
||||||
const accountIds = opts.accountIdsByChannel?.[channelId];
|
const accountIds = opts.accountIdsByChannel?.[channelId];
|
||||||
const filteredSummaries =
|
const filteredSummaries =
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { getChannelPlugin } from "../channels/plugins/index.js";
|
import { getLoadedChannelPlugin } from "../channels/plugins/index.js";
|
||||||
import type { ChannelId, ChannelMessageActionName } from "../channels/plugins/types.public.js";
|
import type { ChannelId, ChannelMessageActionName } from "../channels/plugins/types.public.js";
|
||||||
import type { OutboundDeliveryResult } from "../infra/outbound/deliver.js";
|
import type { OutboundDeliveryResult } from "../infra/outbound/deliver.js";
|
||||||
import { formatGatewaySummary, formatOutboundDeliverySummary } from "../infra/outbound/format.js";
|
import { formatGatewaySummary, formatOutboundDeliverySummary } from "../infra/outbound/format.js";
|
||||||
@@ -11,7 +11,7 @@ import { isRich, theme } from "../terminal/theme.js";
|
|||||||
import { shortenText } from "./text-format.js";
|
import { shortenText } from "./text-format.js";
|
||||||
|
|
||||||
const resolveChannelLabel = (channel: ChannelId) =>
|
const resolveChannelLabel = (channel: ChannelId) =>
|
||||||
getChannelPlugin(channel)?.meta.label ?? channel;
|
getLoadedChannelPlugin(channel)?.meta.label ?? channel;
|
||||||
|
|
||||||
function extractMessageId(payload: unknown): string | null {
|
function extractMessageId(payload: unknown): string | null {
|
||||||
if (!payload || typeof payload !== "object") {
|
if (!payload || typeof payload !== "object") {
|
||||||
|
|||||||
Reference in New Issue
Block a user