@zhafron/opencode-kiro-auth 1.4.9 → 1.4.11
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/dist/plugin/accounts.js +34 -11
- package/dist/plugin/health.d.ts +1 -0
- package/dist/plugin/health.js +9 -0
- package/dist/plugin/storage/locked-operations.d.ts +5 -0
- package/dist/plugin/storage/locked-operations.js +91 -0
- package/dist/plugin/storage/migration.js +3 -1
- package/dist/plugin/storage/sqlite.d.ts +8 -2
- package/dist/plugin/storage/sqlite.js +70 -3
- package/dist/plugin/sync/kiro-cli.js +6 -4
- package/dist/plugin.js +13 -3
- package/package.json +1 -1
package/dist/plugin/accounts.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createHash, randomBytes } from 'node:crypto';
|
|
2
2
|
import { decodeRefreshToken, encodeRefreshToken } from '../kiro/auth';
|
|
3
|
+
import { isPermanentError } from './health';
|
|
4
|
+
import * as logger from './logger';
|
|
3
5
|
import { kiroDb } from './storage/sqlite';
|
|
4
6
|
import { writeToKiroCli } from './sync/kiro-cli';
|
|
5
7
|
export function generateAccountId() {
|
|
@@ -72,6 +74,9 @@ export class AccountManager {
|
|
|
72
74
|
const now = Date.now();
|
|
73
75
|
const available = this.accounts.filter((a) => {
|
|
74
76
|
if (!a.isHealthy) {
|
|
77
|
+
if (isPermanentError(a.unhealthyReason)) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
75
80
|
if (a.failCount < 10 && a.recoveryTime && now >= a.recoveryTime) {
|
|
76
81
|
a.isHealthy = true;
|
|
77
82
|
delete a.unhealthyReason;
|
|
@@ -97,7 +102,7 @@ export class AccountManager {
|
|
|
97
102
|
}
|
|
98
103
|
if (!selected) {
|
|
99
104
|
const fallback = this.accounts
|
|
100
|
-
.filter((a) => !a.isHealthy && a.failCount < 10)
|
|
105
|
+
.filter((a) => !a.isHealthy && a.failCount < 10 && !isPermanentError(a.unhealthyReason))
|
|
101
106
|
.sort((a, b) => (a.usedCount || 0) - (b.usedCount || 0) || (a.lastUsed || 0) - (b.lastUsed || 0))[0];
|
|
102
107
|
if (fallback) {
|
|
103
108
|
fallback.isHealthy = true;
|
|
@@ -121,8 +126,10 @@ export class AccountManager {
|
|
|
121
126
|
a.limitCount = meta.limitCount;
|
|
122
127
|
if (meta.email)
|
|
123
128
|
a.email = meta.email;
|
|
124
|
-
a.
|
|
125
|
-
|
|
129
|
+
if (!isPermanentError(a.unhealthyReason)) {
|
|
130
|
+
a.failCount = 0;
|
|
131
|
+
}
|
|
132
|
+
kiroDb.upsertAccount(a).catch(() => { });
|
|
126
133
|
}
|
|
127
134
|
}
|
|
128
135
|
addAccount(a) {
|
|
@@ -131,14 +138,14 @@ export class AccountManager {
|
|
|
131
138
|
this.accounts.push(a);
|
|
132
139
|
else
|
|
133
140
|
this.accounts[i] = a;
|
|
134
|
-
kiroDb.upsertAccount(a);
|
|
141
|
+
kiroDb.upsertAccount(a).catch(() => { });
|
|
135
142
|
}
|
|
136
143
|
removeAccount(a) {
|
|
137
144
|
const removedIndex = this.accounts.findIndex((x) => x.id === a.id);
|
|
138
145
|
if (removedIndex === -1)
|
|
139
146
|
return;
|
|
140
147
|
this.accounts = this.accounts.filter((x) => x.id !== a.id);
|
|
141
|
-
kiroDb.deleteAccount(a.id);
|
|
148
|
+
kiroDb.deleteAccount(a.id).catch(() => { });
|
|
142
149
|
if (this.accounts.length === 0)
|
|
143
150
|
this.cursor = 0;
|
|
144
151
|
else if (this.cursor >= this.accounts.length)
|
|
@@ -161,7 +168,10 @@ export class AccountManager {
|
|
|
161
168
|
if (p.clientId)
|
|
162
169
|
acc.clientId = p.clientId;
|
|
163
170
|
acc.failCount = 0;
|
|
164
|
-
|
|
171
|
+
acc.isHealthy = true;
|
|
172
|
+
delete acc.unhealthyReason;
|
|
173
|
+
delete acc.recoveryTime;
|
|
174
|
+
kiroDb.upsertAccount(acc).catch(() => { });
|
|
165
175
|
writeToKiroCli(acc).catch(() => { });
|
|
166
176
|
}
|
|
167
177
|
}
|
|
@@ -169,12 +179,26 @@ export class AccountManager {
|
|
|
169
179
|
const acc = this.accounts.find((x) => x.id === a.id);
|
|
170
180
|
if (acc) {
|
|
171
181
|
acc.rateLimitResetTime = Date.now() + ms;
|
|
172
|
-
kiroDb.upsertAccount(acc);
|
|
182
|
+
kiroDb.upsertAccount(acc).catch(() => { });
|
|
173
183
|
}
|
|
174
184
|
}
|
|
175
185
|
markUnhealthy(a, reason, recovery) {
|
|
176
186
|
const acc = this.accounts.find((x) => x.id === a.id);
|
|
177
|
-
if (acc)
|
|
187
|
+
if (!acc)
|
|
188
|
+
return;
|
|
189
|
+
const isPermanent = isPermanentError(reason);
|
|
190
|
+
if (isPermanent) {
|
|
191
|
+
logger.warn('Account marked as permanently unhealthy', {
|
|
192
|
+
email: acc.email,
|
|
193
|
+
reason,
|
|
194
|
+
accountId: acc.id
|
|
195
|
+
});
|
|
196
|
+
acc.failCount = 10;
|
|
197
|
+
acc.isHealthy = false;
|
|
198
|
+
acc.unhealthyReason = reason;
|
|
199
|
+
delete acc.recoveryTime;
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
178
202
|
acc.failCount = (acc.failCount || 0) + 1;
|
|
179
203
|
acc.unhealthyReason = reason;
|
|
180
204
|
acc.lastUsed = Date.now();
|
|
@@ -182,12 +206,11 @@ export class AccountManager {
|
|
|
182
206
|
acc.isHealthy = false;
|
|
183
207
|
acc.recoveryTime = recovery || Date.now() + 3600000;
|
|
184
208
|
}
|
|
185
|
-
kiroDb.upsertAccount(acc);
|
|
186
209
|
}
|
|
210
|
+
kiroDb.upsertAccount(acc).catch(() => { });
|
|
187
211
|
}
|
|
188
212
|
async saveToDisk() {
|
|
189
|
-
|
|
190
|
-
kiroDb.upsertAccount(a);
|
|
213
|
+
await kiroDb.batchUpsertAccounts(this.accounts);
|
|
191
214
|
}
|
|
192
215
|
toAuthDetails(a) {
|
|
193
216
|
const p = {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isPermanentError(reason?: string): boolean;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function isPermanentError(reason) {
|
|
2
|
+
if (!reason)
|
|
3
|
+
return false;
|
|
4
|
+
return (reason.includes('Invalid refresh token') ||
|
|
5
|
+
reason.includes('ExpiredTokenException') ||
|
|
6
|
+
reason.includes('InvalidTokenException') ||
|
|
7
|
+
reason.includes('HTTP_401') ||
|
|
8
|
+
reason.includes('HTTP_403'));
|
|
9
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ManagedAccount } from '../types';
|
|
2
|
+
export declare function withDatabaseLock<T>(dbPath: string, fn: () => Promise<T>): Promise<T>;
|
|
3
|
+
export declare function createDeterministicId(email: string, authMethod: string, clientId?: string, profileArn?: string): string;
|
|
4
|
+
export declare function mergeAccounts(existing: ManagedAccount[], incoming: ManagedAccount[]): ManagedAccount[];
|
|
5
|
+
export declare function deduplicateAccounts(accounts: ManagedAccount[]): ManagedAccount[];
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { existsSync, promises as fs } from 'node:fs';
|
|
3
|
+
import lockfile from 'proper-lockfile';
|
|
4
|
+
import { isPermanentError } from '../health';
|
|
5
|
+
const LOCK_OPTIONS = {
|
|
6
|
+
stale: 10000,
|
|
7
|
+
retries: {
|
|
8
|
+
retries: 5,
|
|
9
|
+
minTimeout: 100,
|
|
10
|
+
maxTimeout: 1000,
|
|
11
|
+
factor: 2
|
|
12
|
+
},
|
|
13
|
+
realpath: false
|
|
14
|
+
};
|
|
15
|
+
export async function withDatabaseLock(dbPath, fn) {
|
|
16
|
+
const lockPath = `${dbPath}.lock`;
|
|
17
|
+
if (!existsSync(dbPath)) {
|
|
18
|
+
const dir = dbPath.substring(0, dbPath.lastIndexOf('/'));
|
|
19
|
+
await fs.mkdir(dir, { recursive: true });
|
|
20
|
+
await fs.writeFile(dbPath, '');
|
|
21
|
+
}
|
|
22
|
+
let release = null;
|
|
23
|
+
try {
|
|
24
|
+
release = await lockfile.lock(dbPath, LOCK_OPTIONS);
|
|
25
|
+
return await fn();
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
if (release) {
|
|
29
|
+
try {
|
|
30
|
+
await release();
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
console.warn('Failed to release lock:', e);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export function createDeterministicId(email, authMethod, clientId, profileArn) {
|
|
39
|
+
const parts = [email, authMethod, clientId || '', profileArn || ''].join(':');
|
|
40
|
+
return createHash('sha256').update(parts).digest('hex');
|
|
41
|
+
}
|
|
42
|
+
export function mergeAccounts(existing, incoming) {
|
|
43
|
+
const accountMap = new Map();
|
|
44
|
+
for (const acc of existing) {
|
|
45
|
+
accountMap.set(acc.id, acc);
|
|
46
|
+
}
|
|
47
|
+
for (const acc of incoming) {
|
|
48
|
+
const existingAcc = accountMap.get(acc.id);
|
|
49
|
+
if (existingAcc) {
|
|
50
|
+
const hasPermanentError = isPermanentError(existingAcc.unhealthyReason) || isPermanentError(acc.unhealthyReason);
|
|
51
|
+
accountMap.set(acc.id, {
|
|
52
|
+
...existingAcc,
|
|
53
|
+
...acc,
|
|
54
|
+
lastUsed: Math.max(existingAcc.lastUsed || 0, acc.lastUsed || 0),
|
|
55
|
+
usedCount: Math.max(existingAcc.usedCount || 0, acc.usedCount || 0),
|
|
56
|
+
limitCount: Math.max(existingAcc.limitCount || 0, acc.limitCount || 0),
|
|
57
|
+
rateLimitResetTime: Math.max(existingAcc.rateLimitResetTime || 0, acc.rateLimitResetTime || 0),
|
|
58
|
+
isHealthy: hasPermanentError ? false : existingAcc.isHealthy || acc.isHealthy,
|
|
59
|
+
failCount: Math.max(existingAcc.failCount || 0, acc.failCount || 0),
|
|
60
|
+
lastSync: Math.max(existingAcc.lastSync || 0, acc.lastSync || 0)
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
accountMap.set(acc.id, acc);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return Array.from(accountMap.values());
|
|
68
|
+
}
|
|
69
|
+
export function deduplicateAccounts(accounts) {
|
|
70
|
+
const accountMap = new Map();
|
|
71
|
+
for (const acc of accounts) {
|
|
72
|
+
const existing = accountMap.get(acc.id);
|
|
73
|
+
if (!existing) {
|
|
74
|
+
accountMap.set(acc.id, acc);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const currLastUsed = acc.lastUsed || 0;
|
|
78
|
+
const existLastUsed = existing.lastUsed || 0;
|
|
79
|
+
if (currLastUsed > existLastUsed) {
|
|
80
|
+
accountMap.set(acc.id, acc);
|
|
81
|
+
}
|
|
82
|
+
else if (currLastUsed === existLastUsed) {
|
|
83
|
+
const currAddedAt = acc.expiresAt || 0;
|
|
84
|
+
const existAddedAt = existing.expiresAt || 0;
|
|
85
|
+
if (currAddedAt > existAddedAt) {
|
|
86
|
+
accountMap.set(acc.id, acc);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return Array.from(accountMap.values());
|
|
91
|
+
}
|
|
@@ -26,9 +26,10 @@ export async function migrateJsonToSqlite() {
|
|
|
26
26
|
const accData = JSON.parse(await fs.readFile(accPath, 'utf-8'));
|
|
27
27
|
const useData = useExists ? JSON.parse(await fs.readFile(usePath, 'utf-8')) : { usage: {} };
|
|
28
28
|
if (accData.accounts && Array.isArray(accData.accounts)) {
|
|
29
|
+
const accounts = [];
|
|
29
30
|
for (const acc of accData.accounts) {
|
|
30
31
|
const usage = useData.usage[acc.id] || {};
|
|
31
|
-
|
|
32
|
+
accounts.push({
|
|
32
33
|
...acc,
|
|
33
34
|
email: acc.realEmail || acc.email,
|
|
34
35
|
rateLimitResetTime: acc.rateLimitResetTime || 0,
|
|
@@ -40,6 +41,7 @@ export async function migrateJsonToSqlite() {
|
|
|
40
41
|
lastSync: usage.lastSync || 0
|
|
41
42
|
});
|
|
42
43
|
}
|
|
44
|
+
await kiroDb.batchUpsertAccounts(accounts);
|
|
43
45
|
}
|
|
44
46
|
await fs.rename(accPath, accPath + '.bak');
|
|
45
47
|
if (useExists)
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
import type { ManagedAccount } from '../types';
|
|
1
2
|
export declare const DB_PATH: string;
|
|
2
3
|
export declare class KiroDatabase {
|
|
3
4
|
private db;
|
|
5
|
+
private path;
|
|
4
6
|
constructor(path?: string);
|
|
5
7
|
private init;
|
|
6
8
|
getAccounts(): any[];
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
private upsertAccountInternal;
|
|
10
|
+
upsertAccount(acc: ManagedAccount): Promise<void>;
|
|
11
|
+
batchUpsertAccounts(accounts: ManagedAccount[]): Promise<void>;
|
|
12
|
+
deleteAccount(id: string): Promise<void>;
|
|
13
|
+
private rowToAccount;
|
|
9
14
|
close(): void;
|
|
10
15
|
}
|
|
16
|
+
export declare function createDatabase(path?: string): KiroDatabase;
|
|
11
17
|
export declare const kiroDb: KiroDatabase;
|
|
@@ -2,6 +2,7 @@ import { Database } from 'bun:sqlite';
|
|
|
2
2
|
import { existsSync, mkdirSync } from 'node:fs';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
|
+
import { deduplicateAccounts, mergeAccounts, withDatabaseLock } from './locked-operations';
|
|
5
6
|
function getBaseDir() {
|
|
6
7
|
const p = process.platform;
|
|
7
8
|
if (p === 'win32')
|
|
@@ -11,7 +12,9 @@ function getBaseDir() {
|
|
|
11
12
|
export const DB_PATH = join(getBaseDir(), 'kiro.db');
|
|
12
13
|
export class KiroDatabase {
|
|
13
14
|
db;
|
|
15
|
+
path;
|
|
14
16
|
constructor(path = DB_PATH) {
|
|
17
|
+
this.path = path;
|
|
15
18
|
const dir = join(path, '..');
|
|
16
19
|
if (!existsSync(dir))
|
|
17
20
|
mkdirSync(dir, { recursive: true });
|
|
@@ -87,7 +90,7 @@ export class KiroDatabase {
|
|
|
87
90
|
getAccounts() {
|
|
88
91
|
return this.db.prepare('SELECT * FROM accounts').all();
|
|
89
92
|
}
|
|
90
|
-
|
|
93
|
+
upsertAccountInternal(acc) {
|
|
91
94
|
this.db
|
|
92
95
|
.prepare(`
|
|
93
96
|
INSERT INTO accounts (
|
|
@@ -108,11 +111,75 @@ export class KiroDatabase {
|
|
|
108
111
|
`)
|
|
109
112
|
.run(acc.id, acc.email, acc.authMethod, acc.region, acc.clientId || null, acc.clientSecret || null, acc.profileArn || 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);
|
|
110
113
|
}
|
|
111
|
-
|
|
112
|
-
this.
|
|
114
|
+
async upsertAccount(acc) {
|
|
115
|
+
await withDatabaseLock(this.path, async () => {
|
|
116
|
+
const existing = this.getAccounts().map(this.rowToAccount);
|
|
117
|
+
const merged = mergeAccounts(existing, [acc]);
|
|
118
|
+
const deduplicated = deduplicateAccounts(merged);
|
|
119
|
+
this.db.run('BEGIN TRANSACTION');
|
|
120
|
+
try {
|
|
121
|
+
for (const account of deduplicated) {
|
|
122
|
+
this.upsertAccountInternal(account);
|
|
123
|
+
}
|
|
124
|
+
this.db.run('COMMIT');
|
|
125
|
+
}
|
|
126
|
+
catch (e) {
|
|
127
|
+
this.db.run('ROLLBACK');
|
|
128
|
+
throw e;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
async batchUpsertAccounts(accounts) {
|
|
133
|
+
await withDatabaseLock(this.path, async () => {
|
|
134
|
+
const existing = this.getAccounts().map(this.rowToAccount);
|
|
135
|
+
const merged = mergeAccounts(existing, accounts);
|
|
136
|
+
const deduplicated = deduplicateAccounts(merged);
|
|
137
|
+
this.db.run('BEGIN TRANSACTION');
|
|
138
|
+
try {
|
|
139
|
+
for (const account of deduplicated) {
|
|
140
|
+
this.upsertAccountInternal(account);
|
|
141
|
+
}
|
|
142
|
+
this.db.run('COMMIT');
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
this.db.run('ROLLBACK');
|
|
146
|
+
throw e;
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
async deleteAccount(id) {
|
|
151
|
+
await withDatabaseLock(this.path, async () => {
|
|
152
|
+
this.db.prepare('DELETE FROM accounts WHERE id = ?').run(id);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
rowToAccount(row) {
|
|
156
|
+
return {
|
|
157
|
+
id: row.id,
|
|
158
|
+
email: row.email,
|
|
159
|
+
authMethod: row.auth_method,
|
|
160
|
+
region: row.region,
|
|
161
|
+
clientId: row.client_id,
|
|
162
|
+
clientSecret: row.client_secret,
|
|
163
|
+
profileArn: row.profile_arn,
|
|
164
|
+
refreshToken: row.refresh_token,
|
|
165
|
+
accessToken: row.access_token,
|
|
166
|
+
expiresAt: row.expires_at,
|
|
167
|
+
rateLimitResetTime: row.rate_limit_reset,
|
|
168
|
+
isHealthy: row.is_healthy === 1,
|
|
169
|
+
unhealthyReason: row.unhealthy_reason,
|
|
170
|
+
recoveryTime: row.recovery_time,
|
|
171
|
+
failCount: row.fail_count,
|
|
172
|
+
lastUsed: row.last_used,
|
|
173
|
+
usedCount: row.used_count,
|
|
174
|
+
limitCount: row.limit_count,
|
|
175
|
+
lastSync: row.last_sync
|
|
176
|
+
};
|
|
113
177
|
}
|
|
114
178
|
close() {
|
|
115
179
|
this.db.close();
|
|
116
180
|
}
|
|
117
181
|
}
|
|
182
|
+
export function createDatabase(path) {
|
|
183
|
+
return new KiroDatabase(path);
|
|
184
|
+
}
|
|
118
185
|
export const kiroDb = new KiroDatabase();
|
|
@@ -168,7 +168,7 @@ export async function syncFromKiroCli() {
|
|
|
168
168
|
if (placeholderId !== id) {
|
|
169
169
|
const placeholderRow = all.find((a) => a.id === placeholderId);
|
|
170
170
|
if (placeholderRow) {
|
|
171
|
-
kiroDb.upsertAccount({
|
|
171
|
+
await kiroDb.upsertAccount({
|
|
172
172
|
id: placeholderId,
|
|
173
173
|
email: placeholderRow.email,
|
|
174
174
|
authMethod,
|
|
@@ -179,7 +179,8 @@ export async function syncFromKiroCli() {
|
|
|
179
179
|
refreshToken: placeholderRow.refresh_token || refreshToken,
|
|
180
180
|
accessToken: placeholderRow.access_token || accessToken,
|
|
181
181
|
expiresAt: placeholderRow.expires_at || cliExpiresAt,
|
|
182
|
-
|
|
182
|
+
rateLimitResetTime: 0,
|
|
183
|
+
isHealthy: false,
|
|
183
184
|
failCount: 10,
|
|
184
185
|
unhealthyReason: 'Replaced by real email',
|
|
185
186
|
recoveryTime: Date.now() + 31536000000,
|
|
@@ -190,7 +191,7 @@ export async function syncFromKiroCli() {
|
|
|
190
191
|
}
|
|
191
192
|
}
|
|
192
193
|
}
|
|
193
|
-
kiroDb.upsertAccount({
|
|
194
|
+
await kiroDb.upsertAccount({
|
|
194
195
|
id,
|
|
195
196
|
email: resolvedEmail,
|
|
196
197
|
authMethod,
|
|
@@ -201,7 +202,8 @@ export async function syncFromKiroCli() {
|
|
|
201
202
|
refreshToken,
|
|
202
203
|
accessToken,
|
|
203
204
|
expiresAt: cliExpiresAt,
|
|
204
|
-
|
|
205
|
+
rateLimitResetTime: 0,
|
|
206
|
+
isHealthy: true,
|
|
205
207
|
failCount: 0,
|
|
206
208
|
usedCount,
|
|
207
209
|
limitCount,
|
package/dist/plugin.js
CHANGED
|
@@ -6,6 +6,7 @@ import { AccountManager, createDeterministicAccountId } from './plugin/accounts'
|
|
|
6
6
|
import { promptAddAnotherAccount, promptLoginMode } from './plugin/cli';
|
|
7
7
|
import { loadConfig } from './plugin/config';
|
|
8
8
|
import { KiroTokenRefreshError } from './plugin/errors';
|
|
9
|
+
import { isPermanentError } from './plugin/health';
|
|
9
10
|
import * as logger from './plugin/logger';
|
|
10
11
|
import { transformToCodeWhisperer } from './plugin/request';
|
|
11
12
|
import { parseEventStream } from './plugin/response';
|
|
@@ -143,7 +144,8 @@ export const createKiroPlugin = (id) => async ({ client, directory }) => {
|
|
|
143
144
|
(e.code === 'ExpiredTokenException' ||
|
|
144
145
|
e.code === 'InvalidTokenException' ||
|
|
145
146
|
e.code === 'HTTP_401' ||
|
|
146
|
-
e.code === 'HTTP_403'
|
|
147
|
+
e.code === 'HTTP_403' ||
|
|
148
|
+
e.message.includes('Invalid refresh token provided'))) {
|
|
147
149
|
am.markUnhealthy(acc, e.message);
|
|
148
150
|
await am.saveToDisk();
|
|
149
151
|
continue;
|
|
@@ -187,8 +189,10 @@ export const createKiroPlugin = (id) => async ({ client, directory }) => {
|
|
|
187
189
|
}
|
|
188
190
|
if (res.ok) {
|
|
189
191
|
if (acc.failCount && acc.failCount > 0) {
|
|
190
|
-
acc.
|
|
191
|
-
|
|
192
|
+
if (!isPermanentError(acc.unhealthyReason)) {
|
|
193
|
+
acc.failCount = 0;
|
|
194
|
+
kiroDb.upsertAccount(acc).catch(() => { });
|
|
195
|
+
}
|
|
192
196
|
}
|
|
193
197
|
if (config.usage_tracking_enabled) {
|
|
194
198
|
const sync = async (att = 0) => {
|
|
@@ -202,6 +206,12 @@ export const createKiroPlugin = (id) => async ({ client, directory }) => {
|
|
|
202
206
|
await sleep(1000 * Math.pow(2, att));
|
|
203
207
|
return sync(att + 1);
|
|
204
208
|
}
|
|
209
|
+
if (e.message?.includes('403') ||
|
|
210
|
+
e.message?.includes('invalid') ||
|
|
211
|
+
e.message?.includes('bearer token')) {
|
|
212
|
+
am.markUnhealthy(acc, e.message);
|
|
213
|
+
am.saveToDisk().catch(() => { });
|
|
214
|
+
}
|
|
205
215
|
}
|
|
206
216
|
};
|
|
207
217
|
sync().catch(() => { });
|