mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 21:07:01 -06:00
fix(cli): reject --agent for global model refresh (#130448)
* fix(cli): models refresh rejects parent --agent like set/aliases/scan `models refresh` refreshes the global hosted catalog (refreshRemoteModelCatalog) and takes no agent, but silently accepted a parent --agent, implying a per-agent scope it does not deliver. #126864 landed rejectAgentScopedModelCommand for set/set-image/aliases/scan but left refresh unaddressed (it scoped out only fallbacks/image-fallbacks). Add "refresh" to GlobalOnlyModelCommandName and switch refresh's action to the same loadModelsRuntime + reject + runModelsCommand pattern, so --agent fails fast with the same error instead of a silent global refresh. Co-Authored-By: Claude <noreply@anthropic.com> * docs(cli): list models refresh among --agent-rejecting commands `docs/cli/models.md` listed `set`/`set-image`/`scan`/`aliases` as rejecting `--agent` but omitted `refresh`, so the new guard landed in the previous commit was not reflected in the docs. Add `refresh` to the global-only list and note it on the refresh section. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: ruel225 <ruel225@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
+2
-2
@@ -28,7 +28,7 @@ openclaw models set-image <model-or-alias>
|
||||
openclaw models scan
|
||||
```
|
||||
|
||||
`status`, `list`, and `auth` subcommands accept `--agent <id>` to target a configured agent; `fallbacks`/`image-fallbacks` always use the configured default agent, and `set`, `set-image`, `scan`, and `aliases` reject `--agent` outright because they are global and never agent-scoped. When omitted, `--agent`-aware commands use `OPENCLAW_AGENT_DIR` if set, otherwise the configured default agent.
|
||||
`status`, `list`, and `auth` subcommands accept `--agent <id>` to target a configured agent; `fallbacks`/`image-fallbacks` always use the configured default agent, and `set`, `set-image`, `scan`, `refresh`, and `aliases` reject `--agent` outright because they are global and never agent-scoped. When omitted, `--agent`-aware commands use `OPENCLAW_AGENT_DIR` if set, otherwise the configured default agent.
|
||||
|
||||
`models set` and `models set-image` require the provider to be declared by an installed plugin or configured under `models.providers`. An unknown provider exits nonzero without changing config. If the provider is known but the model is absent from the local catalog, the command saves the selection and prints a warning because newly released and self-hosted models may not be cataloged yet. `openclaw doctor --json` reports configured unknown providers; add `--severity-min info` to also see active models that the local catalog cannot confirm.
|
||||
|
||||
@@ -73,7 +73,7 @@ For OpenAI ChatGPT/Codex OAuth troubleshooting, `openclaw models status`, `openc
|
||||
|
||||
`openclaw models list` is read-only: it reads config, auth profiles, existing catalog state, and provider-owned catalog rows, but never rewrites `models.json`.
|
||||
|
||||
`openclaw models refresh [--json]` forces an immediate hosted catalog check.
|
||||
`openclaw models refresh [--json]` forces an immediate hosted catalog check. Like `scan`, it rejects `--agent` because the hosted catalog is global, not agent-scoped.
|
||||
Updated rows apply to a running Gateway after its next restart. The command
|
||||
prints a clear disabled result when `models.catalogRefresh.enabled` is `false`.
|
||||
The catalog's public change history lives in
|
||||
|
||||
@@ -27,7 +27,8 @@ export type GlobalOnlyModelCommandName =
|
||||
| "scan"
|
||||
| "aliases list"
|
||||
| "aliases add"
|
||||
| "aliases remove";
|
||||
| "aliases remove"
|
||||
| "refresh";
|
||||
|
||||
export function rejectAgentScopedModelCommand(
|
||||
command: Command,
|
||||
|
||||
@@ -11,6 +11,7 @@ const mocks = vi.hoisted(() => ({
|
||||
modelsStatusCommand: vi.fn().mockResolvedValue(undefined),
|
||||
modelsSetCommand: vi.fn().mockResolvedValue(undefined),
|
||||
modelsSetImageCommand: vi.fn().mockResolvedValue(undefined),
|
||||
modelsRefreshCommand: vi.fn().mockResolvedValue(undefined),
|
||||
noopAsync: vi.fn(async () => undefined),
|
||||
modelsAliasesAddCommand: vi.fn().mockResolvedValue(undefined),
|
||||
modelsAliasesListCommand: vi.fn().mockResolvedValue(undefined),
|
||||
@@ -42,6 +43,7 @@ const {
|
||||
modelsAuthPasteApiKeyCommand,
|
||||
modelsAuthPasteTokenCommand,
|
||||
modelsAuthSetupTokenCommand,
|
||||
modelsRefreshCommand,
|
||||
modelsScanCommand,
|
||||
modelsSetCommand,
|
||||
modelsSetImageCommand,
|
||||
@@ -92,6 +94,9 @@ vi.mock("../commands/models/set.js", () => ({
|
||||
vi.mock("../commands/models/set-image.js", () => ({
|
||||
modelsSetImageCommand: mocks.modelsSetImageCommand,
|
||||
}));
|
||||
vi.mock("../commands/models/refresh.js", () => ({
|
||||
modelsRefreshCommand: mocks.modelsRefreshCommand,
|
||||
}));
|
||||
|
||||
describe("models cli", () => {
|
||||
beforeEach(() => {
|
||||
@@ -99,6 +104,7 @@ describe("models cli", () => {
|
||||
modelsAliasesAddCommand.mockClear();
|
||||
modelsAliasesListCommand.mockClear();
|
||||
modelsAliasesRemoveCommand.mockClear();
|
||||
modelsRefreshCommand.mockClear();
|
||||
modelsScanCommand.mockClear();
|
||||
modelsAuthAddCommand.mockClear();
|
||||
modelsAuthListCommand.mockClear();
|
||||
@@ -576,6 +582,11 @@ describe("models cli", () => {
|
||||
args: ["models", "--agent", "poe", "scan", "--no-probe", "--no-input"],
|
||||
command: modelsScanCommand,
|
||||
},
|
||||
{
|
||||
label: "refresh",
|
||||
args: ["models", "--agent", "poe", "refresh"],
|
||||
command: modelsRefreshCommand,
|
||||
},
|
||||
])("rejects parent --agent for models $label", async ({ args, command }) => {
|
||||
await expect(runModelsCommand(args)).rejects.toThrow("does not support --agent");
|
||||
|
||||
@@ -593,6 +604,11 @@ describe("models cli", () => {
|
||||
args: ["models", "scan", "--no-probe", "--no-input"],
|
||||
command: modelsScanCommand,
|
||||
},
|
||||
{
|
||||
label: "refresh",
|
||||
args: ["models", "refresh"],
|
||||
command: modelsRefreshCommand,
|
||||
},
|
||||
])("still runs models $label without --agent", async ({ args, command }) => {
|
||||
await runModelsCommand(args);
|
||||
|
||||
|
||||
@@ -128,10 +128,12 @@ export function registerModelsCli(program: Command) {
|
||||
.command("refresh")
|
||||
.description("Refresh the hosted model catalog")
|
||||
.option("--json", "Output JSON", false)
|
||||
.action(async (opts) => {
|
||||
await withModelsRuntime(async ({ defaultRuntime }) => {
|
||||
.action(async (opts, command: Command) => {
|
||||
const runtime = await loadModelsRuntime();
|
||||
runtime.rejectAgentScopedModelCommand(command, "refresh");
|
||||
await runtime.runModelsCommand(async () => {
|
||||
const { modelsRefreshCommand } = await import("../commands/models/refresh.js");
|
||||
await modelsRefreshCommand({ json: hasJsonOutput(opts) }, defaultRuntime);
|
||||
await modelsRefreshCommand({ json: hasJsonOutput(opts) }, runtime.defaultRuntime);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user