UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

335 lines (334 loc) 14.8 kB
import { o as normalizeLowercaseStringOrEmpty } from "./string-coerce-CIXf7egm.js"; import { a as writeRuntimeJson, o as writeRuntimeStdout } from "./runtime-CF2WjnNZ.js"; import { n as requestExitAfterOneShotOutput } from "./one-shot-exit-BkFPnjbM.js"; import { t as createLazyImportLoader } from "./lazy-promise-DGqyc4Y4.js"; import { t as formatCliCommand } from "./command-format-C7YfyMTd.js"; import { r as normalizeProviderId } from "./provider-id-DMd-TDFp.js"; import { n as sanitizeTerminalText } from "./safe-text-BGBqp1a4.js"; import "./defaults-CdX9UGcX.js"; import { c as loadManifestMetadataSnapshot } from "./manifest-contract-eligibility-BbV7X6pV.js"; import { n as parseModelRef } from "./model-selection-normalize-D1HuPOqZ.js"; import { r as theme, t as colorize } from "./theme-vjDs9tao.js"; import { t as ExpectedCliError } from "./failure-output-Dc5ce9_F.js"; import { a as resolveLegacyInheritedAuthDir } from "./legacy-inherited-auth-dir-CMGSmv-F.js"; import { s as resolveCliRuntimeExecutionProvider } from "./model-runtime-aliases-BJ2qM8I_.js"; import { n as createModelAuthAvailabilityResolver, t as applyCliRuntimeModelAuthAvailability } from "./model-auth-availability-CRH5-dWY.js"; import { t as resolveConfiguredModelEntries } from "./configured-model-entries-CV1BLgOW.js"; import { i as createModelCatalogProviderAliasCanonicalizer } from "./model-reference-validation-hyAvbbzD.js"; import { d as ensureFlagCompatibility, f as formatTag, g as truncate, h as padTerminalCell, m as isRich, p as formatTokenK, s as resolveModelsTargetAgent } from "./shared-CZFRGTsE.js"; import { n as loadModelsConfigWithSource } from "./load-config-CHI7_3xu.js"; import { t as formatErrorWithStack } from "./list.errors-CvTPa0Ln.js"; //#region src/commands/models/list.auth-index.ts function listValidatedSyntheticAuthProviderRefs(params) { if (params.metadataSnapshot.registryDiagnostics.length > 0 || params.metadataSnapshot.registrySource !== "persisted" && params.metadataSnapshot.registrySource !== "provided") return []; return params.metadataSnapshot.index.plugins.filter((plugin) => plugin.enabled).flatMap((plugin) => plugin.syntheticAuthRefs ?? []); } /** Builds one snapshot-scoped command adapter around the shared evaluator. */ function createModelListAuthIndex(params) { const env = params.env ?? process.env; const resolver = createModelAuthAvailabilityResolver({ cfg: params.cfg, authStore: params.authStore, agentDir: params.agentDir, workspaceDir: params.workspaceDir, env, metadataSnapshot: params.metadataSnapshot, externalCliProviderIds: params.externalCliProviderIds, routeResolverFactory: params.routeResolverFactory, preparedRuntimeAuthModes: params.preparedRuntimeAuthModes, syntheticAuthProviderRefs: params.syntheticAuthProviderRefs ?? listValidatedSyntheticAuthProviderRefs({ metadataSnapshot: params.metadataSnapshot }) }); return { providerDiscoveryProviderIds: resolver.providerDiscoveryProviderIds, evaluateModelAuth: (provider, ref) => { const evaluation = resolver.evaluateModelAuth(provider, ref); return applyCliRuntimeModelAuthAvailability({ authResolver: resolver, evaluation, cfg: params.cfg, agentId: params.agentId, metadataSnapshot: params.metadataSnapshot, provider, modelId: ref?.modelId, preferredProfileId: ref?.preferredProfileId, pinnedProfileId: ref?.pinnedProfileId }); } }; } //#endregion //#region src/commands/models/list.table.ts /** Terminal/JSON/plain table renderer for model-list rows. */ const MODEL_PAD = 42; const INPUT_PAD = 10; const CTX_PAD = 11; const LOCAL_PAD = 5; const AUTH_PAD = 5; function formatContextLabel(row) { if (typeof row.contextTokens === "number" && Number.isFinite(row.contextTokens) && row.contextTokens > 0 && row.contextTokens !== row.contextWindow) return `${formatTokenK(row.contextTokens)}/${formatTokenK(row.contextWindow)}`; return formatTokenK(row.contextWindow); } /** Prints model-list rows in JSON, plain, or fixed-width terminal form. */ function printModelTable(rows, runtime, opts = {}) { if (opts.json) { writeRuntimeJson(runtime, { count: rows.length, models: rows }); return; } if (opts.plain) { for (const row of rows) writeRuntimeStdout(runtime, sanitizeTerminalText(row.key)); return; } const rich = isRich(opts); const header = [ padTerminalCell("Model", MODEL_PAD), padTerminalCell("Input", INPUT_PAD), padTerminalCell("Ctx", CTX_PAD), padTerminalCell("Local", LOCAL_PAD), padTerminalCell("Auth", AUTH_PAD), "Tags" ].join(" "); runtime.log(rich ? theme.heading(header) : header); for (const row of rows) { const keyLabel = padTerminalCell(truncate(sanitizeTerminalText(row.key), MODEL_PAD), MODEL_PAD); const inputLabel = padTerminalCell(sanitizeTerminalText(row.input) || "-", INPUT_PAD); const ctxLabel = padTerminalCell(formatContextLabel(row), CTX_PAD); const localText = row.local === null ? "-" : row.local ? "yes" : "no"; const localLabel = padTerminalCell(localText, LOCAL_PAD); const authText = row.available === null ? "-" : row.available ? "yes" : "no"; const authLabel = padTerminalCell(authText, AUTH_PAD); const tags = row.tags.map(sanitizeTerminalText); const tagsLabel = tags.length > 0 ? rich ? tags.map((tag) => formatTag(tag, rich)).join(",") : tags.join(",") : ""; const coloredInput = colorize(rich, row.input.includes("image") ? theme.accentBright : theme.info, inputLabel); const coloredLocal = colorize(rich, row.local === null ? theme.muted : row.local ? theme.success : theme.muted, localLabel); const coloredAuth = colorize(rich, row.available === null ? theme.muted : row.available ? theme.success : theme.error, authLabel); const line = [ rich ? theme.accent(keyLabel) : keyLabel, coloredInput, ctxLabel, coloredLocal, coloredAuth, tagsLabel ].join(" "); runtime.log(line); } } //#endregion //#region src/commands/models/list.list-command.ts /** Implementation of `openclaw models list`. */ const DISPLAY_MODEL_PARSE_OPTIONS = { allowPluginNormalization: false }; const promotionsModuleLoader = createLazyImportLoader(() => import("./list.promotions-BkiUSW2k.js")); const registryModuleLoader = createLazyImportLoader(() => import("./list.registry-CAzqCql4.js")); const rowSourcesModuleLoader = createLazyImportLoader(() => import("./list.row-sources-CZ6b8Xh-.js")); /** Lists configured, catalog, and runtime-discovered models as text, plain, or JSON. */ async function modelsListCommand(opts, runtime) { ensureFlagCompatibility(opts); const rawProviderFilter = opts.provider?.trim(); const parsedProviderFilter = (() => { if (!rawProviderFilter) return; if (/\s/u.test(rawProviderFilter)) { const message = `Invalid provider filter "${sanitizeTerminalText(rawProviderFilter)}". Use a provider id such as "moonshot", not a display label.`; throw new ExpectedCliError({ message, humanOutput: message, machineOutput: message }); } return parseModelRef(`${rawProviderFilter}/_`, "openai", DISPLAY_MODEL_PARSE_OPTIONS)?.provider ?? normalizeLowercaseStringOrEmpty(rawProviderFilter); })(); const humanReadable = !opts.json && !opts.plain; const [{ loadAuthProfileStoreWithoutExternalProfiles }, { resolveAgentWorkspaceDir }, { resolveDefaultAgentWorkspaceDir }] = await Promise.all([ import("./store-DNxWSPNc.js"), import("./agent-scope-BHLMs19p.js"), import("./workspace-DYBYNr9B.js") ]); const { resolvedConfig: cfg } = await loadModelsConfigWithSource({ commandName: "models list", runtime }); const { agentId, agentDir } = resolveModelsTargetAgent(cfg, opts.agent, { kind: "read" }); const workspaceDir = resolveAgentWorkspaceDir(cfg, agentId) ?? resolveDefaultAgentWorkspaceDir(); const metadataSnapshot = loadManifestMetadataSnapshot({ config: cfg, workspaceDir, env: process.env }); const providerAliasCanonicalizer = createModelCatalogProviderAliasCanonicalizer({ cfg, metadataSnapshot }); const providerFilter = parsedProviderFilter ? providerAliasCanonicalizer.provider(parsedProviderFilter) : void 0; const { entries } = resolveConfiguredModelEntries({ cfg, agentId, ...DISPLAY_MODEL_PARSE_OPTIONS, canonicalizeRef: providerAliasCanonicalizer.ref }); if (providerFilter) { if (!new Set([ ...metadataSnapshot.owners.providers.keys(), ...metadataSnapshot.owners.modelCatalogProviders.keys(), ...Object.keys(cfg.models?.providers ?? {}), ...entries.map((entry) => entry.ref.provider) ].map((providerId) => providerAliasCanonicalizer.provider(providerId))).has(providerFilter)) { const message = `Unknown provider filter "${sanitizeTerminalText(rawProviderFilter ?? providerFilter)}" for this installation. Run ${formatCliCommand("openclaw plugins list --json")} to see installed providers, or configure it under models.providers.`; throw new ExpectedCliError({ message, humanOutput: message, machineOutput: message }); } } const inheritedAuthDir = resolveLegacyInheritedAuthDir(cfg); const authStore = inheritedAuthDir ? loadAuthProfileStoreWithoutExternalProfiles(agentDir, { inheritedAuthDir }) : loadAuthProfileStoreWithoutExternalProfiles(agentDir); const includePreparedCatalog = Boolean(opts.all || providerFilter); let preparedRuntimeAuthModes; let modelRegistry; let registryModels = []; let discoveredKeys = /* @__PURE__ */ new Set(); let availableKeys; let availabilityErrorMessage; const configuredByKey = new Map(entries.map((entry) => [entry.key, entry])); const cliRuntimeProviderIds = [...new Set((opts.local ? [] : entries).filter((entry) => !providerFilter || providerAliasCanonicalizer.provider(entry.ref.provider) === providerFilter).map((entry) => resolveCliRuntimeExecutionProvider({ provider: entry.ref.provider, modelId: entry.ref.model, cfg, agentId, metadataSnapshot })).map((provider) => normalizeProviderId(provider ?? "")).filter((provider) => provider && provider !== "openai"))]; try { if (includePreparedCatalog) { const { loadModelRegistry } = await registryModuleLoader.load(); const loaded = await loadModelRegistry(cfg, { agentId, agentDir, providerFilter, normalizeModels: Boolean(providerFilter), workspaceDir }); modelRegistry = loaded.registry; registryModels = loaded.models; discoveredKeys = loaded.discoveredKeys; availableKeys = loaded.availableKeys; availabilityErrorMessage = loaded.availabilityErrorMessage; preparedRuntimeAuthModes = Object.fromEntries(cliRuntimeProviderIds.flatMap((provider) => { const mode = loaded.authModes[provider]; return mode ? [[provider, mode]] : []; })); } else if (!opts.all && opts.local) { const { loadConfiguredListModelRegistry } = await registryModuleLoader.load(); const loaded = await loadConfiguredListModelRegistry(cfg, entries, { agentId, agentDir, providerFilter, workspaceDir }); modelRegistry = loaded.registry; discoveredKeys = loaded.discoveredKeys; availableKeys = loaded.availableKeys; } } catch (err) { const message = `Model registry unavailable: ${err instanceof Error ? err.message : String(err)}`; throw new ExpectedCliError({ message, humanOutput: `Model registry unavailable:\n${formatErrorWithStack(err)}`, machineOutput: message }); } const unpreparedCliRuntimeProviderIds = includePreparedCatalog ? cliRuntimeProviderIds.filter((provider) => !preparedRuntimeAuthModes?.[provider]) : []; if (unpreparedCliRuntimeProviderIds.length) try { const scopedAuthModes = await (await import("./prepared-model-runtime.scoped-catalog-Cg5j61LG.js")).prepareScopedReadOnlyModelAuthModes({ config: cfg, env: process.env, workspaceDir }, unpreparedCliRuntimeProviderIds, metadataSnapshot); preparedRuntimeAuthModes = { ...preparedRuntimeAuthModes, ...scopedAuthModes }; } catch (err) { runtime.error(`CLI runtime auth lookup failed; leaving availability unknown:\n${formatErrorWithStack(err)}`); } const authIndex = createModelListAuthIndex({ cfg, authStore, agentId, agentDir, workspaceDir, metadataSnapshot, preparedRuntimeAuthModes, externalCliProviderIds: ["openai"] }); const providerDiscoveryProviderIds = (() => { if (opts.all && !providerFilter) return; if (providerFilter) return [providerFilter]; return [.../* @__PURE__ */ new Set([ ...authIndex.providerDiscoveryProviderIds ?? [], ...entries.map((entry) => entry.ref.provider), ...Object.keys(cfg.models?.providers ?? {}) ])].toSorted((left, right) => left.localeCompare(right)); })(); const providerRuntimeDiscoveryProviderIds = providerFilter ? [providerFilter] : opts.all ? void 0 : []; const providerManifestFallbackProviderIds = !providerFilter && !opts.all ? authIndex.providerDiscoveryProviderIds : void 0; const promotionsModulePromise = humanReadable ? promotionsModuleLoader.load() : void 0; const promotionsRefreshPromise = promotionsModulePromise?.then((promotionsModule) => promotionsModule.startPromotionsFeedRefresh()).catch(() => void 0); const rowContext = { cfg, agentId, agentDir, ...inheritedAuthDir ? { inheritedAuthDir } : {}, authIndex, canonicalizeProvider: providerAliasCanonicalizer.provider, providerDiscoveryProviderIds, providerRuntimeDiscoveryProviderIds, providerManifestFallbackProviderIds, availableKeys, configuredByKey, discoveredKeys, filter: { provider: providerFilter, local: opts.local }, metadataSnapshot, workspaceDir }; const rows = []; if (includePreparedCatalog) { const { appendAllModelRowSources } = await rowSourcesModuleLoader.load(); await appendAllModelRowSources({ rows, entries, context: rowContext, modelRegistry, registryModels }); } else { const { appendConfiguredModelRowSources } = await rowSourcesModuleLoader.load(); await appendConfiguredModelRowSources({ rows, entries, modelRegistry, context: rowContext }); } if (availabilityErrorMessage !== void 0) runtime.error(`Model availability lookup failed; falling back to auth heuristics for discovered models: ${availabilityErrorMessage}`); const promotionsModule = await (promotionsModulePromise ?? promotionsModuleLoader.load()); try { promotionsModule.applyPromotionClaimTags(rows); } catch {} if (rows.length === 0 && !opts.json && !opts.plain) runtime.log("No models found."); else printModelTable(rows, runtime, opts); if (promotionsRefreshPromise) try { const refresh = await promotionsRefreshPromise; if (refresh) await promotionsModule.printAvailablePromotionsSection({ configuredKeys: new Set(entries.map((entry) => entry.key)), refresh, runtime }); } catch {} requestExitAfterOneShotOutput(runtime); } //#endregion export { modelsListCommand };