Detect tier across WSL roots, not just native home (\\wsl$\<distro>\... probe)
This commit is contained in:
parent
ef84257ddd
commit
f33bb5481b
3 changed files with 86 additions and 34 deletions
|
|
@ -70,23 +70,18 @@ fn classify(raw: &str) -> PlanTier {
|
|||
}
|
||||
}
|
||||
|
||||
/// Find the most recent on-disk source of `organizationRateLimitTier`.
|
||||
///
|
||||
/// Search order:
|
||||
/// 1. `~/.claude/.claude.json` if it exists (Linux / WSL)
|
||||
/// 2. `%USERPROFILE%\.claude\.claude.json` (Windows native — same logic via dirs::home_dir)
|
||||
/// 3. The newest `~/.claude/backups/.claude.json.backup.*` (this is what
|
||||
/// we observed populating in practice — `.claude.json` itself isn't
|
||||
/// always present, but the backup directory tracks every config change)
|
||||
fn locate_claude_json() -> Option<PathBuf> {
|
||||
let home = dirs::home_dir()?;
|
||||
let primary = home.join(".claude").join(".claude.json");
|
||||
if primary.is_file() {
|
||||
return Some(primary);
|
||||
}
|
||||
/// Read the tier from a single `.claude.json`-shaped file. None if the file
|
||||
/// doesn't exist, isn't valid JSON, or is missing the field.
|
||||
fn read_tier_from(path: &std::path::Path) -> Option<PlanTier> {
|
||||
let bytes = std::fs::read(path).ok()?;
|
||||
let json: serde_json::Value = serde_json::from_slice(&bytes).ok()?;
|
||||
let raw = json.get("organizationRateLimitTier").and_then(|v| v.as_str())?;
|
||||
Some(classify(raw))
|
||||
}
|
||||
|
||||
let backups_dir = home.join(".claude").join("backups");
|
||||
let entries = std::fs::read_dir(&backups_dir).ok()?;
|
||||
/// Find the newest `.claude.json.backup.*` in `dir` and read its tier.
|
||||
fn read_tier_from_backups(dir: &std::path::Path) -> Option<PlanTier> {
|
||||
let entries = std::fs::read_dir(dir).ok()?;
|
||||
let mut latest: Option<(std::time::SystemTime, PathBuf)> = None;
|
||||
for entry in entries.flatten() {
|
||||
let path = entry.path();
|
||||
|
|
@ -104,23 +99,43 @@ fn locate_claude_json() -> Option<PathBuf> {
|
|||
}
|
||||
}
|
||||
}
|
||||
latest.map(|(_, p)| p)
|
||||
let (_, path) = latest?;
|
||||
read_tier_from(&path)
|
||||
}
|
||||
|
||||
pub fn detect() -> PlanTier {
|
||||
let Some(path) = locate_claude_json() else {
|
||||
return PlanTier::NotFound;
|
||||
};
|
||||
let Ok(bytes) = std::fs::read(&path) else {
|
||||
return PlanTier::NotFound;
|
||||
};
|
||||
let Ok(json) = serde_json::from_slice::<serde_json::Value>(&bytes) else {
|
||||
return PlanTier::NotFound;
|
||||
};
|
||||
match json.get("organizationRateLimitTier").and_then(|v| v.as_str()) {
|
||||
Some(raw) => classify(raw),
|
||||
None => PlanTier::NotFound,
|
||||
/// Try each `.claude/` candidate directory in order. The first hit wins.
|
||||
///
|
||||
/// For each candidate `<dir>` we look at:
|
||||
/// 1. `<dir>/.claude.json` (e.g. ~/.claude/.claude.json)
|
||||
/// 2. `<dir>/backups/.claude.json.backup.*` (newest)
|
||||
/// 3. `<parent of dir>/.claude.json` (some setups put it at ~/.claude.json)
|
||||
pub fn detect_in(claude_dirs: &[PathBuf]) -> PlanTier {
|
||||
for dir in claude_dirs {
|
||||
let primary = dir.join(".claude.json");
|
||||
if let Some(t) = read_tier_from(&primary) {
|
||||
return t;
|
||||
}
|
||||
let backups = dir.join("backups");
|
||||
if let Some(t) = read_tier_from_backups(&backups) {
|
||||
return t;
|
||||
}
|
||||
if let Some(parent) = dir.parent() {
|
||||
let alt = parent.join(".claude.json");
|
||||
if let Some(t) = read_tier_from(&alt) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
PlanTier::NotFound
|
||||
}
|
||||
|
||||
/// Native-only fallback path. Most callers should prefer `detect_in` with
|
||||
/// the resolved-roots' parents so the WSL case works.
|
||||
pub fn detect() -> PlanTier {
|
||||
let Some(home) = dirs::home_dir() else {
|
||||
return PlanTier::NotFound;
|
||||
};
|
||||
detect_in(&[home.join(".claude")])
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue