























@@ -1,3 +1,6 @@
1+// Builds channel status rows and account details for `openclaw status --all`.
2+// This layer stays plugin-generic: channel-specific auth rules live in plugin config/status hooks.
3+14import fs from "node:fs";
25import { asRecord } from "@openclaw/normalization-core/record-coerce";
36import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
@@ -62,6 +65,7 @@ function existsSyncMaybe(p: string | undefined): boolean | null {
6265}
6366}
646768+/** Resolves one configured/default account into the normalized row shape used by status rendering. */
6569async function resolveChannelAccountRow(
6670params: ResolvedChannelAccountRowParams,
6771): Promise<ChannelAccountRow> {
@@ -148,6 +152,7 @@ const buildAccountNotes = (params: {
148152const allowFrom =
149153plugin.config.resolveAllowFrom?.({ cfg, accountId: snapshot.accountId }) ?? snapshot.allowFrom;
150154if (allowFrom?.length) {
155+// Cap allow-list output so large channel policies do not dominate the status table.
151156const formatted = formatChannelAllowFrom({
152157 plugin,
153158 cfg,
@@ -168,6 +173,7 @@ function resolveLinkFields(summary: unknown): {
168173authAgeMs: number | null;
169174selfE164: string | null;
170175} {
176+// Plugin summaries are optional extension data; normalize only the fields the core table understands.
171177const rec = asRecord(summary);
172178const statusState = typeof rec.statusState === "string" ? rec.statusState : null;
173179const linked = typeof rec.linked === "boolean" ? rec.linked : null;
@@ -190,6 +196,7 @@ function collectMissingPaths(accounts: ChannelAccountRow[]): string[] {
190196"dbPath",
191197"authDir",
192198]) {
199+// Account config and snapshots can each expose file-backed credential paths.
193200const raw =
194201(accountRec[key] as string | undefined) ?? (snapshotRec[key] as string | undefined);
195202const ok = existsSyncMaybe(raw);
@@ -214,8 +221,7 @@ function formatLoadFailureDetail(message: string): string {
214221return `plugin load failed: ${reason}; run openclaw doctor --fix`;
215222}
216223217-// `status --all` channels table.
218-// Keep this generic: channel-specific rules belong in the channel plugin.
224+/** Builds the `status --all` channel summary and per-account detail tables. */
219225export async function buildChannelsTable(
220226cfg: OpenClawConfig,
221227opts?: {
@@ -249,6 +255,7 @@ export async function buildChannelsTable(
249255 includeSetupFallbackPlugins,
250256});
251257for (const plugin of readOnlyPlugins.plugins) {
258+// Use the plugin's default account even when no accounts are configured so setup guidance is concrete.
252259const accountIds = plugin.config.listAccountIds(cfg);
253260const defaultAccountId = resolveChannelDefaultAccountId({
254261 plugin,
@@ -288,6 +295,7 @@ export async function buildChannelsTable(
288295hasRuntimeCredentialAvailable({ liveAccounts, accountId: entry.accountId }))
289296 ? {
290297 ...entry,
298+// Fast-mode scans may not resolve local secrets; runtime evidence can still prove availability.
291299account: markConfiguredUnavailableCredentialStatusesAvailable(entry.account),
292300}
293301 : entry,
@@ -318,6 +326,7 @@ export async function buildChannelsTable(
318326const label = plugin.meta.label ?? plugin.id;
319327320328const state = (() => {
329+// Precedence matches operator actionability: disabled, local file breakage, plugin issues, auth, link.
321330if (!anyEnabled) {
322331return "off";
323332}
@@ -512,6 +521,7 @@ export async function buildChannelsTable(
512521});
513522if (!hint || hint.channelId !== channelId) {
514523if (!includeSetupFallbackPlugins && explicitConfiguredChannelIds.has(channelId)) {
524+// Fast mode intentionally skips setup fallback plugins, but configured ids still deserve visibility.
515525rows.push({
516526id: channelId,
517527label: sanitizeForLog(channelId).trim() || "configured-channel",
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。