@magpie-community/opencode-mimo-auth 0.1.5 → 0.1.6
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 +7 -1
- package/index.mjs +58 -19
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -29,7 +29,13 @@ Chat completions go to `https://mimo-server-<region>.xiaomimimo.com/api/route/ch
|
|
|
29
29
|
|
|
30
30
|
`mimo-auto`, the app's default model, is requested as `mimo-pro`.
|
|
31
31
|
|
|
32
|
-
The session is renewed with the passToken a day after it was issued.
|
|
32
|
+
The session is renewed with the passToken a day after it was issued.
|
|
33
|
+
magpie (0.1.684 and later) does it ahead of time through `auth.refresh`, ten
|
|
34
|
+
minutes before that day is out (`refreshLead`), once for the account and
|
|
35
|
+
before its requests, models and usage ask for it; a passToken Xiaomi no
|
|
36
|
+
longer takes marks the account for a new sign-in. The check before each
|
|
37
|
+
request stays for OpenCode, which doesn't call `auth.refresh`, and one
|
|
38
|
+
sign-on at a time serves both. A model
|
|
33
39
|
request the server turns away (a 401) is answered as the server answered it,
|
|
34
40
|
as magpie's built-in MiMo account did; reading usage renews the session once
|
|
35
41
|
when the server turns it away. If the passToken no longer works, sign in
|
package/index.mjs
CHANGED
|
@@ -18,6 +18,7 @@ const APP_VERSION = "26.929.292248"
|
|
|
18
18
|
const SOURCE = "mimocode-cli-free"
|
|
19
19
|
const UA = "miNative PC/Normal Windows_NT/10.0.26100 SDKV/1.0.0 DEVT/PC DEVS/Windows APP/miaccount_desktop APPV/0.1.0"
|
|
20
20
|
const RENEW_AFTER = 24 * 60 * 60 * 1000 // the app signs on again after a day
|
|
21
|
+
const LEAD_MS = 10 * 60 * 1000 // this close to it, magpie signs on again ahead of time (auth.refresh)
|
|
21
22
|
const SIGN_IN_LIFE = 10 * 60 * 1000
|
|
22
23
|
|
|
23
24
|
const MODEL = { release_date: "2026-07-01", attachment: true, tool_call: true, limit: { context: 1_000_000, output: 128_000 }, modalities: { input: ["text", "image"], output: ["text"] } }
|
|
@@ -338,8 +339,11 @@ function serverTime(v) {
|
|
|
338
339
|
|
|
339
340
|
export const MimoAuthPlugin = async ({ client }) => {
|
|
340
341
|
// renewals under way, one to an account: two accounts signing on at
|
|
341
|
-
// once each keep their own session
|
|
342
|
+
// once each keep their own session. renewed is the last session each
|
|
343
|
+
// account got here, so magpie's auth.refresh handed a sign-in from
|
|
344
|
+
// before it gives that one rather than signing on again.
|
|
342
345
|
const renewing = new Map()
|
|
346
|
+
const renewed = new Map()
|
|
343
347
|
|
|
344
348
|
const save = async (auth) => {
|
|
345
349
|
try {
|
|
@@ -347,28 +351,20 @@ export const MimoAuthPlugin = async ({ client }) => {
|
|
|
347
351
|
} catch {}
|
|
348
352
|
}
|
|
349
353
|
|
|
350
|
-
//
|
|
351
|
-
//
|
|
352
|
-
//
|
|
353
|
-
|
|
354
|
-
const fresh = async (getAuth, force) => {
|
|
355
|
-
const a = fromAuth(await getAuth())
|
|
356
|
-
if (!a) throw new Error("Xiaomi MiMo: not signed in")
|
|
357
|
-
if (!force && Object.keys(a.cookies).length && Date.now() < a.expires) return a
|
|
354
|
+
// renew signs the account on again, once at a time: those who come
|
|
355
|
+
// while it runs wait for it. keep saves the new session (the request
|
|
356
|
+
// path); magpie's auth.refresh saves what it gives itself.
|
|
357
|
+
const renew = (a, keep) => {
|
|
358
358
|
const who = String(a.creds.userId ?? "")
|
|
359
359
|
let r = renewing.get(who)
|
|
360
360
|
if (!r) {
|
|
361
361
|
r = (async () => {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
// a hiccup: the session in hand may still do
|
|
369
|
-
if (!(e instanceof Lapsed) && !force && Object.keys(a.cookies).length) return a
|
|
370
|
-
throw e
|
|
371
|
-
}
|
|
362
|
+
const s = await session(a.creds, a.creds.base)
|
|
363
|
+
const issued = Date.now()
|
|
364
|
+
const got = { creds: a.creds, cookies: s.cookies, expires: issued + RENEW_AFTER, renewed: true }
|
|
365
|
+
renewed.set(who, got)
|
|
366
|
+
if (keep) await save(toAuth(a.creds, s.cookies, issued))
|
|
367
|
+
return got
|
|
372
368
|
})().finally(() => {
|
|
373
369
|
renewing.delete(who)
|
|
374
370
|
})
|
|
@@ -377,6 +373,44 @@ export const MimoAuthPlugin = async ({ client }) => {
|
|
|
377
373
|
return r
|
|
378
374
|
}
|
|
379
375
|
|
|
376
|
+
// fresh is the account with a live session, signed on again when it is
|
|
377
|
+
// older than the app lets one get, or when force is set (the server
|
|
378
|
+
// turned the last one away); renewed when it was signed on again, which
|
|
379
|
+
// took the built-in's lapse mark off
|
|
380
|
+
const fresh = async (getAuth, force) => {
|
|
381
|
+
const a = fromAuth(await getAuth())
|
|
382
|
+
if (!a) throw new Error("Xiaomi MiMo: not signed in")
|
|
383
|
+
if (!force && Object.keys(a.cookies).length && Date.now() < a.expires) return a
|
|
384
|
+
try {
|
|
385
|
+
return await renew(a, true)
|
|
386
|
+
} catch (e) {
|
|
387
|
+
// a hiccup: the session in hand may still do
|
|
388
|
+
if (!(e instanceof Lapsed) && !force && Object.keys(a.cookies).length) return a
|
|
389
|
+
throw e
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// refresh is magpie's auth.refresh: the session signed on again
|
|
394
|
+
// LEAD_MS before the app would, as the fields that changed (the Xiaomi
|
|
395
|
+
// account in refresh stays as it is). A passToken Xiaomi no longer takes
|
|
396
|
+
// is signIn "expired"; any other failure throws as it is.
|
|
397
|
+
const refresh = async (auth) => {
|
|
398
|
+
const a = fromAuth(auth)
|
|
399
|
+
if (!a) return undefined
|
|
400
|
+
const last = renewed.get(String(a.creds.userId ?? ""))
|
|
401
|
+
// signed on again here already, the store not yet saying so
|
|
402
|
+
if (last && last.expires > a.expires && Date.now() < last.expires - LEAD_MS) {
|
|
403
|
+
return { access: JSON.stringify(last.cookies), expires: last.expires }
|
|
404
|
+
}
|
|
405
|
+
try {
|
|
406
|
+
const s = await renew(a, false)
|
|
407
|
+
return { access: JSON.stringify(s.cookies), expires: s.expires }
|
|
408
|
+
} catch (e) {
|
|
409
|
+
if (e instanceof Lapsed) throw Object.assign(new Error(e.message), { signIn: "expired" })
|
|
410
|
+
throw e
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
380
414
|
// page asks the MiMo server for one of the account's pages, signing on
|
|
381
415
|
// again once when it is turned away, and gives its data. read.signIn is
|
|
382
416
|
// what that did to the built-in's lapse mark: signed on again took it
|
|
@@ -472,6 +506,11 @@ export const MimoAuthPlugin = async ({ client }) => {
|
|
|
472
506
|
auth: {
|
|
473
507
|
provider: ID,
|
|
474
508
|
usage,
|
|
509
|
+
// magpie signs the account on again LEAD_MS before the day is out,
|
|
510
|
+
// once, before its requests, models and usage ask; fresh's check
|
|
511
|
+
// before each request stays for OpenCode, which doesn't call this
|
|
512
|
+
refreshLead: LEAD_MS,
|
|
513
|
+
refresh,
|
|
475
514
|
loader: async (getAuth) => {
|
|
476
515
|
const a = fromAuth(await getAuth())
|
|
477
516
|
if (!a) return {}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@magpie-community/opencode-mimo-auth",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "OpenCode provider plugin for Xiaomi MiMo: the MiMo app's Xiaomi-account sign-in, MiMo Pro and MiMo Flash",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.mjs",
|
|
7
7
|
"exports": "./index.mjs",
|
|
8
8
|
"files": ["index.mjs", "README.md"],
|
|
9
9
|
"keywords": ["opencode", "opencode-plugin", "xiaomi", "mimo"],
|
|
10
|
-
"license": "MIT"
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"repository": { "type": "git", "url": "git+https://github.com/magpie-community/plugins.git", "directory": "packages/mimo" }
|
|
11
12
|
}
|