Skip to content

Commit a50aef8

Browse files
committed
perf: generalize provider-filtered catalog fast path
1 parent 959dedb commit a50aef8

4 files changed

Lines changed: 64 additions & 12 deletions

File tree

src/commands/models/list.list-command.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { RuntimeEnv } from "../../runtime.js";
44
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
55
import { resolveConfiguredEntries } from "./list.configured.js";
66
import { formatErrorWithStack } from "./list.errors.js";
7+
import { hasProviderStaticCatalogForFilter } from "./list.provider-catalog.js";
78
import { loadConfiguredListModelRegistry, loadListModelRegistry } from "./list.registry-load.js";
89
import {
910
appendAllModelRowSources,
@@ -58,11 +59,15 @@ export async function modelsListCommand(
5859
let discoveredKeys = new Set<string>();
5960
let availableKeys: Set<string> | undefined;
6061
let availabilityErrorMessage: string | undefined;
61-
const useProviderCatalogFastPath = Boolean(opts.all && providerFilter === "codex");
6262
const { entries } = resolveConfiguredEntries(cfg);
6363
const configuredByKey = new Map(entries.map((entry) => [entry.key, entry]));
64+
const useProviderCatalogFastPath =
65+
opts.all && providerFilter
66+
? await hasProviderStaticCatalogForFilter({ cfg, providerFilter })
67+
: false;
6468
const shouldLoadRegistry = modelRowSourcesRequireRegistry({
6569
all: opts.all,
70+
providerFilter,
6671
useProviderCatalogFastPath,
6772
});
6873
try {

src/commands/models/list.provider-catalog.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { ModelProviderConfig } from "../../config/types.models.js";
44
import type { OpenClawConfig } from "../../config/types.openclaw.js";
55
import { formatErrorMessage } from "../../infra/errors.js";
66
import { createSubsystemLogger } from "../../logging/subsystem.js";
7+
import { loadPluginManifestRegistry } from "../../plugins/manifest-registry.js";
78
import {
89
groupPluginDiscoveryProvidersByOrder,
910
normalizePluginDiscoveryResult,
@@ -45,6 +46,21 @@ export async function resolveProviderCatalogPluginIdsForFilter(params: {
4546
return undefined;
4647
}
4748

49+
export async function hasProviderStaticCatalogForFilter(params: {
50+
cfg: OpenClawConfig;
51+
env?: NodeJS.ProcessEnv;
52+
providerFilter: string;
53+
}): Promise<boolean> {
54+
const pluginIds = await resolveProviderCatalogPluginIdsForFilter(params);
55+
if (!pluginIds || pluginIds.length === 0) {
56+
return false;
57+
}
58+
const pluginIdSet = new Set(pluginIds);
59+
return loadPluginManifestRegistry({ config: params.cfg, env: params.env }).plugins.some(
60+
(plugin) => pluginIdSet.has(plugin.id) && typeof plugin.providerDiscoverySource === "string",
61+
);
62+
}
63+
4864
function modelFromProviderCatalog(params: {
4965
provider: string;
5066
providerConfig: ModelProviderConfig;
@@ -72,6 +88,7 @@ export async function loadProviderCatalogModelsForList(params: {
7288
agentDir: string;
7389
env?: NodeJS.ProcessEnv;
7490
providerFilter?: string;
91+
staticOnly?: boolean;
7592
}): Promise<Model<Api>[]> {
7693
const env = params.env ?? process.env;
7794
const providerFilter = params.providerFilter ? normalizeProviderId(params.providerFilter) : "";
@@ -104,7 +121,7 @@ export async function loadProviderCatalogModelsForList(params: {
104121
env,
105122
onlyPluginIds: scopedPluginIds,
106123
includeUntrustedWorkspacePlugins: false,
107-
requireCompleteDiscoveryEntryCoverage: true,
124+
requireCompleteDiscoveryEntryCoverage: params.staticOnly === true,
108125
})
109126
).filter(
110127
(provider) =>

src/commands/models/list.row-sources.ts

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,42 @@ type AllModelRowSources = {
1818

1919
export function modelRowSourcesRequireRegistry(params: {
2020
all?: boolean;
21+
providerFilter?: string;
2122
useProviderCatalogFastPath: boolean;
2223
}): boolean {
2324
if (!params.all) {
2425
return false;
2526
}
26-
return !params.useProviderCatalogFastPath;
27+
if (params.providerFilter && params.useProviderCatalogFastPath) {
28+
return false;
29+
}
30+
return true;
2731
}
2832

2933
export async function appendAllModelRowSources(params: AllModelRowSources): Promise<void> {
34+
if (params.context.filter.provider && params.useProviderCatalogFastPath) {
35+
let seenKeys = new Set<string>();
36+
const catalogRows = await appendProviderCatalogRows({
37+
rows: params.rows,
38+
context: params.context,
39+
seenKeys,
40+
staticOnly: true,
41+
});
42+
if (catalogRows === 0) {
43+
seenKeys = appendDiscoveredRows({
44+
rows: params.rows,
45+
models: params.modelRegistry?.getAll() ?? [],
46+
context: params.context,
47+
});
48+
}
49+
appendConfiguredProviderRows({
50+
rows: params.rows,
51+
context: params.context,
52+
seenKeys,
53+
});
54+
return;
55+
}
56+
3057
const seenKeys = appendDiscoveredRows({
3158
rows: params.rows,
3259
models: params.modelRegistry?.getAll() ?? [],
@@ -39,7 +66,7 @@ export async function appendAllModelRowSources(params: AllModelRowSources): Prom
3966
seenKeys,
4067
});
4168

42-
if (params.modelRegistry) {
69+
if (params.modelRegistry && !params.context.filter.provider) {
4370
await appendCatalogSupplementRows({
4471
rows: params.rows,
4572
modelRegistry: params.modelRegistry,
@@ -49,13 +76,11 @@ export async function appendAllModelRowSources(params: AllModelRowSources): Prom
4976
return;
5077
}
5178

52-
if (params.useProviderCatalogFastPath) {
53-
await appendProviderCatalogRows({
54-
rows: params.rows,
55-
context: params.context,
56-
seenKeys,
57-
});
58-
}
79+
await appendProviderCatalogRows({
80+
rows: params.rows,
81+
context: params.context,
82+
seenKeys,
83+
});
5984
}
6085

6186
export function appendConfiguredModelRowSources(params: {

src/commands/models/list.rows.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,11 +245,14 @@ export async function appendProviderCatalogRows(params: {
245245
rows: ModelRow[];
246246
context: RowBuilderContext;
247247
seenKeys: Set<string>;
248-
}): Promise<void> {
248+
staticOnly?: boolean;
249+
}): Promise<number> {
250+
let appended = 0;
249251
for (const model of await loadProviderCatalogModelsForList({
250252
cfg: params.context.cfg,
251253
agentDir: params.context.agentDir,
252254
providerFilter: params.context.filter.provider,
255+
staticOnly: params.staticOnly,
253256
})) {
254257
if (!matchesRowFilter(params.context.filter, model)) {
255258
continue;
@@ -270,7 +273,9 @@ export async function appendProviderCatalogRows(params: {
270273
}),
271274
);
272275
params.seenKeys.add(key);
276+
appended += 1;
273277
}
278+
return appended;
274279
}
275280

276281
export function appendConfiguredRows(params: {

0 commit comments

Comments
 (0)