Rebrand auth guidance strings: grok login/logout -> kigi login/logout

The headless not-signed-in message still pointed at `grok login` and
XAI_API_KEY; error copy across the shell (re-auth prompts, managed-config
rejection, mcp doctor, trace classifier) and kigi-bin did too. All now
reference `kigi login` / `kigi logout`, and the headless fallback points
at the Moonshot open-platform key (KIGI_MOONSHOT_API_KEY).
This commit is contained in:
2026-07-17 19:33:06 -04:00
parent dab3fa71c9
commit 78cd94a751
14 changed files with 30 additions and 34 deletions
@@ -35,7 +35,7 @@ pub trait AuthCredentialProvider: HttpAuth + Send + Sync + 'static {
/// Return the current credential snapshot. Implementations should /// Return the current credential snapshot. Implementations should
/// issue a cheap disk re-read (`AuthManager::refresh`) before /// issue a cheap disk re-read (`AuthManager::refresh`) before
/// snapshotting so callers see updates from sibling processes /// snapshotting so callers see updates from sibling processes
/// (`grok-desktop`, `grok login`). The `token` field MUST mirror /// (`grok-desktop`, `kigi login`). The `token` field MUST mirror
/// the bearer that `HttpAuth::apply` would send on the wire so /// the bearer that `HttpAuth::apply` would send on the wire so
/// 401-attribution prefixes match the actual request. /// 401-attribution prefixes match the actual request.
fn snapshot(&self) -> CredentialSnapshot; fn snapshot(&self) -> CredentialSnapshot;
+2 -3
View File
@@ -120,7 +120,7 @@ async fn run_setup_command(json: bool) {
if !managed_config::has_principal() { if !managed_config::has_principal() {
eprintln!("No deployment key or team sign-in found."); eprintln!("No deployment key or team sign-in found.");
eprintln!(); eprintln!();
eprintln!("To install managed configuration, sign in with a team using `grok login`,"); eprintln!("To install managed configuration, sign in with a team using `kigi login`,");
eprintln!("or set a deployment key:"); eprintln!("or set a deployment key:");
eprintln!(); eprintln!();
if cfg!(unix) { if cfg!(unix) {
@@ -436,7 +436,7 @@ async fn workspace_start(args: WorkspaceStartArgs, restart: bool) -> Result<()>
ensure_authenticated( ensure_authenticated(
&agent_config.kimi_code_config, &agent_config.kimi_code_config,
false, false,
Some("No cached credentials found. Run `grok login` first."), Some("No cached credentials found. Run `kigi login` first."),
) )
.await?; .await?;
let capabilities = ClientCapabilities { let capabilities = ClientCapabilities {
@@ -956,7 +956,6 @@ async fn run_agent_command(
cwd: None, cwd: None,
is_headless: !is_leader, is_headless: !is_leader,
cli_subagents: None, cli_subagents: None,
cli_web_search_model: None,
cli_session_summary_model: None, cli_session_summary_model: None,
cli_experimental_memory: false, cli_experimental_memory: false,
cli_no_memory: false, cli_no_memory: false,
+1 -1
View File
@@ -102,7 +102,7 @@ impl Default for PruningConfig {
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum AuthType { pub enum AuthType {
/// From AuthManager (grok login, OIDC, external binary). Refreshable. /// From AuthManager (kigi login, OIDC, external binary). Refreshable.
#[default] #[default]
SessionToken, SessionToken,
/// From user config ([model.*] api_key, env_key, XAI_API_KEY). Not refreshable. /// From user config ([model.*] api_key, env_key, XAI_API_KEY). Not refreshable.
@@ -112,7 +112,7 @@ pub enum ConfigChangeEvent {
/// comparison) skips the update when nothing actually changed, so the /// comparison) skips the update when nothing actually changed, so the
/// redundant read is harmless. This avoids a class of bugs where an /// redundant read is harmless. This avoids a class of bugs where an
/// optimistic suppression window accidentally swallows writes from external /// optimistic suppression window accidentally swallows writes from external
/// processes (e.g. `grok login` in another terminal). /// processes (e.g. `kigi login` in another terminal).
/// ///
/// Adds two **non-recursive** watches per `cwd` argument: /// Adds two **non-recursive** watches per `cwd` argument:
/// `<cwd>/` (catches `.mcp.json` and `.claude.json` at the project root) and /// `<cwd>/` (catches `.mcp.json` and `.claude.json` at the project root) and
@@ -980,7 +980,7 @@ pub enum RetryState {
/// again. Drives the actionable re-auth banner. /// again. Drives the actionable re-auth banner.
/// ///
/// `legacy_auth` is intentionally excluded: those failures carry their own /// `legacy_auth` is intentionally excluded: those failures carry their own
/// detailed migration guidance (`grok logout` / `grok login`) in the /// detailed migration guidance (`kigi logout` / `kigi login`) in the
/// message, so we surface that verbatim instead of the generic prompt. /// message, so we surface that verbatim instead of the generic prompt.
pub fn is_reauthable_failure(error_type: Option<&str>, message: &str) -> bool { pub fn is_reauthable_failure(error_type: Option<&str>, message: &str) -> bool {
if error_type == Some("legacy_auth") { if error_type == Some("legacy_auth") {
@@ -98,7 +98,7 @@ pub fn clear_orphan() {
} }
/// Best-effort cross-process lock serializing apply/remove of the managed-config /// Best-effort cross-process lock serializing apply/remove of the managed-config
/// files (TUI tick vs `grok login` vs prefetch). `None` on contention — the /// files (TUI tick vs `kigi login` vs prefetch). `None` on contention — the
/// caller skips and retries next cycle. /// caller skips and retries next cycle.
fn try_lock_managed_config(home: &std::path::Path) -> Option<std::fs::File> { fn try_lock_managed_config(home: &std::path::Path) -> Option<std::fs::File> {
use fs2::FileExt; use fs2::FileExt;
@@ -645,7 +645,7 @@ pub enum ManagedConfigSync {
Failed, Failed,
} }
/// Post-login hook for `grok login` and the ACP/TUI authenticate flow: clear any /// Post-login hook for `kigi login` and the ACP/TUI authenticate flow: clear any
/// orphaned files, then fetch the new principal's config immediately rather than /// orphaned files, then fetch the new principal's config immediately rather than
/// waiting for the background tick. `authenticated` pins the just-logged-in /// waiting for the background tick. `authenticated` pins the just-logged-in
/// principal (`None` = on-disk team). Latency-bounded by [`SyncBudget::Login`]; /// principal (`None` = on-disk team). Latency-bounded by [`SyncBudget::Login`];
@@ -42,7 +42,7 @@ pub enum ManagedConfigError {
)] )]
DeploymentKeyRejected, DeploymentKeyRejected,
#[error( #[error(
"Your team sign-in was rejected. It may have expired or lack access. Run `grok login` to sign in again." "Your team sign-in was rejected. It may have expired or lack access. Run `kigi login` to sign in again."
)] )]
TeamAuthRejected, TeamAuthRejected,
#[error("The server returned an unexpected error (HTTP {status}). Try again in a few minutes.")] #[error("The server returned an unexpected error (HTTP {status}). Try again in a few minutes.")]
+1 -1
View File
@@ -284,7 +284,7 @@ async fn try_discover_managed_servers() -> (ConfigSourceStatus, Vec<DiscoveredSe
let token = match auth_manager.get_valid_token().await { let token = match auth_manager.get_valid_token().await {
Ok(key) => key, Ok(key) => key,
Err(_) => return managed_skipped("auth expired — run `grok login`"), Err(_) => return managed_skipped("auth expired — run `kigi login`"),
}; };
let proxy_url = crate::agent::config::EndpointsConfig::from_effective_config().proxy_url(); let proxy_url = crate::agent::config::EndpointsConfig::from_effective_config().proxy_url();
@@ -78,7 +78,7 @@ pub fn map_sampling_err_to_acp(err: SamplingError) -> acp::Error {
format!( format!(
"{message}\n\nYou have an API key set (XAI_API_KEY). \ "{message}\n\nYou have an API key set (XAI_API_KEY). \
Your cached OAuth session is being used instead. \ Your cached OAuth session is being used instead. \
To use your API key, run `grok logout` or type /logout in the TUI." To use your API key, run `kigi logout` or type /logout in the TUI."
) )
} else { } else {
message message
@@ -485,8 +485,8 @@ mod tests {
let data = acp_err.data.unwrap(); let data = acp_err.data.unwrap();
let msg = data.as_str().unwrap(); let msg = data.as_str().unwrap();
assert!( assert!(
msg.contains("grok logout"), msg.contains("kigi logout"),
"should suggest grok logout when API key is available: {msg}" "should suggest kigi logout when API key is available: {msg}"
); );
assert!( assert!(
msg.contains("/logout"), msg.contains("/logout"),
@@ -509,7 +509,7 @@ mod tests {
let data = acp_err.data.unwrap(); let data = acp_err.data.unwrap();
let msg = data.as_str().unwrap(); let msg = data.as_str().unwrap();
assert!( assert!(
!msg.contains("grok logout"), !msg.contains("kigi logout"),
"should NOT suggest logout when no API key is available: {msg}" "should NOT suggest logout when no API key is available: {msg}"
); );
}); });
@@ -529,7 +529,7 @@ mod tests {
let data = acp_err.data.unwrap(); let data = acp_err.data.unwrap();
let msg = data.as_str().unwrap(); let msg = data.as_str().unwrap();
assert!( assert!(
!msg.contains("grok logout"), !msg.contains("kigi logout"),
"should NOT suggest logout for non-subscription 403: {msg}" "should NOT suggest logout for non-subscription 403: {msg}"
); );
}); });
@@ -1052,7 +1052,7 @@ pub async fn resolve_api_key(explicit: Option<&str>, kigi_home: &Path) -> Result
return Ok(key); return Ok(key);
} }
Err(anyhow!( Err(anyhow!(
"no API key: pass --api-key, set XAI_API_KEY, or run `grok login` to populate \ "no API key: pass --api-key, set XAI_API_KEY, or run `kigi login` to populate \
<grok-home>/auth.json. An expired OIDC token is auto-refreshed when a refresh_token \ <grok-home>/auth.json. An expired OIDC token is auto-refreshed when a refresh_token \
is present; if not, re-login is required." is present; if not, re-login is required."
)) ))
@@ -1088,7 +1088,7 @@ async fn non_interactive_auth_key(kigi_home: &Path) -> Result<Option<String>> {
} }
Err(AuthError::NotLoggedIn) => Ok(None), Err(AuthError::NotLoggedIn) => Ok(None),
Err(e) => Err(anyhow!( Err(e) => Err(anyhow!(
"auth.json refresh failed: {e}. Run `grok login` to re-authenticate, \ "auth.json refresh failed: {e}. Run `kigi login` to re-authenticate, \
or pass --api-key / set $XAI_API_KEY to bypass auth.json." or pass --api-key / set $XAI_API_KEY to bypass auth.json."
)), )),
} }
@@ -2134,7 +2134,7 @@ mod tests {
} }
/// Write an `auth.json` whose only entry is at the production /// Write an `auth.json` whose only entry is at the production
/// OIDC scope (the same scope `grok login` writes today and /// OIDC scope (the same scope `kigi login` writes today and
/// `AuthManager` reads). `auth_mode: api_key` skips the refresh /// `AuthManager` reads). `auth_mode: api_key` skips the refresh
/// path entirely — useful for "plain key, no refresh wanted" /// path entirely — useful for "plain key, no refresh wanted"
/// fixtures. /// fixtures.
@@ -2345,7 +2345,7 @@ mod tests {
assert!( assert!(
msg.contains("--api-key") msg.contains("--api-key")
&& msg.contains("XAI_API_KEY") && msg.contains("XAI_API_KEY")
&& msg.contains("grok login") && msg.contains("kigi login")
&& msg.contains("auth.json"), && msg.contains("auth.json"),
"error names all three sources: {msg}", "error names all three sources: {msg}",
); );
@@ -68,7 +68,7 @@ impl KigiAuthCredentials {
if self.deployment_key.is_some() { if self.deployment_key.is_some() {
"Your KIGI_DEPLOYMENT_KEY is invalid or expired. Please contact a team admin." "Your KIGI_DEPLOYMENT_KEY is invalid or expired. Please contact a team admin."
} else if self.user_token.is_some() { } else if self.user_token.is_some() {
"Your auth token is invalid or expired. Run `grok login` to re-authenticate." "Your auth token is invalid or expired. Run `kigi login` to re-authenticate."
} else { } else {
"Not authenticated." "Not authenticated."
} }
@@ -316,8 +316,8 @@
)); ));
} }
/// Legacy WebLogin auth keeps its verbose message (with `grok logout` / /// Legacy WebLogin auth keeps its verbose message (with `kigi logout` /
/// `grok login` guidance), not the generic re-auth prompt. /// `kigi login` guidance), not the generic re-auth prompt.
#[test] #[test]
fn apply_retry_state_legacy_auth_keeps_detailed_message() { fn apply_retry_state_legacy_auth_keeps_detailed_message() {
let mut session = make_session(Some("s1")); let mut session = make_session(Some("s1"));
@@ -326,7 +326,7 @@
&RetryState::Failed { &RetryState::Failed {
error_type: "legacy_auth".into(), error_type: "legacy_auth".into(),
message: "Unauthorized (401) ... deprecated authentication method (WebLogin) ... \ message: "Unauthorized (401) ... deprecated authentication method (WebLogin) ... \
run `grok logout` then `grok login`" run `kigi logout` then `kigi login`"
.into(), .into(),
}, },
&mut session, &mut session,
+5 -8
View File
@@ -505,14 +505,12 @@ fn auto_respond_to_permissions(
/// "Not signed in" error message, tailored to the session type. /// "Not signed in" error message, tailored to the session type.
fn auth_required_message(interactive: bool) -> String { fn auth_required_message(interactive: bool) -> String {
if interactive { if interactive {
"Not signed in. Run `grok login` to authenticate \ "Not signed in. Run `kigi login` to authenticate with Kimi Code.".to_string()
(or `grok login --device-code` if no browser is available)."
.to_string()
} else { } else {
"Not signed in. To authenticate without a browser, run:\n \ "Not signed in. Run `kigi login` to authenticate with Kimi Code \
grok login --device-code\n\n\ (the device flow prints a URL you can open on any machine).\n\
Alternatively, set the XAI_API_KEY environment variable \ Alternatively, set a Moonshot open-platform API key via \
or run `grok login` on a machine with a browser." KIGI_MOONSHOT_API_KEY."
.to_string() .to_string()
} }
} }
@@ -870,7 +868,6 @@ pub async fn run_single_turn(
cwd: Some(&cwd), cwd: Some(&cwd),
is_headless: true, is_headless: true,
cli_subagents: None, cli_subagents: None,
cli_web_search_model: None,
cli_session_summary_model: None, cli_session_summary_model: None,
cli_experimental_memory: false, cli_experimental_memory: false,
cli_no_memory: false, cli_no_memory: false,
@@ -83,7 +83,7 @@ fn default_auth_path() -> anyhow::Result<PathBuf> {
fn read_auth_entry(path: &Path) -> anyhow::Result<(String, AuthEntry)> { fn read_auth_entry(path: &Path) -> anyhow::Result<(String, AuthEntry)> {
if !path.exists() { if !path.exists() {
anyhow::bail!( anyhow::bail!(
"No auth credentials found at {}. Run `grok login` first.", "No auth credentials found at {}. Run `kigi login` first.",
path.display() path.display()
); );
} }
@@ -98,7 +98,7 @@ fn read_auth_entry(path: &Path) -> anyhow::Result<(String, AuthEntry)> {
.find(|(_, e)| e.refresh_token.is_some() && e.oidc_issuer.is_some()) .find(|(_, e)| e.refresh_token.is_some() && e.oidc_issuer.is_some())
.ok_or_else(|| { .ok_or_else(|| {
anyhow::anyhow!( anyhow::anyhow!(
"no OIDC auth entry found in {}. Run `grok login` first.", "no OIDC auth entry found in {}. Run `kigi login` first.",
path.display() path.display()
) )
}) })