mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-09 09:59:45 -10:00
fix(account): keep a DeepSeek or keyed local route when signing in
`codewhale login` switched the local route to the managed Codewhale provider whenever the configured provider equalled ProviderKind::default(), intended as "never configured". DeepSeek is the default provider, so a person who explicitly chose DeepSeek, or stored a DeepSeek key, was silently moved to `provider = "codewhale"`, `model = "auto"` on sign-in. Found while reproducing a stale-sign-in report: a QA login against a loopback account API rewrote the operator's own config this way (restored by hand). Sign-in now takes over the route only when the config file names no provider and the current provider has no local key (config, secret store or environment, via the existing resolve_local_key). An explicit provider, including deepseek, is kept. Evidence: cargo test -p codewhale-cli --lib cloud::tests::login_: with fix 4 passed; 0 failed. Against the previous cloud.rs the two new regressions fail (2 passed; 2 failed), so they pin the defect. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
00b84da0e4
commit
8fb9e13e77
2 files changed
+47
-4
No files matched your search
+16
-4
@@ -2350,9 +2350,21 @@ pub(crate) fn reject_inline_api_key(api_key: Option<&str>) -> Result<()> {
|
||||
|
||||
/// On account sign-in, point a never-configured local route at the managed
|
||||
/// Codewhale provider so chat works immediately. A provider the user chose
|
||||
/// explicitly is left alone.
|
||||
fn select_managed_route_on_login<W: Write>(config: &mut ConfigStore, out: &mut W) -> Result<()> {
|
||||
if config.config.provider == ProviderKind::default() {
|
||||
/// explicitly, or one that already has a local key (config, secret store or
|
||||
/// environment), is left alone: the default provider is DeepSeek, so equality
|
||||
/// with the default cannot tell "never configured" from "chose DeepSeek".
|
||||
fn select_managed_route_on_login<W: Write>(
|
||||
config: &mut ConfigStore,
|
||||
provider_secrets: &Secrets,
|
||||
out: &mut W,
|
||||
) -> Result<()> {
|
||||
let explicit_provider = config
|
||||
.original_body()
|
||||
.and_then(|body| body.parse::<toml::Table>().ok())
|
||||
.is_some_and(|table| table.contains_key("provider"));
|
||||
let has_local_key =
|
||||
resolve_local_key(config, provider_secrets, config.config.provider)?.is_some();
|
||||
if config.config.provider == ProviderKind::default() && !explicit_provider && !has_local_key {
|
||||
config.config.provider = ProviderKind::Codewhale;
|
||||
config.config.model = Some("auto".to_string());
|
||||
config.save()?;
|
||||
@@ -2416,7 +2428,7 @@ fn run_with<T: CloudTransport, W: Write>(
|
||||
client.poll_device(&device, Duration::from_secs(login.timeout_seconds), sleeper)?;
|
||||
let user = client.me()?;
|
||||
write_account(out, "Signed in to Codewhale.", profile, api_base, &user)?;
|
||||
select_managed_route_on_login(config, out)?;
|
||||
select_managed_route_on_login(config, provider_secrets, out)?;
|
||||
Ok(())
|
||||
}
|
||||
CloudCommand::Status => match client.load_auth()? {
|
||||
|
||||
@@ -635,6 +635,37 @@ fn login_keeps_explicitly_configured_route() {
|
||||
assert_eq!(saved.config.model, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn login_keeps_an_explicit_deepseek_route() {
|
||||
// DeepSeek is the default provider; choosing it explicitly must survive sign-in.
|
||||
let (temp, _) = test_config();
|
||||
std::fs::write(temp.path().join("config.toml"), "provider = \"deepseek\"\n").unwrap();
|
||||
let mut config = ConfigStore::load(Some(temp.path().join("config.toml"))).unwrap();
|
||||
let (secrets, _) = test_secrets();
|
||||
let output = run_login(&mut config, &secrets);
|
||||
assert!(
|
||||
output.contains("Keeping your configured deepseek route."),
|
||||
"{output}"
|
||||
);
|
||||
let saved = ConfigStore::load(Some(temp.path().join("config.toml"))).unwrap();
|
||||
assert_eq!(saved.config.provider, ProviderKind::Deepseek);
|
||||
assert_eq!(saved.config.model, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn login_keeps_the_default_route_when_it_has_a_local_key() {
|
||||
let (temp, mut config) = test_config();
|
||||
let (secrets, _) = test_secrets();
|
||||
secrets.set("deepseek", "sk-local-never-print").unwrap();
|
||||
let output = run_login(&mut config, &secrets);
|
||||
assert!(
|
||||
output.contains("Keeping your configured deepseek route."),
|
||||
"{output}"
|
||||
);
|
||||
let saved = ConfigStore::load(Some(temp.path().join("config.toml"))).unwrap();
|
||||
assert_eq!(saved.config.provider, ProviderKind::Deepseek);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cloud_sessions_are_isolated_by_profile_and_api_origin() {
|
||||
let (secrets, _) = test_secrets();
|
||||
|
||||
Reference in new issue
Block a user