@gatemux/dsh-gatemux-login 1.0.1 → 1.0.3
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 +3 -3
- package/account.js +44 -7
- package/package.json +15 -15
package/README.md
CHANGED
|
@@ -22,8 +22,8 @@ keep another default.
|
|
|
22
22
|
|
|
23
23
|
## Requirements
|
|
24
24
|
|
|
25
|
-
- DeepSeek Harness desktop app, `0.1.7.x`.
|
|
26
|
-
The plugin declares `@deepseek-ai/dsh-*` peer dependencies
|
|
25
|
+
- DeepSeek Harness desktop app, `0.1.7.x` or `0.2.x`.
|
|
26
|
+
The plugin declares `@deepseek-ai/dsh-*` peer dependencies across both lines.
|
|
27
27
|
A different DSH release is rejected at install time; installing anyway needs a
|
|
28
28
|
version exemption, which risks crashes and data loss.
|
|
29
29
|
- A GateMux account.
|
|
@@ -105,7 +105,7 @@ module or the patch is skipped.
|
|
|
105
105
|
| `ACCOUNT_QUOTA_EXCEEDED` | Your GateMux balance or spend cap is exhausted. Top up. |
|
|
106
106
|
| `ip_not_allowed` (HTTP 403) | Your network is not in the GateMux application's trusted egress IP allowlist. Contact the plugin operator. Re-authorizing will not fix it. |
|
|
107
107
|
| `scope_denied`, `model_not_allowed` (HTTP 403) | The application registration does not permit this request. Contact the plugin operator. |
|
|
108
|
-
| Install refused for peer dependencies | Your DSH version is outside `0.1.7.x`. |
|
|
108
|
+
| Install refused for peer dependencies | Your DSH version is outside `0.1.7.x` and `0.2.x`. |
|
|
109
109
|
|
|
110
110
|
403 errors are reported as authorization faults, not retried: they are
|
|
111
111
|
configuration problems on the application's side.
|
package/account.js
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import { createHash, randomBytes, randomUUID, timingSafeEqual } from 'node:crypto'
|
|
23
|
+
import { platform, release } from 'node:os'
|
|
23
24
|
import { promises as streamPromises } from 'node:stream'
|
|
24
25
|
|
|
25
26
|
import { Service } from '@deepseek-ai/cordis'
|
|
@@ -68,6 +69,16 @@ function parseGrant(payload, issuer) {
|
|
|
68
69
|
return { version: 1, accessToken, refreshToken, expiresAt, issuer }
|
|
69
70
|
}
|
|
70
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Read a stored record as a grant this deployment may use.
|
|
74
|
+
* @param record - record at this provider's key, or undefined when none is stored.
|
|
75
|
+
* @param issuer - origin a grant must carry to be usable here.
|
|
76
|
+
* @returns the parsed grant, or null when no record is stored or it is unusable.
|
|
77
|
+
*/
|
|
78
|
+
function usableGrant(record, issuer) {
|
|
79
|
+
return record !== undefined && record.kind === 'grant' ? parseGrant(record.payload, issuer) : null
|
|
80
|
+
}
|
|
81
|
+
|
|
71
82
|
/** Accept a bare HTTPS origin, rejecting paths, credentials, and non-HTTPS schemes. */
|
|
72
83
|
function originOf(value) {
|
|
73
84
|
let url
|
|
@@ -182,22 +193,27 @@ export class GateMuxAccount extends DeepSeekAccount {
|
|
|
182
193
|
/** Discard a stored grant issued by another environment. */
|
|
183
194
|
async [Service.init]() {
|
|
184
195
|
const record = await this.ctx.credentials.readRecord(KEY)
|
|
185
|
-
if (record === undefined) return
|
|
186
|
-
const grant = record.kind === 'grant' ? parseGrant(record.payload, this.issuer) : null
|
|
187
|
-
if (grant !== null) return
|
|
196
|
+
if (record === undefined || usableGrant(record, this.issuer) !== null) return
|
|
188
197
|
await this.ctx.credentials.deleteRecord(KEY)
|
|
189
198
|
this.logger.warn('stored grant discarded', { reason: 'unreadable-or-foreign-issuer' })
|
|
190
199
|
}
|
|
191
200
|
|
|
192
201
|
async getState() {
|
|
193
202
|
const record = await this.ctx.credentials.readRecord(KEY)
|
|
194
|
-
|
|
195
|
-
|
|
203
|
+
const grant = usableGrant(record, this.issuer)
|
|
204
|
+
// A record this deployment cannot use reads as absent instead of raising: every
|
|
205
|
+
// caller turns a throw into a failure with no diagnosis. `startSignIn` returns
|
|
206
|
+
// this outside its own catch, so a raise there rejects the start call and the
|
|
207
|
+
// dialog reports a sign-in failure for a record the person never supplied, and
|
|
208
|
+
// `watch` ends the account stream. The record is left in place for a sign-in to
|
|
209
|
+
// overwrite; discarding it here could delete a grant committed since the read.
|
|
210
|
+
if (record !== undefined && grant === null) {
|
|
211
|
+
this.logger.warn('stored grant is unreadable', { reason: 'unreadable-or-foreign-issuer' })
|
|
196
212
|
}
|
|
197
213
|
const attempt = this.attempt?.view ?? null
|
|
198
214
|
return {
|
|
199
|
-
status:
|
|
200
|
-
attempt:
|
|
215
|
+
status: grant === null ? 'signed-out' : 'credential-stored',
|
|
216
|
+
attempt: grant === null && attempt?.phase === 'succeeded' ? null : attempt,
|
|
201
217
|
links: {
|
|
202
218
|
usageUrl: `${this.consoleOrigin}/app/usage`,
|
|
203
219
|
topUpUrl: `${this.consoleOrigin}/app/billing`,
|
|
@@ -378,6 +394,27 @@ export class GateMuxAccount extends DeepSeekAccount {
|
|
|
378
394
|
return null
|
|
379
395
|
}
|
|
380
396
|
|
|
397
|
+
/**
|
|
398
|
+
* Read the signed-in account ID without a request and without credentials.
|
|
399
|
+
*
|
|
400
|
+
* GateMux registers no device, so `deviceId` is omitted rather than invented.
|
|
401
|
+
* The ID comes from the last successful profile read for this same grant; a
|
|
402
|
+
* caller that reads it before that profile read gets the OS version alone.
|
|
403
|
+
*
|
|
404
|
+
* @returns the Node platform version, plus the account ID while a profile for the stored grant is cached.
|
|
405
|
+
*/
|
|
406
|
+
async getDeviceIdentity() {
|
|
407
|
+
const lifetime = this.detailsLifetime
|
|
408
|
+
const grant = await this.readGrant(lifetime)
|
|
409
|
+
const profile = grant !== null && this.lastProfile?.token === grant.accessToken
|
|
410
|
+
? this.lastProfile.profile
|
|
411
|
+
: null
|
|
412
|
+
return {
|
|
413
|
+
...(profile?.id == null ? {} : { userId: profile.id }),
|
|
414
|
+
osVersion: `${platform()} ${release()}`,
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
381
418
|
/**
|
|
382
419
|
* Run one authorization attempt: PKCE, browser callback, code exchange, commit.
|
|
383
420
|
* @param session - the attempt's cancellation signal and commit channel.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gatemux/dsh-gatemux-login",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Sign in with GateMux for DeepSeek Harness: users pay from their own GateMux balance.",
|
|
6
6
|
"publishConfig": {
|
|
@@ -29,22 +29,22 @@
|
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"@deepseek-ai/cordis": "^4.0.4",
|
|
32
|
-
"@deepseek-ai/dsh-authorization": "^0.1.7-rc.2",
|
|
33
|
-
"@deepseek-ai/dsh-credentials": "^0.1.7-rc.2",
|
|
34
|
-
"@deepseek-ai/dsh-deepseek-account": "^0.1.7-rc.2",
|
|
35
|
-
"@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.2",
|
|
36
|
-
"@deepseek-ai/dsh-launch-environment": "^0.1.7-rc.2",
|
|
37
|
-
"@deepseek-ai/dsh-llm": "^0.1.7-rc.2",
|
|
38
|
-
"@deepseek-ai/dsh-llm-deepseek": "^0.1.7-rc.2"
|
|
32
|
+
"@deepseek-ai/dsh-authorization": "^0.1.7-rc.2 || ^0.2.0-rc.2",
|
|
33
|
+
"@deepseek-ai/dsh-credentials": "^0.1.7-rc.2 || ^0.2.0-rc.2",
|
|
34
|
+
"@deepseek-ai/dsh-deepseek-account": "^0.1.7-rc.2 || ^0.2.0-rc.2",
|
|
35
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.2 || ^0.2.0-rc.2",
|
|
36
|
+
"@deepseek-ai/dsh-launch-environment": "^0.1.7-rc.2 || ^0.2.0-rc.2",
|
|
37
|
+
"@deepseek-ai/dsh-llm": "^0.1.7-rc.2 || ^0.2.0-rc.2",
|
|
38
|
+
"@deepseek-ai/dsh-llm-deepseek": "^0.1.7-rc.2 || ^0.2.0-rc.2"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@deepseek-ai/cordis": "^4.0.4",
|
|
42
|
-
"@deepseek-ai/dsh-authorization": "^0.1.7-rc.2",
|
|
43
|
-
"@deepseek-ai/dsh-credentials": "^0.1.7-rc.2",
|
|
44
|
-
"@deepseek-ai/dsh-deepseek-account": "^0.1.7-rc.2",
|
|
45
|
-
"@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.2",
|
|
46
|
-
"@deepseek-ai/dsh-launch-environment": "^0.1.7-rc.2",
|
|
47
|
-
"@deepseek-ai/dsh-llm": "^0.1.7-rc.2",
|
|
48
|
-
"@deepseek-ai/dsh-llm-deepseek": "^0.1.7-rc.2"
|
|
42
|
+
"@deepseek-ai/dsh-authorization": "^0.1.7-rc.2 || ^0.2.0-rc.2",
|
|
43
|
+
"@deepseek-ai/dsh-credentials": "^0.1.7-rc.2 || ^0.2.0-rc.2",
|
|
44
|
+
"@deepseek-ai/dsh-deepseek-account": "^0.1.7-rc.2 || ^0.2.0-rc.2",
|
|
45
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.2 || ^0.2.0-rc.2",
|
|
46
|
+
"@deepseek-ai/dsh-launch-environment": "^0.1.7-rc.2 || ^0.2.0-rc.2",
|
|
47
|
+
"@deepseek-ai/dsh-llm": "^0.1.7-rc.2 || ^0.2.0-rc.2",
|
|
48
|
+
"@deepseek-ai/dsh-llm-deepseek": "^0.1.7-rc.2 || ^0.2.0-rc.2"
|
|
49
49
|
}
|
|
50
50
|
}
|