@sunerpy/opencode-kiro-auth 0.8.0 → 0.9.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/README.md CHANGED
@@ -108,6 +108,10 @@ multi-account or long-idle setups, enable
108
108
  (`token_keepalive_enabled: true`) to keep idle accounts' tokens fresh while
109
109
  OpenCode is running.
110
110
 
111
+ Paid-overage protection is on by default; see
112
+ [Overage protection](docs/CONFIGURATION.md#overage-protection) before disabling
113
+ `stop_on_overage`.
114
+
111
115
  ## Multiple accounts & rotation
112
116
 
113
117
  You can register more than one Kiro account and let the plugin spread
@@ -26,6 +26,9 @@ export class AccountSelector {
26
26
  let acc = this.accountManager.getCurrentOrNext();
27
27
  if (!acc) {
28
28
  this.circuitBreakerTrips++;
29
+ if (this.accountManager.allSelectableBlockedByOverage()) {
30
+ throw new Error('All accounts have exceeded their free quota and entered paid overage. Set "stop_on_overage": false in ~/.config/opencode/kiro.json to continue with paid overage, or wait for the quota to reset.');
31
+ }
29
32
  const wait = this.accountManager.getMinWaitTime();
30
33
  if (wait > 0 && wait < 30000) {
31
34
  if (this.accountManager.shouldShowToast()) {
@@ -10,24 +10,33 @@ export declare class AccountManager {
10
10
  private stickyId?;
11
11
  private quotaAvoidanceEnabled;
12
12
  private quotaReserveThreshold;
13
+ private stopOnOverage;
14
+ private overageThreshold;
13
15
  constructor(accounts: ManagedAccount[], strategy?: AccountSelectionStrategy, opts?: {
14
16
  quotaAvoidanceEnabled?: boolean;
15
17
  quotaReserveThreshold?: number;
18
+ stopOnOverage?: boolean;
19
+ overageThreshold?: number;
16
20
  });
17
21
  static loadFromDisk(strategy?: AccountSelectionStrategy, opts?: {
18
22
  quotaAvoidanceEnabled?: boolean;
19
23
  quotaReserveThreshold?: number;
24
+ stopOnOverage?: boolean;
25
+ overageThreshold?: number;
20
26
  }): Promise<AccountManager>;
21
27
  getAccountCount(): number;
22
28
  getAccounts(): ManagedAccount[];
23
29
  shouldShowToast(debounce?: number): boolean;
24
30
  shouldShowUsageToast(debounce?: number): boolean;
25
31
  getMinWaitTime(): number;
32
+ allSelectableBlockedByOverage(): boolean;
26
33
  getCurrentOrNext(): ManagedAccount | null;
27
34
  updateUsage(id: string, meta: {
28
35
  usedCount: number;
29
36
  limitCount: number;
37
+ overageCount?: number;
30
38
  email?: string;
39
+ lastSync?: number;
31
40
  }): void;
32
41
  addAccount(a: ManagedAccount): void;
33
42
  removeAccount(a: ManagedAccount): void;
@@ -36,4 +45,5 @@ export declare class AccountManager {
36
45
  markUnhealthy(a: ManagedAccount, reason: string, recovery?: number): void;
37
46
  saveToDisk(): Promise<void>;
38
47
  toAuthDetails(a: ManagedAccount): KiroAuthDetails;
48
+ private isOverageBlocked;
39
49
  }
@@ -19,12 +19,16 @@ export class AccountManager {
19
19
  stickyId;
20
20
  quotaAvoidanceEnabled;
21
21
  quotaReserveThreshold;
22
+ stopOnOverage;
23
+ overageThreshold;
22
24
  constructor(accounts, strategy = 'sticky', opts) {
23
25
  this.accounts = accounts;
24
26
  this.cursor = 0;
25
27
  this.strategy = strategy;
26
28
  this.quotaAvoidanceEnabled = opts?.quotaAvoidanceEnabled ?? true;
27
29
  this.quotaReserveThreshold = opts?.quotaReserveThreshold ?? 0.95;
30
+ this.stopOnOverage = opts?.stopOnOverage ?? true;
31
+ this.overageThreshold = opts?.overageThreshold ?? 0;
28
32
  }
29
33
  static async loadFromDisk(strategy, opts) {
30
34
  const rows = kiroDb.getAccounts();
@@ -48,7 +52,9 @@ export class AccountManager {
48
52
  failCount: r.fail_count || 0,
49
53
  lastUsed: r.last_used,
50
54
  usedCount: r.used_count,
51
- limitCount: r.limit_count
55
+ limitCount: r.limit_count,
56
+ overageCount: r.overage_count || 0,
57
+ lastSync: r.last_sync
52
58
  }));
53
59
  return new AccountManager(accounts, strategy || 'sticky', opts);
54
60
  }
@@ -75,9 +81,31 @@ export class AccountManager {
75
81
  const waits = this.accounts.map((a) => (a.rateLimitResetTime || 0) - now).filter((t) => t > 0);
76
82
  return waits.length > 0 ? Math.min(...waits) : 0;
77
83
  }
84
+ allSelectableBlockedByOverage() {
85
+ if (!this.stopOnOverage)
86
+ return false;
87
+ const now = Date.now();
88
+ const healthEligible = (a) => {
89
+ if (isPermanentError(a.unhealthyReason))
90
+ return false;
91
+ if (a.isHealthy)
92
+ return true;
93
+ if (isAccessTokenError(a.unhealthyReason))
94
+ return true;
95
+ return a.failCount < 10;
96
+ };
97
+ const rateLimited = (a) => !!(a.rateLimitResetTime && now < a.rateLimitResetTime);
98
+ const hasOverageBlockedEligible = this.accounts.some((a) => healthEligible(a) && this.isOverageBlocked(a));
99
+ const hasCleanRateLimited = this.accounts.some((a) => healthEligible(a) && rateLimited(a) && !this.isOverageBlocked(a));
100
+ const hasHealthySelectable = this.accounts.some((a) => a.isHealthy && !rateLimited(a) && !this.isOverageBlocked(a));
101
+ return hasOverageBlockedEligible && !hasCleanRateLimited && !hasHealthySelectable;
102
+ }
78
103
  getCurrentOrNext() {
79
104
  const now = Date.now();
105
+ const overageBlocked = (a) => this.isOverageBlocked(a);
80
106
  const available = this.accounts.filter((a) => {
107
+ if (overageBlocked(a))
108
+ return false;
81
109
  if (!a.isHealthy) {
82
110
  if (isPermanentError(a.unhealthyReason)) {
83
111
  return false;
@@ -129,7 +157,10 @@ export class AccountManager {
129
157
  }
130
158
  if (!selected) {
131
159
  const fallback = this.accounts
132
- .filter((a) => !a.isHealthy && a.failCount < 10 && !isPermanentError(a.unhealthyReason))
160
+ .filter((a) => !a.isHealthy &&
161
+ a.failCount < 10 &&
162
+ !isPermanentError(a.unhealthyReason) &&
163
+ !overageBlocked(a))
133
164
  .sort((a, b) => (a.usedCount || 0) - (b.usedCount || 0) || (a.lastUsed || 0) - (b.lastUsed || 0))[0];
134
165
  if (fallback) {
135
166
  fallback.isHealthy = true;
@@ -139,6 +170,8 @@ export class AccountManager {
139
170
  }
140
171
  }
141
172
  if (selected) {
173
+ if (overageBlocked(selected))
174
+ return null;
142
175
  selected.lastUsed = now;
143
176
  selected.usedCount = (selected.usedCount || 0) + 1;
144
177
  return selected;
@@ -150,6 +183,8 @@ export class AccountManager {
150
183
  if (a) {
151
184
  a.usedCount = meta.usedCount;
152
185
  a.limitCount = meta.limitCount;
186
+ a.overageCount = meta.overageCount ?? 0;
187
+ a.lastSync = meta.lastSync ?? a.lastSync;
153
188
  if (meta.email)
154
189
  a.email = meta.email;
155
190
  if (!isPermanentError(a.unhealthyReason)) {
@@ -290,4 +325,7 @@ export class AccountManager {
290
325
  email: a.email
291
326
  };
292
327
  }
328
+ isOverageBlocked(a) {
329
+ return this.stopOnOverage && (a.overageCount ?? 0) > this.overageThreshold;
330
+ }
293
331
  }
@@ -32,6 +32,15 @@ export declare const KiroConfigSchema: z.ZodObject<{
32
32
  * near-full and softly avoided. Default 0.95 (95%).
33
33
  */
34
34
  quota_reserve_threshold: z.ZodDefault<z.ZodNumber>;
35
+ /**
36
+ * Exclude accounts that have entered AWS paid overage from selection.
37
+ */
38
+ stop_on_overage: z.ZodDefault<z.ZodBoolean>;
39
+ /**
40
+ * Paid-overage invocations tolerated before stopping an account. 0 means
41
+ * stop on any overage.
42
+ */
43
+ overage_threshold: z.ZodDefault<z.ZodNumber>;
35
44
  default_region: z.ZodDefault<z.ZodEnum<["us-east-1", "us-east-2", "us-west-1", "us-west-2", "af-south-1", "ap-east-1", "ap-south-2", "ap-southeast-3", "ap-southeast-5", "ap-southeast-4", "ap-south-1", "ap-southeast-6", "ap-northeast-3", "ap-northeast-2", "ap-southeast-1", "ap-southeast-2", "ap-east-2", "ap-southeast-7", "ap-northeast-1", "ca-central-1", "ca-west-1", "eu-central-1", "eu-west-1", "eu-west-2", "eu-south-1", "eu-west-3", "eu-south-2", "eu-north-1", "eu-central-2", "il-central-1", "mx-central-1", "me-south-1", "me-central-1", "sa-east-1"]>>;
36
45
  rate_limit_retry_delay_ms: z.ZodDefault<z.ZodNumber>;
37
46
  rate_limit_max_retries: z.ZodDefault<z.ZodNumber>;
@@ -77,6 +86,8 @@ export declare const KiroConfigSchema: z.ZodObject<{
77
86
  account_selection_strategy: "sticky" | "round-robin" | "lowest-usage";
78
87
  quota_avoidance_enabled: boolean;
79
88
  quota_reserve_threshold: number;
89
+ stop_on_overage: boolean;
90
+ overage_threshold: number;
80
91
  default_region: "us-east-1" | "us-east-2" | "us-west-1" | "us-west-2" | "af-south-1" | "ap-east-1" | "ap-south-2" | "ap-southeast-3" | "ap-southeast-5" | "ap-southeast-4" | "ap-south-1" | "ap-southeast-6" | "ap-northeast-3" | "ap-northeast-2" | "ap-southeast-1" | "ap-southeast-2" | "ap-east-2" | "ap-southeast-7" | "ap-northeast-1" | "ca-central-1" | "ca-west-1" | "eu-central-1" | "eu-west-1" | "eu-west-2" | "eu-south-1" | "eu-west-3" | "eu-south-2" | "eu-north-1" | "eu-central-2" | "il-central-1" | "mx-central-1" | "me-south-1" | "me-central-1" | "sa-east-1";
81
92
  rate_limit_retry_delay_ms: number;
82
93
  rate_limit_max_retries: number;
@@ -106,6 +117,8 @@ export declare const KiroConfigSchema: z.ZodObject<{
106
117
  account_selection_strategy?: "sticky" | "round-robin" | "lowest-usage" | undefined;
107
118
  quota_avoidance_enabled?: boolean | undefined;
108
119
  quota_reserve_threshold?: number | undefined;
120
+ stop_on_overage?: boolean | undefined;
121
+ overage_threshold?: number | undefined;
109
122
  default_region?: "us-east-1" | "us-east-2" | "us-west-1" | "us-west-2" | "af-south-1" | "ap-east-1" | "ap-south-2" | "ap-southeast-3" | "ap-southeast-5" | "ap-southeast-4" | "ap-south-1" | "ap-southeast-6" | "ap-northeast-3" | "ap-northeast-2" | "ap-southeast-1" | "ap-southeast-2" | "ap-east-2" | "ap-southeast-7" | "ap-northeast-1" | "ca-central-1" | "ca-west-1" | "eu-central-1" | "eu-west-1" | "eu-west-2" | "eu-south-1" | "eu-west-3" | "eu-south-2" | "eu-north-1" | "eu-central-2" | "il-central-1" | "mx-central-1" | "me-south-1" | "me-central-1" | "sa-east-1" | undefined;
110
123
  rate_limit_retry_delay_ms?: number | undefined;
111
124
  rate_limit_max_retries?: number | undefined;
@@ -64,6 +64,15 @@ export const KiroConfigSchema = z.object({
64
64
  * near-full and softly avoided. Default 0.95 (95%).
65
65
  */
66
66
  quota_reserve_threshold: z.number().min(0).max(1).default(0.95),
67
+ /**
68
+ * Exclude accounts that have entered AWS paid overage from selection.
69
+ */
70
+ stop_on_overage: z.boolean().default(true),
71
+ /**
72
+ * Paid-overage invocations tolerated before stopping an account. 0 means
73
+ * stop on any overage.
74
+ */
75
+ overage_threshold: z.number().min(0).default(0),
67
76
  default_region: RegionSchema.default('us-east-1'),
68
77
  rate_limit_retry_delay_ms: z.number().min(1000).max(60000).default(5000),
69
78
  rate_limit_max_retries: z.number().min(0).max(10).default(3),
@@ -110,6 +119,8 @@ export const DEFAULT_CONFIG = {
110
119
  account_selection_strategy: 'lowest-usage',
111
120
  quota_avoidance_enabled: true,
112
121
  quota_reserve_threshold: 0.95,
122
+ stop_on_overage: true,
123
+ overage_threshold: 0,
113
124
  default_region: 'us-east-1',
114
125
  rate_limit_retry_delay_ms: 5000,
115
126
  rate_limit_max_retries: 3,
@@ -139,6 +139,7 @@ export function mergeAccounts(existing, incoming) {
139
139
  // in-memory token triple from another process must not clobber a newer
140
140
  // persisted token triple during this cross-process merge.
141
141
  const tokenWinner = (acc.expiresAt || 0) >= (existingAcc.expiresAt || 0) ? acc : existingAcc;
142
+ const usageWinner = (acc.lastSync || 0) >= (existingAcc.lastSync || 0) ? acc : existingAcc;
142
143
  accountMap.set(acc.id, {
143
144
  ...existingAcc,
144
145
  ...acc,
@@ -146,8 +147,9 @@ export function mergeAccounts(existing, incoming) {
146
147
  accessToken: tokenWinner.accessToken,
147
148
  expiresAt: tokenWinner.expiresAt,
148
149
  lastUsed: Math.max(existingAcc.lastUsed || 0, acc.lastUsed || 0),
149
- usedCount: Math.max(existingAcc.usedCount || 0, acc.usedCount || 0),
150
- limitCount: Math.max(existingAcc.limitCount || 0, acc.limitCount || 0),
150
+ usedCount: usageWinner.usedCount ?? 0,
151
+ limitCount: usageWinner.limitCount ?? 0,
152
+ overageCount: usageWinner.overageCount ?? 0,
151
153
  rateLimitResetTime: Math.max(existingAcc.rateLimitResetTime || 0, acc.rateLimitResetTime || 0),
152
154
  isHealthy: incomingRecovered
153
155
  ? true
@@ -6,6 +6,7 @@ export function runMigrations(db) {
6
6
  migrateOidcRegionColumn(db);
7
7
  migrateDropRefreshTokenUniqueIndex(db);
8
8
  migrateRemovedAccountsTable(db);
9
+ migrateOverageColumn(db);
9
10
  }
10
11
  function migrateToUniqueRefreshToken(db) {
11
12
  const hasIndex = db
@@ -159,3 +160,10 @@ function migrateRemovedAccountsTable(db) {
159
160
  // so kiro-cli auto-sync does not silently re-import them. Cleared only on deliberate login.
160
161
  db.exec('CREATE TABLE IF NOT EXISTS removed_accounts (id TEXT PRIMARY KEY, removed_at INTEGER NOT NULL)');
161
162
  }
163
+ function migrateOverageColumn(db) {
164
+ const columns = db.prepare('PRAGMA table_info(accounts)').all();
165
+ const names = new Set(columns.map((c) => c.name));
166
+ if (!names.has('overage_count')) {
167
+ db.exec('ALTER TABLE accounts ADD COLUMN overage_count INTEGER DEFAULT 0');
168
+ }
169
+ }
@@ -33,7 +33,8 @@ export class KiroDatabase {
33
33
  refresh_token TEXT NOT NULL, access_token TEXT NOT NULL, expires_at INTEGER NOT NULL,
34
34
  rate_limit_reset INTEGER DEFAULT 0, is_healthy INTEGER DEFAULT 1, unhealthy_reason TEXT,
35
35
  recovery_time INTEGER, fail_count INTEGER DEFAULT 0, last_used INTEGER DEFAULT 0,
36
- used_count INTEGER DEFAULT 0, limit_count INTEGER DEFAULT 0, last_sync INTEGER DEFAULT 0
36
+ used_count INTEGER DEFAULT 0, limit_count INTEGER DEFAULT 0,
37
+ overage_count INTEGER DEFAULT 0, last_sync INTEGER DEFAULT 0
37
38
  )
38
39
  `);
39
40
  runMigrations(this.db);
@@ -56,8 +57,8 @@ export class KiroDatabase {
56
57
  id, email, auth_method, region, oidc_region, client_id, client_secret,
57
58
  profile_arn, start_url, refresh_token, access_token, expires_at, rate_limit_reset,
58
59
  is_healthy, unhealthy_reason, recovery_time, fail_count, last_used,
59
- used_count, limit_count, last_sync
60
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
60
+ used_count, limit_count, overage_count, last_sync
61
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
61
62
  ON CONFLICT(id) DO UPDATE SET
62
63
  id=excluded.id, email=excluded.email, auth_method=excluded.auth_method,
63
64
  region=excluded.region, oidc_region=excluded.oidc_region, client_id=excluded.client_id, client_secret=excluded.client_secret,
@@ -66,9 +67,10 @@ export class KiroDatabase {
66
67
  rate_limit_reset=excluded.rate_limit_reset, is_healthy=excluded.is_healthy,
67
68
  unhealthy_reason=excluded.unhealthy_reason, recovery_time=excluded.recovery_time,
68
69
  fail_count=excluded.fail_count, last_used=excluded.last_used,
69
- used_count=excluded.used_count, limit_count=excluded.limit_count, last_sync=excluded.last_sync
70
+ used_count=excluded.used_count, limit_count=excluded.limit_count,
71
+ overage_count=excluded.overage_count, last_sync=excluded.last_sync
70
72
  `)
71
- .run(acc.id, acc.email, acc.authMethod, acc.region, acc.oidcRegion || null, acc.clientId || null, acc.clientSecret || null, acc.profileArn || null, acc.startUrl || null, acc.refreshToken, acc.accessToken, acc.expiresAt, acc.rateLimitResetTime || 0, acc.isHealthy ? 1 : 0, acc.unhealthyReason || null, acc.recoveryTime || null, acc.failCount || 0, acc.lastUsed || 0, acc.usedCount || 0, acc.limitCount || 0, acc.lastSync || 0);
73
+ .run(acc.id, acc.email, acc.authMethod, acc.region, acc.oidcRegion || null, acc.clientId || null, acc.clientSecret || null, acc.profileArn || null, acc.startUrl || null, acc.refreshToken, acc.accessToken, acc.expiresAt, acc.rateLimitResetTime || 0, acc.isHealthy ? 1 : 0, acc.unhealthyReason || null, acc.recoveryTime || null, acc.failCount || 0, acc.lastUsed || 0, acc.usedCount || 0, acc.limitCount || 0, acc.overageCount || 0, acc.lastSync || 0);
72
74
  }
73
75
  isRemovedSync(id) {
74
76
  return !!this.db.prepare('SELECT id FROM removed_accounts WHERE id = ?').get(id);
@@ -233,6 +235,7 @@ export class KiroDatabase {
233
235
  lastUsed: row.last_used,
234
236
  usedCount: row.used_count,
235
237
  limitCount: row.limit_count,
238
+ overageCount: row.overage_count || 0,
236
239
  lastSync: row.last_sync
237
240
  };
238
241
  }
@@ -42,6 +42,7 @@ export interface ManagedAccount {
42
42
  failCount: number;
43
43
  usedCount?: number;
44
44
  limitCount?: number;
45
+ overageCount?: number;
45
46
  lastSync?: number;
46
47
  lastUsed?: number;
47
48
  }
@@ -1,3 +1,16 @@
1
- import { KiroAuthDetails, ManagedAccount } from './types.js';
2
- export declare function fetchUsageLimits(auth: KiroAuthDetails): Promise<any>;
3
- export declare function updateAccountQuota(account: ManagedAccount, usage: any, accountManager?: any): void;
1
+ import type { KiroAuthDetails, ManagedAccount } from './types.js';
2
+ interface UsageSnapshot {
3
+ usedCount: number;
4
+ limitCount: number;
5
+ overageCount: number;
6
+ email?: string;
7
+ }
8
+ interface UsageUpdateMeta extends UsageSnapshot {
9
+ lastSync: number;
10
+ }
11
+ interface AccountUsageManager {
12
+ updateUsage(id: string, meta: UsageUpdateMeta): void;
13
+ }
14
+ export declare function fetchUsageLimits(auth: KiroAuthDetails): Promise<UsageSnapshot>;
15
+ export declare function updateAccountQuota(account: ManagedAccount, usage: Partial<UsageSnapshot>, accountManager?: AccountUsageManager): void;
16
+ export {};
@@ -1,3 +1,26 @@
1
+ import { z } from 'zod';
2
+ const UsageLimitsResponseSchema = z
3
+ .object({
4
+ usageBreakdownList: z
5
+ .array(z
6
+ .object({
7
+ currentUsage: z.number().optional(),
8
+ usageLimit: z.number().optional(),
9
+ currentOverages: z.number().optional(),
10
+ freeTrialInfo: z
11
+ .object({
12
+ currentUsage: z.number().optional(),
13
+ usageLimit: z.number().optional()
14
+ })
15
+ .passthrough()
16
+ .nullable()
17
+ .optional()
18
+ })
19
+ .passthrough())
20
+ .optional(),
21
+ userInfo: z.object({ email: z.string().optional() }).passthrough().optional()
22
+ })
23
+ .passthrough();
1
24
  export async function fetchUsageLimits(auth) {
2
25
  // Try different parameter combinations
3
26
  const attempts = [
@@ -42,8 +65,8 @@ export async function fetchUsageLimits(auth) {
42
65
  lastError = new Error(`Status: ${res.status}${errType ? ` (${errType})` : ''}${requestId ? ` [${requestId}]` : ''}: ${msg}`);
43
66
  continue;
44
67
  }
45
- const data = await res.json();
46
- let usedCount = 0, limitCount = 0;
68
+ const data = UsageLimitsResponseSchema.parse(await res.json());
69
+ let usedCount = 0, limitCount = 0, overageCount = 0;
47
70
  if (Array.isArray(data.usageBreakdownList)) {
48
71
  for (const s of data.usageBreakdownList) {
49
72
  if (s.freeTrialInfo) {
@@ -52,9 +75,10 @@ export async function fetchUsageLimits(auth) {
52
75
  }
53
76
  usedCount += s.currentUsage || 0;
54
77
  limitCount += s.usageLimit || 0;
78
+ overageCount += s.currentOverages || 0;
55
79
  }
56
80
  }
57
- return { usedCount, limitCount, email: data.userInfo?.email };
81
+ return { usedCount, limitCount, overageCount, email: data.userInfo?.email };
58
82
  }
59
83
  catch (e) {
60
84
  lastError = e instanceof Error ? e : new Error(String(e));
@@ -68,10 +92,14 @@ export function updateAccountQuota(account, usage, accountManager) {
68
92
  const meta = {
69
93
  usedCount: usage.usedCount || 0,
70
94
  limitCount: usage.limitCount || 0,
95
+ overageCount: usage.overageCount || 0,
96
+ lastSync: Date.now(),
71
97
  email: usage.email
72
98
  };
73
99
  account.usedCount = meta.usedCount;
74
100
  account.limitCount = meta.limitCount;
101
+ account.overageCount = meta.overageCount;
102
+ account.lastSync = meta.lastSync;
75
103
  if (usage.email)
76
104
  account.email = usage.email;
77
105
  if (accountManager)
package/dist/plugin.js CHANGED
@@ -43,7 +43,9 @@ export const createKiroPlugin = (id) => async ({ client, directory }) => {
43
43
  const authHandler = new AuthHandler(config, repository);
44
44
  const accountManager = await AccountManager.loadFromDisk(config.account_selection_strategy, {
45
45
  quotaAvoidanceEnabled: config.quota_avoidance_enabled,
46
- quotaReserveThreshold: config.quota_reserve_threshold
46
+ quotaReserveThreshold: config.quota_reserve_threshold,
47
+ stopOnOverage: config.stop_on_overage,
48
+ overageThreshold: config.overage_threshold
47
49
  });
48
50
  authHandler.setAccountManager(accountManager);
49
51
  const requestHandler = new RequestHandler(accountManager, config, repository, client);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sunerpy/opencode-kiro-auth",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "OpenCode plugin for AWS Kiro (CodeWhisperer) providing access to Claude models",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",