@magpie-community/opencode-kiro-auth 0.1.4 → 0.1.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/index.mjs +38 -20
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -188,11 +188,14 @@ async function saveBack(c) {
|
|
|
188
188
|
|
|
189
189
|
// ---- tokens --------------------------------------------------------------------
|
|
190
190
|
|
|
191
|
+
// EXPIRED is the built-in's words for a sign-in Kiro refused, or one with
|
|
192
|
+
// nothing to refresh it.
|
|
191
193
|
const EXPIRED = "Kiro's sign-in has expired; sign in again"
|
|
194
|
+
const EXPIRED_CLI = EXPIRED + " with `kiro-cli login` or the Kiro IDE"
|
|
192
195
|
|
|
193
196
|
// gone is an error saying the sign-in itself is gone — refused, or never
|
|
194
|
-
// there
|
|
195
|
-
//
|
|
197
|
+
// there. The built-in marked no Kiro account lapsed, not even then, nor
|
|
198
|
+
// cleared one: every answer and usage read says the account is kept.
|
|
196
199
|
const gone = (msg) => Object.assign(new Error(msg), { gone: true })
|
|
197
200
|
const fresh = (c) => c.method === "apikey" || !c.expires || c.expires - Date.now() > 2 * 60 * 1000
|
|
198
201
|
|
|
@@ -206,8 +209,8 @@ async function post(url, contentType, body, headers = {}) {
|
|
|
206
209
|
}
|
|
207
210
|
const text = await res.text()
|
|
208
211
|
if (!res.ok) {
|
|
209
|
-
if ([400, 401, 403].includes(res.status)) throw gone(
|
|
210
|
-
throw new Error(`refreshing Kiro's sign-in: ${res.status}
|
|
212
|
+
if ([400, 401, 403].includes(res.status)) throw gone(EXPIRED_CLI)
|
|
213
|
+
throw new Error(`refreshing Kiro's sign-in: ${res.status} ${STATUS_TEXT[res.status] ?? ""}`.trimEnd()) // Go's res.Status
|
|
211
214
|
}
|
|
212
215
|
return JSON.parse(text)
|
|
213
216
|
}
|
|
@@ -223,7 +226,7 @@ async function refresh(c) {
|
|
|
223
226
|
if (n && n.dbKey === c.dbKey && n.access !== c.access && fresh(n)) return n
|
|
224
227
|
}
|
|
225
228
|
}
|
|
226
|
-
if (!c.refresh) throw gone(
|
|
229
|
+
if (!c.refresh) throw gone(EXPIRED_CLI)
|
|
227
230
|
let out
|
|
228
231
|
switch (c.method) {
|
|
229
232
|
case "social": {
|
|
@@ -246,9 +249,9 @@ async function refresh(c) {
|
|
|
246
249
|
break
|
|
247
250
|
}
|
|
248
251
|
default:
|
|
249
|
-
throw gone(
|
|
252
|
+
throw gone("Kiro's sign-in has expired")
|
|
250
253
|
}
|
|
251
|
-
if (!out.access) throw gone(
|
|
254
|
+
if (!out.access) throw gone(EXPIRED_CLI)
|
|
252
255
|
const n = { ...c, access: out.access, expires: Date.now() + (out.expiresIn > 0 ? out.expiresIn : 3600) * 1000 }
|
|
253
256
|
if (out.refresh) n.refresh = out.refresh
|
|
254
257
|
await saveBack(n)
|
|
@@ -315,7 +318,7 @@ async function profileOf(c) {
|
|
|
315
318
|
signal: AbortSignal.timeout(20_000),
|
|
316
319
|
})
|
|
317
320
|
if (!res.ok) {
|
|
318
|
-
const msg = `Kiro didn't take the API key: ${res.status}
|
|
321
|
+
const msg = `Kiro didn't take the API key: ${res.status} ${STATUS_TEXT[res.status] ?? ""}`.trimEnd()
|
|
319
322
|
throw res.status === 401 || res.status === 403 ? gone(msg) : new Error(msg)
|
|
320
323
|
}
|
|
321
324
|
const arn = (await res.json().catch(() => null))?.profile?.arn
|
|
@@ -431,7 +434,7 @@ function account(client) {
|
|
|
431
434
|
if (stale && c && read.access !== c.access && fresh(read)) stale = false // the owner refreshed it already
|
|
432
435
|
c = read
|
|
433
436
|
if (!fresh(c) || stale) {
|
|
434
|
-
if (c.method === "apikey") throw gone("Kiro turned down the API key")
|
|
437
|
+
if (c.method === "apikey") throw gone("Kiro turned down the API key saved on the provider")
|
|
435
438
|
c = await refresh(c)
|
|
436
439
|
await save(auth, c)
|
|
437
440
|
}
|
|
@@ -712,7 +715,7 @@ function failure(status, body) {
|
|
|
712
715
|
const e = JSON.parse(body)
|
|
713
716
|
if (e?.message) msg = e.message + (e.reason ? ` (${e.reason})` : "")
|
|
714
717
|
} catch {}
|
|
715
|
-
msg ||=
|
|
718
|
+
msg ||= STATUS_TEXT[status] ?? ""
|
|
716
719
|
if (msg.includes("CONTENT_LENGTH_EXCEEDS_THRESHOLD") || msg.toLowerCase().includes("input is too long"))
|
|
717
720
|
return { status: 400, message: "input is too long for the model's context: " + msg }
|
|
718
721
|
if (msg.includes("INSUFFICIENT_MODEL_CAPACITY")) return { status: 503, message: msg }
|
|
@@ -723,12 +726,23 @@ function failure(status, body) {
|
|
|
723
726
|
const ERROR_TYPES = { 400: "invalid_request_error", 401: "authentication_error", 402: "billing_error", 403: "permission_error",
|
|
724
727
|
404: "not_found_error", 413: "request_too_large", 429: "rate_limit_error", 503: "overloaded_error", 529: "overloaded_error" }
|
|
725
728
|
const errorType = (status) => ERROR_TYPES[status] ?? "api_error"
|
|
729
|
+
// Each failure says X-Magpie-Sign-In: kept, as the built-in never marked
|
|
730
|
+
// an account lapsed (see gone).
|
|
726
731
|
const errorResponse = (status, message) =>
|
|
727
732
|
new Response(JSON.stringify({ type: "error", error: { type: errorType(status), message } }), {
|
|
728
733
|
status,
|
|
729
|
-
headers: { "Content-Type": "application/json" },
|
|
734
|
+
headers: { "Content-Type": "application/json", "X-Magpie-Sign-In": "kept" },
|
|
730
735
|
})
|
|
731
736
|
|
|
737
|
+
// kept is res saying the account is kept: a success too, which the
|
|
738
|
+
// built-in never took for a sign-in come back.
|
|
739
|
+
function kept(res) {
|
|
740
|
+
if (res.headers.has("X-Magpie-Sign-In")) return res
|
|
741
|
+
const headers = new Headers(res.headers)
|
|
742
|
+
headers.set("X-Magpie-Sign-In", "kept")
|
|
743
|
+
return new Response(res.body, { status: res.status, statusText: res.statusText, headers })
|
|
744
|
+
}
|
|
745
|
+
|
|
732
746
|
// ---- the reply: an AWS event stream → Messages ---------------------------------------
|
|
733
747
|
|
|
734
748
|
// frames reads an AWS event stream: each message its length, its headers'
|
|
@@ -1087,7 +1101,9 @@ async function reply(it, model, stream) {
|
|
|
1087
1101
|
}
|
|
1088
1102
|
|
|
1089
1103
|
// generate answers a Messages request through Kiro's API: once more,
|
|
1090
|
-
// refreshed, when Kiro turns the token down (403).
|
|
1104
|
+
// refreshed, when Kiro turns the token down (403). As the built-in: no
|
|
1105
|
+
// credentials is a 401, a failed refresh after the 403 a 502; none marks
|
|
1106
|
+
// the account.
|
|
1091
1107
|
async function generate(creds, auth, req, signal) {
|
|
1092
1108
|
const model = String(req.model ?? "auto")
|
|
1093
1109
|
const budget = thinking(req, model)
|
|
@@ -1095,7 +1111,7 @@ async function generate(creds, auth, req, signal) {
|
|
|
1095
1111
|
try {
|
|
1096
1112
|
a = await creds(auth)
|
|
1097
1113
|
} catch (e) {
|
|
1098
|
-
return errorResponse(
|
|
1114
|
+
return errorResponse(401, e.message)
|
|
1099
1115
|
}
|
|
1100
1116
|
let res
|
|
1101
1117
|
try {
|
|
@@ -1109,7 +1125,7 @@ async function generate(creds, auth, req, signal) {
|
|
|
1109
1125
|
try {
|
|
1110
1126
|
a = await creds(auth, true)
|
|
1111
1127
|
} catch (e) {
|
|
1112
|
-
return errorResponse(
|
|
1128
|
+
return errorResponse(502, e.message)
|
|
1113
1129
|
}
|
|
1114
1130
|
try {
|
|
1115
1131
|
res = await sendKiro(a, buildKiro(req, model, a.profile, budget), signal)
|
|
@@ -1119,10 +1135,11 @@ async function generate(creds, auth, req, signal) {
|
|
|
1119
1135
|
}
|
|
1120
1136
|
}
|
|
1121
1137
|
if (!res.ok) {
|
|
1138
|
+
// Kiro's own 401 is passed on, as the built-in did, the sign-in kept
|
|
1122
1139
|
const f = failure(res.status, (await res.text()).slice(0, 1 << 20))
|
|
1123
1140
|
return errorResponse(f.status, f.message)
|
|
1124
1141
|
}
|
|
1125
|
-
return reply(events(res.body, model, budget), model, req.stream === true)
|
|
1142
|
+
return kept(await reply(events(res.body, model, budget), model, req.stream === true))
|
|
1126
1143
|
}
|
|
1127
1144
|
|
|
1128
1145
|
// ---- signing in ----------------------------------------------------------------------
|
|
@@ -1329,14 +1346,15 @@ export async function KiroAuthPlugin({ client } = {}) {
|
|
|
1329
1346
|
},
|
|
1330
1347
|
}
|
|
1331
1348
|
},
|
|
1332
|
-
// the account's credits, as magpie's built-in showed them
|
|
1349
|
+
// the account's credits, as magpie's built-in showed them; a read,
|
|
1350
|
+
// clean or failed, marked the built-in's account nothing
|
|
1333
1351
|
async usage(getAuth) {
|
|
1334
1352
|
const auth = await getAuth()
|
|
1335
|
-
if (!(auth?.type === "api" && auth.key) && auth?.type !== "oauth") return { error: "not signed in" }
|
|
1353
|
+
if (!(auth?.type === "api" && auth.key) && auth?.type !== "oauth") return { error: "not signed in", signIn: "kept" }
|
|
1336
1354
|
try {
|
|
1337
|
-
return usageOf(await usageLimits(await creds(auth), true))
|
|
1355
|
+
return { ...usageOf(await usageLimits(await creds(auth), true)), signIn: "kept" }
|
|
1338
1356
|
} catch (e) {
|
|
1339
|
-
return { error: e.message }
|
|
1357
|
+
return { error: e.message, signIn: "kept" }
|
|
1340
1358
|
}
|
|
1341
1359
|
},
|
|
1342
1360
|
methods: [
|
|
@@ -1373,4 +1391,4 @@ export async function KiroAuthPlugin({ client } = {}) {
|
|
|
1373
1391
|
}
|
|
1374
1392
|
|
|
1375
1393
|
// for tests
|
|
1376
|
-
export const _internal = { usageOf, buildKiro, events, reply, failure, toolID, thinking, readCLI, readIDE, regionOf, planName, frames }
|
|
1394
|
+
export const _internal = { generate, refresh, usageOf, buildKiro, events, reply, failure, toolID, thinking, readCLI, readIDE, regionOf, planName, frames }
|