Skip to content

Commit fe51174

Browse files
fix(models): bypass replace mode check when browsing and resolve default list leak
1 parent f829437 commit fe51174

3 files changed

Lines changed: 67 additions & 0 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ export async function modelsListCommand(
175175
provider: providerFilter,
176176
local: opts.local,
177177
},
178+
browse: enableSourcePlanCascade,
178179
skipRuntimeModelSuppression,
179180
metadataSnapshot,
180181
workspaceDir,

src/commands/models/list.rows.test.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,65 @@ describe("appendProviderCatalogRows", () => {
248248
expect(rows).toHaveLength(1);
249249
expect(rows[0].key).toBe("xai/grok-4");
250250
});
251+
252+
it("does not filter out providers when mode is replace but browse is true", async () => {
253+
const rows: ModelRow[] = [];
254+
255+
await appendProviderCatalogRows({
256+
rows,
257+
seenKeys: new Set(),
258+
catalogModels: [
259+
{
260+
id: "gpt-5.5",
261+
name: "gpt-5.5",
262+
provider: "openai",
263+
api: "openai-responses",
264+
baseUrl: "https://api.openai.com/v1",
265+
input: ["text"],
266+
reasoning: false,
267+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
268+
contextWindow: 8192,
269+
maxTokens: 4096,
270+
},
271+
{
272+
id: "grok-4",
273+
name: "grok-4",
274+
provider: "xai",
275+
api: "xai-responses",
276+
baseUrl: "https://api.xai.com/v1",
277+
input: ["text"],
278+
reasoning: false,
279+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
280+
contextWindow: 8192,
281+
maxTokens: 4096,
282+
},
283+
],
284+
context: {
285+
cfg: {
286+
models: {
287+
mode: "replace",
288+
providers: {
289+
xai: {},
290+
},
291+
},
292+
},
293+
agentDir: "/tmp/openclaw-agent",
294+
authIndex: {
295+
hasProviderAuth: () => true,
296+
allowsProviderAuthAvailabilityFallback: () => false,
297+
},
298+
configuredByKey: new Map(),
299+
discoveredKeys: new Set(),
300+
filter: { local: false },
301+
browse: true,
302+
skipRuntimeModelSuppression: true,
303+
},
304+
});
305+
306+
expect(rows).toHaveLength(2);
307+
expect(rows[0].key).toBe("openai/gpt-5.5");
308+
expect(rows[1].key).toBe("xai/grok-4");
309+
});
251310
});
252311

253312
describe("appendConfiguredProviderRows", () => {

src/commands/models/list.rows.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export type RowBuilderContext = {
4141
configuredByKey: ConfiguredByKey;
4242
discoveredKeys: Set<string>;
4343
filter: RowFilter;
44+
browse?: boolean;
4445
skipRuntimeModelSuppression?: boolean;
4546
metadataSnapshot?: PluginMetadataSnapshot;
4647
workspaceDir?: string;
@@ -81,6 +82,9 @@ function matchesProviderFilter(context: RowBuilderContext, provider: string): bo
8182
}
8283

8384
function isProviderAllowed(context: RowBuilderContext, provider: string): boolean {
85+
if (context.browse) {
86+
return true;
87+
}
8488
if (context.cfg.models?.mode !== "replace") {
8589
return true;
8690
}
@@ -411,6 +415,9 @@ export async function appendAuthenticatedCatalogRows(params: {
411415
metadataSnapshot: params.context.metadataSnapshot,
412416
});
413417
for (const entry of catalog) {
418+
if (!isProviderAllowed(params.context, entry.provider)) {
419+
continue;
420+
}
414421
if (!params.context.authIndex.hasProviderAuth(entry.provider)) {
415422
continue;
416423
}

0 commit comments

Comments
 (0)