mirror of
https://github.com/ultraworkers/claw-code.git
synced 2026-04-24 05:00:25 +08:00
feat: #154 — hint provider prefix and env var when model name looks like different provider
## Problem When a user types `claw --model gpt-4` or `--model qwen-plus`, they get: ``` error: invalid model syntax: 'gpt-4'. Expected provider/model (e.g., anthropic/claude-opus-4-6) or known alias ``` USAGE.md documents that "The error message now includes a hint that names the detected env var" — but this hint does not actually exist. The user has to re-read USAGE.md or guess the correct prefix. ## Fix Enhance `validate_model_syntax` to detect when a model name looks like it belongs to a different provider: 1. **OpenAI models** (starts with `gpt-` or `gpt_`): ``` Did you mean `openai/gpt-4`? (Requires OPENAI_API_KEY env var) ``` 2. **Qwen/DashScope models** (starts with `qwen`): ``` Did you mean `qwen/qwen-plus`? (Requires DASHSCOPE_API_KEY env var) ``` 3. **Grok/xAI models** (starts with `grok`): ``` Did you mean `xai/grok-3`? (Requires XAI_API_KEY env var) ``` Unrelated invalid models (e.g., `asdfgh`) do not get a spurious hint. ## Verification - `claw --model gpt-4` → hints `openai/gpt-4` + `OPENAI_API_KEY` - `claw --model qwen-plus` → hints `qwen/qwen-plus` + `DASHSCOPE_API_KEY` - `claw --model grok-3` → hints `xai/grok-3` + `XAI_API_KEY` - `claw --model asdfgh` → generic error (no hint) ## Tests Added 3 new assertions in `parses_multiple_diagnostic_subcommands`: - GPT model error hints openai/ prefix and OPENAI_API_KEY - Qwen model error hints qwen/ prefix and DASHSCOPE_API_KEY - Unrelated models don't get a spurious hint All 177 rusty-claude-cli tests pass. Closes ROADMAP #154.
This commit is contained in:
parent
71f5f83adb
commit
3cfe6e2b14
26
ROADMAP.md
26
ROADMAP.md
@ -5934,3 +5934,29 @@ This creates a confusing gap: users build successfully but then get "command not
|
||||
**Blocker:** None. Pure documentation.
|
||||
|
||||
**Source:** Clawhip nudge 2026-04-21 21:27 KST — onboarding gap from #claw-code observations earlier this month.
|
||||
|
||||
## Pinpoint #154. Model syntax error doesn't hint at env var when multiple credentials present
|
||||
|
||||
**Gap.** When a user types `claw --model gpt-4` but only has `ANTHROPIC_API_KEY` set (no `OPENAI_API_KEY`), the error is:
|
||||
```
|
||||
error: invalid model syntax: 'gpt-4'. Expected provider/model (e.g., anthropic/claude-opus-4-6) or known alias (opus, sonnet, haiku)
|
||||
```
|
||||
|
||||
But USAGE.md documents that "The error message now includes a hint that names the detected env var" — **this hint is not actually emitted.** The user gets a generic syntax error and has to re-read USAGE.md to discover they should type `openai/gpt-4` instead.
|
||||
|
||||
**Expected behavior (from USAGE.md):** When the user has multiple providers' env vars set, or when a model name looks like it belongs to a different provider (e.g., `gpt-4` looks like OpenAI), the error should hint:
|
||||
- "Did you mean `openai/gpt-4`? (but `OPENAI_API_KEY` is not set)"
|
||||
- or "You have `ANTHROPIC_API_KEY` set but `gpt-4` looks like an OpenAI model. Try `openai/gpt-4` with `OPENAI_API_KEY` exported"
|
||||
|
||||
**Current behavior:** Generic syntax error, user has to infer the fix from USAGE.md or guess.
|
||||
|
||||
**Fix shape (~20 lines).** Enhance `FormatError::InvalidModelSyntax` or the model-parsing validation to:
|
||||
1. Detect if the model name looks like it belongs to a known provider (prefix `gpt-`, `openai/`, `qwen`, etc.)
|
||||
2. If it does, check if that provider's env var is missing
|
||||
3. Append a hint: "Did you mean \`{inferred_prefix}/{model}\`? (requires `{PROVIDER_KEY}` env var)"
|
||||
|
||||
**Acceptance:** `claw --model gpt-4` produces a hint about OpenAI prefix and missing `OPENAI_API_KEY`. Same for `qwen-plus` → hint about `DASHSCOPE_API_KEY`, etc.
|
||||
|
||||
**Blocker:** None. Pure error-message UX improvement.
|
||||
|
||||
**Source:** Clawhip nudge 2026-04-21 21:37 KST — discovered during dogfood probing of model validation.
|
||||
|
||||
@ -1401,10 +1401,27 @@ fn validate_model_syntax(model: &str) -> Result<(), String> {
|
||||
// Check provider/model format: provider_id/model_id
|
||||
let parts: Vec<&str> = trimmed.split('/').collect();
|
||||
if parts.len() != 2 || parts[0].is_empty() || parts[1].is_empty() {
|
||||
return Err(format!(
|
||||
// #154: hint if the model looks like it belongs to a different provider
|
||||
let mut err_msg = format!(
|
||||
"invalid model syntax: '{}'. Expected provider/model (e.g., anthropic/claude-opus-4-6) or known alias (opus, sonnet, haiku)",
|
||||
trimmed
|
||||
));
|
||||
);
|
||||
if trimmed.starts_with("gpt-") || trimmed.starts_with("gpt_") {
|
||||
err_msg.push_str("\nDid you mean `openai/");
|
||||
err_msg.push_str(trimmed);
|
||||
err_msg.push_str("`? (Requires OPENAI_API_KEY env var)");
|
||||
}
|
||||
else if trimmed.starts_with("qwen") {
|
||||
err_msg.push_str("\nDid you mean `qwen/");
|
||||
err_msg.push_str(trimmed);
|
||||
err_msg.push_str("`? (Requires DASHSCOPE_API_KEY env var)");
|
||||
}
|
||||
else if trimmed.starts_with("grok") {
|
||||
err_msg.push_str("\nDid you mean `xai/");
|
||||
err_msg.push_str(trimmed);
|
||||
err_msg.push_str("`? (Requires XAI_API_KEY env var)");
|
||||
}
|
||||
return Err(err_msg);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -10301,6 +10318,34 @@ mod tests {
|
||||
.expect_err("`doctor garbage` should fail without --json hint");
|
||||
assert!(!err_other.contains("--output-format json"),
|
||||
"unrelated args should not trigger --json hint: {err_other}");
|
||||
// #154: model syntax error should hint at provider prefix when applicable
|
||||
let err_gpt = parse_args(&["prompt".to_string(), "test".to_string(), "--model".to_string(), "gpt-4".to_string()])
|
||||
.expect_err("`--model gpt-4` should fail with OpenAI hint");
|
||||
assert!(
|
||||
err_gpt.contains("Did you mean `openai/gpt-4`?"),
|
||||
"GPT model error should hint openai/ prefix: {err_gpt}"
|
||||
);
|
||||
assert!(
|
||||
err_gpt.contains("OPENAI_API_KEY"),
|
||||
"GPT model error should mention env var: {err_gpt}"
|
||||
);
|
||||
let err_qwen = parse_args(&["prompt".to_string(), "test".to_string(), "--model".to_string(), "qwen-plus".to_string()])
|
||||
.expect_err("`--model qwen-plus` should fail with DashScope hint");
|
||||
assert!(
|
||||
err_qwen.contains("Did you mean `qwen/qwen-plus`?"),
|
||||
"Qwen model error should hint qwen/ prefix: {err_qwen}"
|
||||
);
|
||||
assert!(
|
||||
err_qwen.contains("DASHSCOPE_API_KEY"),
|
||||
"Qwen model error should mention env var: {err_qwen}"
|
||||
);
|
||||
// Unrelated invalid model should NOT get a hint
|
||||
let err_garbage = parse_args(&["prompt".to_string(), "test".to_string(), "--model".to_string(), "asdfgh".to_string()])
|
||||
.expect_err("`--model asdfgh` should fail");
|
||||
assert!(
|
||||
!err_garbage.contains("Did you mean"),
|
||||
"Unrelated model errors should not get a hint: {err_garbage}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user