@hienlh/ppm 0.8.46 → 0.8.48

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/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.48] - 2026-03-25
4
+
5
+ ### Fixed
6
+ - **Account auth errors**: Use cooldown instead of permanent disable on `authentication_failed` / 401 — auth issues can be transient (subscription lapse, org changes, API hiccups)
7
+ - **SDK refresh safety**: Pass `disableOnFail=false` in SDK error handlers — prevents `refreshAccessToken` from disabling accounts as side effect during auto-retry
8
+
9
+ ## [0.8.47] - 2026-03-25
10
+
11
+ ### Fixed
12
+ - **Usage polling**: Use `ensureFreshToken()` in background usage poll — prevents 401 from expired tokens causing auto-fetch to always fail
13
+ - **Temp accounts**: Don't auto-disable temporary accounts (no refresh token) when token expires — they now expire naturally and get cleaned up after 7 days
14
+ - **Account export**: `refreshBeforeExport` no longer disables accounts as a side effect on refresh failure
15
+
3
16
  ## [0.8.46] - 2026-03-25
4
17
 
5
18
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hienlh/ppm",
3
- "version": "0.8.46",
3
+ "version": "0.8.48",
4
4
  "description": "Personal Project Manager — mobile-first web IDE with AI assistance",
5
5
  "author": "hienlh",
6
6
  "license": "MIT",
@@ -611,7 +611,7 @@ export class ClaudeAgentSdkProvider implements AIProvider {
611
611
  if (assistantError === "authentication_failed" && account && !authRetried) {
612
612
  authRetried = true;
613
613
  try {
614
- await accountService.refreshAccessToken(account.id);
614
+ await accountService.refreshAccessToken(account.id, false);
615
615
  console.log(`[sdk] session=${sessionId} OAuth token refreshed for ${account.id} — retrying`);
616
616
  // Re-build env with refreshed token
617
617
  const refreshedAccount = accountService.getWithTokens(account.id);
@@ -628,7 +628,9 @@ export class ClaudeAgentSdkProvider implements AIProvider {
628
628
  }
629
629
  } catch (refreshErr) {
630
630
  console.error(`[sdk] session=${sessionId} OAuth refresh failed:`, refreshErr);
631
- accountSelector.onAuthError(account.id);
631
+ // Cooldown instead of permanent disable — auth issues can be transient
632
+ // (subscription lapse, org changes, API hiccups)
633
+ accountSelector.onRateLimit(account.id);
632
634
  }
633
635
  }
634
636
 
@@ -699,10 +701,11 @@ export class ClaudeAgentSdkProvider implements AIProvider {
699
701
  } else if (errCode === 401) {
700
702
  // Try refresh once
701
703
  try {
702
- await accountService.refreshAccessToken(account.id);
704
+ await accountService.refreshAccessToken(account.id, false);
703
705
  console.log(`[sdk] 401 on account ${account.id} — token refreshed`);
704
706
  } catch {
705
- accountSelector.onAuthError(account.id);
707
+ // Cooldown instead of permanent disable — auth issues can be transient
708
+ accountSelector.onRateLimit(account.id);
706
709
  }
707
710
  } else {
708
711
  accountSelector.onSuccess(account.id);
@@ -571,7 +571,7 @@ class AccountService {
571
571
  if (!acc.accessToken.startsWith("sk-ant-oat")) continue;
572
572
  if (!acc.expiresAt) continue;
573
573
  try {
574
- await this.refreshAccessToken(acc.id);
574
+ await this.refreshAccessToken(acc.id, false);
575
575
  } catch {
576
576
  // Best-effort — skip accounts whose refresh token is already invalid
577
577
  }
@@ -174,7 +174,8 @@ async function fetchAllAccountUsages(): Promise<void> {
174
174
  if (acc.status === "disabled") continue;
175
175
  // Skip expired temporary accounts (no refresh token)
176
176
  if (!accountService.hasRefreshToken(acc.id) && acc.expiresAt && acc.expiresAt < nowS) continue;
177
- const withTokens = accountService.getWithTokens(acc.id);
177
+ // Ensure token is fresh before calling usage API (prevents 401 from expired tokens)
178
+ const withTokens = await accountService.ensureFreshToken(acc.id);
178
179
  if (!withTokens) continue;
179
180
  const token = withTokens.accessToken;
180
181
  // Only OAuth tokens have usage endpoint