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:
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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.")]
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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()
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user