Skip to main content

rpi_cli/
auth_guidance.rs

1//! Auth guidance strings.
2//!
3//! Port of the upstream `packages/coding-agent/src/core/auth-guidance.ts`.
4//! These produce the user-facing "you have no model / no key — here's how to fix
5//! it" messages so every entry point (startup, `/model`, provider resolution)
6//! says the same thing.
7
8/// Where the login help points. rpi keeps its documentation embedded in the
9/// crate, so this is a stable identifier rather than a filesystem path.
10pub const DOCS_PROVIDERS: &str = "docs/providers.md";
11pub const DOCS_MODELS: &str = "docs/models.md";
12
13/// Native `getProviderLoginHelp`.
14pub fn provider_login_help() -> String {
15    [
16        "Use /login to log into a provider via OAuth or API key. See:",
17        &format!("  {DOCS_PROVIDERS}"),
18        &format!("  {DOCS_MODELS}"),
19    ]
20    .join("\n")
21}
22
23/// Native `formatNoModelsAvailableMessage`.
24pub fn no_models_available_message() -> String {
25    format!("No models available. {}", provider_login_help())
26}
27
28/// Native `formatNoModelSelectedMessage`.
29pub fn no_model_selected_message() -> String {
30    format!(
31        "No model selected.\n\n{}\n\nThen use /model to select a model.",
32        provider_login_help()
33    )
34}
35
36/// Native `formatNoApiKeyFoundMessage`.
37pub fn no_api_key_found_message(provider: &str) -> String {
38    let display = if provider.is_empty() || provider == "unknown" {
39        "the selected model".to_string()
40    } else {
41        provider.to_string()
42    };
43    format!(
44        "No API key found for {display}.\n\n{}",
45        provider_login_help()
46    )
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn messages_mention_login() {
55        assert!(no_models_available_message().contains("/login"));
56        assert!(no_model_selected_message().contains("/model"));
57        assert!(no_api_key_found_message("anthropic").contains("anthropic"));
58        assert!(no_api_key_found_message("").contains("the selected model"));
59    }
60}