@magpie-community/opencode-kiro-auth 0.1.13 → 0.1.14
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 +11 -4
- package/index.mjs +23 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,14 +17,21 @@ Power) and makes its requests, in OpenCode and in magpie. Provider id:
|
|
|
17
17
|
- Builder ID and Identity Center come back with an AWS sign-in URL and
|
|
18
18
|
region. The plugin registers a client with AWS's OIDC service, sends
|
|
19
19
|
the browser to AWS, and trades the code AWS returns.
|
|
20
|
-
- The account is named by the email Kiro has for it (`Get-Usage-Limits`)
|
|
21
|
-
and
|
|
20
|
+
- The account is named by the email Kiro has for it (`Get-Usage-Limits`)
|
|
21
|
+
and the way it was signed in to: `email (Google)`, `email (GitHub)`,
|
|
22
|
+
`email (Builder ID)`, `email (IAM Identity Center)`, `email
|
|
23
|
+
(Internal)`. Its plan is read from the same call, and its usage names
|
|
24
|
+
it the same way.
|
|
22
25
|
- Kiro keeps a Google, a GitHub, a Builder ID and an Identity Center
|
|
23
26
|
sign-in of one email as different accounts. The sign-in carries a `uid`
|
|
24
27
|
(`google`, `github`, `builderid`, `enterprise`), so magpie keeps each one
|
|
25
28
|
beside the others, and a sign-in again the same way replaces only its
|
|
26
|
-
own account. An account signed in before 0.1.13 is given its `uid
|
|
27
|
-
its
|
|
29
|
+
own account. An account signed in before 0.1.13 is given its `uid`,
|
|
30
|
+
and one named by its bare email before 0.1.14 its name, on its first
|
|
31
|
+
request, model listing, usage read or renewal. Until then, a sign-in
|
|
32
|
+
again the same way goes beside it rather than replacing it: magpie
|
|
33
|
+
matches a sign-in by its name, and the plugin can't see the other
|
|
34
|
+
accounts to match it by `uid`.
|
|
28
35
|
- A company's own identity provider (`external_idp`) is not supported
|
|
29
36
|
here. Sign in with `kiro-cli login` and use the next method instead.
|
|
30
37
|
- **Kiro CLI's or Kiro IDE's sign-in**: uses the account kiro-cli is signed
|
package/index.mjs
CHANGED
|
@@ -56,6 +56,15 @@ const isBuilderID = (provider) => String(provider ?? "").toLowerCase() === "buil
|
|
|
56
56
|
// keeps a sign-in of an email already signed in as that account unless
|
|
57
57
|
// both have a uid and the two differ (#309). "" when it isn't known.
|
|
58
58
|
const uidOf = (loginProvider) => String(loginProvider ?? "").trim().toLowerCase()
|
|
59
|
+
// nameOf is what an account is called: its email and the way it was signed
|
|
60
|
+
// in to, as Kiro's sign-in page names it, so two accounts of one email read
|
|
61
|
+
// apart (#309; magpie names a plugin's account by its accountId). A way not
|
|
62
|
+
// known, kiro-cli's or the Kiro IDE's sign-in among them, leaves the email
|
|
63
|
+
// as it is, and magpie tells two such apart by their slot.
|
|
64
|
+
const WAYS = { google: "Google", github: "GitHub", builderid: "Builder ID", enterprise: "IAM Identity Center", internal: "Internal" }
|
|
65
|
+
const nameOf = (email, loginProvider) => (WAYS[uidOf(loginProvider)] ? `${email} (${WAYS[uidOf(loginProvider)]})` : email)
|
|
66
|
+
// a bare email: what an account was called before nameOf
|
|
67
|
+
const bareEmail = (id) => typeof id === "string" && /^[^\s()]+@[^\s()]+$/.test(id)
|
|
59
68
|
|
|
60
69
|
const env = (k) => process.env[k] ?? ""
|
|
61
70
|
const home = () => env("HOME") || homedir()
|
|
@@ -448,11 +457,17 @@ function account(client) {
|
|
|
448
457
|
// sign-in with another way to the same email no longer replaces it
|
|
449
458
|
const uidSaved = new Set()
|
|
450
459
|
const uidField = (auth) => (!auth?.uid && uidOf(auth?.loginProvider) ? { uid: uidOf(auth.loginProvider) } : {})
|
|
460
|
+
// and one called by its bare email is given its name, the way it was
|
|
461
|
+
// signed in to with it
|
|
462
|
+
const nameField = (auth) =>
|
|
463
|
+
bareEmail(auth?.accountId) && nameOf(auth.accountId, auth.loginProvider) !== auth.accountId
|
|
464
|
+
? { accountId: nameOf(auth.accountId, auth.loginProvider) } : {}
|
|
465
|
+
const idFields = (auth) => ({ ...uidField(auth), ...nameField(auth) })
|
|
451
466
|
const save = async (auth, c) => {
|
|
452
467
|
if (!c.own || !client?.auth?.set) return
|
|
453
468
|
const { type: _t, ...rest } = auth
|
|
454
469
|
await client.auth.set({ path: { id: ID }, body: { ...rest, type: "oauth", access: c.access, refresh: c.refresh, expires: c.expires,
|
|
455
|
-
profileArn: c.profile, region: c.region, ...
|
|
470
|
+
profileArn: c.profile, region: c.region, ...idFields(auth) } }).catch(() => {})
|
|
456
471
|
}
|
|
457
472
|
const creds = (auth, stale = false) =>
|
|
458
473
|
locked(async () => {
|
|
@@ -490,7 +505,7 @@ function account(client) {
|
|
|
490
505
|
}
|
|
491
506
|
}
|
|
492
507
|
// once per token: a save that didn't take isn't tried on every request
|
|
493
|
-
if (!saved && c.own &&
|
|
508
|
+
if (!saved && c.own && Object.keys(idFields(auth)).length && !uidSaved.has(c.access)) {
|
|
494
509
|
uidSaved.add(c.access)
|
|
495
510
|
await save(auth, c)
|
|
496
511
|
}
|
|
@@ -513,7 +528,7 @@ function account(client) {
|
|
|
513
528
|
const out = { access: c.access, expires: c.expires }
|
|
514
529
|
if (c.refresh !== auth.refresh) out.refresh = c.refresh
|
|
515
530
|
if (c.profile && c.profile !== auth.profileArn) out.profileArn = c.profile
|
|
516
|
-
return { ...out, ...
|
|
531
|
+
return { ...out, ...idFields(auth) }
|
|
517
532
|
})
|
|
518
533
|
return creds
|
|
519
534
|
}
|
|
@@ -1423,7 +1438,7 @@ async function browserSignIn() {
|
|
|
1423
1438
|
return fail(e.message)
|
|
1424
1439
|
}
|
|
1425
1440
|
const who = await whoIs(c)
|
|
1426
|
-
const user = who.email
|
|
1441
|
+
const user = who.email ? nameOf(who.email, c.loginProvider) : "Kiro account"
|
|
1427
1442
|
finish({ type: "success", provider: ID, refresh: c.refresh, access: c.access, expires: c.expires, accountId: user,
|
|
1428
1443
|
...(uidOf(c.loginProvider) ? { uid: uidOf(c.loginProvider) } : {}),
|
|
1429
1444
|
method: c.method, loginProvider: c.loginProvider, region: c.region, profileArn: who.profile,
|
|
@@ -1515,7 +1530,10 @@ export async function KiroAuthPlugin({ client } = {}) {
|
|
|
1515
1530
|
const auth = await getAuth()
|
|
1516
1531
|
if (!(auth?.type === "api" && auth.key) && auth?.type !== "oauth") return { error: "not signed in", signIn: "kept" }
|
|
1517
1532
|
try {
|
|
1518
|
-
|
|
1533
|
+
const u = usageOf(await usageLimits(await creds(auth), true))
|
|
1534
|
+
// named as the account is
|
|
1535
|
+
if (u.user && auth.type === "oauth" && !auth.source) u.user = nameOf(u.user, auth.loginProvider)
|
|
1536
|
+
return { ...u, signIn: "kept" }
|
|
1519
1537
|
} catch (e) {
|
|
1520
1538
|
return { error: e.message, signIn: "kept" }
|
|
1521
1539
|
}
|