detect_plan_tier: re-resolve roots fresh; expose searched paths in TierInfo for diagnosis

This commit is contained in:
megaproxy 2026-05-09 01:11:43 +01:00
parent f33bb5481b
commit 9d10c1f46f
4 changed files with 29 additions and 7 deletions

View file

@ -83,19 +83,24 @@ pub struct TierInfo {
/// The caps that this tier maps to. The user's current Settings may
/// differ if they tuned manually.
pub recommended_caps: Caps,
/// Diagnostic: the candidate `.claude/` directories that were probed.
/// Useful for users on novel setups (multi-distro, custom $HOME, etc.).
pub searched: Vec<String>,
}
#[tauri::command]
pub async fn detect_plan_tier(
state: tauri::State<'_, SharedState>,
) -> Result<TierInfo, String> {
// Each resolved root is a `<base>/.claude/projects` path. The tier
// file lives in the parent (`<base>/.claude/`) — so check those, plus
// the native home as a fallback, so this works whether Claude Code
// runs in WSL (UNC paths) or natively.
let mut candidates: Vec<PathBuf> = state
// Resolve roots fresh — `state.roots` may be empty if this command is
// invoked before the cold-start refresh finishes (which IS what happens
// when the user opens Settings shortly after launch).
let s = state.settings.read().clone();
let resolved =
resolve_roots(s.wsl_distro_override.as_deref(), s.include_native);
let mut candidates: Vec<PathBuf> = resolved
.roots
.read()
.iter()
.filter_map(|r| r.parent().map(PathBuf::from))
.collect();
@ -109,5 +114,9 @@ pub async fn detect_plan_tier(
let tier = detect_tier_in(&candidates);
let label = tier.label();
let recommended_caps = tier.caps();
Ok(TierInfo { tier, label, recommended_caps })
Ok(TierInfo { tier, label, recommended_caps, searched: paths_to_strings(&candidates) })
}
fn paths_to_strings(paths: &[PathBuf]) -> Vec<String> {
paths.iter().map(|p| p.display().to_string()).collect()
}

View file

@ -131,6 +131,7 @@ pub fn detect_in(claude_dirs: &[PathBuf]) -> PlanTier {
/// Native-only fallback path. Most callers should prefer `detect_in` with
/// the resolved-roots' parents so the WSL case works.
#[allow(dead_code)]
pub fn detect() -> PlanTier {
let Some(home) = dirs::home_dir() else {
return PlanTier::NotFound;

View file

@ -93,6 +93,14 @@
Approximate — Anthropic doesn't publish exact caps. Tune below
once you actually hit a limit.
</div>
{#if tier.label.startsWith("Unknown") && tier.searched.length > 0}
<details class="muted hint">
<summary>Searched paths</summary>
<ul class="paths">
{#each tier.searched as p (p)}<li><code>{p}</code></li>{/each}
</ul>
</details>
{/if}
</div>
{/if}
@ -194,6 +202,9 @@
gap: 4px;
}
.hint { font-size: 10px; line-height: 1.3; }
details summary { cursor: pointer; font-size: 10px; }
ul.paths { margin: 4px 0 0; padding-left: 14px; max-height: 70px; overflow: auto; }
ul.paths code { font-size: 10px; word-break: break-all; }
.error {
background: rgba(255, 107, 107, 0.15);
border: 1px solid var(--danger);

View file

@ -67,4 +67,5 @@ export interface TierInfo {
tier: unknown;
label: string;
recommended_caps: Caps;
searched: string[];
}