clauddy 1.14.0 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/auth.js +27 -2
- package/main.js +15 -4
- package/package.json +1 -1
- package/renderer/index.html +2 -0
- package/renderer/pet.js +22 -0
- package/renderer/style.css +2 -1
package/auth.js
CHANGED
|
@@ -152,6 +152,32 @@ function win(o) {
|
|
|
152
152
|
: null
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
// Weekly limits scoped to one model (e.g. "Fable" on Max) live in the `limits`
|
|
156
|
+
// array. The older seven_day_<model> windows are kept as a fallback for plans
|
|
157
|
+
// that still report them that way.
|
|
158
|
+
function scopedWeeks(j) {
|
|
159
|
+
const out = []
|
|
160
|
+
for (const l of Array.isArray(j.limits) ? j.limits : []) {
|
|
161
|
+
if (l?.kind !== 'weekly_scoped' || typeof l.percent !== 'number') continue
|
|
162
|
+
const label = l.scope?.model?.display_name
|
|
163
|
+
if (!label) continue
|
|
164
|
+
out.push({
|
|
165
|
+
label,
|
|
166
|
+
pct: l.percent,
|
|
167
|
+
resetMs: l.resets_at ? Date.parse(l.resets_at) - Date.now() : null,
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
if (out.length) return out
|
|
171
|
+
for (const [key, label] of [
|
|
172
|
+
['seven_day_opus', 'Opus'],
|
|
173
|
+
['seven_day_sonnet', 'Sonnet'],
|
|
174
|
+
]) {
|
|
175
|
+
const w = win(j[key])
|
|
176
|
+
if (w) out.push({ label, ...w })
|
|
177
|
+
}
|
|
178
|
+
return out
|
|
179
|
+
}
|
|
180
|
+
|
|
155
181
|
// Step 3: fetch the authoritative usage
|
|
156
182
|
async function fetchUsage() {
|
|
157
183
|
const token = await validToken()
|
|
@@ -173,8 +199,7 @@ async function fetchUsage() {
|
|
|
173
199
|
return {
|
|
174
200
|
session: win(j.five_hour) || { pct: 0, resetMs: null },
|
|
175
201
|
week: win(j.seven_day) || { pct: 0, resetMs: null },
|
|
176
|
-
|
|
177
|
-
opus: win(j.seven_day_opus),
|
|
202
|
+
scoped: scopedWeeks(j),
|
|
178
203
|
}
|
|
179
204
|
}
|
|
180
205
|
|
package/main.js
CHANGED
|
@@ -95,12 +95,22 @@ function loadConfig() {
|
|
|
95
95
|
// native notification when usage crosses a threshold
|
|
96
96
|
const armed = new Set()
|
|
97
97
|
function checkAlerts(config, d) {
|
|
98
|
-
|
|
99
|
-
const ths = config.alertThresholds || [80, 95]
|
|
100
|
-
const scopes = [
|
|
98
|
+
alertScopes(config, [
|
|
101
99
|
['session', d.session.pct],
|
|
102
100
|
['weekly usage', d.week.pct],
|
|
103
|
-
]
|
|
101
|
+
])
|
|
102
|
+
}
|
|
103
|
+
// per-model weekly limits only exist on the account side, so they're checked
|
|
104
|
+
// off the OAuth poll rather than the local tick
|
|
105
|
+
function checkScopedAlerts(config, u) {
|
|
106
|
+
alertScopes(
|
|
107
|
+
config,
|
|
108
|
+
(u?.scoped || []).map((s) => [`${s.label} weekly usage`, s.pct]),
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
function alertScopes(config, scopes) {
|
|
112
|
+
if (!config.alerts || !Notification.isSupported()) return
|
|
113
|
+
const ths = config.alertThresholds || [80, 95]
|
|
104
114
|
for (const [name, pct] of scopes) {
|
|
105
115
|
for (const t of ths) {
|
|
106
116
|
const key = `${name}:${t}`
|
|
@@ -361,6 +371,7 @@ function updateTray() {
|
|
|
361
371
|
function pushRealUsage(u) {
|
|
362
372
|
sessionPct = u?.session ? u.session.pct : null
|
|
363
373
|
updateTray()
|
|
374
|
+
checkScopedAlerts(config, u)
|
|
364
375
|
if (win && !win.isDestroyed()) win.webContents.send('real-usage', u)
|
|
365
376
|
}
|
|
366
377
|
|
package/package.json
CHANGED
package/renderer/index.html
CHANGED
|
@@ -253,6 +253,8 @@
|
|
|
253
253
|
<div class="track"><div class="fill week" id="week-fill"></div></div>
|
|
254
254
|
<div class="sub" id="week-sub">—</div>
|
|
255
255
|
</div>
|
|
256
|
+
<!-- per-model weekly limits (e.g. Fable), one meter each -->
|
|
257
|
+
<div id="scoped-meters"></div>
|
|
256
258
|
</div>
|
|
257
259
|
<button id="limits-connect">
|
|
258
260
|
<svg class="lc-ico" viewBox="0 0 24 24" aria-hidden="true">
|
package/renderer/pet.js
CHANGED
|
@@ -404,6 +404,27 @@ function fitNames(box) {
|
|
|
404
404
|
box.style.setProperty('--name-w', `${w}px`)
|
|
405
405
|
}
|
|
406
406
|
|
|
407
|
+
// per-model weekly limits (e.g. "Fable" on Max) — one meter each, in the same
|
|
408
|
+
// shape as the all-models one. The token count pairs the limit with the local
|
|
409
|
+
// log totals for that model family (a "Fable" limit covers every Fable row).
|
|
410
|
+
function renderScoped(list, byModel) {
|
|
411
|
+
const box = el('scoped-meters')
|
|
412
|
+
box.innerHTML = ''
|
|
413
|
+
for (const s of list) {
|
|
414
|
+
const key = s.label.toLowerCase()
|
|
415
|
+
const tokens = byModel
|
|
416
|
+
.filter((m) => m.label.toLowerCase().startsWith(key))
|
|
417
|
+
.reduce((n, m) => n + m.tokens, 0)
|
|
418
|
+
const m = document.createElement('div')
|
|
419
|
+
m.className = 'meter'
|
|
420
|
+
m.innerHTML =
|
|
421
|
+
`<div class="meter-top"><span>weekly · ${esc(key)}</span><span>${Math.round(s.pct)}%</span></div>` +
|
|
422
|
+
`<div class="track"><div class="fill week${s.pct >= 80 ? ' high' : ''}" style="width:${s.pct}%"></div></div>` +
|
|
423
|
+
`<div class="sub">${s.resetMs != null ? `resets in ${fmtReset(s.resetMs)} · ` : ''}${fmtTokens(tokens)} tokens</div>`
|
|
424
|
+
box.appendChild(m)
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
407
428
|
// by model (7 days)
|
|
408
429
|
function renderModels(list) {
|
|
409
430
|
renderBars('bymodel-list', list, 4)
|
|
@@ -571,6 +592,7 @@ function render(d) {
|
|
|
571
592
|
? `resets in ${fmtReset(wkReset)} · ${fmtTokens(d.week.tokens)} tokens`
|
|
572
593
|
: `${fmtTokens(d.week.tokens)} tokens · last 7 days`
|
|
573
594
|
|
|
595
|
+
renderScoped(liveOn ? realUsage.scoped || [] : [], d.byModel || [])
|
|
574
596
|
renderModels(d.byModel || [])
|
|
575
597
|
renderProjects(d.byProject || [])
|
|
576
598
|
renderHeat(d.days30 || [])
|