Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da270de6d6 | ||
|
|
f4bed1b585 |
@@ -82,11 +82,13 @@ public partial class LoginWindow : Window
|
||||
const string script = @"(async()=>{try{
|
||||
const h={headers:{accept:'application/json'}};
|
||||
const b=await(await fetch('/api/bootstrap',h)).json();
|
||||
const rawB=JSON.stringify(b).slice(0,600);
|
||||
let id=b?.account?.memberships?.[0]?.organization?.uuid
|
||||
||b?.memberships?.[0]?.organization?.uuid||b?.organizations?.[0]?.uuid
|
||||
||b?.default_organization?.uuid||null;
|
||||
const org0=b?.account?.memberships?.[0]?.organization;
|
||||
let id=org0?.uuid||b?.memberships?.[0]?.organization?.uuid
|
||||
||b?.organizations?.[0]?.uuid||b?.default_organization?.uuid||null;
|
||||
const e=b?.account?.email_address||b?.account?.email||b?.email||null;
|
||||
const caps=org0?.capabilities||[];
|
||||
const capStr=caps.find(c=>typeof c==='string'&&c.startsWith('claude_'))||null;
|
||||
const planLabel=capStr?(capStr.slice(7,8).toUpperCase()+capStr.slice(8).toLowerCase()):null;
|
||||
let orgSrc='bootstrap';
|
||||
if(!id){
|
||||
try{const ol=await(await fetch('/api/organizations',h)).json();
|
||||
@@ -95,12 +97,11 @@ public partial class LoginWindow : Window
|
||||
if(!id){
|
||||
let pu=null;
|
||||
try{pu=await(await fetch('/api/usage',h)).json();}catch(e3){}
|
||||
window.chrome.webview.postMessage({email:e,orgId:null,usage:(pu&&!pu.error?pu:null),debug:'no-org|raw:'+rawB});
|
||||
window.chrome.webview.postMessage({email:e,orgId:null,planLabel,usage:(pu&&!pu.error?pu:null),debug:'no-org'});
|
||||
return;
|
||||
}
|
||||
const u=await(await fetch('/api/organizations/'+id+'/usage',h)).json();
|
||||
const rawU=JSON.stringify(u).slice(0,400);
|
||||
window.chrome.webview.postMessage({email:e,orgId:id,usage:u,debug:'src:'+orgSrc+'|ukeys:'+Object.keys(u||{}).join(',')+'|rawU:'+rawU+'|rawB:'+rawB});
|
||||
window.chrome.webview.postMessage({email:e,orgId:id,planLabel,usage:u,debug:'src:'+orgSrc+'|plan:'+(planLabel||'none')});
|
||||
}catch(ex){window.chrome.webview.postMessage({error:String(ex)});}})()";
|
||||
|
||||
await Browser.CoreWebView2.ExecuteScriptAsync(script);
|
||||
@@ -123,6 +124,10 @@ public partial class LoginWindow : Window
|
||||
if (root.TryGetProperty("usage", out var us) && us.ValueKind == JsonValueKind.Object)
|
||||
AppSettings.Default.UsageJson = us.GetRawText();
|
||||
|
||||
if (root.TryGetProperty("planLabel", out var pl) && pl.ValueKind == JsonValueKind.String
|
||||
&& !string.IsNullOrEmpty(pl.GetString()))
|
||||
AppSettings.Default.PlanLabel = pl.GetString()!;
|
||||
|
||||
if (root.TryGetProperty("debug", out var dbg) && dbg.ValueKind == JsonValueKind.String)
|
||||
AppSettings.Default.DebugInfo = dbg.GetString() ?? "";
|
||||
else if (root.TryGetProperty("error", out var err))
|
||||
|
||||
@@ -220,10 +220,12 @@ public class UsageViewModel : INotifyPropertyChanged
|
||||
AppSettings.Default.Save();
|
||||
|
||||
var usageUrl = $"https://claude.ai/api/organizations/{orgId}/usage";
|
||||
var ut = http.GetAsync(usageUrl);
|
||||
var ot = FetchAsync<OverageSpendLimit>(http, $"https://claude.ai/api/organizations/{orgId}/overage_spend_limit");
|
||||
var pt = FetchAsync<PrepaidCredits>(http, $"https://claude.ai/api/organizations/{orgId}/prepaid/credits");
|
||||
await Task.WhenAll(ut, ot, pt);
|
||||
var ut = http.GetAsync(usageUrl);
|
||||
var ot = FetchAsync<OverageSpendLimit>(http, $"https://claude.ai/api/organizations/{orgId}/overage_spend_limit");
|
||||
var pt = FetchAsync<PrepaidCredits>(http, $"https://claude.ai/api/organizations/{orgId}/prepaid/credits");
|
||||
// Fetch org details as a fallback source for capabilities (bootstrap omits them via HttpClient)
|
||||
var odt = http.GetAsync($"https://claude.ai/api/organizations/{orgId}");
|
||||
await Task.WhenAll(ut, ot, pt, odt);
|
||||
|
||||
var usageResp = ut.Result;
|
||||
if (!usageResp.IsSuccessStatusCode)
|
||||
@@ -232,6 +234,32 @@ public class UsageViewModel : INotifyPropertyChanged
|
||||
var usageJson = await usageResp.Content.ReadAsStringAsync();
|
||||
var usage = JsonSerializer.Deserialize<UsageResponse>(usageJson, JsonOpts);
|
||||
|
||||
// Try org endpoint for capabilities if bootstrap didn't return them
|
||||
if (string.IsNullOrEmpty(planLabel) && odt.Result.IsSuccessStatusCode)
|
||||
{
|
||||
try
|
||||
{
|
||||
var orgJson = await odt.Result.Content.ReadAsStringAsync();
|
||||
using var orgDoc = JsonDocument.Parse(orgJson);
|
||||
if (orgDoc.RootElement.TryGetProperty("capabilities", out var orgCaps) &&
|
||||
orgCaps.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
foreach (var cap in orgCaps.EnumerateArray())
|
||||
{
|
||||
var s = cap.GetString() ?? "";
|
||||
if (s.StartsWith("claude_", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var name = s.Substring("claude_".Length);
|
||||
if (name.Length > 0)
|
||||
planLabel = char.ToUpper(name[0]) + name.Substring(1).ToLower();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { /* best-effort */ }
|
||||
}
|
||||
|
||||
// Persist fresh usage so cache reflects live data
|
||||
AppSettings.Default.UsageJson = usageJson;
|
||||
if (!string.IsNullOrEmpty(planLabel)) AppSettings.Default.PlanLabel = planLabel;
|
||||
|
||||
Reference in New Issue
Block a user