dsh-connect-minimaxcode 0.4.2 → 0.5.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.en.md +421 -0
- package/README.md +426 -350
- package/lib/client.js +165 -8
- package/lib/index.d.ts +304 -1
- package/lib/index.js +968 -26
- package/package.json +94 -94
package/lib/client.js
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
const BUNDLE_NAME = 'dsh-connect-minimaxcode';
|
|
19
19
|
const NAMESPACE = 'dsh-connect-minimaxcode';
|
|
20
20
|
const STATUS_PATH = '/plugins/dsh-connect-minimaxcode/status';
|
|
21
|
+
const ACTION_PATH = '/plugins/dsh-connect-minimaxcode/action';
|
|
21
22
|
const POLL_INTERVAL_MS = 20000;
|
|
22
23
|
const zh = {
|
|
23
24
|
title: 'MiniMax Code 积分',
|
|
@@ -36,9 +37,28 @@
|
|
|
36
37
|
expiringIn: '{amount} 积分 · {date} 到期',
|
|
37
38
|
expiringNone: '7 天内没有积分到期',
|
|
38
39
|
expiringSoon: '30 天内到期 {amount} 积分',
|
|
39
|
-
nextExpiry: '
|
|
40
|
+
nextExpiry: '最近到期日',
|
|
40
41
|
lots: '到期批次',
|
|
41
42
|
noLots: '没有待到期的积分批次',
|
|
43
|
+
loginTitle: '登录',
|
|
44
|
+
loginPlugin: '已在插件内登录',
|
|
45
|
+
loginDesktop: '使用 MiniMax Code 桌面 App 的登录态',
|
|
46
|
+
loginSignedOut: '未登录',
|
|
47
|
+
loginPending: '等待你在浏览器里确认',
|
|
48
|
+
loginCode: '设备码',
|
|
49
|
+
loginOpen: '打开授权页面',
|
|
50
|
+
loginPolled: '我已授权,检查一下',
|
|
51
|
+
loginStart: '登录 MiniMax Code',
|
|
52
|
+
signinTitle: '每日签到',
|
|
53
|
+
signinToday: '第 {day} 天 · {points} 积分',
|
|
54
|
+
signinClaimed: '今日已签到',
|
|
55
|
+
signinClaimable: '今日可签到',
|
|
56
|
+
signinUnavailable: '签到信息不可用',
|
|
57
|
+
signinCycle: '一轮共 {points} 积分',
|
|
58
|
+
signinLast: '上次签到 {day},{points} 积分',
|
|
59
|
+
signinAuto: '每天自动签到',
|
|
60
|
+
signinClaim: '签到',
|
|
61
|
+
claimableToday: '今日可签到',
|
|
42
62
|
};
|
|
43
63
|
const en = {
|
|
44
64
|
title: 'MiniMax Code credits',
|
|
@@ -60,6 +80,25 @@
|
|
|
60
80
|
nextExpiry: 'Next expiry',
|
|
61
81
|
lots: 'Expiring grants',
|
|
62
82
|
noLots: 'No grant is waiting to expire',
|
|
83
|
+
loginTitle: 'Sign-in',
|
|
84
|
+
loginPlugin: 'Signed in through the plugin',
|
|
85
|
+
loginDesktop: 'Using the MiniMax Code desktop app sign-in',
|
|
86
|
+
loginSignedOut: 'Not signed in',
|
|
87
|
+
loginPending: 'Waiting for you to confirm in the browser',
|
|
88
|
+
loginCode: 'Device code',
|
|
89
|
+
loginOpen: 'Open the authorization page',
|
|
90
|
+
loginPolled: 'I authorized it — check',
|
|
91
|
+
loginStart: 'Sign in to MiniMax Code',
|
|
92
|
+
signinTitle: 'Daily check-in',
|
|
93
|
+
signinToday: 'Day {day} · {points} credits',
|
|
94
|
+
signinClaimed: 'Claimed today',
|
|
95
|
+
signinClaimable: 'Claimable today',
|
|
96
|
+
signinUnavailable: 'Check-in information unavailable',
|
|
97
|
+
signinCycle: '{points} credits per cycle',
|
|
98
|
+
signinLast: 'Last claim on {day}, {points} credits',
|
|
99
|
+
signinAuto: 'Claim daily on its own',
|
|
100
|
+
signinClaim: 'Claim',
|
|
101
|
+
claimableToday: 'Claimable today',
|
|
63
102
|
};
|
|
64
103
|
const loader = globalThis.__ModuleLoader__;
|
|
65
104
|
if (loader === undefined)
|
|
@@ -144,7 +183,7 @@
|
|
|
144
183
|
function useStatus() {
|
|
145
184
|
const [status, setStatus] = React.useState(undefined);
|
|
146
185
|
React.useEffect(() => subscribe(setStatus), []);
|
|
147
|
-
return status;
|
|
186
|
+
return [status, () => { void load(); }];
|
|
148
187
|
}
|
|
149
188
|
/** A row of label and value. */
|
|
150
189
|
function row(label, value) {
|
|
@@ -164,7 +203,7 @@
|
|
|
164
203
|
}
|
|
165
204
|
/** The pill in the composer's dock. */
|
|
166
205
|
function CreditPill(props) {
|
|
167
|
-
const status = useStatus();
|
|
206
|
+
const [status] = useStatus();
|
|
168
207
|
const [open, setOpen] = React.useState(false);
|
|
169
208
|
const t = props.t ?? ((key, params) => {
|
|
170
209
|
const template = zh[key] ?? key;
|
|
@@ -192,6 +231,86 @@
|
|
|
192
231
|
onClick: () => setOpen(!open),
|
|
193
232
|
}, label), open ? detail : null);
|
|
194
233
|
}
|
|
234
|
+
/** Ask the host to do something, and let the card read the result. */
|
|
235
|
+
async function act(action, body) {
|
|
236
|
+
try {
|
|
237
|
+
await fetch(`${ACTION_PATH}?action=${encodeURIComponent(action)}`, {
|
|
238
|
+
method: 'POST',
|
|
239
|
+
headers: { 'content-type': 'application/json' },
|
|
240
|
+
body: JSON.stringify(body ?? {}),
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
// The card shows the state the host reports; a failed request is
|
|
245
|
+
// reported there too.
|
|
246
|
+
}
|
|
247
|
+
// Read the state the host produced, so the card shows what happened.
|
|
248
|
+
void load();
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* The sign-in block.
|
|
252
|
+
*
|
|
253
|
+
* The plugin can sign in on its own: the person authorizes in their own
|
|
254
|
+
* browser, and the plugin never sees a password. When the desktop app
|
|
255
|
+
* is already signed in, that credential is used and this block says so.
|
|
256
|
+
*/
|
|
257
|
+
function loginBlock(t, login, refresh) {
|
|
258
|
+
if (login === undefined)
|
|
259
|
+
return null;
|
|
260
|
+
if (login.state === 'signed-in') {
|
|
261
|
+
return h('div', { style: sectionBoxStyle, 'data-minimax-login': true }, row(t('loginTitle'), login.source === 'plugin' ? t('loginPlugin') : t('loginDesktop')));
|
|
262
|
+
}
|
|
263
|
+
if (login.state === 'pending') {
|
|
264
|
+
return h('div', { style: sectionBoxStyle, 'data-minimax-login': true }, row(t('loginTitle'), t('loginPending')), login.userCode !== undefined && login.userCode.length > 0
|
|
265
|
+
? row(t('loginCode'), login.userCode)
|
|
266
|
+
: null, login.verificationUriComplete !== undefined && login.verificationUriComplete.length > 0
|
|
267
|
+
? h('a', {
|
|
268
|
+
href: login.verificationUriComplete,
|
|
269
|
+
target: '_blank',
|
|
270
|
+
rel: 'noreferrer',
|
|
271
|
+
style: linkStyle,
|
|
272
|
+
}, t('loginOpen'))
|
|
273
|
+
: null, h('button', { type: 'button', style: actionButtonStyle, onClick: () => { void act('login-poll'); } }, t('loginPolled')));
|
|
274
|
+
}
|
|
275
|
+
return h('div', { style: sectionBoxStyle, 'data-minimax-login': true }, row(t('loginTitle'), t('loginSignedOut')), h('button', { type: 'button', style: actionButtonStyle, onClick: () => { void act('login-start'); } }, t('loginStart')));
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* The check-in block.
|
|
279
|
+
*
|
|
280
|
+
* The cycle is seven days; the card shows which day it is and what the
|
|
281
|
+
* day is worth, and lets the person claim it — or leave it to the
|
|
282
|
+
* plugin, once a day, and only when the server says the day can be
|
|
283
|
+
* claimed.
|
|
284
|
+
*/
|
|
285
|
+
function signinBlock(t, signin, refresh) {
|
|
286
|
+
if (signin === undefined)
|
|
287
|
+
return null;
|
|
288
|
+
return h('div', { style: sectionBoxStyle, 'data-minimax-signin': true }, h('div', { style: sectionTitleStyle }, t('signinTitle')), signin.today === undefined
|
|
289
|
+
? h('div', { style: mutedStyle }, t('signinUnavailable'))
|
|
290
|
+
: h('div', { style: rowStyle }, h('span', null, t('signinToday', { day: signin.today.dayNo, points: signin.today.points })), h('span', null, signin.today.claimed ? t('signinClaimed') : signin.today.claimable ? t('signinClaimable') : t('signinUnavailable'))), (signin.days ?? []).length === 0
|
|
291
|
+
? null
|
|
292
|
+
: h('div', { style: dayRowStyle }, ...(signin.days ?? []).map(day_ => h('span', {
|
|
293
|
+
key: `day-${day_.dayNo}`,
|
|
294
|
+
title: `${day_.dayNo}: ${day_.points}`,
|
|
295
|
+
style: {
|
|
296
|
+
...dayDotStyle,
|
|
297
|
+
...day_.isToday ? dayTodayStyle : {},
|
|
298
|
+
...day_.status === 3 ? dayClaimedStyle : {},
|
|
299
|
+
},
|
|
300
|
+
}, String(day_.dayNo)))), signin.cyclePoints !== undefined
|
|
301
|
+
? h('div', { style: mutedStyle }, t('signinCycle', { points: signin.cyclePoints }))
|
|
302
|
+
: null, signin.lastClaimDay !== undefined
|
|
303
|
+
? h('div', { style: mutedStyle }, t('signinLast', { day: signin.lastClaimDay, points: signin.lastClaimPoints ?? 0 }))
|
|
304
|
+
: null, h('div', { style: rowStyle }, h('label', { style: checkboxStyle }, h('input', {
|
|
305
|
+
type: 'checkbox',
|
|
306
|
+
checked: signin.autoCheckin === true,
|
|
307
|
+
onChange: (event) => {
|
|
308
|
+
void act('settings', { autoCheckin: event.target?.checked === true });
|
|
309
|
+
},
|
|
310
|
+
}), h('span', null, t('signinAuto'))), signin.today?.claimable === true
|
|
311
|
+
? h('button', { type: 'button', style: actionButtonStyle, onClick: () => { void act('claim'); } }, t('signinClaim'))
|
|
312
|
+
: null), signin.error !== undefined ? h('div', { style: mutedStyle }, signin.error) : null);
|
|
313
|
+
}
|
|
195
314
|
/**
|
|
196
315
|
* The card on the plugin's own page.
|
|
197
316
|
*
|
|
@@ -199,29 +318,31 @@
|
|
|
199
318
|
* is the full card, where the expiry detail belongs.
|
|
200
319
|
*/
|
|
201
320
|
function PluginPage(props) {
|
|
202
|
-
const status = useStatus();
|
|
321
|
+
const [status, refresh] = useStatus();
|
|
203
322
|
const t = props.t ?? ((key, params) => {
|
|
204
323
|
const template = zh[key] ?? key;
|
|
205
324
|
return template.replace(/\{(\w+)\}/g, (_match, name) => String(params?.[name] ?? ''));
|
|
206
325
|
});
|
|
207
326
|
const credits_ = status?.credits;
|
|
208
327
|
const usage = status?.usage;
|
|
328
|
+
const signin = status?.signin;
|
|
329
|
+
const login = status?.login;
|
|
209
330
|
const available = credits_?.state === 'ok' && credits_.total !== undefined;
|
|
210
331
|
if (props.view === 'summary') {
|
|
211
332
|
if (!available)
|
|
212
333
|
return h('span', null, t('unavailable'));
|
|
213
334
|
return h('span', { 'data-minimax-credits-summary': true }, t('balance', { total: credits(credits_.total, 2) }), credits_.expiring !== undefined && credits_.expiring > 0
|
|
214
335
|
? ` · ${t('expiringIn', { amount: credits(credits_.expiring, 2), date: day(credits_.nextExpiryAtMs) })}`
|
|
215
|
-
: '');
|
|
336
|
+
: '', signin?.today?.claimable === true ? ` · ${t('claimableToday')}` : '');
|
|
216
337
|
}
|
|
217
338
|
if (!available) {
|
|
218
|
-
return h('div', { style: cardStyle, 'data-minimax-credits-card': true }, h('div', { style: cardTitleStyle }, t('title')), h('div', { style: rowStyle }, h('span', null, t('unavailable')), h('span', null, credits_?.state === 'expired' ? t('expired') : '')));
|
|
339
|
+
return h('div', { style: cardStyle, 'data-minimax-credits-card': true }, h('div', { style: cardTitleStyle }, t('title')), h('div', { style: rowStyle }, h('span', null, t('unavailable')), h('span', null, credits_?.state === 'expired' ? t('expired') : '')), loginBlock(t, login, refresh));
|
|
219
340
|
}
|
|
220
|
-
return h('div', { style: cardStyle, 'data-minimax-credits-card': true }, h('div', { style: cardTitleStyle }, t('title')), h('div', { style: bigNumberStyle }, t('balance', { total: credits(credits_.total, 2) })), row(t('free'), credits(credits_.free, 3)), row(t('purchased'), credits(credits_.purchased, 3)), expiryBlock(t, credits_), h('div', { style: sectionTitleStyle }, t('lots')), (credits_.upcoming ?? []).length === 0
|
|
341
|
+
return h('div', { style: cardStyle, 'data-minimax-credits-card': true }, h('div', { style: cardTitleStyle }, t('title')), h('div', { style: bigNumberStyle }, t('balance', { total: credits(credits_.total, 2) })), row(t('free'), credits(credits_.free, 3)), row(t('purchased'), credits(credits_.purchased, 3)), expiryBlock(t, credits_), signinBlock(t, signin, refresh), h('div', { style: sectionTitleStyle }, t('lots')), (credits_.upcoming ?? []).length === 0
|
|
221
342
|
? h('div', { style: mutedStyle }, t('noLots'))
|
|
222
343
|
: h('ul', { style: listStyle }, ...(credits_.upcoming ?? []).map((lot, index) => h('li', { key: `${lot.expireAtMs}-${index}`, style: rowStyle }, h('span', null, day(lot.expireAtMs)), h('span', null, credits(lot.amount, 2))))), usage !== undefined
|
|
223
344
|
? h('div', { style: usageBoxStyle }, row(t('tokens', { count: tokens(usage.inputTokens + usage.outputTokens + usage.cacheReadTokens) }), ''), row(t('cost', { amount: money(usage.estimatedCny) }), ''), usage.requests > 0 ? row(t('requests', { count: usage.requests }), usage.lastModel ?? '') : null)
|
|
224
|
-
: null, credits_.updatedAtMs !== undefined
|
|
345
|
+
: null, loginBlock(t, login, refresh), credits_.updatedAtMs !== undefined
|
|
225
346
|
? h('div', { style: mutedStyle }, t('updated', { time: new Date(credits_.updatedAtMs).toLocaleTimeString() }))
|
|
226
347
|
: null);
|
|
227
348
|
}
|
|
@@ -283,6 +404,42 @@
|
|
|
283
404
|
const sectionTitleStyle = { marginTop: '8px', fontWeight: 600 };
|
|
284
405
|
const mutedStyle = { opacity: 0.7, fontSize: '12px' };
|
|
285
406
|
const listStyle = { listStyle: 'none', margin: 0, padding: 0 };
|
|
407
|
+
const sectionBoxStyle = {
|
|
408
|
+
marginTop: '10px',
|
|
409
|
+
paddingTop: '8px',
|
|
410
|
+
borderTop: '1px solid var(--dsh-panel-border, currentColor)',
|
|
411
|
+
display: 'flex',
|
|
412
|
+
flexDirection: 'column',
|
|
413
|
+
gap: '6px',
|
|
414
|
+
};
|
|
415
|
+
const actionButtonStyle = {
|
|
416
|
+
appearance: 'none',
|
|
417
|
+
background: 'transparent',
|
|
418
|
+
border: '1px solid var(--dsh-panel-border, currentColor)',
|
|
419
|
+
borderRadius: '6px',
|
|
420
|
+
color: 'inherit',
|
|
421
|
+
cursor: 'pointer',
|
|
422
|
+
font: 'inherit',
|
|
423
|
+
fontSize: '12px',
|
|
424
|
+
padding: '2px 10px',
|
|
425
|
+
width: 'fit-content',
|
|
426
|
+
};
|
|
427
|
+
const linkStyle = { color: 'inherit', fontSize: '12px' };
|
|
428
|
+
const checkboxStyle = { display: 'inline-flex', alignItems: 'center', gap: '6px', fontSize: '12px' };
|
|
429
|
+
const dayRowStyle = { display: 'flex', gap: '6px', flexWrap: 'wrap' };
|
|
430
|
+
const dayDotStyle = {
|
|
431
|
+
display: 'inline-flex',
|
|
432
|
+
alignItems: 'center',
|
|
433
|
+
justifyContent: 'center',
|
|
434
|
+
width: '22px',
|
|
435
|
+
height: '22px',
|
|
436
|
+
borderRadius: '999px',
|
|
437
|
+
border: '1px solid var(--dsh-panel-border, currentColor)',
|
|
438
|
+
fontSize: '11px',
|
|
439
|
+
opacity: 0.6,
|
|
440
|
+
};
|
|
441
|
+
const dayTodayStyle = { opacity: 1, fontWeight: 600 };
|
|
442
|
+
const dayClaimedStyle = { background: 'var(--dsh-panel-border, currentColor)', opacity: 0.9 };
|
|
286
443
|
const usageBoxStyle = {
|
|
287
444
|
marginTop: '8px',
|
|
288
445
|
paddingTop: '6px',
|
package/lib/index.d.ts
CHANGED
|
@@ -475,9 +475,304 @@ declare class UsageMeter {
|
|
|
475
475
|
reset(): void;
|
|
476
476
|
}
|
|
477
477
|
//#endregion
|
|
478
|
+
//#region src/credentials.d.ts
|
|
479
|
+
/** The file the plugin's own credential lives in. */
|
|
480
|
+
declare const PLUGIN_CREDENTIAL_FILENAME = ".minimaxcode-auth.json";
|
|
481
|
+
/** The file the plugin's own settings and session live in. */
|
|
482
|
+
declare const PLUGIN_STATE_FILENAME = ".minimaxcode-state.json";
|
|
483
|
+
/** The credential the plugin obtained for itself. */
|
|
484
|
+
interface PluginCredential {
|
|
485
|
+
/** The document's shape. */
|
|
486
|
+
schemaVersion: number;
|
|
487
|
+
/** The OAuth client the token was issued to. */
|
|
488
|
+
clientId: string;
|
|
489
|
+
/** The scopes the token carries. */
|
|
490
|
+
scopes: string[];
|
|
491
|
+
/** The audience the token was issued for. */
|
|
492
|
+
audience: string;
|
|
493
|
+
/** The `mmoat_` bearer token. */
|
|
494
|
+
accessToken: string;
|
|
495
|
+
/** The refresh token, when the server issued one. */
|
|
496
|
+
refreshToken?: string;
|
|
497
|
+
/** Expiry in milliseconds since the epoch. */
|
|
498
|
+
expiresAtMs?: number;
|
|
499
|
+
/** When the token was obtained, in milliseconds since the epoch. */
|
|
500
|
+
obtainedAtMs?: number;
|
|
501
|
+
}
|
|
502
|
+
/** A device login waiting for the person to authorize it. */
|
|
503
|
+
interface DeviceLoginSession {
|
|
504
|
+
/** The device code the token endpoint is polled with. */
|
|
505
|
+
deviceCode: string;
|
|
506
|
+
/** The PKCE verifier that goes with the device code. */
|
|
507
|
+
codeVerifier: string;
|
|
508
|
+
/** The code the person types on the account page. */
|
|
509
|
+
userCode: string;
|
|
510
|
+
/** Where to authorize. */
|
|
511
|
+
verificationUri: string;
|
|
512
|
+
/** Where to authorize, with the code filled in. */
|
|
513
|
+
verificationUriComplete: string;
|
|
514
|
+
/** When the device code stops working, in milliseconds since the epoch. */
|
|
515
|
+
expiresAtMs: number;
|
|
516
|
+
}
|
|
517
|
+
/** The plugin's own settings. */
|
|
518
|
+
interface PluginState {
|
|
519
|
+
/** The document's shape. */
|
|
520
|
+
schemaVersion: number;
|
|
521
|
+
/** Whether the plugin claims the daily grant on its own. */
|
|
522
|
+
autoCheckin: boolean;
|
|
523
|
+
/** The day the last claim happened, in the account's time zone. */
|
|
524
|
+
lastClaimDay?: string;
|
|
525
|
+
/** When the last claim happened, in milliseconds since the epoch. */
|
|
526
|
+
lastClaimAtMs?: number;
|
|
527
|
+
/** The points the last claim granted. */
|
|
528
|
+
lastClaimPoints?: number;
|
|
529
|
+
/** A device login waiting to be authorized. */
|
|
530
|
+
deviceLogin?: DeviceLoginSession;
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* The Harness home.
|
|
534
|
+
*
|
|
535
|
+
* The host resolves it the same way: the `DSH_HOME` environment variable when
|
|
536
|
+
* it is set, otherwise `~/.dsh`. The plugin resolves it on its own rather
|
|
537
|
+
* than importing the host's helper, so it also works in a plain command line
|
|
538
|
+
* where the host's packages are not installed.
|
|
539
|
+
*/
|
|
540
|
+
declare function dshHome(env?: NodeJS.ProcessEnv): string;
|
|
541
|
+
/** Where the plugin's credential lives. */
|
|
542
|
+
declare function pluginCredentialPath(env?: NodeJS.ProcessEnv): string;
|
|
543
|
+
/** Where the plugin's state lives. */
|
|
544
|
+
declare function pluginStatePath(env?: NodeJS.ProcessEnv): string;
|
|
545
|
+
/** Read the plugin's own credential. */
|
|
546
|
+
declare function readPluginCredential(env?: NodeJS.ProcessEnv): Promise<PluginCredential | undefined>;
|
|
547
|
+
/** Write the plugin's own credential. */
|
|
548
|
+
declare function writePluginCredential(credential: PluginCredential, env?: NodeJS.ProcessEnv): Promise<void>;
|
|
549
|
+
/** Read the plugin's own state. */
|
|
550
|
+
declare function readPluginState(env?: NodeJS.ProcessEnv): Promise<PluginState>;
|
|
551
|
+
/** Write the plugin's own state. */
|
|
552
|
+
declare function writePluginState(state: PluginState, env?: NodeJS.ProcessEnv): Promise<void>;
|
|
553
|
+
//#endregion
|
|
554
|
+
//#region src/login.d.ts
|
|
555
|
+
/** The endpoint that issues device codes. */
|
|
556
|
+
declare const DEVICE_CODE_PATH = "/oauth2/device/code";
|
|
557
|
+
/** The device authorization grant type. */
|
|
558
|
+
declare const DEVICE_CODE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
|
|
559
|
+
/** How a device login is going. */
|
|
560
|
+
type DeviceLoginState =
|
|
561
|
+
/** The person has not authorized it yet. */
|
|
562
|
+
{
|
|
563
|
+
state: 'pending';
|
|
564
|
+
} |
|
|
565
|
+
/** The authorization server asked the client to slow down. */
|
|
566
|
+
{
|
|
567
|
+
state: 'slow-down';
|
|
568
|
+
} |
|
|
569
|
+
/** The device code expired before the person authorized it. */
|
|
570
|
+
{
|
|
571
|
+
state: 'expired';
|
|
572
|
+
message?: string;
|
|
573
|
+
} |
|
|
574
|
+
/** The person declined. */
|
|
575
|
+
{
|
|
576
|
+
state: 'denied';
|
|
577
|
+
message?: string;
|
|
578
|
+
} |
|
|
579
|
+
/** The grant arrived. */
|
|
580
|
+
{
|
|
581
|
+
state: 'signed-in';
|
|
582
|
+
credential: PluginCredential;
|
|
583
|
+
};
|
|
584
|
+
/**
|
|
585
|
+
* Make a PKCE verifier and its S256 challenge.
|
|
586
|
+
*
|
|
587
|
+
* The verifier is 43 characters of base64url entropy, which is what RFC 7636
|
|
588
|
+
* asks for, and it never leaves this process.
|
|
589
|
+
*/
|
|
590
|
+
declare function makePkce(): {
|
|
591
|
+
verifier: string;
|
|
592
|
+
challenge: string;
|
|
593
|
+
};
|
|
594
|
+
/**
|
|
595
|
+
* Ask for a device code.
|
|
596
|
+
*
|
|
597
|
+
* @returns The session the person authorizes, or `undefined` when the server
|
|
598
|
+
* would not issue one.
|
|
599
|
+
*/
|
|
600
|
+
declare function startDeviceLogin(region: MinimaxRegion, fetchImpl?: typeof fetch, now?: number): Promise<DeviceLoginSession | undefined>;
|
|
601
|
+
/**
|
|
602
|
+
* Poll for the grant.
|
|
603
|
+
*
|
|
604
|
+
* The authorization server answers `400` while the person has not authorized
|
|
605
|
+
* yet, with `authorization_pending` in the body; that is a normal answer, not
|
|
606
|
+
* an error.
|
|
607
|
+
*/
|
|
608
|
+
declare function pollDeviceLogin(session: DeviceLoginSession, region: MinimaxRegion, fetchImpl?: typeof fetch, now?: number): Promise<DeviceLoginState>;
|
|
609
|
+
/**
|
|
610
|
+
* Exchange the stored refresh token for a fresh access token.
|
|
611
|
+
*
|
|
612
|
+
* The authorization server rotates the refresh token, so the new pair
|
|
613
|
+
* replaces the old one wherever it is kept.
|
|
614
|
+
*/
|
|
615
|
+
declare function refreshPluginCredential(credential: PluginCredential, region: MinimaxRegion, fetchImpl?: typeof fetch, now?: number): Promise<PluginCredential>;
|
|
616
|
+
//#endregion
|
|
617
|
+
//#region src/signin.d.ts
|
|
618
|
+
/** The claim endpoint. */
|
|
619
|
+
declare const SIGNIN_CLAIM_PATH = "/minimax-cloud/api/v1/signin/claim";
|
|
620
|
+
/** The cycle endpoint, which reports the panel. */
|
|
621
|
+
declare const SIGNIN_PANEL_PATH = "/minimax-cloud/api/v1/signin/status";
|
|
622
|
+
/** Per-day status, as the desktop app enumerates it. */
|
|
623
|
+
declare const SIGNIN_DAY_STATUS: {
|
|
624
|
+
/** The day has not come yet. */
|
|
625
|
+
readonly upcoming: 1;
|
|
626
|
+
/** The day is today and can be claimed. */
|
|
627
|
+
readonly claimable: 2;
|
|
628
|
+
/** The day is claimed. */
|
|
629
|
+
readonly claimed: 3;
|
|
630
|
+
/** The day does not grant anything. */
|
|
631
|
+
readonly disabled: 4;
|
|
632
|
+
};
|
|
633
|
+
/** The status of one day in the cycle. */
|
|
634
|
+
type SigninDayStatus = (typeof SIGNIN_DAY_STATUS)[keyof typeof SIGNIN_DAY_STATUS];
|
|
635
|
+
/** How many days a cycle runs. */
|
|
636
|
+
declare const SIGNIN_CYCLE_DAYS = 7;
|
|
637
|
+
/** The outcome of a claim. */
|
|
638
|
+
declare const SIGNIN_CLAIM_RESULT: {
|
|
639
|
+
/** The grant was credited. */
|
|
640
|
+
readonly credited: 1;
|
|
641
|
+
/** Today was already claimed; nothing was granted. */
|
|
642
|
+
readonly alreadyClaimed: 2;
|
|
643
|
+
};
|
|
644
|
+
/** The outcome of a claim. */
|
|
645
|
+
type SigninClaimResult = (typeof SIGNIN_CLAIM_RESULT)[keyof typeof SIGNIN_CLAIM_RESULT];
|
|
646
|
+
/** One day of the cycle. */
|
|
647
|
+
interface SigninDay {
|
|
648
|
+
/** Which day of the cycle this is, 1 to 7. */
|
|
649
|
+
dayNo: number;
|
|
650
|
+
/** Points the day grants. */
|
|
651
|
+
points: number;
|
|
652
|
+
/** Extra points on top, when the day carries a bonus. */
|
|
653
|
+
bonusPoints: number;
|
|
654
|
+
/** The day's status. */
|
|
655
|
+
status: SigninDayStatus;
|
|
656
|
+
/** Whether this is today. */
|
|
657
|
+
isToday: boolean;
|
|
658
|
+
}
|
|
659
|
+
/** The cycle as the server reports it. */
|
|
660
|
+
interface SigninPanel {
|
|
661
|
+
/** Which cycle the account is in. */
|
|
662
|
+
scene: number;
|
|
663
|
+
/** The days of the cycle. */
|
|
664
|
+
days: SigninDay[];
|
|
665
|
+
}
|
|
666
|
+
/** The result of claiming today's grant. */
|
|
667
|
+
interface SigninClaim {
|
|
668
|
+
/** The server's identifier for the claim. */
|
|
669
|
+
claimId: string;
|
|
670
|
+
/** Whether the grant was credited or the day was already claimed. */
|
|
671
|
+
result: SigninClaimResult;
|
|
672
|
+
/** Which day of the cycle was claimed. */
|
|
673
|
+
dayNo: number;
|
|
674
|
+
/** Points granted. */
|
|
675
|
+
points: number;
|
|
676
|
+
/** Extra points granted. */
|
|
677
|
+
bonusPoints: number;
|
|
678
|
+
/** When the granted points expire, in milliseconds since the epoch. */
|
|
679
|
+
expireAtMs: number;
|
|
680
|
+
/** The cycle after the claim. */
|
|
681
|
+
panel?: SigninPanel;
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* The time zone the server should treat the request as coming from.
|
|
685
|
+
*
|
|
686
|
+
* The server wants an IANA name; an offset or a missing value is refused.
|
|
687
|
+
* The system's own name is the right answer, since "today" should be the
|
|
688
|
+
* user's today.
|
|
689
|
+
*/
|
|
690
|
+
declare function timezoneId(): string;
|
|
691
|
+
/**
|
|
692
|
+
* Read the cycle out of a panel response.
|
|
693
|
+
*
|
|
694
|
+
* The server marks exactly one day as today and at most one day as claimable;
|
|
695
|
+
* a panel that says otherwise is not something to act on, so it is refused
|
|
696
|
+
* rather than half-believed.
|
|
697
|
+
*/
|
|
698
|
+
declare function parseSigninPanel(document: unknown): SigninPanel | undefined;
|
|
699
|
+
/** Read the result of a claim. */
|
|
700
|
+
declare function parseSigninClaim(document: unknown): SigninClaim | undefined;
|
|
701
|
+
/**
|
|
702
|
+
* Read the cycle.
|
|
703
|
+
*
|
|
704
|
+
* @returns The panel, or `undefined` when the account cannot read it.
|
|
705
|
+
*/
|
|
706
|
+
declare function fetchSigninPanel(credential: OAuthCredential, region: MinimaxRegion, fetchImpl?: typeof fetch, timezone?: string): Promise<SigninPanel | undefined>;
|
|
707
|
+
/**
|
|
708
|
+
* Claim today's grant.
|
|
709
|
+
*
|
|
710
|
+
* This is the only request in the plugin that changes something upstream. It
|
|
711
|
+
* grants the day's points, which expire thirty days later.
|
|
712
|
+
*
|
|
713
|
+
* @returns What the server answered, or `undefined` when it refused.
|
|
714
|
+
*/
|
|
715
|
+
declare function claimSignin(credential: OAuthCredential, region: MinimaxRegion, fetchImpl?: typeof fetch, timezone?: string): Promise<SigninClaim | undefined>;
|
|
716
|
+
/** The day's key in the account's own time zone, `YYYY-MM-DD`. */
|
|
717
|
+
declare function localDay(now?: number, timezone?: string): string;
|
|
718
|
+
//#endregion
|
|
478
719
|
//#region src/status-route.d.ts
|
|
479
720
|
/** Route this plugin mounts, matching its settings card. */
|
|
480
721
|
declare const MINIMAX_STATUS_PATH = "/plugins/dsh-connect-minimaxcode/status";
|
|
722
|
+
/** The daily check-in, as the card reads it. */
|
|
723
|
+
interface SigninStatus {
|
|
724
|
+
/** Whether the cycle could be read. */
|
|
725
|
+
state: 'ok' | 'unavailable';
|
|
726
|
+
/** Today's day in the cycle. */
|
|
727
|
+
today?: {
|
|
728
|
+
/** Which day of the cycle it is, 1 to 7. */
|
|
729
|
+
dayNo: number;
|
|
730
|
+
/** Points the day grants. */
|
|
731
|
+
points: number;
|
|
732
|
+
/** The day's status, as the upstream numbers it. */
|
|
733
|
+
status: number;
|
|
734
|
+
/** Whether the day can be claimed. */
|
|
735
|
+
claimable: boolean;
|
|
736
|
+
/** Whether the day is already claimed. */
|
|
737
|
+
claimed: boolean;
|
|
738
|
+
};
|
|
739
|
+
/** The days of the cycle. */
|
|
740
|
+
days?: {
|
|
741
|
+
dayNo: number;
|
|
742
|
+
points: number;
|
|
743
|
+
status: number;
|
|
744
|
+
isToday: boolean;
|
|
745
|
+
}[];
|
|
746
|
+
/** Points the whole cycle is worth. */
|
|
747
|
+
cyclePoints?: number;
|
|
748
|
+
/** Whether the plugin claims the day's grant on its own. */
|
|
749
|
+
autoCheckin: boolean;
|
|
750
|
+
/** The day the last claim happened. */
|
|
751
|
+
lastClaimDay?: string;
|
|
752
|
+
/** When the last claim happened, in milliseconds since the epoch. */
|
|
753
|
+
lastClaimAtMs?: number;
|
|
754
|
+
/** Points the last claim granted. */
|
|
755
|
+
lastClaimPoints?: number;
|
|
756
|
+
/** Whether the last claim was credited, or the day was already claimed. */
|
|
757
|
+
lastClaimResult?: number;
|
|
758
|
+
/** Why the cycle or the claim could not be read. */
|
|
759
|
+
error?: string;
|
|
760
|
+
}
|
|
761
|
+
/** How the plugin is signed in, as the card reads it. */
|
|
762
|
+
interface LoginStatus {
|
|
763
|
+
/** Whether the plugin has a usable credential. */
|
|
764
|
+
state: 'signed-in' | 'signed-out' | 'pending';
|
|
765
|
+
/** Where the credential came from. */
|
|
766
|
+
source?: 'plugin' | 'desktop-app';
|
|
767
|
+
/** The code to type on the account page, while a sign-in is waiting. */
|
|
768
|
+
userCode?: string;
|
|
769
|
+
/** Where to authorize. */
|
|
770
|
+
verificationUri?: string;
|
|
771
|
+
/** Where to authorize, with the code filled in. */
|
|
772
|
+
verificationUriComplete?: string;
|
|
773
|
+
/** When the device code stops working, in milliseconds since the epoch. */
|
|
774
|
+
expiresAtMs?: number;
|
|
775
|
+
}
|
|
481
776
|
/** The account's credit balance, as the desktop app shows it. */
|
|
482
777
|
interface CreditStatus {
|
|
483
778
|
/** Whether the balance could be read. */
|
|
@@ -552,6 +847,10 @@ interface StatusDocument {
|
|
|
552
847
|
credits?: CreditStatus;
|
|
553
848
|
/** What this host's requests have used. */
|
|
554
849
|
usage?: UsageStatus;
|
|
850
|
+
/** The daily check-in, when it could be read. */
|
|
851
|
+
signin?: SigninStatus;
|
|
852
|
+
/** How the plugin is signed in. */
|
|
853
|
+
login?: LoginStatus;
|
|
555
854
|
}
|
|
556
855
|
/** Inputs the document is derived from. */
|
|
557
856
|
interface StatusDeps {
|
|
@@ -574,6 +873,10 @@ interface StatusDeps {
|
|
|
574
873
|
credits?: CreditStatus;
|
|
575
874
|
/** What this host's requests have used. */
|
|
576
875
|
usage?: UsageStatus;
|
|
876
|
+
/** The daily check-in, when the account API could be reached. */
|
|
877
|
+
signin?: SigninStatus;
|
|
878
|
+
/** How the plugin is signed in. */
|
|
879
|
+
login?: LoginStatus;
|
|
577
880
|
}
|
|
578
881
|
/**
|
|
579
882
|
* Build the card's status document.
|
|
@@ -646,4 +949,4 @@ declare const inject: string[];
|
|
|
646
949
|
*/
|
|
647
950
|
declare function apply(ctx: Context): void;
|
|
648
951
|
//#endregion
|
|
649
|
-
export { type AuthState, type CatalogModel, type CatalogSource, type Credential, type CreditSummary, EMPTY_USAGE, FALLBACK_MODELS, MEMBERSHIP_PATH, MINIMAXCODE_PROVIDER_ID, MINIMAX_AUTH_FILENAME, MINIMAX_DATA_DIR, MINIMAX_GATEWAYS, MINIMAX_OAUTH_CLIENT_ID, MINIMAX_REGIONS, MINIMAX_STATUS_PATH, MINIMAX_STREAM_IDLE_TIMEOUT_MS, MODEL_PRICES, MinimaxCatalog, MinimaxCredits, type MinimaxRegion, type ModelUsage, type OAuthCredential, type OAuthState, type StatusDocument, type TokenClaims, UsageMeter, apply, authPath, bearerToken, catalogUrl, chatBaseUrl, createMinimaxCodeAdapter, dataDir, daysRemaining, decodeClaims, ensureOAuthCredential, estimateCny, expiresInMs, expiryLevel, fetchCreditSummary, inject, name, parseAuthDocument, parseCatalog, parseCreditSummary, parseOAuthDocument, priceFor, readCredential, readOAuthCredential, refreshOAuthCredential, statusDocument, writeOAuthCredential };
|
|
952
|
+
export { type AuthState, type CatalogModel, type CatalogSource, type Credential, type CreditSummary, DEVICE_CODE_GRANT, DEVICE_CODE_PATH, type DeviceLoginState, EMPTY_USAGE, FALLBACK_MODELS, MEMBERSHIP_PATH, MINIMAXCODE_PROVIDER_ID, MINIMAX_AUTH_FILENAME, MINIMAX_DATA_DIR, MINIMAX_GATEWAYS, MINIMAX_OAUTH_CLIENT_ID, MINIMAX_REGIONS, MINIMAX_STATUS_PATH, MINIMAX_STREAM_IDLE_TIMEOUT_MS, MODEL_PRICES, MinimaxCatalog, MinimaxCredits, type MinimaxRegion, type ModelUsage, type OAuthCredential, type OAuthState, PLUGIN_CREDENTIAL_FILENAME, PLUGIN_STATE_FILENAME, type PluginCredential, type PluginState, SIGNIN_CLAIM_PATH, SIGNIN_CLAIM_RESULT, SIGNIN_CYCLE_DAYS, SIGNIN_DAY_STATUS, SIGNIN_PANEL_PATH, type SigninClaim, type SigninDay, type SigninPanel, type StatusDocument, type TokenClaims, UsageMeter, apply, authPath, bearerToken, catalogUrl, chatBaseUrl, claimSignin, createMinimaxCodeAdapter, dataDir, daysRemaining, decodeClaims, dshHome, ensureOAuthCredential, estimateCny, expiresInMs, expiryLevel, fetchCreditSummary, fetchSigninPanel, inject, localDay, makePkce, name, parseAuthDocument, parseCatalog, parseCreditSummary, parseOAuthDocument, parseSigninClaim, parseSigninPanel, pluginCredentialPath, pluginStatePath, pollDeviceLogin, priceFor, readCredential, readOAuthCredential, readPluginCredential, readPluginState, refreshOAuthCredential, refreshPluginCredential, startDeviceLogin, statusDocument, timezoneId, writeOAuthCredential, writePluginCredential, writePluginState };
|