@javargasm/pi-kiro 0.3.0 → 0.4.3
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 +24 -0
- package/dist/core.js +341 -107
- package/dist/extension.d.ts.map +1 -1
- package/dist/extension.js +352 -111
- package/dist/kiro-cli-sync.d.ts +39 -13
- package/dist/kiro-cli-sync.d.ts.map +1 -1
- package/dist/models.d.ts +1 -1
- package/dist/models.d.ts.map +1 -1
- package/dist/oauth.d.ts +5 -0
- package/dist/oauth.d.ts.map +1 -1
- package/dist/stream.d.ts +8 -0
- package/dist/stream.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/core.js
CHANGED
|
@@ -120,19 +120,37 @@ var init_debug = __esm(() => {
|
|
|
120
120
|
// src/kiro-cli-sync.ts
|
|
121
121
|
var exports_kiro_cli_sync = {};
|
|
122
122
|
__export(exports_kiro_cli_sync, {
|
|
123
|
+
selectKiroTokenRowForWrite: () => selectKiroTokenRowForWrite,
|
|
123
124
|
saveKiroCliCredentials: () => saveKiroCliCredentials,
|
|
125
|
+
sameKiroCliCredential: () => sameKiroCliCredential,
|
|
126
|
+
importFromKiroSsoCache: () => importFromKiroSsoCache,
|
|
124
127
|
importFromKiroCli: () => importFromKiroCli,
|
|
125
128
|
getKiroCliCredentialsAllowExpired: () => getKiroCliCredentialsAllowExpired
|
|
126
129
|
});
|
|
127
130
|
import { homedir } from "node:os";
|
|
128
131
|
import { join } from "node:path";
|
|
129
|
-
import {
|
|
132
|
+
import { spawn } from "node:child_process";
|
|
133
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
130
134
|
function getKiroDbPath() {
|
|
131
135
|
const home = homedir();
|
|
136
|
+
if (process.platform === "darwin") {
|
|
137
|
+
return join(home, "Library", "Application Support", "kiro-cli", "data.sqlite3");
|
|
138
|
+
}
|
|
132
139
|
if (process.platform === "win32") {
|
|
133
|
-
return join(process.env.APPDATA || join(home, "AppData", "Roaming"), "kiro", "
|
|
140
|
+
return join(process.env.APPDATA || join(home, "AppData", "Roaming"), "kiro-cli", "data.sqlite3");
|
|
141
|
+
}
|
|
142
|
+
const xdgData = process.env.XDG_DATA_HOME;
|
|
143
|
+
if (xdgData && xdgData.length > 0) {
|
|
144
|
+
return join(xdgData, "kiro-cli", "data.sqlite3");
|
|
134
145
|
}
|
|
135
|
-
return join(home, ".
|
|
146
|
+
return join(home, ".local", "share", "kiro-cli", "data.sqlite3");
|
|
147
|
+
}
|
|
148
|
+
function getKiroSsoCachePath() {
|
|
149
|
+
const home = homedir();
|
|
150
|
+
if (process.platform === "win32") {
|
|
151
|
+
return join(process.env.USERPROFILE || home, ".aws", "sso", "cache", "kiro-auth-token.json");
|
|
152
|
+
}
|
|
153
|
+
return join(home, ".aws", "sso", "cache", "kiro-auth-token.json");
|
|
136
154
|
}
|
|
137
155
|
function safeJsonParse(value) {
|
|
138
156
|
if (typeof value !== "string")
|
|
@@ -143,11 +161,112 @@ function safeJsonParse(value) {
|
|
|
143
161
|
return null;
|
|
144
162
|
}
|
|
145
163
|
}
|
|
164
|
+
function sqliteQuote(value) {
|
|
165
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
166
|
+
}
|
|
167
|
+
function runSqliteCli(dbPath, sql, options) {
|
|
168
|
+
return new Promise((resolve2) => {
|
|
169
|
+
const args = [
|
|
170
|
+
...options.readonly ? ["-readonly"] : [],
|
|
171
|
+
"-cmd",
|
|
172
|
+
`.timeout ${SQLITE_CLI_TIMEOUT_MS}`,
|
|
173
|
+
...options.json ? ["-json"] : [],
|
|
174
|
+
dbPath
|
|
175
|
+
];
|
|
176
|
+
const child = spawn("sqlite3", args, { stdio: "pipe" });
|
|
177
|
+
let stdout = "";
|
|
178
|
+
let settled = false;
|
|
179
|
+
const finish = (result) => {
|
|
180
|
+
if (settled)
|
|
181
|
+
return;
|
|
182
|
+
settled = true;
|
|
183
|
+
clearTimeout(timeout);
|
|
184
|
+
resolve2(result);
|
|
185
|
+
};
|
|
186
|
+
const timeout = setTimeout(() => {
|
|
187
|
+
child.kill();
|
|
188
|
+
log.debug("sqlite3 CLI timed out while reading Kiro DB");
|
|
189
|
+
finish(null);
|
|
190
|
+
}, SQLITE_CLI_TIMEOUT_MS);
|
|
191
|
+
child.stdout?.setEncoding("utf8");
|
|
192
|
+
child.stdout?.on("data", (chunk) => {
|
|
193
|
+
stdout += chunk;
|
|
194
|
+
});
|
|
195
|
+
child.on("error", () => {
|
|
196
|
+
log.debug("sqlite3 CLI unavailable for Kiro DB access");
|
|
197
|
+
finish(null);
|
|
198
|
+
});
|
|
199
|
+
child.on("close", (code) => {
|
|
200
|
+
if (code === 0)
|
|
201
|
+
finish(stdout);
|
|
202
|
+
else {
|
|
203
|
+
log.debug("sqlite3 CLI failed while accessing Kiro DB");
|
|
204
|
+
finish(null);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
child.stdin?.end(`${sql}
|
|
208
|
+
`);
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
function parseAuthKvRows(value) {
|
|
212
|
+
if (!Array.isArray(value))
|
|
213
|
+
return null;
|
|
214
|
+
const rows = [];
|
|
215
|
+
for (const item of value) {
|
|
216
|
+
if (!item || typeof item !== "object")
|
|
217
|
+
continue;
|
|
218
|
+
const record = item;
|
|
219
|
+
if (typeof record.key === "string" && typeof record.value === "string") {
|
|
220
|
+
rows.push({ key: record.key, value: record.value });
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return rows;
|
|
224
|
+
}
|
|
225
|
+
function extractActiveProfileArnFromStateRows(value) {
|
|
226
|
+
if (!Array.isArray(value))
|
|
227
|
+
return;
|
|
228
|
+
const first = value[0];
|
|
229
|
+
if (!first || typeof first !== "object")
|
|
230
|
+
return;
|
|
231
|
+
const record = first;
|
|
232
|
+
const parsed = safeJsonParse(record.value);
|
|
233
|
+
const arn = parsed?.arn || parsed?.profileArn || parsed?.profile_arn;
|
|
234
|
+
return typeof arn === "string" && arn.trim() ? arn.trim() : undefined;
|
|
235
|
+
}
|
|
236
|
+
function parseSqliteChanges(value) {
|
|
237
|
+
if (!Array.isArray(value))
|
|
238
|
+
return 0;
|
|
239
|
+
const first = value[0];
|
|
240
|
+
if (!first || typeof first !== "object")
|
|
241
|
+
return 0;
|
|
242
|
+
const changes = first.changes;
|
|
243
|
+
return typeof changes === "number" ? changes : 0;
|
|
244
|
+
}
|
|
245
|
+
async function readKiroAuthKvRowsWithSqliteCli(dbPath) {
|
|
246
|
+
const rowsRaw = await runSqliteCli(dbPath, "SELECT key, value FROM auth_kv", { readonly: true, json: true });
|
|
247
|
+
if (!rowsRaw)
|
|
248
|
+
return null;
|
|
249
|
+
return parseAuthKvRows(safeJsonParse(rowsRaw));
|
|
250
|
+
}
|
|
251
|
+
async function readKiroDbWithSqliteCli(dbPath) {
|
|
252
|
+
const rows = await readKiroAuthKvRowsWithSqliteCli(dbPath);
|
|
253
|
+
if (!rows)
|
|
254
|
+
return null;
|
|
255
|
+
const stateRaw = await runSqliteCli(dbPath, "SELECT value FROM state WHERE key = 'api.codewhisperer.profile'", { readonly: true, json: true });
|
|
256
|
+
const activeProfileArn = stateRaw ? extractActiveProfileArnFromStateRows(safeJsonParse(stateRaw)) : undefined;
|
|
257
|
+
return { rows, activeProfileArn };
|
|
258
|
+
}
|
|
259
|
+
async function writeKiroDbWithSqliteCli(dbPath, tokenKey, updatedValue) {
|
|
260
|
+
const resultRaw = await runSqliteCli(dbPath, `UPDATE auth_kv SET value = ${sqliteQuote(updatedValue)} WHERE key = ${sqliteQuote(tokenKey)}; ` + "SELECT changes() AS changes", { readonly: false, json: true });
|
|
261
|
+
return parseSqliteChanges(safeJsonParse(resultRaw)) > 0;
|
|
262
|
+
}
|
|
146
263
|
function findClientCreds(obj) {
|
|
147
264
|
if (!obj || typeof obj !== "object")
|
|
148
265
|
return {};
|
|
149
|
-
|
|
150
|
-
|
|
266
|
+
const id = obj.clientId ?? obj.client_id;
|
|
267
|
+
const secret = obj.clientSecret ?? obj.client_secret;
|
|
268
|
+
if (typeof id === "string" && typeof secret === "string") {
|
|
269
|
+
return { clientId: id, clientSecret: secret };
|
|
151
270
|
}
|
|
152
271
|
for (const key of Object.keys(obj)) {
|
|
153
272
|
const result = findClientCreds(obj[key]);
|
|
@@ -156,6 +275,26 @@ function findClientCreds(obj) {
|
|
|
156
275
|
}
|
|
157
276
|
return {};
|
|
158
277
|
}
|
|
278
|
+
function isIdcTokenKey(key) {
|
|
279
|
+
return key.includes("odic") || key.includes("oidc") || key.includes("idc");
|
|
280
|
+
}
|
|
281
|
+
function isTokenRow(row) {
|
|
282
|
+
return row.key.includes(":token");
|
|
283
|
+
}
|
|
284
|
+
function tokenReadRank(row) {
|
|
285
|
+
return isIdcTokenKey(row.key) ? 0 : 1;
|
|
286
|
+
}
|
|
287
|
+
function selectKiroTokenRowForWrite(rows, creds) {
|
|
288
|
+
const tokenRows = rows.filter(isTokenRow);
|
|
289
|
+
if (!creds.tokenKey)
|
|
290
|
+
return;
|
|
291
|
+
return tokenRows.find((row) => row.key === creds.tokenKey);
|
|
292
|
+
}
|
|
293
|
+
function sameKiroCliCredential(left, right) {
|
|
294
|
+
if (!left || !right)
|
|
295
|
+
return false;
|
|
296
|
+
return left.source === right.source && left.tokenKey === right.tokenKey && left.accessToken === right.accessToken && left.refreshToken === right.refreshToken && left.region === right.region && left.authMethod === right.authMethod;
|
|
297
|
+
}
|
|
159
298
|
function extractRegionFromArn(arn) {
|
|
160
299
|
if (!arn)
|
|
161
300
|
return;
|
|
@@ -165,55 +304,64 @@ function extractRegionFromArn(arn) {
|
|
|
165
304
|
const region = parts[3];
|
|
166
305
|
return region && region.length > 0 ? region : undefined;
|
|
167
306
|
}
|
|
168
|
-
async function
|
|
307
|
+
async function importFromKiroDb() {
|
|
169
308
|
const dbPath = getKiroDbPath();
|
|
170
309
|
if (!existsSync(dbPath)) {
|
|
171
310
|
log.debug(`Kiro CLI DB not found at ${dbPath}`);
|
|
172
311
|
return null;
|
|
173
312
|
}
|
|
174
313
|
try {
|
|
175
|
-
let
|
|
314
|
+
let rows;
|
|
315
|
+
let activeProfileArn;
|
|
316
|
+
let Database = null;
|
|
176
317
|
try {
|
|
177
318
|
Database = (await import("bun:sqlite")).Database;
|
|
178
319
|
} catch {
|
|
179
320
|
try {
|
|
180
321
|
Database = (await import("better-sqlite3")).default;
|
|
181
322
|
} catch {
|
|
182
|
-
log.debug("No SQLite driver available (need bun:sqlite or better-sqlite3)");
|
|
183
|
-
return null;
|
|
323
|
+
log.debug("No SQLite driver available (need bun:sqlite or better-sqlite3); trying sqlite3 CLI");
|
|
184
324
|
}
|
|
185
325
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
326
|
+
if (Database) {
|
|
327
|
+
const db = new Database(dbPath, { readonly: true });
|
|
328
|
+
try {
|
|
329
|
+
db.run?.("PRAGMA busy_timeout = 5000") ?? db.exec?.("PRAGMA busy_timeout = 5000");
|
|
330
|
+
} catch {}
|
|
331
|
+
try {
|
|
332
|
+
const stmt = db.prepare("SELECT key, value FROM auth_kv");
|
|
333
|
+
rows = stmt.all();
|
|
334
|
+
} catch {
|
|
335
|
+
log.debug("Failed to read auth_kv table from Kiro DB");
|
|
336
|
+
try {
|
|
337
|
+
db.close();
|
|
338
|
+
} catch {}
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
try {
|
|
342
|
+
const stateStmt = db.prepare("SELECT value FROM state WHERE key = ?");
|
|
343
|
+
const stateRow = stateStmt.get("api.codewhisperer.profile");
|
|
344
|
+
const parsed = safeJsonParse(stateRow?.value);
|
|
345
|
+
const arn = parsed?.arn || parsed?.profileArn || parsed?.profile_arn;
|
|
346
|
+
if (typeof arn === "string" && arn.trim()) {
|
|
347
|
+
activeProfileArn = arn.trim();
|
|
348
|
+
}
|
|
349
|
+
} catch {}
|
|
196
350
|
try {
|
|
197
351
|
db.close();
|
|
198
352
|
} catch {}
|
|
199
|
-
|
|
353
|
+
} else {
|
|
354
|
+
const snapshot = await readKiroDbWithSqliteCli(dbPath);
|
|
355
|
+
if (!snapshot)
|
|
356
|
+
return null;
|
|
357
|
+
rows = snapshot.rows;
|
|
358
|
+
activeProfileArn = snapshot.activeProfileArn;
|
|
200
359
|
}
|
|
201
|
-
let activeProfileArn;
|
|
202
|
-
try {
|
|
203
|
-
const stateStmt = db.prepare("SELECT value FROM state WHERE key = ?");
|
|
204
|
-
const stateRow = stateStmt.get("api.codewhisperer.profile");
|
|
205
|
-
const parsed = safeJsonParse(stateRow?.value);
|
|
206
|
-
const arn = parsed?.arn || parsed?.profileArn || parsed?.profile_arn;
|
|
207
|
-
if (typeof arn === "string" && arn.trim()) {
|
|
208
|
-
activeProfileArn = arn.trim();
|
|
209
|
-
}
|
|
210
|
-
} catch {}
|
|
211
360
|
const deviceRegRow = rows.find((r) => typeof r?.key === "string" && r.key.includes("device-registration"));
|
|
212
361
|
const deviceReg = safeJsonParse(deviceRegRow?.value);
|
|
213
362
|
const regCreds = deviceReg ? findClientCreds(deviceReg) : {};
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
continue;
|
|
363
|
+
const tokenRows = rows.filter(isTokenRow).sort((a, b) => tokenReadRank(a) - tokenReadRank(b));
|
|
364
|
+
for (const row of tokenRows) {
|
|
217
365
|
const data = safeJsonParse(row.value);
|
|
218
366
|
if (!data)
|
|
219
367
|
continue;
|
|
@@ -221,7 +369,7 @@ async function importFromKiroCli() {
|
|
|
221
369
|
const refreshToken = data.refreshToken || data.refresh_token;
|
|
222
370
|
if (!accessToken && !refreshToken)
|
|
223
371
|
continue;
|
|
224
|
-
const isIdc =
|
|
372
|
+
const isIdc = isIdcTokenKey(row.key);
|
|
225
373
|
const authMethod = isIdc ? "idc" : "desktop";
|
|
226
374
|
const oidcRegion = data.region || "us-east-1";
|
|
227
375
|
let profileArn = data.profile_arn || data.profileArn;
|
|
@@ -235,21 +383,17 @@ async function importFromKiroCli() {
|
|
|
235
383
|
region: serviceRegion,
|
|
236
384
|
authMethod,
|
|
237
385
|
profileArn,
|
|
238
|
-
email: data.email || data.emailAddress
|
|
386
|
+
email: data.email || data.emailAddress,
|
|
387
|
+
source: "kiro-cli-db",
|
|
388
|
+
tokenKey: row.key
|
|
239
389
|
};
|
|
240
390
|
if (isIdc && regCreds.clientId) {
|
|
241
391
|
result.clientId = regCreds.clientId;
|
|
242
392
|
result.clientSecret = regCreds.clientSecret;
|
|
243
393
|
}
|
|
244
|
-
try {
|
|
245
|
-
db.close();
|
|
246
|
-
} catch {}
|
|
247
394
|
log.info(`Imported Kiro CLI credentials (method=${authMethod}, region=${serviceRegion}${result.email ? `, email=${result.email}` : ""})`);
|
|
248
395
|
return result;
|
|
249
396
|
}
|
|
250
|
-
try {
|
|
251
|
-
db.close();
|
|
252
|
-
} catch {}
|
|
253
397
|
log.debug("No valid token entries found in Kiro CLI DB");
|
|
254
398
|
return null;
|
|
255
399
|
} catch (err) {
|
|
@@ -257,47 +401,108 @@ async function importFromKiroCli() {
|
|
|
257
401
|
return null;
|
|
258
402
|
}
|
|
259
403
|
}
|
|
260
|
-
|
|
261
|
-
|
|
404
|
+
function mapSsoCacheAuthMethod(value) {
|
|
405
|
+
if (typeof value !== "string")
|
|
406
|
+
return "idc";
|
|
407
|
+
const v = value.toLowerCase();
|
|
408
|
+
if (v === "builderid" || v === "builder-id")
|
|
409
|
+
return "desktop";
|
|
410
|
+
return "idc";
|
|
411
|
+
}
|
|
412
|
+
async function importFromKiroSsoCache() {
|
|
413
|
+
const path = getKiroSsoCachePath();
|
|
414
|
+
if (!existsSync(path)) {
|
|
415
|
+
log.debug(`Kiro SSO cache not found at ${path}`);
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
418
|
+
let raw;
|
|
419
|
+
try {
|
|
420
|
+
raw = readFileSync(path, "utf8");
|
|
421
|
+
} catch (err) {
|
|
422
|
+
log.warn(`Failed to read Kiro SSO cache at ${path}: ${err}`);
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
const token = safeJsonParse(raw);
|
|
426
|
+
if (!token || typeof token !== "object") {
|
|
427
|
+
log.debug(`Kiro SSO cache at ${path} is not valid JSON`);
|
|
428
|
+
return null;
|
|
429
|
+
}
|
|
430
|
+
const accessToken = typeof token.accessToken === "string" ? token.accessToken : "";
|
|
431
|
+
const refreshToken = typeof token.refreshToken === "string" ? token.refreshToken : "";
|
|
432
|
+
if (!accessToken && !refreshToken) {
|
|
433
|
+
log.debug(`Kiro SSO cache at ${path} has no tokens`);
|
|
434
|
+
return null;
|
|
435
|
+
}
|
|
436
|
+
const region = typeof token.region === "string" && token.region.length > 0 ? token.region : "us-east-1";
|
|
437
|
+
const authMethod = mapSsoCacheAuthMethod(token.authMethod);
|
|
438
|
+
log.info(`Imported Kiro SSO cache credentials (method=${authMethod}, region=${region})`);
|
|
439
|
+
return {
|
|
440
|
+
accessToken,
|
|
441
|
+
refreshToken,
|
|
442
|
+
region,
|
|
443
|
+
authMethod,
|
|
444
|
+
source: "kiro-sso-cache"
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
async function importFromKiroCli() {
|
|
448
|
+
const dbResult = await importFromKiroDb();
|
|
449
|
+
if (dbResult)
|
|
450
|
+
return dbResult;
|
|
451
|
+
return importFromKiroSsoCache();
|
|
452
|
+
}
|
|
453
|
+
async function getKiroCliCredentialsAllowExpired(exclude) {
|
|
454
|
+
const imported = await importFromKiroCli();
|
|
455
|
+
return sameKiroCliCredential(imported, exclude ?? null) ? null : imported;
|
|
262
456
|
}
|
|
263
457
|
async function saveKiroCliCredentials(creds) {
|
|
458
|
+
if (creds.source !== "kiro-cli-db" || !creds.tokenKey) {
|
|
459
|
+
log.debug("Credential write-back skipped: credential did not originate from kiro-cli DB");
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
264
462
|
const dbPath = getKiroDbPath();
|
|
265
463
|
if (!existsSync(dbPath)) {
|
|
266
464
|
log.debug(`Kiro CLI DB not found at ${dbPath} — cannot save credentials`);
|
|
267
465
|
return false;
|
|
268
466
|
}
|
|
269
467
|
try {
|
|
270
|
-
let Database;
|
|
468
|
+
let Database = null;
|
|
271
469
|
try {
|
|
272
470
|
Database = (await import("bun:sqlite")).Database;
|
|
273
471
|
} catch {
|
|
274
472
|
try {
|
|
275
473
|
Database = (await import("better-sqlite3")).default;
|
|
276
474
|
} catch {
|
|
277
|
-
log.debug("No SQLite driver available for credential write-back");
|
|
278
|
-
return false;
|
|
475
|
+
log.debug("No SQLite driver available for credential write-back; trying sqlite3 CLI");
|
|
279
476
|
}
|
|
280
477
|
}
|
|
281
|
-
const db = new Database(dbPath);
|
|
282
|
-
try {
|
|
283
|
-
db.run?.("PRAGMA busy_timeout = 5000") ?? db.exec?.("PRAGMA busy_timeout = 5000");
|
|
284
|
-
} catch {}
|
|
285
478
|
let rows;
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
} catch {
|
|
290
|
-
log.debug("Failed to read auth_kv table for credential write-back");
|
|
479
|
+
let db = null;
|
|
480
|
+
if (Database) {
|
|
481
|
+
db = new Database(dbPath);
|
|
291
482
|
try {
|
|
292
|
-
db.
|
|
483
|
+
db.run?.("PRAGMA busy_timeout = 5000") ?? db.exec?.("PRAGMA busy_timeout = 5000");
|
|
293
484
|
} catch {}
|
|
294
|
-
|
|
485
|
+
try {
|
|
486
|
+
const stmt = db.prepare("SELECT key, value FROM auth_kv");
|
|
487
|
+
rows = stmt.all();
|
|
488
|
+
} catch {
|
|
489
|
+
log.debug("Failed to read auth_kv table for credential write-back");
|
|
490
|
+
try {
|
|
491
|
+
db.close();
|
|
492
|
+
} catch {}
|
|
493
|
+
return false;
|
|
494
|
+
}
|
|
495
|
+
} else {
|
|
496
|
+
const cliRows = await readKiroAuthKvRowsWithSqliteCli(dbPath);
|
|
497
|
+
if (!cliRows)
|
|
498
|
+
return false;
|
|
499
|
+
rows = cliRows;
|
|
295
500
|
}
|
|
296
|
-
const tokenRow = rows
|
|
501
|
+
const tokenRow = selectKiroTokenRowForWrite(rows, creds);
|
|
297
502
|
if (!tokenRow) {
|
|
298
|
-
log.debug("No token entry found in auth_kv — cannot write back");
|
|
503
|
+
log.debug("No matching token entry found in auth_kv — cannot write back");
|
|
299
504
|
try {
|
|
300
|
-
db
|
|
505
|
+
db?.close();
|
|
301
506
|
} catch {}
|
|
302
507
|
return false;
|
|
303
508
|
}
|
|
@@ -309,19 +514,26 @@ async function saveKiroCliCredentials(creds) {
|
|
|
309
514
|
refreshToken: creds.refreshToken,
|
|
310
515
|
refresh_token: creds.refreshToken
|
|
311
516
|
};
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
517
|
+
const updatedValue = JSON.stringify(updated);
|
|
518
|
+
if (db) {
|
|
519
|
+
try {
|
|
520
|
+
const updateStmt = db.prepare("UPDATE auth_kv SET value = ? WHERE key = ?");
|
|
521
|
+
updateStmt.run(updatedValue, tokenRow.key);
|
|
522
|
+
} catch (err) {
|
|
523
|
+
log.warn(`Failed to write credentials back to Kiro CLI DB: ${err}`);
|
|
524
|
+
try {
|
|
525
|
+
db.close();
|
|
526
|
+
} catch {}
|
|
527
|
+
return false;
|
|
528
|
+
}
|
|
317
529
|
try {
|
|
318
530
|
db.close();
|
|
319
531
|
} catch {}
|
|
320
|
-
|
|
532
|
+
} else {
|
|
533
|
+
const wrote = await writeKiroDbWithSqliteCli(dbPath, tokenRow.key, updatedValue);
|
|
534
|
+
if (!wrote)
|
|
535
|
+
return false;
|
|
321
536
|
}
|
|
322
|
-
try {
|
|
323
|
-
db.close();
|
|
324
|
-
} catch {}
|
|
325
537
|
log.info("Wrote refreshed credentials back to Kiro CLI DB");
|
|
326
538
|
return true;
|
|
327
539
|
} catch (err) {
|
|
@@ -329,6 +541,7 @@ async function saveKiroCliCredentials(creds) {
|
|
|
329
541
|
return false;
|
|
330
542
|
}
|
|
331
543
|
}
|
|
544
|
+
var SQLITE_CLI_TIMEOUT_MS = 5000;
|
|
332
545
|
var init_kiro_cli_sync = __esm(() => {
|
|
333
546
|
init_debug();
|
|
334
547
|
});
|
|
@@ -1132,6 +1345,9 @@ function abortableDelay(ms, signal) {
|
|
|
1132
1345
|
}
|
|
1133
1346
|
var profileArnCache = new Map;
|
|
1134
1347
|
var profileArnSkipResolution = false;
|
|
1348
|
+
function seedProfileArn(endpoint, arn) {
|
|
1349
|
+
profileArnCache.set(endpoint, arn);
|
|
1350
|
+
}
|
|
1135
1351
|
async function resolveProfileArn(accessToken, endpoint) {
|
|
1136
1352
|
if (profileArnSkipResolution)
|
|
1137
1353
|
return;
|
|
@@ -1611,8 +1827,9 @@ ${currentContent}`;
|
|
|
1611
1827
|
let transientRetryCount = 0;
|
|
1612
1828
|
let contextTruncationAttempt = 0;
|
|
1613
1829
|
while (true) {
|
|
1614
|
-
const
|
|
1615
|
-
const ua = `aws-sdk-rust/1.
|
|
1830
|
+
const osName = resolveOS();
|
|
1831
|
+
const ua = `aws-sdk-rust/1.3.15 ua/2.1 api/codewhispererstreaming/0.1.16551 os/${osName} lang/rust/1.92.0 md/appVersion-2.7.1 app/AmazonQ-For-CLI`;
|
|
1832
|
+
const xAmzUa = `aws-sdk-rust/1.3.15 ua/2.1 api/codewhispererstreaming/0.1.16551 os/${osName} lang/rust/1.92.0 m/F app/AmazonQ-For-CLI`;
|
|
1616
1833
|
const requestBody = JSON.stringify(request);
|
|
1617
1834
|
const requestShape = log.isDebug() ? summarizeKiroRequest(request, requestBody) : undefined;
|
|
1618
1835
|
if (requestShape)
|
|
@@ -1630,15 +1847,17 @@ ${currentContent}`;
|
|
|
1630
1847
|
method: "POST",
|
|
1631
1848
|
headers: {
|
|
1632
1849
|
"Content-Type": "application/x-amz-json-1.0",
|
|
1633
|
-
Accept: "
|
|
1850
|
+
Accept: "*/*",
|
|
1851
|
+
"Accept-Encoding": "gzip",
|
|
1634
1852
|
Authorization: `Bearer ${accessToken}`,
|
|
1635
1853
|
"X-Amz-Target": "AmazonCodeWhispererStreamingService.GenerateAssistantResponse",
|
|
1636
1854
|
"x-amzn-codewhisperer-optout": "true",
|
|
1637
1855
|
"amz-sdk-invocation-id": crypto.randomUUID(),
|
|
1638
|
-
"amz-sdk-request": "attempt=1; max=
|
|
1639
|
-
"
|
|
1640
|
-
"x-amz-user-agent":
|
|
1641
|
-
"
|
|
1856
|
+
"amz-sdk-request": "attempt=1; max=3",
|
|
1857
|
+
"user-agent": ua,
|
|
1858
|
+
"x-amz-user-agent": xAmzUa,
|
|
1859
|
+
Pragma: "no-cache",
|
|
1860
|
+
"Cache-Control": "no-cache"
|
|
1642
1861
|
},
|
|
1643
1862
|
body: requestBody,
|
|
1644
1863
|
signal: options?.signal
|
|
@@ -2128,7 +2347,8 @@ var kiroModels = [
|
|
|
2128
2347
|
contextWindow: 1e6,
|
|
2129
2348
|
maxTokens: 128000,
|
|
2130
2349
|
firstTokenTimeout: 180000,
|
|
2131
|
-
supportedEfforts: ["low", "medium", "high", "xhigh", "max"]
|
|
2350
|
+
supportedEfforts: ["low", "medium", "high", "xhigh", "max"],
|
|
2351
|
+
supportsThinkingConfig: true
|
|
2132
2352
|
},
|
|
2133
2353
|
{
|
|
2134
2354
|
...KIRO_DEFAULTS,
|
|
@@ -2139,7 +2359,8 @@ var kiroModels = [
|
|
|
2139
2359
|
contextWindow: 1e6,
|
|
2140
2360
|
maxTokens: 128000,
|
|
2141
2361
|
firstTokenTimeout: 180000,
|
|
2142
|
-
supportedEfforts: ["low", "medium", "high", "xhigh", "max"]
|
|
2362
|
+
supportedEfforts: ["low", "medium", "high", "xhigh", "max"],
|
|
2363
|
+
supportsThinkingConfig: true
|
|
2143
2364
|
},
|
|
2144
2365
|
{
|
|
2145
2366
|
...KIRO_DEFAULTS,
|
|
@@ -2150,7 +2371,8 @@ var kiroModels = [
|
|
|
2150
2371
|
contextWindow: 1e6,
|
|
2151
2372
|
maxTokens: 128000,
|
|
2152
2373
|
firstTokenTimeout: 180000,
|
|
2153
|
-
supportedEfforts: ["low", "medium", "high", "xhigh", "max"]
|
|
2374
|
+
supportedEfforts: ["low", "medium", "high", "xhigh", "max"],
|
|
2375
|
+
supportsThinkingConfig: true
|
|
2154
2376
|
},
|
|
2155
2377
|
{
|
|
2156
2378
|
...KIRO_DEFAULTS,
|
|
@@ -2160,7 +2382,8 @@ var kiroModels = [
|
|
|
2160
2382
|
input: MULTIMODAL,
|
|
2161
2383
|
contextWindow: 1e6,
|
|
2162
2384
|
maxTokens: 64000,
|
|
2163
|
-
supportedEfforts: ["low", "medium", "high", "max"]
|
|
2385
|
+
supportedEfforts: ["low", "medium", "high", "max"],
|
|
2386
|
+
supportsThinkingConfig: true
|
|
2164
2387
|
},
|
|
2165
2388
|
{
|
|
2166
2389
|
...KIRO_DEFAULTS,
|
|
@@ -2170,7 +2393,8 @@ var kiroModels = [
|
|
|
2170
2393
|
input: MULTIMODAL,
|
|
2171
2394
|
contextWindow: 1e6,
|
|
2172
2395
|
maxTokens: 64000,
|
|
2173
|
-
supportedEfforts: ["low", "medium", "high", "max"]
|
|
2396
|
+
supportedEfforts: ["low", "medium", "high", "max"],
|
|
2397
|
+
supportsThinkingConfig: true
|
|
2174
2398
|
},
|
|
2175
2399
|
{
|
|
2176
2400
|
...KIRO_DEFAULTS,
|
|
@@ -2180,7 +2404,8 @@ var kiroModels = [
|
|
|
2180
2404
|
input: MULTIMODAL,
|
|
2181
2405
|
contextWindow: 1e6,
|
|
2182
2406
|
maxTokens: 64000,
|
|
2183
|
-
supportedEfforts: ["low", "medium", "high", "max"]
|
|
2407
|
+
supportedEfforts: ["low", "medium", "high", "max"],
|
|
2408
|
+
supportsThinkingConfig: true
|
|
2184
2409
|
},
|
|
2185
2410
|
{
|
|
2186
2411
|
...KIRO_DEFAULTS,
|
|
@@ -2190,7 +2415,8 @@ var kiroModels = [
|
|
|
2190
2415
|
input: MULTIMODAL,
|
|
2191
2416
|
contextWindow: 1e6,
|
|
2192
2417
|
maxTokens: 64000,
|
|
2193
|
-
supportedEfforts: ["low", "medium", "high", "max"]
|
|
2418
|
+
supportedEfforts: ["low", "medium", "high", "max"],
|
|
2419
|
+
supportsThinkingConfig: true
|
|
2194
2420
|
},
|
|
2195
2421
|
{
|
|
2196
2422
|
...KIRO_DEFAULTS,
|
|
@@ -2328,9 +2554,12 @@ var kiroModels = [
|
|
|
2328
2554
|
maxTokens: 65536
|
|
2329
2555
|
}
|
|
2330
2556
|
];
|
|
2331
|
-
async function fetchAvailableModels(accessToken, apiRegion) {
|
|
2557
|
+
async function fetchAvailableModels(accessToken, apiRegion, fallbackProfileArn) {
|
|
2332
2558
|
const runtimeUrl = `https://runtime.${apiRegion}.kiro.dev/`;
|
|
2333
|
-
|
|
2559
|
+
let profileArn = await resolveProfileArn(accessToken, runtimeUrl);
|
|
2560
|
+
if (!profileArn && fallbackProfileArn) {
|
|
2561
|
+
profileArn = fallbackProfileArn;
|
|
2562
|
+
}
|
|
2334
2563
|
if (!profileArn) {
|
|
2335
2564
|
throw new Error("Missing profileArn: cannot fetch available models.");
|
|
2336
2565
|
}
|
|
@@ -2518,7 +2747,7 @@ async function loginKiro(callbacks) {
|
|
|
2518
2747
|
options: [
|
|
2519
2748
|
{ id: "builder-id", label: "AWS Builder ID (personal account)" },
|
|
2520
2749
|
{ id: "idc", label: "IAM Identity Center (enterprise SSO)" },
|
|
2521
|
-
{ id: "sync", label: "Import from Kiro IDE (auto-sync local DB)" },
|
|
2750
|
+
{ id: "sync", label: "Import from Kiro CLI/IDE (auto-sync local DB)" },
|
|
2522
2751
|
{ id: "desktop", label: "Desktop refresh token (manual)" }
|
|
2523
2752
|
]
|
|
2524
2753
|
});
|
|
@@ -2564,22 +2793,13 @@ Alternatively, use 'desktop' to paste a refresh token manually.`);
|
|
|
2564
2793
|
callbacks.onProgress?.(`Imported from Kiro IDE (${imported.authMethod}, ${imported.region}${imported.email ? `, ${imported.email}` : ""})`);
|
|
2565
2794
|
try {
|
|
2566
2795
|
const apiRegion = resolveApiRegion(imported.region);
|
|
2567
|
-
const apiModels = await fetchAvailableModels(imported.accessToken, apiRegion);
|
|
2796
|
+
const apiModels = await fetchAvailableModels(imported.accessToken, apiRegion, imported.profileArn);
|
|
2568
2797
|
setCachedDynamicModels(buildModelsFromApi(apiModels));
|
|
2569
2798
|
log.info(`Fetched and cached ${apiModels.length} models after CLI sync`);
|
|
2570
2799
|
} catch (err) {
|
|
2571
2800
|
log.warn(`Failed to fetch models after CLI sync: ${err}`);
|
|
2572
2801
|
}
|
|
2573
|
-
|
|
2574
|
-
return {
|
|
2575
|
-
refresh: refreshPacked,
|
|
2576
|
-
access: imported.accessToken,
|
|
2577
|
-
expires: Date.now() + 3600000 - EXPIRES_BUFFER_MS,
|
|
2578
|
-
clientId: imported.clientId ?? "",
|
|
2579
|
-
clientSecret: imported.clientSecret ?? "",
|
|
2580
|
-
region: imported.region,
|
|
2581
|
-
authMethod: imported.authMethod
|
|
2582
|
-
};
|
|
2802
|
+
return kiroCredsFromCliImport(imported);
|
|
2583
2803
|
}
|
|
2584
2804
|
async function loginDesktopManual(callbacks) {
|
|
2585
2805
|
const refreshRaw = await callbacks.onPrompt({
|
|
@@ -2654,13 +2874,19 @@ Complete authorization within 10 minutes.`
|
|
|
2654
2874
|
};
|
|
2655
2875
|
}
|
|
2656
2876
|
async function syncBackToKiroCli(result) {
|
|
2877
|
+
if (result.kiroSyncSource !== "kiro-cli-db" || !result.kiroSyncTokenKey) {
|
|
2878
|
+
log.debug("Credential sync-back skipped: credential did not originate from kiro-cli DB");
|
|
2879
|
+
return;
|
|
2880
|
+
}
|
|
2657
2881
|
try {
|
|
2658
2882
|
const { saveKiroCliCredentials: saveKiroCliCredentials2 } = await Promise.resolve().then(() => (init_kiro_cli_sync(), exports_kiro_cli_sync));
|
|
2659
2883
|
const synced = await saveKiroCliCredentials2({
|
|
2660
2884
|
accessToken: result.access,
|
|
2661
2885
|
refreshToken: result.refresh.split("|")[0] ?? "",
|
|
2662
2886
|
region: result.region,
|
|
2663
|
-
authMethod: result.authMethod === "builder-id" ? "idc" : result.authMethod
|
|
2887
|
+
authMethod: result.authMethod === "builder-id" ? "idc" : result.authMethod,
|
|
2888
|
+
source: result.kiroSyncSource,
|
|
2889
|
+
tokenKey: result.kiroSyncTokenKey
|
|
2664
2890
|
});
|
|
2665
2891
|
if (synced)
|
|
2666
2892
|
log.info("Synced refreshed credentials back to Kiro CLI DB");
|
|
@@ -2669,8 +2895,9 @@ async function syncBackToKiroCli(result) {
|
|
|
2669
2895
|
}
|
|
2670
2896
|
}
|
|
2671
2897
|
function kiroCredsFromCliImport(imported) {
|
|
2672
|
-
const
|
|
2673
|
-
const
|
|
2898
|
+
const hasOidcCreds = !!imported.clientId && !!imported.clientSecret;
|
|
2899
|
+
const authMethod = hasOidcCreds && imported.authMethod === "idc" ? "idc" : "desktop";
|
|
2900
|
+
const refreshPacked = hasOidcCreds ? `${imported.refreshToken}|${imported.clientId}|${imported.clientSecret ?? ""}|${authMethod}` : `${imported.refreshToken}|||desktop`;
|
|
2674
2901
|
return {
|
|
2675
2902
|
refresh: refreshPacked,
|
|
2676
2903
|
access: imported.accessToken,
|
|
@@ -2678,7 +2905,9 @@ function kiroCredsFromCliImport(imported) {
|
|
|
2678
2905
|
clientId: imported.clientId ?? "",
|
|
2679
2906
|
clientSecret: imported.clientSecret ?? "",
|
|
2680
2907
|
region: imported.region,
|
|
2681
|
-
authMethod
|
|
2908
|
+
authMethod,
|
|
2909
|
+
kiroSyncSource: imported.source,
|
|
2910
|
+
kiroSyncTokenKey: imported.tokenKey
|
|
2682
2911
|
};
|
|
2683
2912
|
}
|
|
2684
2913
|
async function refreshTokenInner(credentials) {
|
|
@@ -2721,7 +2950,9 @@ async function refreshTokenInner(credentials) {
|
|
|
2721
2950
|
clientId: "",
|
|
2722
2951
|
clientSecret: "",
|
|
2723
2952
|
region,
|
|
2724
|
-
authMethod: "desktop"
|
|
2953
|
+
authMethod: "desktop",
|
|
2954
|
+
kiroSyncSource: credentials.kiroSyncSource,
|
|
2955
|
+
kiroSyncTokenKey: credentials.kiroSyncTokenKey
|
|
2725
2956
|
};
|
|
2726
2957
|
}
|
|
2727
2958
|
const endpoint = `https://oidc.${region}.amazonaws.com/token`;
|
|
@@ -2750,7 +2981,9 @@ async function refreshTokenInner(credentials) {
|
|
|
2750
2981
|
clientId,
|
|
2751
2982
|
clientSecret,
|
|
2752
2983
|
region,
|
|
2753
|
-
authMethod
|
|
2984
|
+
authMethod,
|
|
2985
|
+
kiroSyncSource: credentials.kiroSyncSource,
|
|
2986
|
+
kiroSyncTokenKey: credentials.kiroSyncTokenKey
|
|
2754
2987
|
};
|
|
2755
2988
|
}
|
|
2756
2989
|
async function refreshKiroToken(credentials) {
|
|
@@ -2812,14 +3045,15 @@ async function refreshKiroToken(credentials) {
|
|
|
2812
3045
|
try {
|
|
2813
3046
|
log.debug("refresh.cascade: layer 4 — expired kiro-cli import");
|
|
2814
3047
|
const { getKiroCliCredentialsAllowExpired: getKiroCliCredentialsAllowExpired2 } = await Promise.resolve().then(() => (init_kiro_cli_sync(), exports_kiro_cli_sync));
|
|
2815
|
-
expiredImport = await getKiroCliCredentialsAllowExpired2();
|
|
2816
|
-
if (expiredImport?.accessToken
|
|
3048
|
+
expiredImport = await getKiroCliCredentialsAllowExpired2(freshImport);
|
|
3049
|
+
if (expiredImport?.accessToken) {
|
|
2817
3050
|
const result = kiroCredsFromCliImport(expiredImport);
|
|
2818
3051
|
log.info("refresh.cascade: layer 4 succeeded — using expired kiro-cli credentials");
|
|
2819
3052
|
return result;
|
|
3053
|
+
} else {
|
|
3054
|
+
errors.push("L4(expired-import): no different expired credentials");
|
|
3055
|
+
log.debug("refresh.cascade: layer 4 — no additional expired credentials");
|
|
2820
3056
|
}
|
|
2821
|
-
errors.push("L4(expired-import): no different expired credentials");
|
|
2822
|
-
log.debug("refresh.cascade: layer 4 — no additional expired credentials");
|
|
2823
3057
|
} catch (err) {
|
|
2824
3058
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2825
3059
|
errors.push(`L4(expired-import): ${msg}`);
|