
























@@ -1,9 +1,12 @@
11import type { Api, Model } from "@mariozechner/pi-ai";
22import type { ModelRegistry } from "@mariozechner/pi-coding-agent";
33import type { AuthProfileStore } from "../../agents/auth-profiles/types.js";
4+import { DEFAULT_CONTEXT_TOKENS } from "../../agents/defaults.js";
45import { shouldSuppressBuiltInModel } from "../../agents/model-suppression.js";
56import { normalizeProviderId } from "../../agents/provider-id.js";
7+import type { ModelDefinitionConfig, ModelProviderConfig } from "../../config/types.models.js";
68import type { OpenClawConfig } from "../../config/types.openclaw.js";
9+import type { ListRowModel } from "./list.model-row.js";
710import { loadModelRegistry, toModelRow } from "./list.registry.js";
811import {
912loadModelCatalog,
@@ -42,7 +45,7 @@ function matchesRowFilter(filter: RowFilter, model: { provider: string; baseUrl?
4245}
43464447function buildRow(params: {
45-model: Model<Api>;
48+model: ListRowModel;
4649key: string;
4750context: RowBuilderContext;
4851allowProviderAvailabilityFallback?: boolean;
@@ -75,9 +78,35 @@ function shouldSuppressListModel(params: {
7578});
7679}
778081+function resolveConfiguredModelInput(params: {
82+model: Partial<ModelDefinitionConfig>;
83+}): Array<"text" | "image"> {
84+const input = Array.isArray(params.model.input)
85+ ? params.model.input.filter(
86+(item): item is "text" | "image" => item === "text" || item === "image",
87+)
88+ : [];
89+return input.length > 0 ? input : ["text"];
90+}
91+92+function toConfiguredProviderListModel(params: {
93+provider: string;
94+providerConfig: Partial<ModelProviderConfig>;
95+model: Partial<ModelDefinitionConfig> & Pick<ModelDefinitionConfig, "id">;
96+}): ListRowModel {
97+return {
98+provider: params.provider,
99+id: params.model.id,
100+name: params.model.name ?? params.model.id,
101+baseUrl: params.model.baseUrl ?? params.providerConfig.baseUrl,
102+input: resolveConfiguredModelInput({ model: params.model }),
103+contextWindow: params.model.contextWindow ?? DEFAULT_CONTEXT_TOKENS,
104+};
105+}
106+78107export async function loadListModelRegistry(
79108cfg: OpenClawConfig,
80-opts?: { sourceConfig?: OpenClawConfig; providerFilter?: string },
109+opts?: { providerFilter?: string },
81110) {
82111const loaded = await loadModelRegistry(cfg, opts);
83112return {
@@ -121,6 +150,43 @@ export function appendDiscoveredRows(params: {
121150return seenKeys;
122151}
123152153+export function appendConfiguredProviderRows(params: {
154+rows: ModelRow[];
155+context: RowBuilderContext;
156+seenKeys: Set<string>;
157+}): void {
158+for (const [provider, providerConfig] of Object.entries(
159+params.context.cfg.models?.providers ?? {},
160+)) {
161+for (const configuredModel of providerConfig.models ?? []) {
162+const key = modelKey(provider, configuredModel.id);
163+if (params.seenKeys.has(key)) {
164+continue;
165+}
166+const model = toConfiguredProviderListModel({
167+ provider,
168+ providerConfig,
169+model: configuredModel,
170+});
171+if (!matchesRowFilter(params.context.filter, model)) {
172+continue;
173+}
174+if (shouldSuppressListModel({ model, context: params.context })) {
175+continue;
176+}
177+params.rows.push(
178+buildRow({
179+ model,
180+ key,
181+context: params.context,
182+allowProviderAvailabilityFallback: !params.context.discoveredKeys.has(key),
183+}),
184+);
185+params.seenKeys.add(key);
186+}
187+}
188+}
189+124190export async function appendCatalogSupplementRows(params: {
125191rows: ModelRow[];
126192modelRegistry: ModelRegistry;
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。