From feb6dc6bb6ee919254a86f6905d25fc4cd568e77 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 4 Jun 2026 12:27:15 -0400 Subject: [PATCH] docs: document model list comments --- src/commands/models/list.auth-index.ts | 7 +++++++ src/commands/models/list.auth-overview.ts | 4 ++++ src/commands/models/list.configured.ts | 4 ++++ src/commands/models/list.errors.ts | 4 ++++ src/commands/models/list.format.ts | 5 +++++ src/commands/models/list.list-command.ts | 6 ++++++ src/commands/models/list.local-url.ts | 2 ++ src/commands/models/list.manifest-catalog.ts | 3 +++ 8 files changed, 35 insertions(+) diff --git a/src/commands/models/list.auth-index.ts b/src/commands/models/list.auth-index.ts index a36f3d57728d..b4fb0d69dc76 100644 --- a/src/commands/models/list.auth-index.ts +++ b/src/commands/models/list.auth-index.ts @@ -1,3 +1,4 @@ +/** Auth availability index for `openclaw models list` rows. */ import { normalizeProviderIdForAuth } from "@openclaw/model-catalog-core/provider-id"; import type { AuthProfileStore } from "../../agents/auth-profiles/types.js"; import type { AuthProfileCredential } from "../../agents/auth-profiles/types.js"; @@ -26,6 +27,7 @@ export type ModelListAuthIndex = { allowsProviderAuthAvailabilityFallback(provider: string): boolean; }; +/** Inputs used to build the auth index without re-reading process-wide state. */ export type CreateModelListAuthIndexParams = { cfg: OpenClawConfig; authStore: AuthProfileStore; @@ -77,6 +79,7 @@ function listValidatedSyntheticAuthProviderRefs(params: { .flatMap((plugin) => plugin.syntheticAuthRefs ?? []); } +/** Builds a provider-auth lookup from profiles, env, config, and synthetic plugin refs. */ export function createModelListAuthIndex( params: CreateModelListAuthIndexParams, ): ModelListAuthIndex { @@ -104,6 +107,8 @@ export function createModelListAuthIndex( if (credential.type !== "oauth" && credential.type !== "token") { return false; } + // OpenAI OAuth/token profiles only authenticate provider rows when config + // routes OpenAI through Codex runtime semantics. return openAIProviderUsesCodexRuntimeByDefault({ provider: normalizedProvider, config: params.cfg, @@ -160,6 +165,8 @@ export function createModelListAuthIndex( params.cfg.agents?.defaults?.model, )?.split("/", 1)[0]; if (primaryModelProvider === "codex") { + // A Codex primary model is a synthetic provider auth signal even when no + // normal provider key exists in the profile store. addSyntheticProvider("codex"); } diff --git a/src/commands/models/list.auth-overview.ts b/src/commands/models/list.auth-overview.ts index 56c2cc67389d..ef56f6b74427 100644 --- a/src/commands/models/list.auth-overview.ts +++ b/src/commands/models/list.auth-overview.ts @@ -1,3 +1,4 @@ +/** Builds provider auth summaries for model-list/status output. */ import { normalizeProviderIdForAuth } from "@openclaw/model-catalog-core/provider-id"; import { normalizeLowercaseStringOrEmpty, @@ -62,6 +63,7 @@ function resolveProfileSourceAgentDir(params: { : params.agentDir; } +/** Resolves the effective auth source and profile counts for a provider. */ export function resolveProviderAuthOverview(params: { provider: string; cfg: OpenClawConfig; @@ -150,6 +152,8 @@ export function resolveProviderAuthOverview(params: { const effective: ProviderAuthOverview["effective"] = (() => { if (profiles.length > 0) { + // Profiles win over env/config markers because runtime auth selection uses + // the profile store before provider-wide fallback material. return { kind: "profiles", detail: shortenHomePath( diff --git a/src/commands/models/list.configured.ts b/src/commands/models/list.configured.ts index 1d608187d7d2..00e81f2e0e59 100644 --- a/src/commands/models/list.configured.ts +++ b/src/commands/models/list.configured.ts @@ -1,3 +1,4 @@ +/** Resolves configured model refs and tags for model-list rows. */ import { buildModelAliasIndex, resolveConfiguredModelRef, @@ -15,6 +16,7 @@ import { DEFAULT_MODEL, DEFAULT_PROVIDER, modelKey } from "./shared.js"; const DISPLAY_MODEL_PARSE_OPTIONS = { allowPluginNormalization: false } as const; +/** Returns canonical configured model entries with default/fallback/image/configured tags. */ export function resolveConfiguredEntries( cfg: OpenClawConfig, metadataSnapshot?: Pick, @@ -47,6 +49,8 @@ export function resolveConfiguredEntries( const key = modelKey(canonicalRef.provider, canonicalRef.model); const originalKey = modelKey(ref.provider, ref.model); if (originalKey !== key) { + // Preserve aliases attached to pre-canonical provider keys so display rows + // still show user-facing aliases after catalog provider canonicalization. const aliases = aliasesByKey.get(originalKey); if (aliases) { aliasesByKey.set(key, [...new Set([...(aliasesByKey.get(key) ?? []), ...aliases])]); diff --git a/src/commands/models/list.errors.ts b/src/commands/models/list.errors.ts index 3c501e095db4..e4357b33fa5a 100644 --- a/src/commands/models/list.errors.ts +++ b/src/commands/models/list.errors.ts @@ -1,5 +1,8 @@ +// Shared error helpers for model-list availability fallback behavior. +/** Error code used when model availability lookup is unavailable but auth heuristics can continue. */ export const MODEL_AVAILABILITY_UNAVAILABLE_CODE = "MODEL_AVAILABILITY_UNAVAILABLE"; +/** Formats an unknown error with stack detail when available. */ export function formatErrorWithStack(err: unknown): string { if (err instanceof Error) { return err.stack ?? `${err.name}: ${err.message}`; @@ -7,6 +10,7 @@ export function formatErrorWithStack(err: unknown): string { return String(err); } +/** Returns true when model list should continue with auth heuristics. */ export function shouldFallbackToAuthHeuristics(err: unknown): boolean { if (!(err instanceof Error)) { return false; diff --git a/src/commands/models/list.format.ts b/src/commands/models/list.format.ts index edc5a492f7c6..0bfbe0652c5b 100644 --- a/src/commands/models/list.format.ts +++ b/src/commands/models/list.format.ts @@ -1,11 +1,15 @@ +/** Formatting helpers for model-list terminal tables. */ import { isRich as isRichTerminal, theme } from "../../../packages/terminal-core/src/theme.js"; export { maskApiKey } from "../../utils/mask-api-key.js"; +/** Enables rich formatting only for non-machine-readable output. */ export const isRich = (opts?: { json?: boolean; plain?: boolean }) => isRichTerminal() && !opts?.json && !opts?.plain; +/** Pads a table cell to a fixed width. */ export const pad = (value: string, size: number) => value.padEnd(size); +/** Applies terminal color based on a model-list tag. */ export const formatTag = (tag: string, rich: boolean) => { if (!rich) { return tag; @@ -34,6 +38,7 @@ export const formatTag = (tag: string, rich: boolean) => { return theme.muted(tag); }; +/** Truncates model-list cells with an ASCII ellipsis. */ export const truncate = (value: string, max: number) => { if (value.length <= max) { return value; diff --git a/src/commands/models/list.list-command.ts b/src/commands/models/list.list-command.ts index 72b402218591..232fc9c1c961 100644 --- a/src/commands/models/list.list-command.ts +++ b/src/commands/models/list.list-command.ts @@ -1,3 +1,4 @@ +/** Implementation of `openclaw models list`. */ import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce"; import { parseModelRef } from "../../agents/model-selection.js"; import type { ModelRegistry } from "../../llm/model-registry.js"; @@ -42,6 +43,7 @@ function loadSourcePlanModule(): Promise { return sourcePlanModuleLoader.load(); } +/** Lists configured, catalog, and runtime-discovered models as text, plain, or JSON. */ export async function modelsListCommand( opts: { all?: boolean; @@ -114,6 +116,8 @@ export async function modelsListCommand( const { entries } = resolveConfiguredEntries(cfg, metadataSnapshot); const configuredByKey = new Map(entries.map((entry) => [entry.key, entry])); const enableSourcePlanCascade = Boolean(opts.all) || Boolean(providerFilter); + // Full/provider-filtered lists may need runtime, manifest, and registry rows. + // Defer that planning so default configured-only output stays cheap. const sourcePlanModule = enableSourcePlanCascade ? await loadSourcePlanModule() : undefined; const sourcePlan = sourcePlanModule ? await sourcePlanModule.planAllModelListSources({ @@ -193,6 +197,8 @@ export async function modelsListCommand( }); if (initialAppend.requiresRegistryFallback) { const useScopedRegistryFallback = sourcePlan.kind === "provider-runtime-scoped"; + // Runtime-scoped providers can fail catalog availability while still being + // useful for a provider-filtered list; retry through the registry fallback. try { await loadRegistryState( useScopedRegistryFallback diff --git a/src/commands/models/list.local-url.ts b/src/commands/models/list.local-url.ts index 808dbe028e18..d4d9522323ae 100644 --- a/src/commands/models/list.local-url.ts +++ b/src/commands/models/list.local-url.ts @@ -1,5 +1,7 @@ +/** Local URL classifier for model provider status/list output. */ import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce"; +/** Returns true for loopback, wildcard, and mDNS local base URLs. */ export const isLocalBaseUrl = (baseUrl: string) => { try { const url = new URL(baseUrl); diff --git a/src/commands/models/list.manifest-catalog.ts b/src/commands/models/list.manifest-catalog.ts index 0bd4c57bc41e..822f21a99f77 100644 --- a/src/commands/models/list.manifest-catalog.ts +++ b/src/commands/models/list.manifest-catalog.ts @@ -1,3 +1,4 @@ +/** Manifest-backed model catalog row loaders for `openclaw models list`. */ import { normalizeModelCatalogProviderId } from "@openclaw/model-catalog-core/model-catalog-refs"; import type { NormalizedModelCatalogRow } from "@openclaw/model-catalog-core/model-catalog-types"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; @@ -145,6 +146,7 @@ function loadManifestCatalogRowsForList(params: { }); } +/** Loads authoritative static manifest catalog rows for model-list output. */ export function loadStaticManifestCatalogRowsForList(params: { cfg: OpenClawConfig; providerFilter?: string; @@ -157,6 +159,7 @@ export function loadStaticManifestCatalogRowsForList(params: { }); } +/** Loads supplemental non-runtime manifest catalog rows for fallback list sources. */ export function loadSupplementalManifestCatalogRowsForList(params: { cfg: OpenClawConfig; providerFilter?: string;