@zhafron/opencode-kiro-auth 1.4.0 → 1.4.2

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.
@@ -51,13 +51,13 @@ export class AccountManager {
51
51
  getAccounts() {
52
52
  return [...this.accounts];
53
53
  }
54
- shouldShowToast(debounce = 30000) {
54
+ shouldShowToast(debounce = 10000) {
55
55
  if (Date.now() - this.lastToastTime < debounce)
56
56
  return false;
57
57
  this.lastToastTime = Date.now();
58
58
  return true;
59
59
  }
60
- shouldShowUsageToast(debounce = 30000) {
60
+ shouldShowUsageToast(debounce = 10000) {
61
61
  if (Date.now() - this.lastUsageToastTime < debounce)
62
62
  return false;
63
63
  this.lastUsageToastTime = Date.now();
@@ -72,7 +72,7 @@ export class AccountManager {
72
72
  const now = Date.now();
73
73
  const available = this.accounts.filter((a) => {
74
74
  if (!a.isHealthy) {
75
- if (a.failCount < 3 && a.recoveryTime && now >= a.recoveryTime) {
75
+ if (a.failCount < 10 && a.recoveryTime && now >= a.recoveryTime) {
76
76
  a.isHealthy = true;
77
77
  delete a.unhealthyReason;
78
78
  delete a.recoveryTime;
@@ -97,7 +97,7 @@ export class AccountManager {
97
97
  }
98
98
  if (!selected) {
99
99
  const fallback = this.accounts
100
- .filter((a) => !a.isHealthy && a.failCount < 3)
100
+ .filter((a) => !a.isHealthy && a.failCount < 10)
101
101
  .sort((a, b) => (a.usedCount || 0) - (b.usedCount || 0) || (a.lastUsed || 0) - (b.lastUsed || 0))[0];
102
102
  if (fallback) {
103
103
  fallback.isHealthy = true;
@@ -175,10 +175,13 @@ export class AccountManager {
175
175
  markUnhealthy(a, reason, recovery) {
176
176
  const acc = this.accounts.find((x) => x.id === a.id);
177
177
  if (acc) {
178
- acc.isHealthy = false;
179
- acc.unhealthyReason = reason;
180
178
  acc.failCount = (acc.failCount || 0) + 1;
181
- acc.recoveryTime = acc.failCount >= 3 ? undefined : recovery || Date.now() + 3600000;
179
+ acc.unhealthyReason = reason;
180
+ acc.lastUsed = Date.now();
181
+ if (acc.failCount >= 10) {
182
+ acc.isHealthy = false;
183
+ acc.recoveryTime = recovery || Date.now() + 3600000;
184
+ }
182
185
  kiroDb.upsertAccount(acc);
183
186
  }
184
187
  }
package/dist/plugin.js CHANGED
@@ -11,6 +11,7 @@ import { transformToCodeWhisperer } from './plugin/request';
11
11
  import { parseEventStream } from './plugin/response';
12
12
  import { startIDCAuthServer } from './plugin/server';
13
13
  import { migrateJsonToSqlite } from './plugin/storage/migration';
14
+ import { kiroDb } from './plugin/storage/sqlite';
14
15
  import { transformKiroStream } from './plugin/streaming';
15
16
  import { syncFromKiroCli } from './plugin/sync/kiro-cli';
16
17
  import { refreshAccessToken } from './plugin/token';
@@ -103,7 +104,7 @@ export const createKiroPlugin = (id) => async ({ client, directory }) => {
103
104
  }
104
105
  throw new Error('All accounts are unhealthy or rate-limited');
105
106
  }
106
- if (count > 1 && am.shouldShowToast())
107
+ if (am.shouldShowToast())
107
108
  showToast(`Using ${acc.email} (${am.getAccounts().indexOf(acc) + 1}/${count})`, 'info');
108
109
  if (am.shouldShowUsageToast() &&
109
110
  acc.usedCount !== undefined &&
@@ -176,6 +177,10 @@ export const createKiroPlugin = (id) => async ({ client, directory }) => {
176
177
  }, apiTimestamp);
177
178
  }
178
179
  if (res.ok) {
180
+ if (acc.failCount && acc.failCount > 0) {
181
+ acc.failCount = 0;
182
+ kiroDb.upsertAccount(acc);
183
+ }
179
184
  if (config.usage_tracking_enabled) {
180
185
  const sync = async (att = 0) => {
181
186
  try {
@@ -261,9 +266,35 @@ export const createKiroPlugin = (id) => async ({ client, directory }) => {
261
266
  continue;
262
267
  }
263
268
  if ((res.status === 402 || res.status === 403) && count > 1) {
264
- am.markUnhealthy(acc, res.status === 402 ? 'Quota' : 'Forbidden');
265
- await am.saveToDisk();
266
- continue;
269
+ let errorReason = res.status === 402 ? 'Quota' : 'Forbidden';
270
+ let isPermanent = false;
271
+ let shouldSkipAccount = false;
272
+ try {
273
+ const errorBody = await res.text();
274
+ const errorData = JSON.parse(errorBody);
275
+ if (errorData.reason === 'TEMPORARILY_SUSPENDED') {
276
+ errorReason = 'Account Suspended';
277
+ isPermanent = true;
278
+ shouldSkipAccount = true;
279
+ }
280
+ else if (errorData.reason === 'INVALID_MODEL_ID') {
281
+ logger.warn(`Invalid model ID for ${acc.email}: ${errorData.message}`);
282
+ throw new Error(`Invalid model: ${errorData.message}`);
283
+ }
284
+ }
285
+ catch (e) {
286
+ if (e instanceof Error && e.message.includes('Invalid model')) {
287
+ throw e;
288
+ }
289
+ }
290
+ if (shouldSkipAccount) {
291
+ if (isPermanent) {
292
+ acc.failCount = 10;
293
+ }
294
+ am.markUnhealthy(acc, errorReason);
295
+ await am.saveToDisk();
296
+ continue;
297
+ }
267
298
  }
268
299
  const h = {};
269
300
  res.headers.forEach((v, k) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhafron/opencode-kiro-auth",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "OpenCode plugin for AWS Kiro (CodeWhisperer) providing access to Claude models",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",