





















@@ -64,6 +64,7 @@ type CapabilityProviderCandidate = {
6464id: string;
6565aliases?: readonly string[];
6666defaultModel?: string | null;
67+models?: readonly string[];
6768isConfigured?: (ctx: { cfg?: OpenClawConfig; agentDir?: string }) => boolean;
6869};
6970@@ -162,6 +163,34 @@ function resolveAutoCapabilityFallbackRefs(params: {
162163});
163164}
164165166+function providerMatchesId(provider: CapabilityProviderCandidate, providerId: string): boolean {
167+const normalizedProviderId = normalizeOptionalString(providerId);
168+if (!normalizedProviderId) {
169+return false;
170+}
171+return (
172+normalizeOptionalString(provider.id) === normalizedProviderId ||
173+(provider.aliases ?? []).some(
174+(alias) => normalizeOptionalString(alias) === normalizedProviderId,
175+)
176+);
177+}
178+179+function resolveProviderModelOnlyRef(params: {
180+raw: string;
181+providers: CapabilityProviderCandidate[];
182+}): ParsedProviderModelRef | null {
183+const model = normalizeOptionalString(params.raw);
184+if (!model) {
185+return null;
186+}
187+const provider = params.providers.find((candidate) => {
188+const models = [candidate.defaultModel, ...(candidate.models ?? [])];
189+return models.some((entry) => normalizeOptionalString(entry) === model);
190+});
191+return provider ? { provider: provider.id, model } : null;
192+}
193+165194export function resolveCapabilityModelCandidates(params: {
166195cfg: OpenClawConfig;
167196modelConfig: AgentModelConfig | undefined;
@@ -173,20 +202,42 @@ export function resolveCapabilityModelCandidates(params: {
173202}): ParsedProviderModelRef[] {
174203const candidates: ParsedProviderModelRef[] = [];
175204const seen = new Set<string>();
205+let providers: CapabilityProviderCandidate[] | undefined;
206+const getProviders = (): CapabilityProviderCandidate[] => {
207+providers ??= params.listProviders?.(params.cfg) ?? [];
208+return providers;
209+};
176210const add = (raw: string | undefined) => {
211+const trimmed = normalizeOptionalString(raw);
212+if (!trimmed) {
213+return;
214+}
177215const parsed = params.parseModelRef(raw);
178-if (!parsed) {
216+const candidate =
217+parsed && getProviders().some((provider) => providerMatchesId(provider, parsed.provider))
218+ ? parsed
219+ : (resolveProviderModelOnlyRef({ raw: trimmed, providers: getProviders() }) ?? parsed);
220+if (!candidate) {
179221return;
180222}
181-const key = `${parsed.provider}/${parsed.model}`;
223+const key = `${candidate.provider}/${candidate.model}`;
182224if (seen.has(key)) {
183225return;
184226}
185227seen.add(key);
186-candidates.push(parsed);
228+candidates.push(candidate);
187229};
188230189-const override = params.parseModelRef(params.modelOverride);
231+const override = (() => {
232+const raw = normalizeOptionalString(params.modelOverride);
233+if (!raw) {
234+return null;
235+}
236+const parsed = params.parseModelRef(raw);
237+return parsed && getProviders().some((provider) => providerMatchesId(provider, parsed.provider))
238+ ? parsed
239+ : (resolveProviderModelOnlyRef({ raw, providers: getProviders() }) ?? parsed);
240+})();
190241if (override) {
191242return [override];
192243}
@@ -203,7 +254,7 @@ export function resolveCapabilityModelCandidates(params: {
203254for (const candidate of resolveAutoCapabilityFallbackRefs({
204255cfg: params.cfg,
205256agentDir: params.agentDir,
206-listProviders: params.listProviders,
257+listProviders: () => getProviders(),
207258})) {
208259add(candidate);
209260}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。