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}
6467
68+ /** Resolves one configured/default account into the normalized row shape used by status rendering. */
6569async function resolveChannelAccountRow (
6670 params : ResolvedChannelAccountRowParams ,
6771) : Promise < ChannelAccountRow > {
@@ -148,6 +152,7 @@ const buildAccountNotes = (params: {
148152 const allowFrom =
149153 plugin . config . resolveAllowFrom ?.( { cfg, accountId : snapshot . accountId } ) ?? snapshot . allowFrom ;
150154 if ( allowFrom ?. length ) {
155+ // Cap allow-list output so large channel policies do not dominate the status table.
151156 const formatted = formatChannelAllowFrom ( {
152157 plugin,
153158 cfg,
@@ -168,6 +173,7 @@ function resolveLinkFields(summary: unknown): {
168173 authAgeMs : number | null ;
169174 selfE164 : string | null ;
170175} {
176+ // Plugin summaries are optional extension data; normalize only the fields the core table understands.
171177 const rec = asRecord ( summary ) ;
172178 const statusState = typeof rec . statusState === "string" ? rec . statusState : null ;
173179 const 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.
193200 const raw =
194201 ( accountRec [ key ] as string | undefined ) ?? ( snapshotRec [ key ] as string | undefined ) ;
195202 const ok = existsSyncMaybe ( raw ) ;
@@ -214,8 +221,7 @@ function formatLoadFailureDetail(message: string): string {
214221 return `plugin load failed: ${ reason } ; run openclaw doctor --fix` ;
215222}
216223
217- // `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 (
220226 cfg : OpenClawConfig ,
221227 opts ?: {
@@ -249,6 +255,7 @@ export async function buildChannelsTable(
249255 includeSetupFallbackPlugins,
250256 } ) ;
251257 for ( const plugin of readOnlyPlugins . plugins ) {
258+ // Use the plugin's default account even when no accounts are configured so setup guidance is concrete.
252259 const accountIds = plugin . config . listAccountIds ( cfg ) ;
253260 const defaultAccountId = resolveChannelDefaultAccountId ( {
254261 plugin,
@@ -288,6 +295,7 @@ export async function buildChannelsTable(
288295 hasRuntimeCredentialAvailable ( { liveAccounts, accountId : entry . accountId } ) )
289296 ? {
290297 ...entry ,
298+ // Fast-mode scans may not resolve local secrets; runtime evidence can still prove availability.
291299 account : markConfiguredUnavailableCredentialStatusesAvailable ( entry . account ) ,
292300 }
293301 : entry ,
@@ -318,6 +326,7 @@ export async function buildChannelsTable(
318326 const label = plugin . meta . label ?? plugin . id ;
319327
320328 const state = ( ( ) => {
329+ // Precedence matches operator actionability: disabled, local file breakage, plugin issues, auth, link.
321330 if ( ! anyEnabled ) {
322331 return "off" ;
323332 }
@@ -512,6 +521,7 @@ export async function buildChannelsTable(
512521 } ) ;
513522 if ( ! hint || hint . channelId !== channelId ) {
514523 if ( ! includeSetupFallbackPlugins && explicitConfiguredChannelIds . has ( channelId ) ) {
524+ // Fast mode intentionally skips setup fallback plugins, but configured ids still deserve visibility.
515525 rows . push ( {
516526 id : channelId ,
517527 label : sanitizeForLog ( channelId ) . trim ( ) || "configured-channel" ,
0 commit comments