ralph_workflow/agents/providers/
validation.rs1use super::detection::strip_model_flag_prefix;
6use super::types::OpenCodeProviderType;
7
8pub fn validate_model_flag(model_flag: &str) -> Vec<String> {
12 let mut warnings = Vec::new();
13
14 let model = strip_model_flag_prefix(model_flag);
15 if model.is_empty() {
16 return warnings;
17 }
18
19 if !model.contains('/') {
21 warnings.push(format!(
22 "Model '{model}' has no provider prefix. Expected format: 'provider/model' (e.g., 'opencode/glm-4.7-free')"
23 ));
24 return warnings;
25 }
26
27 let provider_type = OpenCodeProviderType::from_model_flag(model);
28
29 if provider_type == OpenCodeProviderType::OpenCodeZen && model.to_lowercase().contains("zai") {
31 warnings.push(
32 "Model flag uses 'opencode/' prefix but contains 'zai'. \
33 For Z.AI Direct access, use 'zai/' prefix instead."
34 .to_string(),
35 );
36 }
37
38 if provider_type.requires_cloud_config() {
40 warnings.push(format!(
41 "{} provider requires cloud configuration. {}",
42 provider_type.name(),
43 provider_type.auth_command()
44 ));
45 }
46
47 if provider_type == OpenCodeProviderType::Custom {
49 let prefix = model.split('/').next().unwrap_or("");
50 warnings.push(format!(
51 "Unknown provider prefix '{prefix}'. This may work if OpenCode supports it. \
52 Run 'ralph --list-providers' to see known providers."
53 ));
54 }
55
56 if provider_type.is_local() {
58 warnings.push(format!(
59 "{} is a local provider. {}",
60 provider_type.name(),
61 provider_type.auth_command()
62 ));
63 }
64
65 warnings
66}
67
68pub fn auth_failure_advice(model_flag: Option<&str>) -> String {
70 match model_flag {
71 Some(flag) => {
72 let model = strip_model_flag_prefix(flag);
73 let prefix = model.split('/').next().unwrap_or("").to_lowercase();
74 if matches!(prefix.as_str(), "zai" | "zhipuai") {
75 return "Authentication failed for Z.AI provider. Run: opencode auth login -> select 'Z.AI' or 'Z.AI Coding Plan'".to_string();
76 }
77 let provider = OpenCodeProviderType::from_model_flag(flag);
78 format!(
79 "Authentication failed for {} provider. Run: {}",
80 provider.name(),
81 provider.auth_command()
82 )
83 }
84 None => "Check API key or run 'opencode auth login' to authenticate.".to_string(),
85 }
86}