clauddy 1.22.0 → 1.23.1

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/README.md CHANGED
@@ -56,19 +56,19 @@ It only appears once there's enough to say honestly — roughly 5 minutes into a
56
56
 
57
57
  <table>
58
58
  <tr>
59
- <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/main/docs/media/idle.gif" width="280" alt="idle" /><br /><b>idle</b><br /><sub>breathes &amp; blinks</sub></td>
60
- <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/main/docs/media/working.gif" width="280" alt="working" /><br /><b>working</b><br /><sub>hops &amp; eats token coins</sub></td>
59
+ <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/a8491cea34c4a8547965eadc3b24618ba50218e1/docs/media/idle.gif" width="280" alt="idle" /><br /><b>idle</b><br /><sub>breathes &amp; blinks</sub></td>
60
+ <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/a8491cea34c4a8547965eadc3b24618ba50218e1/docs/media/working.gif" width="280" alt="working" /><br /><b>working</b><br /><sub>hops &amp; eats token coins</sub></td>
61
61
  </tr>
62
62
  <tr>
63
- <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/main/docs/media/on-fire.gif" width="280" alt="on fire" /><br /><b>on fire</b><br /><sub>session ≥ 90% → red, shivers, flames</sub></td>
64
- <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/main/docs/media/tired.gif" width="280" alt="maxed out" /><br /><b>maxed out</b><br /><sub>session at 100% → drained, slumped, sweating</sub></td>
63
+ <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/a8491cea34c4a8547965eadc3b24618ba50218e1/docs/media/on-fire.gif" width="280" alt="on fire" /><br /><b>on fire</b><br /><sub>session ≥ 90% → red, shivers, flames</sub></td>
64
+ <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/a8491cea34c4a8547965eadc3b24618ba50218e1/docs/media/tired.gif" width="280" alt="maxed out" /><br /><b>maxed out</b><br /><sub>session at 100% → drained, slumped, sweating</sub></td>
65
65
  </tr>
66
66
  <tr>
67
- <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/main/docs/media/sleeping.gif" width="280" alt="sleeping" /><br /><b>sleeping</b><br /><sub>idle 5+ min → blue zzz &amp; moonlight</sub></td>
68
- <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/main/docs/media/poke.gif" width="280" alt="poke" /><br /><b>poke</b><br /><sub>click the pet → squish &amp; hearts</sub></td>
67
+ <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/a8491cea34c4a8547965eadc3b24618ba50218e1/docs/media/sleeping.gif" width="280" alt="sleeping" /><br /><b>sleeping</b><br /><sub>idle 5+ min → blue zzz &amp; moonlight</sub></td>
68
+ <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/a8491cea34c4a8547965eadc3b24618ba50218e1/docs/media/poke.gif" width="280" alt="poke" /><br /><b>poke</b><br /><sub>click the pet → squish &amp; hearts</sub></td>
69
69
  </tr>
70
70
  <tr>
71
- <td colspan="2" align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/main/docs/media/celebrate.gif" width="280" alt="celebrate" /><br /><b>celebrate</b><br /><sub>session resets → jump &amp; confetti</sub></td>
71
+ <td colspan="2" align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/a8491cea34c4a8547965eadc3b24618ba50218e1/docs/media/celebrate.gif" width="280" alt="celebrate" /><br /><b>celebrate</b><br /><sub>session resets → jump &amp; confetti</sub></td>
72
72
  </tr>
73
73
  </table>
74
74
 
@@ -83,11 +83,11 @@ own animated scene:
83
83
 
84
84
  <table>
85
85
  <tr>
86
- <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/main/docs/media/reading.gif" width="280" alt="reading" /><br /><b>reading</b><br /><sub>puts on glasses &amp; flips through docs</sub></td>
87
- <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/main/docs/media/editing.gif" width="280" alt="editing" /><br /><b>editing</b><br /><sub>types at the laptop, coffee in reach</sub></td>
86
+ <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/a8491cea34c4a8547965eadc3b24618ba50218e1/docs/media/reading.gif" width="280" alt="reading" /><br /><b>reading</b><br /><sub>an open book under the reading lamp</sub></td>
87
+ <td align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/a8491cea34c4a8547965eadc3b24618ba50218e1/docs/media/editing.gif" width="280" alt="editing" /><br /><b>editing</b><br /><sub>types at the desk, coffee in reach</sub></td>
88
88
  </tr>
89
89
  <tr>
90
- <td colspan="2" align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/main/docs/media/running.gif" width="280" alt="running" /><br /><b>running</b><br /><sub>watches a task log tick through its checks</sub></td>
90
+ <td colspan="2" align="center"><img src="https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/a8491cea34c4a8547965eadc3b24618ba50218e1/docs/media/running.gif" width="280" alt="running" /><br /><b>running</b><br /><sub>watches a task log tick through its checks</sub></td>
91
91
  </tr>
92
92
  </table>
93
93
 
package/auth.js CHANGED
@@ -139,7 +139,15 @@ async function complete(pasted) {
139
139
  pending = null
140
140
  }
141
141
 
142
- async function refresh() {
142
+ // Usage and profile both ask for a valid token at once. Two refreshes would
143
+ // rotate the refresh token twice, and the loser's grant comes back rejected —
144
+ // so callers share the one in flight.
145
+ let refreshing = null
146
+ function refresh() {
147
+ if (!refreshing) refreshing = doRefresh().finally(() => (refreshing = null))
148
+ return refreshing
149
+ }
150
+ async function doRefresh() {
143
151
  const t = load()
144
152
  if (!t?.refresh_token) throw Object.assign(new Error('no refresh token'), { status: 401 })
145
153
  const res = await fetch(TOKEN_URL, {
package/main.js CHANGED
@@ -273,6 +273,7 @@ function switchAccount(id) {
273
273
  win.webContents.send('auth-state', { connected: auth.isConnected() })
274
274
  win.webContents.send('profile', null)
275
275
  }
276
+ profileShown = false
276
277
  sendAccounts(id) // the row goes pending right away…
277
278
 
278
279
  // …because the rest is synchronous and slow: re-reading the new account's
@@ -684,6 +685,13 @@ async function pollUsage() {
684
685
  usageBackoff = 5 * 60 * 1000
685
686
  authFails = 0
686
687
  pushRealUsage(u)
688
+ // a token that came back after being cleared (a refresh that landed late)
689
+ // brings the % back, but nothing re-sent the chip: restate who this is
690
+ if (!profileShown) {
691
+ if (win && !win.isDestroyed()) win.webContents.send('auth-state', { connected: true })
692
+ sendAccounts()
693
+ sendProfile()
694
+ }
687
695
  } catch (e) {
688
696
  if (e && e.status === 429) {
689
697
  usageBackoff = Math.min(usageBackoff * 2, 30 * 60 * 1000)
@@ -705,6 +713,7 @@ async function pollUsage() {
705
713
  win.webContents.send('auth-state', { connected: false })
706
714
  win.webContents.send('profile', null)
707
715
  }
716
+ profileShown = false
708
717
  }
709
718
  }
710
719
  scheduleUsagePoll()
@@ -729,6 +738,7 @@ function onResume() {
729
738
 
730
739
  // push the logged-in account's identity (email + plan) to the renderer
731
740
  let profileTimer = null
741
+ let profileShown = false // the renderer holds this account's profile
732
742
  async function sendProfile(tries = 0) {
733
743
  clearTimeout(profileTimer)
734
744
  if (!auth.isConnected()) return
@@ -743,6 +753,7 @@ async function sendProfile(tries = 0) {
743
753
  sendAccounts()
744
754
  }
745
755
  if (win && !win.isDestroyed()) win.webContents.send('profile', p)
756
+ profileShown = true
746
757
  } catch {
747
758
  // a rate limit or a blip would otherwise hide the chip — and with it the
748
759
  // account switcher — until the app is restarted, so keep trying for a while
@@ -804,6 +815,7 @@ ipcMain.on('auth-logout', () => {
804
815
  win.webContents.send('auth-state', { connected: false })
805
816
  win.webContents.send('profile', null)
806
817
  }
818
+ profileShown = false
807
819
  })
808
820
 
809
821
  ipcMain.on('save-config', (_e, patch) => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "clauddy",
3
3
  "desktopName": "clauddy.desktop",
4
- "version": "1.22.0",
4
+ "version": "1.23.1",
5
5
  "description": "A cute desktop pet that tracks your Claude Code usage",
6
6
  "main": "main.js",
7
7
  "bin": {