@zhafron/opencode-kiro-auth 1.6.6 → 1.7.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 +53 -8
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +13 -0
- package/dist/core/account/account-selector.js +0 -9
- package/dist/core/auth/auth-handler.js +25 -1
- package/dist/core/auth/idc-auth-method.d.ts +2 -3
- package/dist/core/auth/idc-auth-method.js +106 -167
- package/dist/core/request/error-handler.js +0 -2
- package/dist/infrastructure/database/account-repository.js +1 -0
- package/dist/kiro/oauth-idc.js +20 -6
- package/dist/plugin/accounts.js +2 -0
- package/dist/plugin/config/schema.d.ts +6 -0
- package/dist/plugin/config/schema.js +2 -0
- package/dist/plugin/logger.js +16 -1
- package/dist/plugin/request.js +2 -0
- package/dist/plugin/storage/migrations.js +14 -3
- package/dist/plugin/storage/sqlite.js +6 -5
- package/dist/plugin/sync/kiro-cli-profile.d.ts +1 -0
- package/dist/plugin/sync/kiro-cli-profile.js +30 -0
- package/dist/plugin/sync/kiro-cli.js +36 -9
- package/dist/plugin/token.js +4 -1
- package/dist/plugin/types.d.ts +2 -0
- package/dist/plugin/usage.js +19 -4
- package/package.json +1 -1
- package/dist/plugin/cli.d.ts +0 -8
- package/dist/plugin/cli.js +0 -103
- package/dist/plugin/server.d.ts +0 -34
- package/dist/plugin/server.js +0 -362
|
@@ -39,6 +39,8 @@ export const RegionSchema = z.enum([
|
|
|
39
39
|
export const KiroConfigSchema = z.object({
|
|
40
40
|
$schema: z.string().optional(),
|
|
41
41
|
idc_start_url: z.string().url().optional(),
|
|
42
|
+
idc_region: RegionSchema.optional(),
|
|
43
|
+
idc_profile_arn: z.string().optional(),
|
|
42
44
|
account_selection_strategy: AccountSelectionStrategySchema.default('lowest-usage'),
|
|
43
45
|
default_region: RegionSchema.default('us-east-1'),
|
|
44
46
|
rate_limit_retry_delay_ms: z.number().min(1000).max(60000).default(5000),
|
package/dist/plugin/logger.js
CHANGED
|
@@ -14,7 +14,22 @@ const writeToFile = (level, message, ...args) => {
|
|
|
14
14
|
mkdirSync(dir, { recursive: true });
|
|
15
15
|
const path = join(dir, 'plugin.log');
|
|
16
16
|
const timestamp = new Date().toISOString();
|
|
17
|
-
const content = `[${timestamp}] ${level}: ${message} ${args
|
|
17
|
+
const content = `[${timestamp}] ${level}: ${message} ${args
|
|
18
|
+
.map((a) => {
|
|
19
|
+
if (a instanceof Error) {
|
|
20
|
+
return `${a.name}: ${a.message}${a.stack ? `\n${a.stack}` : ''}`;
|
|
21
|
+
}
|
|
22
|
+
if (typeof a === 'object') {
|
|
23
|
+
try {
|
|
24
|
+
return JSON.stringify(a);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return '[Unserializable object]';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return String(a);
|
|
31
|
+
})
|
|
32
|
+
.join(' ')}\n`;
|
|
18
33
|
appendFileSync(path, content);
|
|
19
34
|
}
|
|
20
35
|
catch (e) { }
|
package/dist/plugin/request.js
CHANGED
|
@@ -135,6 +135,8 @@ export function transformToCodeWhisperer(url, body, model, auth, think = false,
|
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
};
|
|
138
|
+
if (auth.profileArn)
|
|
139
|
+
request.profileArn = auth.profileArn;
|
|
138
140
|
const toolUsesInHistory = history.flatMap((h) => h.assistantResponseMessage?.toolUses || []);
|
|
139
141
|
const allToolUseIdsInHistory = new Set(toolUsesInHistory.map((tu) => tu.toolUseId));
|
|
140
142
|
const finalCurTrs = [];
|
|
@@ -3,6 +3,7 @@ export function runMigrations(db) {
|
|
|
3
3
|
migrateRealEmailColumn(db);
|
|
4
4
|
migrateUsageTable(db);
|
|
5
5
|
migrateStartUrlColumn(db);
|
|
6
|
+
migrateOidcRegionColumn(db);
|
|
6
7
|
}
|
|
7
8
|
function migrateToUniqueRefreshToken(db) {
|
|
8
9
|
const hasIndex = db
|
|
@@ -62,7 +63,8 @@ function migrateRealEmailColumn(db) {
|
|
|
62
63
|
db.run(`
|
|
63
64
|
CREATE TABLE accounts_new (
|
|
64
65
|
id TEXT PRIMARY KEY, email TEXT NOT NULL, auth_method TEXT NOT NULL,
|
|
65
|
-
region TEXT NOT NULL, client_id TEXT, client_secret TEXT, profile_arn TEXT,
|
|
66
|
+
region TEXT NOT NULL, oidc_region TEXT, client_id TEXT, client_secret TEXT, profile_arn TEXT,
|
|
67
|
+
start_url TEXT,
|
|
66
68
|
refresh_token TEXT NOT NULL, access_token TEXT NOT NULL, expires_at INTEGER NOT NULL,
|
|
67
69
|
rate_limit_reset INTEGER DEFAULT 0, is_healthy INTEGER DEFAULT 1, unhealthy_reason TEXT,
|
|
68
70
|
recovery_time INTEGER, fail_count INTEGER DEFAULT 0, last_used INTEGER DEFAULT 0,
|
|
@@ -70,8 +72,8 @@ function migrateRealEmailColumn(db) {
|
|
|
70
72
|
)
|
|
71
73
|
`);
|
|
72
74
|
db.run(`
|
|
73
|
-
INSERT INTO accounts_new (id, email, auth_method, region, client_id, client_secret, profile_arn, refresh_token, access_token, expires_at, rate_limit_reset, is_healthy, unhealthy_reason, recovery_time, fail_count, last_used, used_count, limit_count, last_sync)
|
|
74
|
-
SELECT id, email, auth_method, region, client_id, client_secret, profile_arn, refresh_token, access_token, expires_at, COALESCE(rate_limit_reset, 0), COALESCE(is_healthy, 1), unhealthy_reason, recovery_time, COALESCE(fail_count, 0), COALESCE(last_used, 0), 0, 0, 0 FROM accounts
|
|
75
|
+
INSERT INTO accounts_new (id, email, auth_method, region, oidc_region, client_id, client_secret, profile_arn, start_url, refresh_token, access_token, expires_at, rate_limit_reset, is_healthy, unhealthy_reason, recovery_time, fail_count, last_used, used_count, limit_count, last_sync)
|
|
76
|
+
SELECT id, email, auth_method, region, NULL, client_id, client_secret, profile_arn, NULL, refresh_token, access_token, expires_at, COALESCE(rate_limit_reset, 0), COALESCE(is_healthy, 1), unhealthy_reason, recovery_time, COALESCE(fail_count, 0), COALESCE(last_used, 0), 0, 0, 0 FROM accounts
|
|
75
77
|
`);
|
|
76
78
|
db.run('DROP TABLE accounts');
|
|
77
79
|
db.run('ALTER TABLE accounts_new RENAME TO accounts');
|
|
@@ -115,3 +117,12 @@ function migrateStartUrlColumn(db) {
|
|
|
115
117
|
db.run('ALTER TABLE accounts ADD COLUMN start_url TEXT');
|
|
116
118
|
}
|
|
117
119
|
}
|
|
120
|
+
function migrateOidcRegionColumn(db) {
|
|
121
|
+
const columns = db.prepare('PRAGMA table_info(accounts)').all();
|
|
122
|
+
const names = new Set(columns.map((c) => c.name));
|
|
123
|
+
if (!names.has('oidc_region')) {
|
|
124
|
+
db.run('ALTER TABLE accounts ADD COLUMN oidc_region TEXT');
|
|
125
|
+
}
|
|
126
|
+
// Backfill: historically `region` was used for both service + OIDC.
|
|
127
|
+
db.run('UPDATE accounts SET oidc_region = region WHERE oidc_region IS NULL OR oidc_region = \"\"');
|
|
128
|
+
}
|
|
@@ -28,7 +28,7 @@ export class KiroDatabase {
|
|
|
28
28
|
this.db.run(`
|
|
29
29
|
CREATE TABLE IF NOT EXISTS accounts (
|
|
30
30
|
id TEXT PRIMARY KEY, email TEXT NOT NULL, auth_method TEXT NOT NULL,
|
|
31
|
-
region TEXT NOT NULL, client_id TEXT, client_secret TEXT, profile_arn TEXT,
|
|
31
|
+
region TEXT NOT NULL, oidc_region TEXT, client_id TEXT, client_secret TEXT, profile_arn TEXT,
|
|
32
32
|
start_url TEXT,
|
|
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,
|
|
@@ -45,14 +45,14 @@ export class KiroDatabase {
|
|
|
45
45
|
this.db
|
|
46
46
|
.prepare(`
|
|
47
47
|
INSERT INTO accounts (
|
|
48
|
-
id, email, auth_method, region, client_id, client_secret,
|
|
48
|
+
id, email, auth_method, region, oidc_region, client_id, client_secret,
|
|
49
49
|
profile_arn, start_url, refresh_token, access_token, expires_at, rate_limit_reset,
|
|
50
50
|
is_healthy, unhealthy_reason, recovery_time, fail_count, last_used,
|
|
51
51
|
used_count, limit_count, last_sync
|
|
52
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
52
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
53
53
|
ON CONFLICT(refresh_token) DO UPDATE SET
|
|
54
54
|
id=excluded.id, email=excluded.email, auth_method=excluded.auth_method,
|
|
55
|
-
region=excluded.region, client_id=excluded.client_id, client_secret=excluded.client_secret,
|
|
55
|
+
region=excluded.region, oidc_region=excluded.oidc_region, client_id=excluded.client_id, client_secret=excluded.client_secret,
|
|
56
56
|
profile_arn=excluded.profile_arn, start_url=excluded.start_url,
|
|
57
57
|
access_token=excluded.access_token, expires_at=excluded.expires_at,
|
|
58
58
|
rate_limit_reset=excluded.rate_limit_reset, is_healthy=excluded.is_healthy,
|
|
@@ -60,7 +60,7 @@ export class KiroDatabase {
|
|
|
60
60
|
fail_count=excluded.fail_count, last_used=excluded.last_used,
|
|
61
61
|
used_count=excluded.used_count, limit_count=excluded.limit_count, last_sync=excluded.last_sync
|
|
62
62
|
`)
|
|
63
|
-
.run(acc.id, acc.email, acc.authMethod, acc.region, 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);
|
|
63
|
+
.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);
|
|
64
64
|
}
|
|
65
65
|
async upsertAccount(acc) {
|
|
66
66
|
await withDatabaseLock(this.path, async () => {
|
|
@@ -109,6 +109,7 @@ export class KiroDatabase {
|
|
|
109
109
|
email: row.email,
|
|
110
110
|
authMethod: row.auth_method,
|
|
111
111
|
region: row.region,
|
|
112
|
+
oidcRegion: row.oidc_region || undefined,
|
|
112
113
|
clientId: row.client_id,
|
|
113
114
|
clientSecret: row.client_secret,
|
|
114
115
|
profileArn: row.profile_arn,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function readActiveProfileArnFromKiroCli(): string | undefined;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Database } from 'bun:sqlite';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { getCliDbPath, safeJsonParse } from './kiro-cli-parser';
|
|
4
|
+
export function readActiveProfileArnFromKiroCli() {
|
|
5
|
+
const dbPath = getCliDbPath();
|
|
6
|
+
if (!existsSync(dbPath))
|
|
7
|
+
return undefined;
|
|
8
|
+
let cliDb;
|
|
9
|
+
try {
|
|
10
|
+
cliDb = new Database(dbPath, { readonly: true });
|
|
11
|
+
cliDb.run('PRAGMA busy_timeout = 5000');
|
|
12
|
+
const row = cliDb
|
|
13
|
+
.prepare('SELECT value FROM state WHERE key = ?')
|
|
14
|
+
.get('api.codewhisperer.profile');
|
|
15
|
+
const parsed = safeJsonParse(row?.value);
|
|
16
|
+
const arn = parsed?.arn || parsed?.profileArn || parsed?.profile_arn;
|
|
17
|
+
return typeof arn === 'string' && arn.trim() ? arn.trim() : undefined;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
try {
|
|
24
|
+
cliDb?.close();
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// ignore
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Database } from 'bun:sqlite';
|
|
2
2
|
import { existsSync } from 'node:fs';
|
|
3
|
+
import { extractRegionFromArn, normalizeRegion } from '../../constants';
|
|
3
4
|
import { createDeterministicAccountId } from '../accounts';
|
|
4
5
|
import * as logger from '../logger';
|
|
5
6
|
import { kiroDb } from '../storage/sqlite';
|
|
6
7
|
import { fetchUsageLimits } from '../usage';
|
|
7
8
|
import { findClientCredsRecursive, getCliDbPath, makePlaceholderEmail, normalizeExpiresAt, safeJsonParse } from './kiro-cli-parser';
|
|
9
|
+
import { readActiveProfileArnFromKiroCli } from './kiro-cli-profile';
|
|
8
10
|
export async function syncFromKiroCli() {
|
|
9
11
|
const dbPath = getCliDbPath();
|
|
10
12
|
if (!existsSync(dbPath))
|
|
@@ -13,6 +15,19 @@ export async function syncFromKiroCli() {
|
|
|
13
15
|
const cliDb = new Database(dbPath, { readonly: true });
|
|
14
16
|
cliDb.run('PRAGMA busy_timeout = 5000');
|
|
15
17
|
const rows = cliDb.prepare('SELECT key, value FROM auth_kv').all();
|
|
18
|
+
let activeProfileArn;
|
|
19
|
+
try {
|
|
20
|
+
const stateRow = cliDb
|
|
21
|
+
.prepare('SELECT value FROM state WHERE key = ?')
|
|
22
|
+
.get('api.codewhisperer.profile');
|
|
23
|
+
const parsed = safeJsonParse(stateRow?.value);
|
|
24
|
+
const arn = parsed?.arn || parsed?.profileArn || parsed?.profile_arn;
|
|
25
|
+
if (typeof arn === 'string' && arn.trim())
|
|
26
|
+
activeProfileArn = arn.trim();
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// Ignore state read failures; token import can proceed.
|
|
30
|
+
}
|
|
16
31
|
const deviceRegRow = rows.find((r) => typeof r?.key === 'string' && r.key.includes('device-registration'));
|
|
17
32
|
const deviceReg = safeJsonParse(deviceRegRow?.value);
|
|
18
33
|
const regCreds = deviceReg ? findClientCredsRecursive(deviceReg) : {};
|
|
@@ -23,8 +38,16 @@ export async function syncFromKiroCli() {
|
|
|
23
38
|
continue;
|
|
24
39
|
const isIdc = row.key.includes('odic');
|
|
25
40
|
const authMethod = isIdc ? 'idc' : 'desktop';
|
|
26
|
-
const
|
|
27
|
-
|
|
41
|
+
const oidcRegion = normalizeRegion(data.region);
|
|
42
|
+
let profileArn = data.profile_arn || data.profileArn;
|
|
43
|
+
if (!profileArn && isIdc)
|
|
44
|
+
profileArn = activeProfileArn || readActiveProfileArnFromKiroCli();
|
|
45
|
+
const serviceRegion = extractRegionFromArn(profileArn) || oidcRegion;
|
|
46
|
+
const startUrl = typeof data.start_url === 'string'
|
|
47
|
+
? data.start_url
|
|
48
|
+
: typeof data.startUrl === 'string'
|
|
49
|
+
? data.startUrl
|
|
50
|
+
: undefined;
|
|
28
51
|
const accessToken = data.access_token || data.accessToken || '';
|
|
29
52
|
const refreshToken = data.refresh_token || data.refreshToken;
|
|
30
53
|
if (!refreshToken)
|
|
@@ -46,7 +69,7 @@ export async function syncFromKiroCli() {
|
|
|
46
69
|
access: accessToken,
|
|
47
70
|
expires: cliExpiresAt,
|
|
48
71
|
authMethod,
|
|
49
|
-
region,
|
|
72
|
+
region: serviceRegion,
|
|
50
73
|
profileArn,
|
|
51
74
|
clientId,
|
|
52
75
|
clientSecret,
|
|
@@ -63,7 +86,8 @@ export async function syncFromKiroCli() {
|
|
|
63
86
|
catch (e) {
|
|
64
87
|
logger.warn('Kiro CLI sync: failed to fetch usage/email; falling back', {
|
|
65
88
|
authMethod,
|
|
66
|
-
|
|
89
|
+
serviceRegion,
|
|
90
|
+
oidcRegion
|
|
67
91
|
});
|
|
68
92
|
logger.debug('Kiro CLI sync: usage fetch error', e);
|
|
69
93
|
}
|
|
@@ -80,10 +104,10 @@ export async function syncFromKiroCli() {
|
|
|
80
104
|
email = existing.email;
|
|
81
105
|
}
|
|
82
106
|
else {
|
|
83
|
-
email = makePlaceholderEmail(authMethod,
|
|
107
|
+
email = makePlaceholderEmail(authMethod, serviceRegion, clientId, profileArn);
|
|
84
108
|
}
|
|
85
109
|
}
|
|
86
|
-
const resolvedEmail = email || makePlaceholderEmail(authMethod,
|
|
110
|
+
const resolvedEmail = email || makePlaceholderEmail(authMethod, serviceRegion, clientId, profileArn);
|
|
87
111
|
const id = createDeterministicAccountId(resolvedEmail, authMethod, clientId, profileArn);
|
|
88
112
|
const existingById = all.find((a) => a.id === id);
|
|
89
113
|
if (existingById &&
|
|
@@ -91,7 +115,7 @@ export async function syncFromKiroCli() {
|
|
|
91
115
|
existingById.expires_at >= cliExpiresAt)
|
|
92
116
|
continue;
|
|
93
117
|
if (usageOk) {
|
|
94
|
-
const placeholderEmail = makePlaceholderEmail(authMethod,
|
|
118
|
+
const placeholderEmail = makePlaceholderEmail(authMethod, serviceRegion, clientId, profileArn);
|
|
95
119
|
const placeholderId = createDeterministicAccountId(placeholderEmail, authMethod, clientId, profileArn);
|
|
96
120
|
if (placeholderId !== id) {
|
|
97
121
|
const placeholderRow = all.find((a) => a.id === placeholderId);
|
|
@@ -100,7 +124,8 @@ export async function syncFromKiroCli() {
|
|
|
100
124
|
id: placeholderId,
|
|
101
125
|
email: placeholderRow.email,
|
|
102
126
|
authMethod,
|
|
103
|
-
region: placeholderRow.region ||
|
|
127
|
+
region: placeholderRow.region || serviceRegion,
|
|
128
|
+
oidcRegion: placeholderRow.oidc_region || oidcRegion,
|
|
104
129
|
clientId,
|
|
105
130
|
clientSecret,
|
|
106
131
|
profileArn,
|
|
@@ -123,10 +148,12 @@ export async function syncFromKiroCli() {
|
|
|
123
148
|
id,
|
|
124
149
|
email: resolvedEmail,
|
|
125
150
|
authMethod,
|
|
126
|
-
region,
|
|
151
|
+
region: serviceRegion,
|
|
152
|
+
oidcRegion,
|
|
127
153
|
clientId,
|
|
128
154
|
clientSecret,
|
|
129
155
|
profileArn,
|
|
156
|
+
startUrl,
|
|
130
157
|
refreshToken,
|
|
131
158
|
accessToken,
|
|
132
159
|
expiresAt: cliExpiresAt,
|
package/dist/plugin/token.js
CHANGED
|
@@ -3,8 +3,9 @@ import { KiroTokenRefreshError } from './errors';
|
|
|
3
3
|
export async function refreshAccessToken(auth) {
|
|
4
4
|
const p = decodeRefreshToken(auth.refresh);
|
|
5
5
|
const isIdc = auth.authMethod === 'idc';
|
|
6
|
+
const oidcRegion = auth.oidcRegion || auth.region;
|
|
6
7
|
const url = isIdc
|
|
7
|
-
? `https://oidc.${
|
|
8
|
+
? `https://oidc.${oidcRegion}.amazonaws.com/token`
|
|
8
9
|
: `https://prod.${auth.region}.auth.desktop.kiro.dev/refreshToken`;
|
|
9
10
|
if (isIdc && (!p.clientId || !p.clientSecret)) {
|
|
10
11
|
throw new KiroTokenRefreshError('Missing creds', 'MISSING_CREDENTIALS');
|
|
@@ -62,6 +63,8 @@ export async function refreshAccessToken(auth) {
|
|
|
62
63
|
expires: Date.now() + (d.expires_in || d.expiresIn || 3600) * 1000,
|
|
63
64
|
authMethod: auth.authMethod,
|
|
64
65
|
region: auth.region,
|
|
66
|
+
oidcRegion: auth.oidcRegion,
|
|
67
|
+
profileArn: auth.profileArn,
|
|
65
68
|
clientId: auth.clientId,
|
|
66
69
|
clientSecret: auth.clientSecret,
|
|
67
70
|
email: auth.email || d.userInfo?.email
|
package/dist/plugin/types.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface KiroAuthDetails {
|
|
|
8
8
|
expires: number;
|
|
9
9
|
authMethod: KiroAuthMethod;
|
|
10
10
|
region: KiroRegion;
|
|
11
|
+
oidcRegion?: KiroRegion;
|
|
11
12
|
clientId?: string;
|
|
12
13
|
clientSecret?: string;
|
|
13
14
|
email?: string;
|
|
@@ -25,6 +26,7 @@ export interface ManagedAccount {
|
|
|
25
26
|
email: string;
|
|
26
27
|
authMethod: KiroAuthMethod;
|
|
27
28
|
region: KiroRegion;
|
|
29
|
+
oidcRegion?: KiroRegion;
|
|
28
30
|
clientId?: string;
|
|
29
31
|
clientSecret?: string;
|
|
30
32
|
profileArn?: string;
|
package/dist/plugin/usage.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
export async function fetchUsageLimits(auth) {
|
|
2
|
-
const url = `https://q.${auth.region}.amazonaws.com/getUsageLimits
|
|
2
|
+
const url = new URL(`https://q.${auth.region}.amazonaws.com/getUsageLimits`);
|
|
3
|
+
url.searchParams.set('isEmailRequired', 'true');
|
|
4
|
+
url.searchParams.set('origin', 'AI_EDITOR');
|
|
5
|
+
url.searchParams.set('resourceType', 'AGENTIC_REQUEST');
|
|
6
|
+
if (auth.profileArn)
|
|
7
|
+
url.searchParams.set('profileArn', auth.profileArn);
|
|
3
8
|
try {
|
|
4
|
-
const res = await fetch(url, {
|
|
9
|
+
const res = await fetch(url.toString(), {
|
|
5
10
|
method: 'GET',
|
|
6
11
|
headers: {
|
|
7
12
|
Authorization: `Bearer ${auth.access}`,
|
|
@@ -10,8 +15,18 @@ export async function fetchUsageLimits(auth) {
|
|
|
10
15
|
'amz-sdk-request': 'attempt=1; max=1'
|
|
11
16
|
}
|
|
12
17
|
});
|
|
13
|
-
if (!res.ok)
|
|
14
|
-
|
|
18
|
+
if (!res.ok) {
|
|
19
|
+
const body = await res.text().catch(() => '');
|
|
20
|
+
const requestId = res.headers.get('x-amzn-requestid') ||
|
|
21
|
+
res.headers.get('x-amzn-request-id') ||
|
|
22
|
+
res.headers.get('x-amz-request-id') ||
|
|
23
|
+
'';
|
|
24
|
+
const errType = res.headers.get('x-amzn-errortype') || res.headers.get('x-amzn-error-type') || '';
|
|
25
|
+
const msg = body && body.length > 0
|
|
26
|
+
? `${body.slice(0, 2000)}${body.length > 2000 ? '…' : ''}`
|
|
27
|
+
: `HTTP ${res.status}`;
|
|
28
|
+
throw new Error(`Status: ${res.status}${errType ? ` (${errType})` : ''}${requestId ? ` [${requestId}]` : ''}: ${msg}`);
|
|
29
|
+
}
|
|
15
30
|
const data = await res.json();
|
|
16
31
|
let usedCount = 0, limitCount = 0;
|
|
17
32
|
if (Array.isArray(data.usageBreakdownList)) {
|
package/package.json
CHANGED
package/dist/plugin/cli.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export declare function promptAddAnotherAccount(currentCount: number): Promise<boolean>;
|
|
2
|
-
export declare function promptDeleteAccount(accounts: ExistingAccountInfo[]): Promise<number[] | null>;
|
|
3
|
-
export type LoginMode = 'add' | 'fresh' | 'delete';
|
|
4
|
-
export interface ExistingAccountInfo {
|
|
5
|
-
email?: string;
|
|
6
|
-
index: number;
|
|
7
|
-
}
|
|
8
|
-
export declare function promptLoginMode(existingAccounts: ExistingAccountInfo[]): Promise<LoginMode>;
|
package/dist/plugin/cli.js
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { stdin as input, stdout as output } from 'node:process';
|
|
2
|
-
import { createInterface } from 'node:readline/promises';
|
|
3
|
-
export async function promptAddAnotherAccount(currentCount) {
|
|
4
|
-
const rl = createInterface({ input, output });
|
|
5
|
-
try {
|
|
6
|
-
const answer = await rl.question(`Add another account? (${currentCount} added) (y/n): `);
|
|
7
|
-
const normalized = answer.trim().toLowerCase();
|
|
8
|
-
return normalized === 'y' || normalized === 'yes';
|
|
9
|
-
}
|
|
10
|
-
finally {
|
|
11
|
-
rl.close();
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
export async function promptDeleteAccount(accounts) {
|
|
15
|
-
const rl = createInterface({ input, output });
|
|
16
|
-
try {
|
|
17
|
-
console.log(`\nSelect account(s) to delete:`);
|
|
18
|
-
for (const acc of accounts) {
|
|
19
|
-
const label = acc.email || `Account ${acc.index + 1}`;
|
|
20
|
-
console.log(` ${acc.index + 1}. ${label}`);
|
|
21
|
-
}
|
|
22
|
-
console.log(` 0. Cancel`);
|
|
23
|
-
console.log('');
|
|
24
|
-
while (true) {
|
|
25
|
-
const answer = await rl.question('Enter account number(s) (e.g., 1,2,3 or 1): ');
|
|
26
|
-
const trimmed = answer.trim();
|
|
27
|
-
if (trimmed === '0') {
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
const parts = trimmed.split(',').map((s) => s.trim());
|
|
31
|
-
const numbers = [];
|
|
32
|
-
let invalid = false;
|
|
33
|
-
for (const part of parts) {
|
|
34
|
-
const num = parseInt(part, 10);
|
|
35
|
-
if (isNaN(num) || num < 1 || num > accounts.length) {
|
|
36
|
-
invalid = true;
|
|
37
|
-
break;
|
|
38
|
-
}
|
|
39
|
-
if (!numbers.includes(num)) {
|
|
40
|
-
numbers.push(num);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
if (invalid) {
|
|
44
|
-
console.log(`Please enter valid numbers between 1 and ${accounts.length}, separated by commas`);
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
if (numbers.length === 0) {
|
|
48
|
-
console.log(`Please enter at least one account number`);
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
const indices = numbers.map((n) => n - 1);
|
|
52
|
-
const selectedAccounts = indices
|
|
53
|
-
.map((i) => accounts[i])
|
|
54
|
-
.filter((acc) => acc !== undefined);
|
|
55
|
-
if (selectedAccounts.length === 0) {
|
|
56
|
-
console.log(`No valid accounts selected`);
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
console.log(`\nYou are about to delete ${selectedAccounts.length} account(s):`);
|
|
60
|
-
for (const acc of selectedAccounts) {
|
|
61
|
-
const label = acc.email || `Account ${acc.index + 1}`;
|
|
62
|
-
console.log(` - ${label}`);
|
|
63
|
-
}
|
|
64
|
-
const confirm = await rl.question(`\nConfirm deletion? (y/n): `);
|
|
65
|
-
const normalized = confirm.trim().toLowerCase();
|
|
66
|
-
if (normalized === 'y' || normalized === 'yes') {
|
|
67
|
-
return selectedAccounts.map((acc) => acc.index);
|
|
68
|
-
}
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
finally {
|
|
73
|
-
rl.close();
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
export async function promptLoginMode(existingAccounts) {
|
|
77
|
-
const rl = createInterface({ input, output });
|
|
78
|
-
try {
|
|
79
|
-
console.log(`\n${existingAccounts.length} account(s) saved:`);
|
|
80
|
-
for (const acc of existingAccounts) {
|
|
81
|
-
const label = acc.email || `Account ${acc.index + 1}`;
|
|
82
|
-
console.log(` ${acc.index + 1}. ${label}`);
|
|
83
|
-
}
|
|
84
|
-
console.log('');
|
|
85
|
-
while (true) {
|
|
86
|
-
const answer = await rl.question('(a)dd new account(s), (f)resh start, or (d)elete account? [a/f/d]: ');
|
|
87
|
-
const normalized = answer.trim().toLowerCase();
|
|
88
|
-
if (normalized === 'a' || normalized === 'add') {
|
|
89
|
-
return 'add';
|
|
90
|
-
}
|
|
91
|
-
if (normalized === 'f' || normalized === 'fresh') {
|
|
92
|
-
return 'fresh';
|
|
93
|
-
}
|
|
94
|
-
if (normalized === 'd' || normalized === 'delete') {
|
|
95
|
-
return 'delete';
|
|
96
|
-
}
|
|
97
|
-
console.log("Please enter 'a' to add accounts, 'f' to start fresh, or 'd' to delete account.");
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
finally {
|
|
101
|
-
rl.close();
|
|
102
|
-
}
|
|
103
|
-
}
|
package/dist/plugin/server.d.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { KiroRegion } from './types';
|
|
2
|
-
export interface KiroIDCTokenResult {
|
|
3
|
-
email: string;
|
|
4
|
-
accessToken: string;
|
|
5
|
-
refreshToken: string;
|
|
6
|
-
expiresAt: number;
|
|
7
|
-
clientId: string;
|
|
8
|
-
clientSecret: string;
|
|
9
|
-
}
|
|
10
|
-
export interface IDCAuthData {
|
|
11
|
-
verificationUrl: string;
|
|
12
|
-
verificationUriComplete: string;
|
|
13
|
-
userCode: string;
|
|
14
|
-
deviceCode: string;
|
|
15
|
-
clientId: string;
|
|
16
|
-
clientSecret: string;
|
|
17
|
-
interval: number;
|
|
18
|
-
expiresIn: number;
|
|
19
|
-
region: KiroRegion;
|
|
20
|
-
startUrl: string;
|
|
21
|
-
}
|
|
22
|
-
export declare function startIDCAuthServer(authData: IDCAuthData, startPort?: number, portRange?: number): Promise<{
|
|
23
|
-
url: string;
|
|
24
|
-
waitForAuth: () => Promise<KiroIDCTokenResult>;
|
|
25
|
-
}>;
|
|
26
|
-
/**
|
|
27
|
-
* Starts a local auth server that first shows a Start URL input page.
|
|
28
|
-
* After the user submits, it calls authorizeKiroIDC internally and transitions
|
|
29
|
-
* to the verification code page — no need to call authorizeKiroIDC beforehand.
|
|
30
|
-
*/
|
|
31
|
-
export declare function startIDCAuthServerWithInput(region: KiroRegion, defaultStartUrl: string | undefined, startPort?: number, portRange?: number): Promise<{
|
|
32
|
-
url: string;
|
|
33
|
-
waitForAuth: () => Promise<KiroIDCTokenResult>;
|
|
34
|
-
}>;
|