@javargasm/pi-kiro 0.4.4 → 0.4.5
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 +10 -0
- package/dist/core.js +439 -10
- package/dist/extension.d.ts.map +1 -1
- package/dist/extension.js +480 -21
- package/dist/models.d.ts +6 -0
- package/dist/models.d.ts.map +1 -1
- package/dist/oauth.d.ts +1 -1
- package/dist/oauth.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fix: resolve profileArn automatically for Builder ID accounts
|
|
8
|
+
|
|
9
|
+
Builder ID device-code login never receives a profileArn, which prevented
|
|
10
|
+
model fetching and streaming. Now the startup resolves it via
|
|
11
|
+
`ListAvailableProfiles` and persists it to auth.json.
|
|
12
|
+
|
|
3
13
|
## 0.4.4
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
package/dist/core.js
CHANGED
|
@@ -897,6 +897,24 @@ var kiroModels = [
|
|
|
897
897
|
maxTokens: 65536
|
|
898
898
|
}
|
|
899
899
|
];
|
|
900
|
+
async function resolveProfileArn(accessToken, apiRegion) {
|
|
901
|
+
const resp = await fetch(`https://management.${apiRegion}.kiro.dev/`, {
|
|
902
|
+
method: "POST",
|
|
903
|
+
headers: {
|
|
904
|
+
Authorization: `Bearer ${accessToken}`,
|
|
905
|
+
"Content-Type": "application/x-amz-json-1.0",
|
|
906
|
+
"X-Amz-Target": "AmazonCodeWhispererService.ListAvailableProfiles",
|
|
907
|
+
"User-Agent": "pi-kiro"
|
|
908
|
+
},
|
|
909
|
+
body: "{}"
|
|
910
|
+
});
|
|
911
|
+
if (!resp.ok)
|
|
912
|
+
return null;
|
|
913
|
+
const data = await resp.json();
|
|
914
|
+
const profiles = data.profiles ?? [];
|
|
915
|
+
const kiroProfile = profiles.find((p) => p.profileType === "KIRO" && p.status === "ACTIVE");
|
|
916
|
+
return kiroProfile?.arn ?? profiles[0]?.arn ?? null;
|
|
917
|
+
}
|
|
900
918
|
async function fetchAvailableModels(accessToken, apiRegion, profileArn) {
|
|
901
919
|
const url = `https://management.${apiRegion}.kiro.dev/?origin=KIRO_CLI&profileArn=${encodeURIComponent(profileArn)}`;
|
|
902
920
|
const resp = await fetch(url, {
|
|
@@ -980,6 +998,8 @@ function setCachedDynamicModels(models) {
|
|
|
980
998
|
}
|
|
981
999
|
|
|
982
1000
|
// src/oauth.ts
|
|
1001
|
+
import { createServer } from "node:http";
|
|
1002
|
+
import { randomBytes, createHash } from "node:crypto";
|
|
983
1003
|
var BUILDER_ID_START_URL = "https://view.awsapps.com/start";
|
|
984
1004
|
var BUILDER_ID_REGION = "us-east-1";
|
|
985
1005
|
var SSO_SCOPES = [
|
|
@@ -1089,6 +1109,415 @@ async function pollForToken(oidcEndpoint, clientId, clientSecret, devAuth, signa
|
|
|
1089
1109
|
}
|
|
1090
1110
|
throw new Error("Authorization timed out");
|
|
1091
1111
|
}
|
|
1112
|
+
var KIRO_SOCIAL_PORTAL = "https://app.kiro.dev";
|
|
1113
|
+
var KIRO_SOCIAL_AUTH_ENDPOINT = `https://prod.${BUILDER_ID_REGION}.auth.desktop.kiro.dev`;
|
|
1114
|
+
var SOCIAL_REDIRECT_PORT = 49153;
|
|
1115
|
+
var SOCIAL_REDIRECT_URI = `http://localhost:${SOCIAL_REDIRECT_PORT}`;
|
|
1116
|
+
function generateRandomState() {
|
|
1117
|
+
return randomBytes(16).toString("base64url");
|
|
1118
|
+
}
|
|
1119
|
+
function generateCodeVerifier() {
|
|
1120
|
+
return randomBytes(32).toString("base64url");
|
|
1121
|
+
}
|
|
1122
|
+
function generateCodeChallenge(verifier) {
|
|
1123
|
+
return createHash("sha256").update(verifier).digest("base64url");
|
|
1124
|
+
}
|
|
1125
|
+
function buildSocialSignInURL(redirectUri, codeChallenge, state) {
|
|
1126
|
+
const params = new URLSearchParams;
|
|
1127
|
+
params.set("code_challenge", codeChallenge);
|
|
1128
|
+
params.set("code_challenge_method", "S256");
|
|
1129
|
+
params.set("redirect_from", "kirocli");
|
|
1130
|
+
params.set("redirect_uri", redirectUri);
|
|
1131
|
+
params.set("state", state);
|
|
1132
|
+
return `${KIRO_SOCIAL_PORTAL}/signin?${params.toString()}`;
|
|
1133
|
+
}
|
|
1134
|
+
function parseAuthRedirectInput(input) {
|
|
1135
|
+
const trimmed = input.trim();
|
|
1136
|
+
if (!trimmed)
|
|
1137
|
+
return {};
|
|
1138
|
+
try {
|
|
1139
|
+
const url = new URL(trimmed);
|
|
1140
|
+
return {
|
|
1141
|
+
code: url.searchParams.get("code") ?? undefined,
|
|
1142
|
+
state: url.searchParams.get("state") ?? undefined
|
|
1143
|
+
};
|
|
1144
|
+
} catch {
|
|
1145
|
+
return { code: trimmed };
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
function buildTokenRedirectUri(callbackPath, loginOption) {
|
|
1149
|
+
const path = callbackPath || "/oauth/callback";
|
|
1150
|
+
const base = `${SOCIAL_REDIRECT_URI}${path}`;
|
|
1151
|
+
if (loginOption) {
|
|
1152
|
+
return `${base}?login_option=${encodeURIComponent(loginOption)}`;
|
|
1153
|
+
}
|
|
1154
|
+
return base;
|
|
1155
|
+
}
|
|
1156
|
+
function oauthCallbackPage(kind, title, message, redirectUrl = "https://app.kiro.dev") {
|
|
1157
|
+
const borderColor = kind === "success" ? "#22c55e" : "#ef4444";
|
|
1158
|
+
const iconSvg = kind === "success" ? `<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M16.67 5L7.5 14.17 3.33 10" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>` : `<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M15 5L5 15M5 5l10 10" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/></svg>`;
|
|
1159
|
+
const ghostSvg = `<svg width="56" height="56" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
1160
|
+
<path d="M50 5C28.5 5 11 22.5 11 44v36c0 2.8 1.2 5.4 3.2 7.2 2 1.8 4.7 2.6 7.4 2.2l3.4-.5c3.2-.5 6.5.4 9 2.5l2.2 1.8c2.4 2 5.4 3 8.5 3h10.6c3.1 0 6.1-1.1 8.5-3l2.2-1.8c2.5-2.1 5.8-3 9-2.5l3.4.5c2.7.4 5.4-.4 7.4-2.2 2-1.8 3.2-4.4 3.2-7.2V44C89 22.5 71.5 5 50 5z" fill="white"/>
|
|
1161
|
+
<circle cx="37" cy="45" r="7" fill="#0a0a0a"/>
|
|
1162
|
+
<circle cx="63" cy="45" r="7" fill="#0a0a0a"/>
|
|
1163
|
+
</svg>`;
|
|
1164
|
+
const redirectHost = (() => {
|
|
1165
|
+
try {
|
|
1166
|
+
return new URL(redirectUrl).hostname;
|
|
1167
|
+
} catch {
|
|
1168
|
+
return redirectUrl;
|
|
1169
|
+
}
|
|
1170
|
+
})();
|
|
1171
|
+
const countdownHtml = kind === "success" ? `
|
|
1172
|
+
<div class="countdown" id="countdown">
|
|
1173
|
+
<svg class="ring" viewBox="0 0 60 60">
|
|
1174
|
+
<circle cx="30" cy="30" r="26" stroke="#1a1a1a" stroke-width="3" fill="none"/>
|
|
1175
|
+
<circle id="ring-progress" cx="30" cy="30" r="26" stroke="#22c55e" stroke-width="3" fill="none"
|
|
1176
|
+
stroke-dasharray="163.36" stroke-dashoffset="0" stroke-linecap="round"
|
|
1177
|
+
transform="rotate(-90 30 30)" style="transition:stroke-dashoffset 1s linear"/>
|
|
1178
|
+
</svg>
|
|
1179
|
+
<span class="countdown-num" id="countdown-num">3</span>
|
|
1180
|
+
</div>
|
|
1181
|
+
<p class="subtitle">Redirecting to <strong>${redirectHost}</strong>…</p>
|
|
1182
|
+
<script>
|
|
1183
|
+
(function(){
|
|
1184
|
+
var n=3, el=document.getElementById('countdown-num'),
|
|
1185
|
+
ring=document.getElementById('ring-progress'), circ=163.36;
|
|
1186
|
+
function tick(){
|
|
1187
|
+
if(n<=0){window.location.href=${JSON.stringify(redirectUrl)};return}
|
|
1188
|
+
el.textContent=n;
|
|
1189
|
+
ring.setAttribute('stroke-dashoffset', String(circ*(1-n/3)));
|
|
1190
|
+
n--;
|
|
1191
|
+
setTimeout(tick,1000);
|
|
1192
|
+
}
|
|
1193
|
+
tick();
|
|
1194
|
+
})();
|
|
1195
|
+
</script>` : `<p class="subtitle">Please close this window and try again</p>`;
|
|
1196
|
+
return `<!DOCTYPE html>
|
|
1197
|
+
<html lang="en">
|
|
1198
|
+
<head>
|
|
1199
|
+
<meta charset="utf-8">
|
|
1200
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1201
|
+
<title>PI-KIRO — Authentication</title>
|
|
1202
|
+
<style>
|
|
1203
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
1204
|
+
body{background:#0a0a0a;color:#e5e5e5;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;text-align:center}
|
|
1205
|
+
.container{max-width:420px;padding:2rem}
|
|
1206
|
+
.logo{display:flex;align-items:center;justify-content:center;gap:16px;margin-bottom:48px}
|
|
1207
|
+
.logo-text{font-size:42px;font-weight:700;letter-spacing:6px;color:#7c3aed;font-family:'Courier New',monospace}
|
|
1208
|
+
.status-box{border:1.5px solid ${borderColor};border-radius:12px;padding:20px 28px;display:flex;align-items:flex-start;gap:14px;text-align:left;margin-bottom:20px;background:rgba(${kind === "success" ? "34,197,94" : "239,68,68"},0.04)}
|
|
1209
|
+
.status-icon{flex-shrink:0;margin-top:2px}
|
|
1210
|
+
.status-title{font-size:15px;font-weight:600;color:${borderColor};margin-bottom:4px}
|
|
1211
|
+
.status-msg{font-size:13px;color:#a3a3a3;line-height:1.4}
|
|
1212
|
+
.subtitle{font-size:13px;color:#737373;margin-top:4px}
|
|
1213
|
+
.subtitle strong{color:#a3a3a3}
|
|
1214
|
+
.countdown{position:relative;width:60px;height:60px;margin:24px auto 12px}
|
|
1215
|
+
.ring{width:60px;height:60px}
|
|
1216
|
+
.countdown-num{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:24px;font-weight:700;color:#22c55e;font-variant-numeric:tabular-nums}
|
|
1217
|
+
</style>
|
|
1218
|
+
</head>
|
|
1219
|
+
<body>
|
|
1220
|
+
<div class="container">
|
|
1221
|
+
<div class="logo">
|
|
1222
|
+
${ghostSvg}
|
|
1223
|
+
<span class="logo-text">PI-KIRO</span>
|
|
1224
|
+
</div>
|
|
1225
|
+
<div class="status-box">
|
|
1226
|
+
<span class="status-icon">${iconSvg}</span>
|
|
1227
|
+
<div>
|
|
1228
|
+
<div class="status-title">${title}</div>
|
|
1229
|
+
<div class="status-msg">${message}</div>
|
|
1230
|
+
</div>
|
|
1231
|
+
</div>
|
|
1232
|
+
${countdownHtml}
|
|
1233
|
+
</div>
|
|
1234
|
+
</body>
|
|
1235
|
+
</html>`;
|
|
1236
|
+
}
|
|
1237
|
+
function oauthIdcDelegationPage() {
|
|
1238
|
+
const ghostSvg = `<svg width="56" height="56" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
1239
|
+
<path d="M50 5C28.5 5 11 22.5 11 44v36c0 2.8 1.2 5.4 3.2 7.2 2 1.8 4.7 2.6 7.4 2.2l3.4-.5c3.2-.5 6.5.4 9 2.5l2.2 1.8c2.4 2 5.4 3 8.5 3h10.6c3.1 0 6.1-1.1 8.5-3l2.2-1.8c2.5-2.1 5.8-3 9-2.5l3.4.5c2.7.4 5.4-.4 7.4-2.2 2-1.8 3.2-4.4 3.2-7.2V44C89 22.5 71.5 5 50 5z" fill="white"/>
|
|
1240
|
+
<circle cx="37" cy="45" r="7" fill="#0a0a0a"/>
|
|
1241
|
+
<circle cx="63" cy="45" r="7" fill="#0a0a0a"/>
|
|
1242
|
+
</svg>`;
|
|
1243
|
+
return `<!DOCTYPE html>
|
|
1244
|
+
<html lang="en">
|
|
1245
|
+
<head>
|
|
1246
|
+
<meta charset="utf-8">
|
|
1247
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1248
|
+
<title>PI-KIRO — Enterprise Sign-In</title>
|
|
1249
|
+
<style>
|
|
1250
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
1251
|
+
body{background:#0a0a0a;color:#e5e5e5;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;text-align:center}
|
|
1252
|
+
.container{max-width:420px;padding:2rem}
|
|
1253
|
+
.logo{display:flex;align-items:center;justify-content:center;gap:16px;margin-bottom:48px}
|
|
1254
|
+
.logo-text{font-size:42px;font-weight:700;letter-spacing:6px;color:#7c3aed;font-family:'Courier New',monospace}
|
|
1255
|
+
.status-box{border:1.5px solid #22c55e;border-radius:12px;padding:20px 28px;display:flex;align-items:flex-start;gap:14px;text-align:left;margin-bottom:20px;background:rgba(34,197,94,0.04)}
|
|
1256
|
+
.status-icon{flex-shrink:0;margin-top:2px}
|
|
1257
|
+
.status-title{font-size:15px;font-weight:600;color:#22c55e;margin-bottom:4px}
|
|
1258
|
+
.status-msg{font-size:13px;color:#a3a3a3;line-height:1.4}
|
|
1259
|
+
.subtitle{font-size:13px;color:#737373;margin-top:4px}
|
|
1260
|
+
.subtitle strong{color:#a3a3a3}
|
|
1261
|
+
.spinner{width:28px;height:28px;border:3px solid #1a1a1a;border-top-color:#22c55e;border-radius:50%;animation:spin 0.8s linear infinite;margin:24px auto 12px}
|
|
1262
|
+
@keyframes spin{to{transform:rotate(360deg)}}
|
|
1263
|
+
.countdown{position:relative;width:60px;height:60px;margin:24px auto 12px;display:none}
|
|
1264
|
+
.ring{width:60px;height:60px}
|
|
1265
|
+
.countdown-num{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:24px;font-weight:700;color:#22c55e;font-variant-numeric:tabular-nums}
|
|
1266
|
+
</style>
|
|
1267
|
+
</head>
|
|
1268
|
+
<body>
|
|
1269
|
+
<div class="container">
|
|
1270
|
+
<div class="logo">
|
|
1271
|
+
${ghostSvg}
|
|
1272
|
+
<span class="logo-text">PI-KIRO</span>
|
|
1273
|
+
</div>
|
|
1274
|
+
<div class="status-box">
|
|
1275
|
+
<span class="status-icon"><svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M16.67 5L7.5 14.17 3.33 10" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
|
|
1276
|
+
<div>
|
|
1277
|
+
<div class="status-title">Enterprise sign-in</div>
|
|
1278
|
+
<div class="status-msg" id="status-msg">Preparing device authorization…</div>
|
|
1279
|
+
</div>
|
|
1280
|
+
</div>
|
|
1281
|
+
<div class="spinner" id="spinner"></div>
|
|
1282
|
+
<div class="countdown" id="countdown">
|
|
1283
|
+
<svg class="ring" viewBox="0 0 60 60">
|
|
1284
|
+
<circle cx="30" cy="30" r="26" stroke="#1a1a1a" stroke-width="3" fill="none"/>
|
|
1285
|
+
<circle id="ring-progress" cx="30" cy="30" r="26" stroke="#22c55e" stroke-width="3" fill="none"
|
|
1286
|
+
stroke-dasharray="163.36" stroke-dashoffset="0" stroke-linecap="round"
|
|
1287
|
+
transform="rotate(-90 30 30)" style="transition:stroke-dashoffset 1s linear"/>
|
|
1288
|
+
</svg>
|
|
1289
|
+
<span class="countdown-num" id="countdown-num">3</span>
|
|
1290
|
+
</div>
|
|
1291
|
+
<p class="subtitle" id="subtitle">Waiting for device authorization…</p>
|
|
1292
|
+
<script>
|
|
1293
|
+
(function(){
|
|
1294
|
+
var msg=document.getElementById('status-msg'),
|
|
1295
|
+
spinner=document.getElementById('spinner'),
|
|
1296
|
+
cd=document.getElementById('countdown'),
|
|
1297
|
+
cdNum=document.getElementById('countdown-num'),
|
|
1298
|
+
ring=document.getElementById('ring-progress'),
|
|
1299
|
+
sub=document.getElementById('subtitle'),
|
|
1300
|
+
circ=163.36;
|
|
1301
|
+
|
|
1302
|
+
function poll(){
|
|
1303
|
+
fetch('/idc-verify').then(function(r){return r.json()}).then(function(d){
|
|
1304
|
+
if(d.url){
|
|
1305
|
+
spinner.style.display='none';
|
|
1306
|
+
cd.style.display='block';
|
|
1307
|
+
msg.textContent='Device authorization ready';
|
|
1308
|
+
try{sub.innerHTML='Redirecting to <strong>'+new URL(d.url).hostname+'</strong>…'}catch(e){}
|
|
1309
|
+
countdown(3,d.url);
|
|
1310
|
+
} else {
|
|
1311
|
+
setTimeout(poll,500);
|
|
1312
|
+
}
|
|
1313
|
+
}).catch(function(){setTimeout(poll,1000)});
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
function countdown(n,url){
|
|
1317
|
+
if(n<=0){window.location.href=url;return}
|
|
1318
|
+
cdNum.textContent=n;
|
|
1319
|
+
ring.setAttribute('stroke-dashoffset',String(circ*(1-n/3)));
|
|
1320
|
+
setTimeout(function(){countdown(n-1,url)},1000);
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
poll();
|
|
1324
|
+
})();
|
|
1325
|
+
</script>
|
|
1326
|
+
</div>
|
|
1327
|
+
</body>
|
|
1328
|
+
</html>`;
|
|
1329
|
+
}
|
|
1330
|
+
function startCallbackServer(expectedState) {
|
|
1331
|
+
return new Promise((resolve2, reject) => {
|
|
1332
|
+
let settleWait;
|
|
1333
|
+
const waitForCodePromise = new Promise((res) => {
|
|
1334
|
+
settleWait = res;
|
|
1335
|
+
});
|
|
1336
|
+
let idcVerifyUrl = null;
|
|
1337
|
+
const server = createServer((req, res) => {
|
|
1338
|
+
try {
|
|
1339
|
+
const url = new URL(req.url ?? "", SOCIAL_REDIRECT_URI);
|
|
1340
|
+
if (url.pathname === "/idc-verify") {
|
|
1341
|
+
res.writeHead(200, {
|
|
1342
|
+
"Content-Type": "application/json",
|
|
1343
|
+
"Access-Control-Allow-Origin": "*",
|
|
1344
|
+
"Cache-Control": "no-store"
|
|
1345
|
+
});
|
|
1346
|
+
res.end(JSON.stringify({ url: idcVerifyUrl }));
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1349
|
+
const code = url.searchParams.get("code");
|
|
1350
|
+
const state = url.searchParams.get("state");
|
|
1351
|
+
const loginOption = url.searchParams.get("login_option");
|
|
1352
|
+
const issuerUrl = url.searchParams.get("issuer_url");
|
|
1353
|
+
const idcRegion = url.searchParams.get("idc_region");
|
|
1354
|
+
const isIdcDelegation = loginOption === "awsidc" && !!issuerUrl && !!state;
|
|
1355
|
+
if (!state || !code && !isIdcDelegation) {
|
|
1356
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
1357
|
+
res.end("");
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
if (state !== expectedState) {
|
|
1361
|
+
res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
|
|
1362
|
+
res.end(oauthCallbackPage("error", "State mismatch", "The OAuth state parameter did not match. Please try logging in again."));
|
|
1363
|
+
return;
|
|
1364
|
+
}
|
|
1365
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
1366
|
+
if (isIdcDelegation) {
|
|
1367
|
+
res.end(oauthIdcDelegationPage());
|
|
1368
|
+
} else {
|
|
1369
|
+
res.end(oauthCallbackPage("success", "Request approved", "PI-KIRO has been given requested permissions."));
|
|
1370
|
+
}
|
|
1371
|
+
settleWait?.({
|
|
1372
|
+
code,
|
|
1373
|
+
state,
|
|
1374
|
+
callbackPath: url.pathname,
|
|
1375
|
+
loginOption,
|
|
1376
|
+
issuerUrl: issuerUrl ?? undefined,
|
|
1377
|
+
idcRegion: idcRegion ?? undefined
|
|
1378
|
+
});
|
|
1379
|
+
} catch {
|
|
1380
|
+
res.writeHead(500, { "Content-Type": "text/plain; charset=utf-8" });
|
|
1381
|
+
res.end("Internal error");
|
|
1382
|
+
}
|
|
1383
|
+
});
|
|
1384
|
+
server.on("error", (err) => {
|
|
1385
|
+
reject(err);
|
|
1386
|
+
});
|
|
1387
|
+
server.listen(SOCIAL_REDIRECT_PORT, "localhost", () => {
|
|
1388
|
+
resolve2({
|
|
1389
|
+
server,
|
|
1390
|
+
redirectUri: SOCIAL_REDIRECT_URI,
|
|
1391
|
+
cancelWait: () => {
|
|
1392
|
+
settleWait?.(null);
|
|
1393
|
+
},
|
|
1394
|
+
waitForCode: () => waitForCodePromise,
|
|
1395
|
+
setIdcVerifyUrl: (url) => {
|
|
1396
|
+
idcVerifyUrl = url;
|
|
1397
|
+
}
|
|
1398
|
+
});
|
|
1399
|
+
});
|
|
1400
|
+
});
|
|
1401
|
+
}
|
|
1402
|
+
async function runSocialSignInFlow(callbacks) {
|
|
1403
|
+
const verifier = generateCodeVerifier();
|
|
1404
|
+
const challenge = generateCodeChallenge(verifier);
|
|
1405
|
+
const state = generateRandomState();
|
|
1406
|
+
const callbackServer = await startCallbackServer(state);
|
|
1407
|
+
try {
|
|
1408
|
+
const signInUrl = buildSocialSignInURL(callbackServer.redirectUri, challenge, state);
|
|
1409
|
+
callbacks.onAuth({
|
|
1410
|
+
url: signInUrl,
|
|
1411
|
+
instructions: "Complete sign-in in your browser."
|
|
1412
|
+
});
|
|
1413
|
+
callbacks.onProgress?.("Waiting for browser sign-in…");
|
|
1414
|
+
let code;
|
|
1415
|
+
let tokenRedirectUri = SOCIAL_REDIRECT_URI;
|
|
1416
|
+
let callbackResult = null;
|
|
1417
|
+
if (callbacks.onManualCodeInput) {
|
|
1418
|
+
let manualInput;
|
|
1419
|
+
let manualError;
|
|
1420
|
+
const manualPromise = callbacks.onManualCodeInput().then((input) => {
|
|
1421
|
+
manualInput = input;
|
|
1422
|
+
callbackServer.cancelWait();
|
|
1423
|
+
}).catch((err) => {
|
|
1424
|
+
manualError = err instanceof Error ? err : new Error(String(err));
|
|
1425
|
+
callbackServer.cancelWait();
|
|
1426
|
+
});
|
|
1427
|
+
callbackResult = await callbackServer.waitForCode();
|
|
1428
|
+
if (manualError)
|
|
1429
|
+
throw manualError;
|
|
1430
|
+
if (callbackResult?.loginOption !== "awsidc" || !callbackResult.issuerUrl) {
|
|
1431
|
+
if (callbackResult?.code) {
|
|
1432
|
+
code = callbackResult.code;
|
|
1433
|
+
tokenRedirectUri = buildTokenRedirectUri(callbackResult.callbackPath, callbackResult.loginOption);
|
|
1434
|
+
} else if (manualInput) {
|
|
1435
|
+
code = parseAuthRedirectInput(manualInput).code;
|
|
1436
|
+
}
|
|
1437
|
+
if (!code) {
|
|
1438
|
+
await manualPromise;
|
|
1439
|
+
if (manualError)
|
|
1440
|
+
throw manualError;
|
|
1441
|
+
if (manualInput) {
|
|
1442
|
+
code = parseAuthRedirectInput(manualInput).code;
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
} else {
|
|
1447
|
+
callbackResult = await callbackServer.waitForCode();
|
|
1448
|
+
if (callbackResult?.code) {
|
|
1449
|
+
code = callbackResult.code;
|
|
1450
|
+
tokenRedirectUri = buildTokenRedirectUri(callbackResult.callbackPath, callbackResult.loginOption);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
if (callbackResult?.loginOption === "awsidc" && callbackResult.issuerUrl) {
|
|
1454
|
+
callbacks.onProgress?.("Enterprise sign-in detected — starting device authorization…");
|
|
1455
|
+
const idcRegion = callbackResult.idcRegion || BUILDER_ID_REGION;
|
|
1456
|
+
const wrappedCallbacks = {
|
|
1457
|
+
...callbacks,
|
|
1458
|
+
onAuth: (info) => {
|
|
1459
|
+
callbackServer.setIdcVerifyUrl(info.url);
|
|
1460
|
+
callbacks.onAuth(info);
|
|
1461
|
+
}
|
|
1462
|
+
};
|
|
1463
|
+
try {
|
|
1464
|
+
return await runDeviceCodeFlow(wrappedCallbacks, callbackResult.issuerUrl, [idcRegion], "idc");
|
|
1465
|
+
} finally {
|
|
1466
|
+
callbackServer.server.close();
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
if (!code) {
|
|
1470
|
+
const input = await callbacks.onPrompt({
|
|
1471
|
+
message: "Paste the authorization code or the full redirect URL:",
|
|
1472
|
+
placeholder: SOCIAL_REDIRECT_URI
|
|
1473
|
+
});
|
|
1474
|
+
code = parseAuthRedirectInput(input).code;
|
|
1475
|
+
}
|
|
1476
|
+
if (!code) {
|
|
1477
|
+
throw new Error("Missing authorization code — sign-in was not completed");
|
|
1478
|
+
}
|
|
1479
|
+
callbacks.onProgress?.("Exchanging authorization code…");
|
|
1480
|
+
const resp = await fetch(`${KIRO_SOCIAL_AUTH_ENDPOINT}/oauth/token`, {
|
|
1481
|
+
method: "POST",
|
|
1482
|
+
headers: { "Content-Type": "application/json", "User-Agent": "pi-kiro" },
|
|
1483
|
+
body: JSON.stringify({
|
|
1484
|
+
code,
|
|
1485
|
+
code_verifier: verifier,
|
|
1486
|
+
redirect_uri: tokenRedirectUri
|
|
1487
|
+
})
|
|
1488
|
+
});
|
|
1489
|
+
if (!resp.ok) {
|
|
1490
|
+
const body = await resp.text().catch(() => "");
|
|
1491
|
+
throw new Error(`Token exchange failed: ${resp.status} ${body}`);
|
|
1492
|
+
}
|
|
1493
|
+
const data = await resp.json();
|
|
1494
|
+
if (!data.accessToken || !data.refreshToken) {
|
|
1495
|
+
throw new Error("Token exchange returned no tokens");
|
|
1496
|
+
}
|
|
1497
|
+
if (data.profileArn) {
|
|
1498
|
+
try {
|
|
1499
|
+
const apiRegion = resolveApiRegion(BUILDER_ID_REGION);
|
|
1500
|
+
const apiModels = await fetchAvailableModels(data.accessToken, apiRegion, data.profileArn);
|
|
1501
|
+
setCachedDynamicModels(buildModelsFromApi(apiModels));
|
|
1502
|
+
log.info(`Fetched and cached ${apiModels.length} models after social sign-in`);
|
|
1503
|
+
} catch (err) {
|
|
1504
|
+
log.warn(`Failed to fetch models after social sign-in: ${err}`);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
return {
|
|
1508
|
+
refresh: `${data.refreshToken}|||social`,
|
|
1509
|
+
access: data.accessToken,
|
|
1510
|
+
expires: Date.now() + (data.expiresIn ?? 3600) * 1000 - EXPIRES_BUFFER_MS,
|
|
1511
|
+
clientId: "",
|
|
1512
|
+
clientSecret: "",
|
|
1513
|
+
region: BUILDER_ID_REGION,
|
|
1514
|
+
authMethod: "social",
|
|
1515
|
+
profileArn: data.profileArn
|
|
1516
|
+
};
|
|
1517
|
+
} finally {
|
|
1518
|
+
callbackServer.server.close();
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1092
1521
|
async function loginKiro(callbacks) {
|
|
1093
1522
|
const method = await callbacks.onSelect({
|
|
1094
1523
|
message: "Select login method:",
|
|
@@ -1108,7 +1537,7 @@ async function loginKiro(callbacks) {
|
|
|
1108
1537
|
return loginDesktopManual(callbacks);
|
|
1109
1538
|
}
|
|
1110
1539
|
if (method === "builder-id") {
|
|
1111
|
-
return
|
|
1540
|
+
return runSocialSignInFlow(callbacks);
|
|
1112
1541
|
}
|
|
1113
1542
|
const startUrl = (await callbacks.onPrompt({
|
|
1114
1543
|
message: "Paste your IAM Identity Center start URL:",
|
|
@@ -1226,7 +1655,7 @@ async function syncBackToKiroCli(result) {
|
|
|
1226
1655
|
accessToken: result.access,
|
|
1227
1656
|
refreshToken: result.refresh.split("|")[0] ?? "",
|
|
1228
1657
|
region: result.region,
|
|
1229
|
-
authMethod: result.authMethod === "builder-id" ? "
|
|
1658
|
+
authMethod: result.authMethod === "builder-id" || result.authMethod === "social" ? "desktop" : result.authMethod,
|
|
1230
1659
|
source: result.kiroSyncSource,
|
|
1231
1660
|
tokenKey: result.kiroSyncTokenKey
|
|
1232
1661
|
});
|
|
@@ -1263,10 +1692,10 @@ async function refreshTokenInner(credentials) {
|
|
|
1263
1692
|
if (!refreshToken || !region) {
|
|
1264
1693
|
throw new Error("Refresh token is missing region — re-login required");
|
|
1265
1694
|
}
|
|
1266
|
-
if (authMethod !== "desktop" && (!clientId || !clientSecret)) {
|
|
1695
|
+
if (authMethod !== "desktop" && authMethod !== "social" && (!clientId || !clientSecret)) {
|
|
1267
1696
|
throw new Error("Refresh token is missing clientId/clientSecret — re-login required");
|
|
1268
1697
|
}
|
|
1269
|
-
if (authMethod === "desktop") {
|
|
1698
|
+
if (authMethod === "desktop" || authMethod === "social") {
|
|
1270
1699
|
const desktopEndpoint = `https://prod.${region}.auth.desktop.kiro.dev/refreshToken`;
|
|
1271
1700
|
const resp2 = await fetch(desktopEndpoint, {
|
|
1272
1701
|
method: "POST",
|
|
@@ -1289,13 +1718,13 @@ async function refreshTokenInner(credentials) {
|
|
|
1289
1718
|
}
|
|
1290
1719
|
}
|
|
1291
1720
|
return {
|
|
1292
|
-
refresh: `${data2.refreshToken}
|
|
1721
|
+
refresh: `${data2.refreshToken}|||${authMethod}`,
|
|
1293
1722
|
access: data2.accessToken,
|
|
1294
1723
|
expires: Date.now() + (data2.expiresIn ?? 3600) * 1000 - EXPIRES_BUFFER_MS,
|
|
1295
1724
|
clientId: "",
|
|
1296
1725
|
clientSecret: "",
|
|
1297
1726
|
region,
|
|
1298
|
-
authMethod
|
|
1727
|
+
authMethod,
|
|
1299
1728
|
profileArn: credentials.profileArn,
|
|
1300
1729
|
kiroSyncSource: credentials.kiroSyncSource,
|
|
1301
1730
|
kiroSyncTokenKey: credentials.kiroSyncTokenKey
|
|
@@ -1337,8 +1766,8 @@ async function refreshTokenInner(credentials) {
|
|
|
1337
1766
|
}
|
|
1338
1767
|
async function refreshKiroToken(credentials) {
|
|
1339
1768
|
const inputMethod = credentials.authMethod;
|
|
1340
|
-
const authMethod = inputMethod === "builder-id" || inputMethod === "idc" || inputMethod === "desktop" ? inputMethod : "idc";
|
|
1341
|
-
if (inputMethod !== undefined && inputMethod !== "builder-id" && inputMethod !== "idc" && inputMethod !== "desktop") {
|
|
1769
|
+
const authMethod = inputMethod === "builder-id" || inputMethod === "idc" || inputMethod === "desktop" || inputMethod === "social" ? inputMethod : "idc";
|
|
1770
|
+
if (inputMethod !== undefined && inputMethod !== "builder-id" && inputMethod !== "idc" && inputMethod !== "desktop" && inputMethod !== "social") {
|
|
1342
1771
|
log.warn(`refreshKiroToken: unrecognized authMethod "${String(inputMethod)}" — defaulting to "idc"`);
|
|
1343
1772
|
}
|
|
1344
1773
|
const baseCreds = {
|
|
@@ -1868,7 +2297,7 @@ function countTokens(text) {
|
|
|
1868
2297
|
}
|
|
1869
2298
|
|
|
1870
2299
|
// src/transform.ts
|
|
1871
|
-
import { createHash } from "node:crypto";
|
|
2300
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
1872
2301
|
function normalizeMessages(messages) {
|
|
1873
2302
|
return messages.filter((msg) => msg.role !== "assistant" || msg.stopReason !== "error" && msg.stopReason !== "aborted");
|
|
1874
2303
|
}
|
|
@@ -1921,7 +2350,7 @@ var KIRO_TOOL_USE_ID_RE = /^tooluse_[A-Za-z0-9]+$/;
|
|
|
1921
2350
|
function toKiroToolUseId(id) {
|
|
1922
2351
|
if (KIRO_TOOL_USE_ID_RE.test(id))
|
|
1923
2352
|
return id;
|
|
1924
|
-
const digest =
|
|
2353
|
+
const digest = createHash2("sha256").update(id).digest("hex").slice(0, 22);
|
|
1925
2354
|
return `tooluse_${digest}`;
|
|
1926
2355
|
}
|
|
1927
2356
|
function convertImagesToKiro(images) {
|
package/dist/extension.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EACV,GAAG,EACH,2BAA2B,EAC3B,OAAO,EACP,KAAK,EACL,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EACV,GAAG,EACH,2BAA2B,EAC3B,OAAO,EACP,KAAK,EACL,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,uBAAuB,CAAC;AAuB/B,UAAU,mBAAmB;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,CAAC,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;IAC5B,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/E,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;CAC3D;AAED,UAAU,cAAc;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,YAAY,CAAC,EAAE,CACb,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,KAC1B,2BAA2B,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAC/B,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,CAAC,SAAS,EAAE,mBAAmB,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACrE,YAAY,EAAE,CAAC,WAAW,EAAE,gBAAgB,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC3E,SAAS,EAAE,CAAC,WAAW,EAAE,gBAAgB,KAAK,MAAM,CAAC;QACrD,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,WAAW,EAAE,gBAAgB,KAAK,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;KACtF,CAAC;CACH;AAED,UAAU,YAAY;IACpB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;CAC9D;AA4HD,yBAA+B,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAmG9D"}
|
package/dist/extension.js
CHANGED
|
@@ -899,6 +899,24 @@ var kiroModels = [
|
|
|
899
899
|
maxTokens: 65536
|
|
900
900
|
}
|
|
901
901
|
];
|
|
902
|
+
async function resolveProfileArn(accessToken, apiRegion) {
|
|
903
|
+
const resp = await fetch(`https://management.${apiRegion}.kiro.dev/`, {
|
|
904
|
+
method: "POST",
|
|
905
|
+
headers: {
|
|
906
|
+
Authorization: `Bearer ${accessToken}`,
|
|
907
|
+
"Content-Type": "application/x-amz-json-1.0",
|
|
908
|
+
"X-Amz-Target": "AmazonCodeWhispererService.ListAvailableProfiles",
|
|
909
|
+
"User-Agent": "pi-kiro"
|
|
910
|
+
},
|
|
911
|
+
body: "{}"
|
|
912
|
+
});
|
|
913
|
+
if (!resp.ok)
|
|
914
|
+
return null;
|
|
915
|
+
const data = await resp.json();
|
|
916
|
+
const profiles = data.profiles ?? [];
|
|
917
|
+
const kiroProfile = profiles.find((p) => p.profileType === "KIRO" && p.status === "ACTIVE");
|
|
918
|
+
return kiroProfile?.arn ?? profiles[0]?.arn ?? null;
|
|
919
|
+
}
|
|
902
920
|
async function fetchAvailableModels(accessToken, apiRegion, profileArn) {
|
|
903
921
|
const url = `https://management.${apiRegion}.kiro.dev/?origin=KIRO_CLI&profileArn=${encodeURIComponent(profileArn)}`;
|
|
904
922
|
const resp = await fetch(url, {
|
|
@@ -983,6 +1001,8 @@ function setCachedDynamicModels(models) {
|
|
|
983
1001
|
|
|
984
1002
|
// src/oauth.ts
|
|
985
1003
|
init_debug();
|
|
1004
|
+
import { createServer } from "node:http";
|
|
1005
|
+
import { randomBytes, createHash } from "node:crypto";
|
|
986
1006
|
var BUILDER_ID_START_URL = "https://view.awsapps.com/start";
|
|
987
1007
|
var BUILDER_ID_REGION = "us-east-1";
|
|
988
1008
|
var SSO_SCOPES = [
|
|
@@ -1092,6 +1112,415 @@ async function pollForToken(oidcEndpoint, clientId, clientSecret, devAuth, signa
|
|
|
1092
1112
|
}
|
|
1093
1113
|
throw new Error("Authorization timed out");
|
|
1094
1114
|
}
|
|
1115
|
+
var KIRO_SOCIAL_PORTAL = "https://app.kiro.dev";
|
|
1116
|
+
var KIRO_SOCIAL_AUTH_ENDPOINT = `https://prod.${BUILDER_ID_REGION}.auth.desktop.kiro.dev`;
|
|
1117
|
+
var SOCIAL_REDIRECT_PORT = 49153;
|
|
1118
|
+
var SOCIAL_REDIRECT_URI = `http://localhost:${SOCIAL_REDIRECT_PORT}`;
|
|
1119
|
+
function generateRandomState() {
|
|
1120
|
+
return randomBytes(16).toString("base64url");
|
|
1121
|
+
}
|
|
1122
|
+
function generateCodeVerifier() {
|
|
1123
|
+
return randomBytes(32).toString("base64url");
|
|
1124
|
+
}
|
|
1125
|
+
function generateCodeChallenge(verifier) {
|
|
1126
|
+
return createHash("sha256").update(verifier).digest("base64url");
|
|
1127
|
+
}
|
|
1128
|
+
function buildSocialSignInURL(redirectUri, codeChallenge, state) {
|
|
1129
|
+
const params = new URLSearchParams;
|
|
1130
|
+
params.set("code_challenge", codeChallenge);
|
|
1131
|
+
params.set("code_challenge_method", "S256");
|
|
1132
|
+
params.set("redirect_from", "kirocli");
|
|
1133
|
+
params.set("redirect_uri", redirectUri);
|
|
1134
|
+
params.set("state", state);
|
|
1135
|
+
return `${KIRO_SOCIAL_PORTAL}/signin?${params.toString()}`;
|
|
1136
|
+
}
|
|
1137
|
+
function parseAuthRedirectInput(input) {
|
|
1138
|
+
const trimmed = input.trim();
|
|
1139
|
+
if (!trimmed)
|
|
1140
|
+
return {};
|
|
1141
|
+
try {
|
|
1142
|
+
const url = new URL(trimmed);
|
|
1143
|
+
return {
|
|
1144
|
+
code: url.searchParams.get("code") ?? undefined,
|
|
1145
|
+
state: url.searchParams.get("state") ?? undefined
|
|
1146
|
+
};
|
|
1147
|
+
} catch {
|
|
1148
|
+
return { code: trimmed };
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
function buildTokenRedirectUri(callbackPath, loginOption) {
|
|
1152
|
+
const path = callbackPath || "/oauth/callback";
|
|
1153
|
+
const base = `${SOCIAL_REDIRECT_URI}${path}`;
|
|
1154
|
+
if (loginOption) {
|
|
1155
|
+
return `${base}?login_option=${encodeURIComponent(loginOption)}`;
|
|
1156
|
+
}
|
|
1157
|
+
return base;
|
|
1158
|
+
}
|
|
1159
|
+
function oauthCallbackPage(kind, title, message, redirectUrl = "https://app.kiro.dev") {
|
|
1160
|
+
const borderColor = kind === "success" ? "#22c55e" : "#ef4444";
|
|
1161
|
+
const iconSvg = kind === "success" ? `<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M16.67 5L7.5 14.17 3.33 10" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>` : `<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M15 5L5 15M5 5l10 10" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/></svg>`;
|
|
1162
|
+
const ghostSvg = `<svg width="56" height="56" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
1163
|
+
<path d="M50 5C28.5 5 11 22.5 11 44v36c0 2.8 1.2 5.4 3.2 7.2 2 1.8 4.7 2.6 7.4 2.2l3.4-.5c3.2-.5 6.5.4 9 2.5l2.2 1.8c2.4 2 5.4 3 8.5 3h10.6c3.1 0 6.1-1.1 8.5-3l2.2-1.8c2.5-2.1 5.8-3 9-2.5l3.4.5c2.7.4 5.4-.4 7.4-2.2 2-1.8 3.2-4.4 3.2-7.2V44C89 22.5 71.5 5 50 5z" fill="white"/>
|
|
1164
|
+
<circle cx="37" cy="45" r="7" fill="#0a0a0a"/>
|
|
1165
|
+
<circle cx="63" cy="45" r="7" fill="#0a0a0a"/>
|
|
1166
|
+
</svg>`;
|
|
1167
|
+
const redirectHost = (() => {
|
|
1168
|
+
try {
|
|
1169
|
+
return new URL(redirectUrl).hostname;
|
|
1170
|
+
} catch {
|
|
1171
|
+
return redirectUrl;
|
|
1172
|
+
}
|
|
1173
|
+
})();
|
|
1174
|
+
const countdownHtml = kind === "success" ? `
|
|
1175
|
+
<div class="countdown" id="countdown">
|
|
1176
|
+
<svg class="ring" viewBox="0 0 60 60">
|
|
1177
|
+
<circle cx="30" cy="30" r="26" stroke="#1a1a1a" stroke-width="3" fill="none"/>
|
|
1178
|
+
<circle id="ring-progress" cx="30" cy="30" r="26" stroke="#22c55e" stroke-width="3" fill="none"
|
|
1179
|
+
stroke-dasharray="163.36" stroke-dashoffset="0" stroke-linecap="round"
|
|
1180
|
+
transform="rotate(-90 30 30)" style="transition:stroke-dashoffset 1s linear"/>
|
|
1181
|
+
</svg>
|
|
1182
|
+
<span class="countdown-num" id="countdown-num">3</span>
|
|
1183
|
+
</div>
|
|
1184
|
+
<p class="subtitle">Redirecting to <strong>${redirectHost}</strong>…</p>
|
|
1185
|
+
<script>
|
|
1186
|
+
(function(){
|
|
1187
|
+
var n=3, el=document.getElementById('countdown-num'),
|
|
1188
|
+
ring=document.getElementById('ring-progress'), circ=163.36;
|
|
1189
|
+
function tick(){
|
|
1190
|
+
if(n<=0){window.location.href=${JSON.stringify(redirectUrl)};return}
|
|
1191
|
+
el.textContent=n;
|
|
1192
|
+
ring.setAttribute('stroke-dashoffset', String(circ*(1-n/3)));
|
|
1193
|
+
n--;
|
|
1194
|
+
setTimeout(tick,1000);
|
|
1195
|
+
}
|
|
1196
|
+
tick();
|
|
1197
|
+
})();
|
|
1198
|
+
</script>` : `<p class="subtitle">Please close this window and try again</p>`;
|
|
1199
|
+
return `<!DOCTYPE html>
|
|
1200
|
+
<html lang="en">
|
|
1201
|
+
<head>
|
|
1202
|
+
<meta charset="utf-8">
|
|
1203
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1204
|
+
<title>PI-KIRO — Authentication</title>
|
|
1205
|
+
<style>
|
|
1206
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
1207
|
+
body{background:#0a0a0a;color:#e5e5e5;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;text-align:center}
|
|
1208
|
+
.container{max-width:420px;padding:2rem}
|
|
1209
|
+
.logo{display:flex;align-items:center;justify-content:center;gap:16px;margin-bottom:48px}
|
|
1210
|
+
.logo-text{font-size:42px;font-weight:700;letter-spacing:6px;color:#7c3aed;font-family:'Courier New',monospace}
|
|
1211
|
+
.status-box{border:1.5px solid ${borderColor};border-radius:12px;padding:20px 28px;display:flex;align-items:flex-start;gap:14px;text-align:left;margin-bottom:20px;background:rgba(${kind === "success" ? "34,197,94" : "239,68,68"},0.04)}
|
|
1212
|
+
.status-icon{flex-shrink:0;margin-top:2px}
|
|
1213
|
+
.status-title{font-size:15px;font-weight:600;color:${borderColor};margin-bottom:4px}
|
|
1214
|
+
.status-msg{font-size:13px;color:#a3a3a3;line-height:1.4}
|
|
1215
|
+
.subtitle{font-size:13px;color:#737373;margin-top:4px}
|
|
1216
|
+
.subtitle strong{color:#a3a3a3}
|
|
1217
|
+
.countdown{position:relative;width:60px;height:60px;margin:24px auto 12px}
|
|
1218
|
+
.ring{width:60px;height:60px}
|
|
1219
|
+
.countdown-num{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:24px;font-weight:700;color:#22c55e;font-variant-numeric:tabular-nums}
|
|
1220
|
+
</style>
|
|
1221
|
+
</head>
|
|
1222
|
+
<body>
|
|
1223
|
+
<div class="container">
|
|
1224
|
+
<div class="logo">
|
|
1225
|
+
${ghostSvg}
|
|
1226
|
+
<span class="logo-text">PI-KIRO</span>
|
|
1227
|
+
</div>
|
|
1228
|
+
<div class="status-box">
|
|
1229
|
+
<span class="status-icon">${iconSvg}</span>
|
|
1230
|
+
<div>
|
|
1231
|
+
<div class="status-title">${title}</div>
|
|
1232
|
+
<div class="status-msg">${message}</div>
|
|
1233
|
+
</div>
|
|
1234
|
+
</div>
|
|
1235
|
+
${countdownHtml}
|
|
1236
|
+
</div>
|
|
1237
|
+
</body>
|
|
1238
|
+
</html>`;
|
|
1239
|
+
}
|
|
1240
|
+
function oauthIdcDelegationPage() {
|
|
1241
|
+
const ghostSvg = `<svg width="56" height="56" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
1242
|
+
<path d="M50 5C28.5 5 11 22.5 11 44v36c0 2.8 1.2 5.4 3.2 7.2 2 1.8 4.7 2.6 7.4 2.2l3.4-.5c3.2-.5 6.5.4 9 2.5l2.2 1.8c2.4 2 5.4 3 8.5 3h10.6c3.1 0 6.1-1.1 8.5-3l2.2-1.8c2.5-2.1 5.8-3 9-2.5l3.4.5c2.7.4 5.4-.4 7.4-2.2 2-1.8 3.2-4.4 3.2-7.2V44C89 22.5 71.5 5 50 5z" fill="white"/>
|
|
1243
|
+
<circle cx="37" cy="45" r="7" fill="#0a0a0a"/>
|
|
1244
|
+
<circle cx="63" cy="45" r="7" fill="#0a0a0a"/>
|
|
1245
|
+
</svg>`;
|
|
1246
|
+
return `<!DOCTYPE html>
|
|
1247
|
+
<html lang="en">
|
|
1248
|
+
<head>
|
|
1249
|
+
<meta charset="utf-8">
|
|
1250
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1251
|
+
<title>PI-KIRO — Enterprise Sign-In</title>
|
|
1252
|
+
<style>
|
|
1253
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
1254
|
+
body{background:#0a0a0a;color:#e5e5e5;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;text-align:center}
|
|
1255
|
+
.container{max-width:420px;padding:2rem}
|
|
1256
|
+
.logo{display:flex;align-items:center;justify-content:center;gap:16px;margin-bottom:48px}
|
|
1257
|
+
.logo-text{font-size:42px;font-weight:700;letter-spacing:6px;color:#7c3aed;font-family:'Courier New',monospace}
|
|
1258
|
+
.status-box{border:1.5px solid #22c55e;border-radius:12px;padding:20px 28px;display:flex;align-items:flex-start;gap:14px;text-align:left;margin-bottom:20px;background:rgba(34,197,94,0.04)}
|
|
1259
|
+
.status-icon{flex-shrink:0;margin-top:2px}
|
|
1260
|
+
.status-title{font-size:15px;font-weight:600;color:#22c55e;margin-bottom:4px}
|
|
1261
|
+
.status-msg{font-size:13px;color:#a3a3a3;line-height:1.4}
|
|
1262
|
+
.subtitle{font-size:13px;color:#737373;margin-top:4px}
|
|
1263
|
+
.subtitle strong{color:#a3a3a3}
|
|
1264
|
+
.spinner{width:28px;height:28px;border:3px solid #1a1a1a;border-top-color:#22c55e;border-radius:50%;animation:spin 0.8s linear infinite;margin:24px auto 12px}
|
|
1265
|
+
@keyframes spin{to{transform:rotate(360deg)}}
|
|
1266
|
+
.countdown{position:relative;width:60px;height:60px;margin:24px auto 12px;display:none}
|
|
1267
|
+
.ring{width:60px;height:60px}
|
|
1268
|
+
.countdown-num{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:24px;font-weight:700;color:#22c55e;font-variant-numeric:tabular-nums}
|
|
1269
|
+
</style>
|
|
1270
|
+
</head>
|
|
1271
|
+
<body>
|
|
1272
|
+
<div class="container">
|
|
1273
|
+
<div class="logo">
|
|
1274
|
+
${ghostSvg}
|
|
1275
|
+
<span class="logo-text">PI-KIRO</span>
|
|
1276
|
+
</div>
|
|
1277
|
+
<div class="status-box">
|
|
1278
|
+
<span class="status-icon"><svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M16.67 5L7.5 14.17 3.33 10" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
|
|
1279
|
+
<div>
|
|
1280
|
+
<div class="status-title">Enterprise sign-in</div>
|
|
1281
|
+
<div class="status-msg" id="status-msg">Preparing device authorization…</div>
|
|
1282
|
+
</div>
|
|
1283
|
+
</div>
|
|
1284
|
+
<div class="spinner" id="spinner"></div>
|
|
1285
|
+
<div class="countdown" id="countdown">
|
|
1286
|
+
<svg class="ring" viewBox="0 0 60 60">
|
|
1287
|
+
<circle cx="30" cy="30" r="26" stroke="#1a1a1a" stroke-width="3" fill="none"/>
|
|
1288
|
+
<circle id="ring-progress" cx="30" cy="30" r="26" stroke="#22c55e" stroke-width="3" fill="none"
|
|
1289
|
+
stroke-dasharray="163.36" stroke-dashoffset="0" stroke-linecap="round"
|
|
1290
|
+
transform="rotate(-90 30 30)" style="transition:stroke-dashoffset 1s linear"/>
|
|
1291
|
+
</svg>
|
|
1292
|
+
<span class="countdown-num" id="countdown-num">3</span>
|
|
1293
|
+
</div>
|
|
1294
|
+
<p class="subtitle" id="subtitle">Waiting for device authorization…</p>
|
|
1295
|
+
<script>
|
|
1296
|
+
(function(){
|
|
1297
|
+
var msg=document.getElementById('status-msg'),
|
|
1298
|
+
spinner=document.getElementById('spinner'),
|
|
1299
|
+
cd=document.getElementById('countdown'),
|
|
1300
|
+
cdNum=document.getElementById('countdown-num'),
|
|
1301
|
+
ring=document.getElementById('ring-progress'),
|
|
1302
|
+
sub=document.getElementById('subtitle'),
|
|
1303
|
+
circ=163.36;
|
|
1304
|
+
|
|
1305
|
+
function poll(){
|
|
1306
|
+
fetch('/idc-verify').then(function(r){return r.json()}).then(function(d){
|
|
1307
|
+
if(d.url){
|
|
1308
|
+
spinner.style.display='none';
|
|
1309
|
+
cd.style.display='block';
|
|
1310
|
+
msg.textContent='Device authorization ready';
|
|
1311
|
+
try{sub.innerHTML='Redirecting to <strong>'+new URL(d.url).hostname+'</strong>…'}catch(e){}
|
|
1312
|
+
countdown(3,d.url);
|
|
1313
|
+
} else {
|
|
1314
|
+
setTimeout(poll,500);
|
|
1315
|
+
}
|
|
1316
|
+
}).catch(function(){setTimeout(poll,1000)});
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
function countdown(n,url){
|
|
1320
|
+
if(n<=0){window.location.href=url;return}
|
|
1321
|
+
cdNum.textContent=n;
|
|
1322
|
+
ring.setAttribute('stroke-dashoffset',String(circ*(1-n/3)));
|
|
1323
|
+
setTimeout(function(){countdown(n-1,url)},1000);
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
poll();
|
|
1327
|
+
})();
|
|
1328
|
+
</script>
|
|
1329
|
+
</div>
|
|
1330
|
+
</body>
|
|
1331
|
+
</html>`;
|
|
1332
|
+
}
|
|
1333
|
+
function startCallbackServer(expectedState) {
|
|
1334
|
+
return new Promise((resolve2, reject) => {
|
|
1335
|
+
let settleWait;
|
|
1336
|
+
const waitForCodePromise = new Promise((res) => {
|
|
1337
|
+
settleWait = res;
|
|
1338
|
+
});
|
|
1339
|
+
let idcVerifyUrl = null;
|
|
1340
|
+
const server = createServer((req, res) => {
|
|
1341
|
+
try {
|
|
1342
|
+
const url = new URL(req.url ?? "", SOCIAL_REDIRECT_URI);
|
|
1343
|
+
if (url.pathname === "/idc-verify") {
|
|
1344
|
+
res.writeHead(200, {
|
|
1345
|
+
"Content-Type": "application/json",
|
|
1346
|
+
"Access-Control-Allow-Origin": "*",
|
|
1347
|
+
"Cache-Control": "no-store"
|
|
1348
|
+
});
|
|
1349
|
+
res.end(JSON.stringify({ url: idcVerifyUrl }));
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
const code = url.searchParams.get("code");
|
|
1353
|
+
const state = url.searchParams.get("state");
|
|
1354
|
+
const loginOption = url.searchParams.get("login_option");
|
|
1355
|
+
const issuerUrl = url.searchParams.get("issuer_url");
|
|
1356
|
+
const idcRegion = url.searchParams.get("idc_region");
|
|
1357
|
+
const isIdcDelegation = loginOption === "awsidc" && !!issuerUrl && !!state;
|
|
1358
|
+
if (!state || !code && !isIdcDelegation) {
|
|
1359
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
1360
|
+
res.end("");
|
|
1361
|
+
return;
|
|
1362
|
+
}
|
|
1363
|
+
if (state !== expectedState) {
|
|
1364
|
+
res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
|
|
1365
|
+
res.end(oauthCallbackPage("error", "State mismatch", "The OAuth state parameter did not match. Please try logging in again."));
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
1369
|
+
if (isIdcDelegation) {
|
|
1370
|
+
res.end(oauthIdcDelegationPage());
|
|
1371
|
+
} else {
|
|
1372
|
+
res.end(oauthCallbackPage("success", "Request approved", "PI-KIRO has been given requested permissions."));
|
|
1373
|
+
}
|
|
1374
|
+
settleWait?.({
|
|
1375
|
+
code,
|
|
1376
|
+
state,
|
|
1377
|
+
callbackPath: url.pathname,
|
|
1378
|
+
loginOption,
|
|
1379
|
+
issuerUrl: issuerUrl ?? undefined,
|
|
1380
|
+
idcRegion: idcRegion ?? undefined
|
|
1381
|
+
});
|
|
1382
|
+
} catch {
|
|
1383
|
+
res.writeHead(500, { "Content-Type": "text/plain; charset=utf-8" });
|
|
1384
|
+
res.end("Internal error");
|
|
1385
|
+
}
|
|
1386
|
+
});
|
|
1387
|
+
server.on("error", (err) => {
|
|
1388
|
+
reject(err);
|
|
1389
|
+
});
|
|
1390
|
+
server.listen(SOCIAL_REDIRECT_PORT, "localhost", () => {
|
|
1391
|
+
resolve2({
|
|
1392
|
+
server,
|
|
1393
|
+
redirectUri: SOCIAL_REDIRECT_URI,
|
|
1394
|
+
cancelWait: () => {
|
|
1395
|
+
settleWait?.(null);
|
|
1396
|
+
},
|
|
1397
|
+
waitForCode: () => waitForCodePromise,
|
|
1398
|
+
setIdcVerifyUrl: (url) => {
|
|
1399
|
+
idcVerifyUrl = url;
|
|
1400
|
+
}
|
|
1401
|
+
});
|
|
1402
|
+
});
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
async function runSocialSignInFlow(callbacks) {
|
|
1406
|
+
const verifier = generateCodeVerifier();
|
|
1407
|
+
const challenge = generateCodeChallenge(verifier);
|
|
1408
|
+
const state = generateRandomState();
|
|
1409
|
+
const callbackServer = await startCallbackServer(state);
|
|
1410
|
+
try {
|
|
1411
|
+
const signInUrl = buildSocialSignInURL(callbackServer.redirectUri, challenge, state);
|
|
1412
|
+
callbacks.onAuth({
|
|
1413
|
+
url: signInUrl,
|
|
1414
|
+
instructions: "Complete sign-in in your browser."
|
|
1415
|
+
});
|
|
1416
|
+
callbacks.onProgress?.("Waiting for browser sign-in…");
|
|
1417
|
+
let code;
|
|
1418
|
+
let tokenRedirectUri = SOCIAL_REDIRECT_URI;
|
|
1419
|
+
let callbackResult = null;
|
|
1420
|
+
if (callbacks.onManualCodeInput) {
|
|
1421
|
+
let manualInput;
|
|
1422
|
+
let manualError;
|
|
1423
|
+
const manualPromise = callbacks.onManualCodeInput().then((input) => {
|
|
1424
|
+
manualInput = input;
|
|
1425
|
+
callbackServer.cancelWait();
|
|
1426
|
+
}).catch((err) => {
|
|
1427
|
+
manualError = err instanceof Error ? err : new Error(String(err));
|
|
1428
|
+
callbackServer.cancelWait();
|
|
1429
|
+
});
|
|
1430
|
+
callbackResult = await callbackServer.waitForCode();
|
|
1431
|
+
if (manualError)
|
|
1432
|
+
throw manualError;
|
|
1433
|
+
if (callbackResult?.loginOption !== "awsidc" || !callbackResult.issuerUrl) {
|
|
1434
|
+
if (callbackResult?.code) {
|
|
1435
|
+
code = callbackResult.code;
|
|
1436
|
+
tokenRedirectUri = buildTokenRedirectUri(callbackResult.callbackPath, callbackResult.loginOption);
|
|
1437
|
+
} else if (manualInput) {
|
|
1438
|
+
code = parseAuthRedirectInput(manualInput).code;
|
|
1439
|
+
}
|
|
1440
|
+
if (!code) {
|
|
1441
|
+
await manualPromise;
|
|
1442
|
+
if (manualError)
|
|
1443
|
+
throw manualError;
|
|
1444
|
+
if (manualInput) {
|
|
1445
|
+
code = parseAuthRedirectInput(manualInput).code;
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
} else {
|
|
1450
|
+
callbackResult = await callbackServer.waitForCode();
|
|
1451
|
+
if (callbackResult?.code) {
|
|
1452
|
+
code = callbackResult.code;
|
|
1453
|
+
tokenRedirectUri = buildTokenRedirectUri(callbackResult.callbackPath, callbackResult.loginOption);
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
if (callbackResult?.loginOption === "awsidc" && callbackResult.issuerUrl) {
|
|
1457
|
+
callbacks.onProgress?.("Enterprise sign-in detected — starting device authorization…");
|
|
1458
|
+
const idcRegion = callbackResult.idcRegion || BUILDER_ID_REGION;
|
|
1459
|
+
const wrappedCallbacks = {
|
|
1460
|
+
...callbacks,
|
|
1461
|
+
onAuth: (info) => {
|
|
1462
|
+
callbackServer.setIdcVerifyUrl(info.url);
|
|
1463
|
+
callbacks.onAuth(info);
|
|
1464
|
+
}
|
|
1465
|
+
};
|
|
1466
|
+
try {
|
|
1467
|
+
return await runDeviceCodeFlow(wrappedCallbacks, callbackResult.issuerUrl, [idcRegion], "idc");
|
|
1468
|
+
} finally {
|
|
1469
|
+
callbackServer.server.close();
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
if (!code) {
|
|
1473
|
+
const input = await callbacks.onPrompt({
|
|
1474
|
+
message: "Paste the authorization code or the full redirect URL:",
|
|
1475
|
+
placeholder: SOCIAL_REDIRECT_URI
|
|
1476
|
+
});
|
|
1477
|
+
code = parseAuthRedirectInput(input).code;
|
|
1478
|
+
}
|
|
1479
|
+
if (!code) {
|
|
1480
|
+
throw new Error("Missing authorization code — sign-in was not completed");
|
|
1481
|
+
}
|
|
1482
|
+
callbacks.onProgress?.("Exchanging authorization code…");
|
|
1483
|
+
const resp = await fetch(`${KIRO_SOCIAL_AUTH_ENDPOINT}/oauth/token`, {
|
|
1484
|
+
method: "POST",
|
|
1485
|
+
headers: { "Content-Type": "application/json", "User-Agent": "pi-kiro" },
|
|
1486
|
+
body: JSON.stringify({
|
|
1487
|
+
code,
|
|
1488
|
+
code_verifier: verifier,
|
|
1489
|
+
redirect_uri: tokenRedirectUri
|
|
1490
|
+
})
|
|
1491
|
+
});
|
|
1492
|
+
if (!resp.ok) {
|
|
1493
|
+
const body = await resp.text().catch(() => "");
|
|
1494
|
+
throw new Error(`Token exchange failed: ${resp.status} ${body}`);
|
|
1495
|
+
}
|
|
1496
|
+
const data = await resp.json();
|
|
1497
|
+
if (!data.accessToken || !data.refreshToken) {
|
|
1498
|
+
throw new Error("Token exchange returned no tokens");
|
|
1499
|
+
}
|
|
1500
|
+
if (data.profileArn) {
|
|
1501
|
+
try {
|
|
1502
|
+
const apiRegion = resolveApiRegion(BUILDER_ID_REGION);
|
|
1503
|
+
const apiModels = await fetchAvailableModels(data.accessToken, apiRegion, data.profileArn);
|
|
1504
|
+
setCachedDynamicModels(buildModelsFromApi(apiModels));
|
|
1505
|
+
log.info(`Fetched and cached ${apiModels.length} models after social sign-in`);
|
|
1506
|
+
} catch (err) {
|
|
1507
|
+
log.warn(`Failed to fetch models after social sign-in: ${err}`);
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
return {
|
|
1511
|
+
refresh: `${data.refreshToken}|||social`,
|
|
1512
|
+
access: data.accessToken,
|
|
1513
|
+
expires: Date.now() + (data.expiresIn ?? 3600) * 1000 - EXPIRES_BUFFER_MS,
|
|
1514
|
+
clientId: "",
|
|
1515
|
+
clientSecret: "",
|
|
1516
|
+
region: BUILDER_ID_REGION,
|
|
1517
|
+
authMethod: "social",
|
|
1518
|
+
profileArn: data.profileArn
|
|
1519
|
+
};
|
|
1520
|
+
} finally {
|
|
1521
|
+
callbackServer.server.close();
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1095
1524
|
async function loginKiro(callbacks) {
|
|
1096
1525
|
const method = await callbacks.onSelect({
|
|
1097
1526
|
message: "Select login method:",
|
|
@@ -1111,7 +1540,7 @@ async function loginKiro(callbacks) {
|
|
|
1111
1540
|
return loginDesktopManual(callbacks);
|
|
1112
1541
|
}
|
|
1113
1542
|
if (method === "builder-id") {
|
|
1114
|
-
return
|
|
1543
|
+
return runSocialSignInFlow(callbacks);
|
|
1115
1544
|
}
|
|
1116
1545
|
const startUrl = (await callbacks.onPrompt({
|
|
1117
1546
|
message: "Paste your IAM Identity Center start URL:",
|
|
@@ -1229,7 +1658,7 @@ async function syncBackToKiroCli(result) {
|
|
|
1229
1658
|
accessToken: result.access,
|
|
1230
1659
|
refreshToken: result.refresh.split("|")[0] ?? "",
|
|
1231
1660
|
region: result.region,
|
|
1232
|
-
authMethod: result.authMethod === "builder-id" ? "
|
|
1661
|
+
authMethod: result.authMethod === "builder-id" || result.authMethod === "social" ? "desktop" : result.authMethod,
|
|
1233
1662
|
source: result.kiroSyncSource,
|
|
1234
1663
|
tokenKey: result.kiroSyncTokenKey
|
|
1235
1664
|
});
|
|
@@ -1266,10 +1695,10 @@ async function refreshTokenInner(credentials) {
|
|
|
1266
1695
|
if (!refreshToken || !region) {
|
|
1267
1696
|
throw new Error("Refresh token is missing region — re-login required");
|
|
1268
1697
|
}
|
|
1269
|
-
if (authMethod !== "desktop" && (!clientId || !clientSecret)) {
|
|
1698
|
+
if (authMethod !== "desktop" && authMethod !== "social" && (!clientId || !clientSecret)) {
|
|
1270
1699
|
throw new Error("Refresh token is missing clientId/clientSecret — re-login required");
|
|
1271
1700
|
}
|
|
1272
|
-
if (authMethod === "desktop") {
|
|
1701
|
+
if (authMethod === "desktop" || authMethod === "social") {
|
|
1273
1702
|
const desktopEndpoint = `https://prod.${region}.auth.desktop.kiro.dev/refreshToken`;
|
|
1274
1703
|
const resp2 = await fetch(desktopEndpoint, {
|
|
1275
1704
|
method: "POST",
|
|
@@ -1292,13 +1721,13 @@ async function refreshTokenInner(credentials) {
|
|
|
1292
1721
|
}
|
|
1293
1722
|
}
|
|
1294
1723
|
return {
|
|
1295
|
-
refresh: `${data2.refreshToken}
|
|
1724
|
+
refresh: `${data2.refreshToken}|||${authMethod}`,
|
|
1296
1725
|
access: data2.accessToken,
|
|
1297
1726
|
expires: Date.now() + (data2.expiresIn ?? 3600) * 1000 - EXPIRES_BUFFER_MS,
|
|
1298
1727
|
clientId: "",
|
|
1299
1728
|
clientSecret: "",
|
|
1300
1729
|
region,
|
|
1301
|
-
authMethod
|
|
1730
|
+
authMethod,
|
|
1302
1731
|
profileArn: credentials.profileArn,
|
|
1303
1732
|
kiroSyncSource: credentials.kiroSyncSource,
|
|
1304
1733
|
kiroSyncTokenKey: credentials.kiroSyncTokenKey
|
|
@@ -1340,8 +1769,8 @@ async function refreshTokenInner(credentials) {
|
|
|
1340
1769
|
}
|
|
1341
1770
|
async function refreshKiroToken(credentials) {
|
|
1342
1771
|
const inputMethod = credentials.authMethod;
|
|
1343
|
-
const authMethod = inputMethod === "builder-id" || inputMethod === "idc" || inputMethod === "desktop" ? inputMethod : "idc";
|
|
1344
|
-
if (inputMethod !== undefined && inputMethod !== "builder-id" && inputMethod !== "idc" && inputMethod !== "desktop") {
|
|
1772
|
+
const authMethod = inputMethod === "builder-id" || inputMethod === "idc" || inputMethod === "desktop" || inputMethod === "social" ? inputMethod : "idc";
|
|
1773
|
+
if (inputMethod !== undefined && inputMethod !== "builder-id" && inputMethod !== "idc" && inputMethod !== "desktop" && inputMethod !== "social") {
|
|
1345
1774
|
log.warn(`refreshKiroToken: unrecognized authMethod "${String(inputMethod)}" — defaulting to "idc"`);
|
|
1346
1775
|
}
|
|
1347
1776
|
const baseCreds = {
|
|
@@ -1872,7 +2301,7 @@ function countTokens(text) {
|
|
|
1872
2301
|
}
|
|
1873
2302
|
|
|
1874
2303
|
// src/transform.ts
|
|
1875
|
-
import { createHash } from "node:crypto";
|
|
2304
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
1876
2305
|
function normalizeMessages(messages) {
|
|
1877
2306
|
return messages.filter((msg) => msg.role !== "assistant" || msg.stopReason !== "error" && msg.stopReason !== "aborted");
|
|
1878
2307
|
}
|
|
@@ -1925,7 +2354,7 @@ var KIRO_TOOL_USE_ID_RE = /^tooluse_[A-Za-z0-9]+$/;
|
|
|
1925
2354
|
function toKiroToolUseId(id) {
|
|
1926
2355
|
if (KIRO_TOOL_USE_ID_RE.test(id))
|
|
1927
2356
|
return id;
|
|
1928
|
-
const digest =
|
|
2357
|
+
const digest = createHash2("sha256").update(id).digest("hex").slice(0, 22);
|
|
1929
2358
|
return `tooluse_${digest}`;
|
|
1930
2359
|
}
|
|
1931
2360
|
function convertImagesToKiro(images) {
|
|
@@ -3012,10 +3441,22 @@ function writeKiroCredentials(refreshed) {
|
|
|
3012
3441
|
log.warn(`Failed to persist refreshed credentials: ${err}`);
|
|
3013
3442
|
}
|
|
3014
3443
|
}
|
|
3444
|
+
function writeKiroCredentialsPartial(fields) {
|
|
3445
|
+
try {
|
|
3446
|
+
const authPath = join2(homedir2(), ".pi", "agent", "auth.json");
|
|
3447
|
+
const raw = existsSync2(authPath) ? readFileSync2(authPath, "utf-8") : "{}";
|
|
3448
|
+
const data = JSON.parse(raw);
|
|
3449
|
+
const existing = data["kiro"] ?? {};
|
|
3450
|
+
data["kiro"] = { ...existing, ...fields };
|
|
3451
|
+
writeFileSync(authPath, JSON.stringify(data, null, 2), { mode: 384 });
|
|
3452
|
+
} catch (err) {
|
|
3453
|
+
log.warn(`Failed to persist partial credentials: ${err}`);
|
|
3454
|
+
}
|
|
3455
|
+
}
|
|
3015
3456
|
async function extension_default(pi) {
|
|
3016
3457
|
let modelDefs = toProviderModels(kiroModels);
|
|
3017
3458
|
const creds = readKiroCredentials();
|
|
3018
|
-
if (creds?.
|
|
3459
|
+
if (creds?.access || creds?.refresh) {
|
|
3019
3460
|
let accessToken = creds.access;
|
|
3020
3461
|
if (creds.refresh) {
|
|
3021
3462
|
try {
|
|
@@ -3027,16 +3468,34 @@ async function extension_default(pi) {
|
|
|
3027
3468
|
log.warn(`Startup token refresh failed, trying with existing token: ${err}`);
|
|
3028
3469
|
}
|
|
3029
3470
|
}
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3471
|
+
let profileArn = creds.profileArn;
|
|
3472
|
+
if (!profileArn && accessToken) {
|
|
3473
|
+
try {
|
|
3474
|
+
const apiRegion = resolveApiRegion(creds.region);
|
|
3475
|
+
log.info("profileArn missing, resolving via ListAvailableProfiles…");
|
|
3476
|
+
profileArn = await resolveProfileArn(accessToken, apiRegion) ?? undefined;
|
|
3477
|
+
if (profileArn) {
|
|
3478
|
+
log.info(`Resolved profileArn: ${profileArn}`);
|
|
3479
|
+
writeKiroCredentialsPartial({ profileArn });
|
|
3480
|
+
} else {
|
|
3481
|
+
log.warn("Could not resolve profileArn — model fetch and streaming will fail");
|
|
3482
|
+
}
|
|
3483
|
+
} catch (err) {
|
|
3484
|
+
log.warn(`profileArn resolution failed: ${err}`);
|
|
3485
|
+
}
|
|
3486
|
+
}
|
|
3487
|
+
if (profileArn) {
|
|
3488
|
+
seedProfileArn(profileArn);
|
|
3489
|
+
try {
|
|
3490
|
+
const apiRegion = resolveApiRegion(creds.region);
|
|
3491
|
+
const apiModels = await fetchAvailableModels(accessToken, apiRegion, profileArn);
|
|
3492
|
+
const dynamicDefs = buildModelsFromApi(apiModels);
|
|
3493
|
+
setCachedDynamicModels(dynamicDefs);
|
|
3494
|
+
modelDefs = toProviderModels(dynamicDefs);
|
|
3495
|
+
log.info(`Loaded ${modelDefs.length} models dynamically from Kiro API`);
|
|
3496
|
+
} catch (err) {
|
|
3497
|
+
log.warn(`Failed to fetch models at startup, using hardcoded fallback: ${err}`);
|
|
3498
|
+
}
|
|
3040
3499
|
}
|
|
3041
3500
|
} else {
|
|
3042
3501
|
log.warn("Run 'kiro login' to authenticate and fetch models dynamically. Note: This extension does not have the same authentication mechanism as other Kiro tools.");
|
package/dist/models.d.ts
CHANGED
|
@@ -93,6 +93,12 @@ export interface KiroApiModel {
|
|
|
93
93
|
};
|
|
94
94
|
};
|
|
95
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Resolve the Kiro profile ARN by calling ListAvailableProfiles.
|
|
98
|
+
* Builder ID device-code login doesn't receive a profileArn, so we
|
|
99
|
+
* discover it here. Returns null on failure (graceful fallback).
|
|
100
|
+
*/
|
|
101
|
+
export declare function resolveProfileArn(accessToken: string, apiRegion: string): Promise<string | null>;
|
|
96
102
|
/**
|
|
97
103
|
* Fetch the list of models actually available for this account from Kiro.
|
|
98
104
|
* Filters out "auto" — it appears in ListAvailableModels but is rejected
|
package/dist/models.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"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"}
|
package/dist/oauth.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export interface KiroCredentials extends OAuthCredentials {
|
|
|
21
21
|
* - `idc`: IAM Identity Center (enterprise SSO, any region).
|
|
22
22
|
* - `desktop`: Kiro IDE native install (bare refresh token, no clientId/clientSecret).
|
|
23
23
|
*/
|
|
24
|
-
authMethod: "builder-id" | "idc" | "desktop";
|
|
24
|
+
authMethod: "builder-id" | "idc" | "desktop" | "social";
|
|
25
25
|
/** Profile ARN from Kiro, used to scope API calls. */
|
|
26
26
|
profileArn?: string;
|
|
27
27
|
/** Local Kiro source, used only to decide safe CLI DB write-back. */
|
package/dist/oauth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AASnF,OAAO,KAAK,EAAsB,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AASnF,OAAO,KAAK,EAAsB,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAIhF,eAAO,MAAM,oBAAoB,mCAAmC,CAAC;AACrE,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAC7C,eAAO,MAAM,UAAU,UAMtB,CAAC;AAmBF,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;OAOG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,UAAU,EAAE,YAAY,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAC;IACxD,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AA8pBD;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,eAAe,CAAC,CAsDxF;AA8TD;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,gBAAgB,GAC5B,OAAO,CAAC,eAAe,CAAC,CAkH1B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@javargasm/pi-kiro",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "Kiro provider for the pi coding agent: AWS Builder ID / IAM Identity Center login and the CodeWhisperer streaming API, exposing the Kiro Claude model family.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|