mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 12:00:44 +00:00
fix(model): guide runtime allowlist repairs
This commit is contained in:
@@ -119,7 +119,8 @@ openclaw config set agents.defaults.models '{"openai/gpt-5.4":{}}' --strict-json
|
||||
If `agents.defaults.models` is set, it becomes the **allowlist** for `/model` and for session overrides. When a user selects a model that isn't in that allowlist, OpenClaw returns:
|
||||
|
||||
```
|
||||
Model "provider/model" is not allowed. Use /model to list available models.
|
||||
Model "provider/model" is not allowed. Use /models to list providers, or /models <provider> to list models.
|
||||
Add it with: openclaw config set agents.defaults.models '{"provider/model":{}}' --strict-json --merge
|
||||
```
|
||||
|
||||
<Warning>
|
||||
@@ -131,6 +132,8 @@ This happens **before** a normal reply is generated, so the message can feel lik
|
||||
|
||||
</Warning>
|
||||
|
||||
When the rejected command included a runtime override such as `/model openai/gpt-5.5 --runtime codex`, fix the allowlist first, then retry the same `/model ... --runtime ...` command. For native Codex execution, the selected model is still `openai/gpt-5.5`; the `codex` runtime selects the harness and uses Codex auth separately.
|
||||
|
||||
For local/GGUF models, store the full provider-prefixed ref in the allowlist,
|
||||
for example `ollama/gemma4:26b`, `lmstudio/Gemma4-26b-a4-it-gguf`, or the
|
||||
exact provider/model shown by `openclaw models list --provider <provider>`.
|
||||
|
||||
@@ -191,11 +191,14 @@ troubleshooting, see the main [FAQ](/help/faq).
|
||||
session overrides. Choosing a model that isn't in that list returns:
|
||||
|
||||
```
|
||||
Model "provider/model" is not allowed. Use /model to list available models.
|
||||
Model "provider/model" is not allowed. Use /models to list providers, or /models <provider> to list models.
|
||||
Add it with: openclaw config set agents.defaults.models '{"provider/model":{}}' --strict-json --merge
|
||||
```
|
||||
|
||||
That error is returned **instead of** a normal reply. Fix: add the model to
|
||||
`agents.defaults.models`, remove the allowlist, or pick a model from `/model list`.
|
||||
If the command also included `--runtime codex`, add the model first and then retry
|
||||
the same `/model provider/model --runtime codex` command.
|
||||
|
||||
</Accordion>
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ export function resolveModelSelectionFromDirective(params: {
|
||||
defaultModel: params.defaultModel,
|
||||
aliasIndex: params.aliasIndex,
|
||||
allowedModelKeys: params.allowedModelKeys,
|
||||
rawRuntime: params.directives.rawModelRuntime,
|
||||
})
|
||||
: null;
|
||||
const useStoredNumericProfile =
|
||||
@@ -131,6 +132,7 @@ export function resolveModelSelectionFromDirective(params: {
|
||||
defaultModel: params.defaultModel,
|
||||
aliasIndex: params.aliasIndex,
|
||||
allowedModelKeys: params.allowedModelKeys,
|
||||
rawRuntime: params.directives.rawModelRuntime,
|
||||
});
|
||||
|
||||
if (resolved.error) {
|
||||
|
||||
@@ -611,6 +611,22 @@ describe("/model chat UX", () => {
|
||||
expect(resolved.errorText).toContain("Browse: /models or /models <provider>");
|
||||
});
|
||||
|
||||
it("includes additive allowlist repair when a runtime switch targets a blocked model", () => {
|
||||
const resolved = resolveModelSelectionForCommand({
|
||||
command: "/model openai/gpt-5.5 --runtime codex",
|
||||
allowedModelKeys: new Set(["anthropic/claude-opus-4-6"]),
|
||||
allowedModelCatalog: [],
|
||||
});
|
||||
|
||||
expect(resolved.modelSelection).toBeUndefined();
|
||||
expect(resolved.errorText).toContain('Model "openai/gpt-5.5" is not allowed.');
|
||||
expect(resolved.errorText).toContain(
|
||||
`openclaw config set agents.defaults.models '{"openai/gpt-5.5":{}}' --strict-json --merge`,
|
||||
);
|
||||
expect(resolved.errorText).toContain("Then retry: /model openai/gpt-5.5 --runtime codex");
|
||||
expect(resolved.errorText).toContain("openclaw plugins enable codex");
|
||||
});
|
||||
|
||||
it("treats explicit default /model selection as resettable default", () => {
|
||||
const resolved = resolveModelSelectionForCommand({
|
||||
command: "/model anthropic/claude-opus-4-6",
|
||||
|
||||
@@ -265,6 +265,7 @@ export async function maybeHandleModelDirectiveInfo(params: {
|
||||
"",
|
||||
"Tap below to browse models, or use:",
|
||||
"/model <provider/model> to switch",
|
||||
"/model <provider/model> --runtime <runtime> to switch harnesses",
|
||||
"/model status for details",
|
||||
]
|
||||
.filter(Boolean)
|
||||
|
||||
@@ -20,6 +20,29 @@ export type ModelDirectiveSelection = {
|
||||
alias?: string;
|
||||
};
|
||||
|
||||
function formatAddModelCommand(modelRef: string): string {
|
||||
return `openclaw config set agents.defaults.models '${JSON.stringify({ [modelRef]: {} })}' --strict-json --merge`;
|
||||
}
|
||||
|
||||
function formatNotAllowedError(params: {
|
||||
modelRef: string;
|
||||
rawRuntime?: string | undefined;
|
||||
}): string {
|
||||
const rawRuntime = params.rawRuntime?.trim();
|
||||
const retryCommand = rawRuntime
|
||||
? `/model ${params.modelRef} --runtime ${rawRuntime}`
|
||||
: `/model ${params.modelRef}`;
|
||||
const lines = [
|
||||
`Model "${params.modelRef}" is not allowed. Use /models to list providers, or /models <provider> to list models.`,
|
||||
`Add it with: ${formatAddModelCommand(params.modelRef)}`,
|
||||
`Then retry: ${retryCommand}`,
|
||||
];
|
||||
if (rawRuntime && normalizeProviderId(rawRuntime) === "codex") {
|
||||
lines.push("If the Codex runtime is missing, run: openclaw plugins enable codex");
|
||||
}
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
const FUZZY_VARIANT_TOKENS = [
|
||||
"lightning",
|
||||
"preview",
|
||||
@@ -238,6 +261,7 @@ export function resolveModelDirectiveSelection(params: {
|
||||
defaultModel: string;
|
||||
aliasIndex: ModelAliasIndex;
|
||||
allowedModelKeys: Set<string>;
|
||||
rawRuntime?: string | undefined;
|
||||
}): { selection?: ModelDirectiveSelection; error?: string } {
|
||||
const { raw, defaultProvider, defaultModel, aliasIndex, allowedModelKeys } = params;
|
||||
|
||||
@@ -401,6 +425,9 @@ export function resolveModelDirectiveSelection(params: {
|
||||
}
|
||||
|
||||
return {
|
||||
error: `Model "${resolved.ref.provider}/${resolved.ref.model}" is not allowed. Use /models to list providers, or /models <provider> to list models.`,
|
||||
error: formatNotAllowedError({
|
||||
modelRef: `${resolved.ref.provider}/${resolved.ref.model}`,
|
||||
rawRuntime: params.rawRuntime,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user