mirror of
https://github.com/ultraworkers/claw-code.git
synced 2026-04-26 22:47:38 +08:00
fix: #124 --model validation rejects malformed syntax at parse time
Adds validate_model_syntax() that rejects: - Empty strings - Strings with spaces (e.g., 'bad model') - Invalid provider/model format Accepts: - Known aliases (opus, sonnet, haiku) - Valid provider/model format (provider/model) Wired into parse_args for both --model <value> and --model=<value> forms. Errors exit with clear message before any API calls (no token burn). Verified: - 'claw --model "bad model" version' → error, exit 1 - 'claw --model "" version' → error, exit 1 - 'claw --model opus version' → works - 'claw --model anthropic/claude-opus-4-6 version' → works Refs: ROADMAP #124 (debbcbe cluster — parser-level trust gap family)
This commit is contained in:
parent
b9990bb27c
commit
2678fa0af5
@ -447,11 +447,14 @@ fn parse_args(args: &[String]) -> Result<CliAction, String> {
|
|||||||
let value = args
|
let value = args
|
||||||
.get(index + 1)
|
.get(index + 1)
|
||||||
.ok_or_else(|| "missing value for --model".to_string())?;
|
.ok_or_else(|| "missing value for --model".to_string())?;
|
||||||
|
validate_model_syntax(value)?;
|
||||||
model = resolve_model_alias_with_config(value);
|
model = resolve_model_alias_with_config(value);
|
||||||
index += 2;
|
index += 2;
|
||||||
}
|
}
|
||||||
flag if flag.starts_with("--model=") => {
|
flag if flag.starts_with("--model=") => {
|
||||||
model = resolve_model_alias_with_config(&flag[8..]);
|
let value = &flag[8..];
|
||||||
|
validate_model_syntax(value)?;
|
||||||
|
model = resolve_model_alias_with_config(value);
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
"--output-format" => {
|
"--output-format" => {
|
||||||
@ -1035,6 +1038,37 @@ fn resolve_model_alias_with_config(model: &str) -> String {
|
|||||||
resolve_model_alias(trimmed).to_string()
|
resolve_model_alias(trimmed).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Validate model syntax at parse time.
|
||||||
|
/// Accepts: known aliases (opus, sonnet, haiku) or provider/model pattern.
|
||||||
|
/// Rejects: empty, whitespace-only, strings with spaces, or invalid chars.
|
||||||
|
fn validate_model_syntax(model: &str) -> Result<(), String> {
|
||||||
|
let trimmed = model.trim();
|
||||||
|
if trimmed.is_empty() {
|
||||||
|
return Err("model string cannot be empty".to_string());
|
||||||
|
}
|
||||||
|
// Known aliases are always valid
|
||||||
|
match trimmed {
|
||||||
|
"opus" | "sonnet" | "haiku" => return Ok(()),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
// Check for spaces (malformed)
|
||||||
|
if trimmed.contains(' ') {
|
||||||
|
return Err(format!(
|
||||||
|
"invalid model syntax: '{}' contains spaces. Use provider/model format or known alias",
|
||||||
|
trimmed
|
||||||
|
));
|
||||||
|
}
|
||||||
|
// 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!(
|
||||||
|
"invalid model syntax: '{}'. Expected provider/model (e.g., anthropic/claude-opus-4-6) or known alias (opus, sonnet, haiku)",
|
||||||
|
trimmed
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn config_alias_for_current_dir(alias: &str) -> Option<String> {
|
fn config_alias_for_current_dir(alias: &str) -> Option<String> {
|
||||||
if alias.is_empty() {
|
if alias.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user