@goodandready/dsh-subscriptions 0.6.41 → 0.6.44
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/lib/accounts.js +47 -12
- package/lib/adapter-manager.js +1 -0
- package/lib/adapter.js +8 -4
- package/lib/backoff.js +13 -1
- package/lib/code-assist.js +1 -0
- package/lib/crypto.js +1 -1
- package/lib/google-validation.js +1 -1
- package/lib/http.js +130 -15
- package/lib/import-auth.js +91 -44
- package/lib/index.js +16 -8
- package/lib/oauth.js +12 -0
- package/lib/routes/accounts.js +6 -5
- package/lib/routes/status.js +51 -13
- package/lib/runaway-guard.js +5 -0
- package/lib/session-pin.js +9 -4
- package/lib/sse.js +6 -1
- package/lib/stream-rotate.js +1 -1
- package/lib/subscriptions.js +22 -3
- package/lib/vault.js +1 -1
- package/lib/vendor-factory.js +6 -4
- package/lib/vendors/claude-cli.js +2 -1
- package/lib/vendors/codex.js +4 -2
- package/lib/vendors/copilot.js +1 -0
- package/lib/vendors/cursor.js +1 -0
- package/lib/vendors/glm.js +1 -0
- package/lib/vendors/kimi.js +1 -0
- package/lib/vendors/kiro.js +1 -0
- package/lib/vendors/qwen.js +1 -0
- package/lib/wire.js +12 -11
- package/package.json +13 -8
package/lib/vendor-factory.js
CHANGED
|
@@ -69,7 +69,8 @@ export function createVendorFromProfile(profile) {
|
|
|
69
69
|
code_verifier: pkce.verifier,
|
|
70
70
|
}
|
|
71
71
|
const req = tokenStyle === "json" ? jsonTokenRequest : formTokenRequest
|
|
72
|
-
const
|
|
72
|
+
const tokenFetch = (u, i, o) => fetchWithTimeout(fetchImpl || fetch, u, i, { timeoutMs: 30000, ...(o || {}) })
|
|
73
|
+
const json = await req(profile.tokenUrl, params, tokenFetch)
|
|
73
74
|
const blob = tokenBlobFromOAuth(json)
|
|
74
75
|
return { ...blob, email: blob.email || emailFromToken(blob.accessToken), label: blob.label || name }
|
|
75
76
|
},
|
|
@@ -80,7 +81,8 @@ export function createVendorFromProfile(profile) {
|
|
|
80
81
|
refresh_token: blob.refreshToken,
|
|
81
82
|
}
|
|
82
83
|
const req = tokenStyle === "json" ? jsonTokenRequest : formTokenRequest
|
|
83
|
-
const
|
|
84
|
+
const tokenFetch = (u, i, o) => fetchWithTimeout(fetchImpl || fetch, u, i, { timeoutMs: 30000, ...(o || {}) })
|
|
85
|
+
const json = await req(profile.tokenUrl, params, tokenFetch)
|
|
84
86
|
return tokenBlobFromOAuth(json, { label: blob.label, email: blob.email })
|
|
85
87
|
},
|
|
86
88
|
async listModels(blob, cfg, fetchImpl) {
|
|
@@ -112,7 +114,7 @@ export function createVendorFromProfile(profile) {
|
|
|
112
114
|
async* streamOnce({ blob, options, fetchImpl, headers, config, signal }) {
|
|
113
115
|
const body = codexResponsesBody(options, "")
|
|
114
116
|
if (!body.instructions) delete body.instructions
|
|
115
|
-
const res = await (fetchImpl || fetch
|
|
117
|
+
const res = await fetchWithTimeout(fetchImpl || fetch, `${base}/responses`, {
|
|
116
118
|
method: "POST",
|
|
117
119
|
headers: {
|
|
118
120
|
...headers,
|
|
@@ -122,7 +124,7 @@ export function createVendorFromProfile(profile) {
|
|
|
122
124
|
},
|
|
123
125
|
body: JSON.stringify(body),
|
|
124
126
|
signal,
|
|
125
|
-
})
|
|
127
|
+
}, { timeoutMs: 60000, stream: true })
|
|
126
128
|
if (!res.ok) throw httpError(res.status, await res.text())
|
|
127
129
|
yield* codexResponsesStream(res.body)
|
|
128
130
|
},
|
|
@@ -18,7 +18,8 @@ export async function readClaudeCredentials(home) {
|
|
|
18
18
|
accessToken: oauth.accessToken || oauth.access_token,
|
|
19
19
|
refreshToken: oauth.refreshToken || oauth.refresh_token || '',
|
|
20
20
|
expiresAt: oauth.expiresAt || (oauth.expires_in ? Date.now() + oauth.expires_in * 1000 : Date.now() + 3600000),
|
|
21
|
-
subscriptionType: oauth.subscriptionType || 'Claude Code'
|
|
21
|
+
subscriptionType: oauth.subscriptionType || 'Claude Code',
|
|
22
|
+
email: oauth.email || json.email || 'Claude Code CLI User',
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
return null
|
package/lib/vendors/codex.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isTimeoutError } from "../http.js"
|
|
1
2
|
import { randomUUID, createHash } from 'node:crypto'
|
|
2
3
|
import { buildAuthorizeUrl } from '../oauth.js'
|
|
3
4
|
import { codexResponsesBody, modelCatalog } from '../messages.js'
|
|
@@ -203,14 +204,15 @@ export async function usage(blob, cfg, fetchImpl) {
|
|
|
203
204
|
const snap = asUsageSnapshot(deepestUsedPercent(json))
|
|
204
205
|
if (snap) snap.windows = usageWindows(json)
|
|
205
206
|
return snap
|
|
206
|
-
} catch {
|
|
207
|
+
} catch (err) {
|
|
208
|
+
if (isTimeoutError(err)) throw err
|
|
207
209
|
return null
|
|
208
210
|
}
|
|
209
211
|
}
|
|
210
212
|
|
|
211
213
|
export async function* streamOnce({ blob, options, fetchImpl, headers, config, signal }) {
|
|
212
214
|
const base = (config.baseUrl || defaults().baseUrl).replace(/\/$/, '')
|
|
213
|
-
const body = codexResponsesBody(options, INSTRUCTIONS, config)
|
|
215
|
+
const body = /** @type {Record<string, any>} */ (codexResponsesBody(options, INSTRUCTIONS, config))
|
|
214
216
|
const sessionId = deriveSessionId(options)
|
|
215
217
|
|
|
216
218
|
// Prompt Cache Affinity
|
package/lib/vendors/copilot.js
CHANGED
|
@@ -296,6 +296,7 @@ export async function* streamOnce({ blob, options, fetchImpl, headers, config, s
|
|
|
296
296
|
|
|
297
297
|
if (!copilotToken) throw new LlmError("GitHub Copilot not authenticated", "AUTH")
|
|
298
298
|
|
|
299
|
+
/** @type {Record<string, any>} */
|
|
299
300
|
const body = {
|
|
300
301
|
model: options.model || "claude-3.7-sonnet",
|
|
301
302
|
messages: openaiMessages(options),
|
package/lib/vendors/cursor.js
CHANGED
|
@@ -175,6 +175,7 @@ export async function* streamOnce({ blob, options, fetchImpl, headers, config, s
|
|
|
175
175
|
const token = blob && (blob.accessToken || blob.access_token)
|
|
176
176
|
if (!token) throw new LlmError('Cursor not authenticated', 'AUTH')
|
|
177
177
|
|
|
178
|
+
/** @type {Record<string, any>} */
|
|
178
179
|
const body = {
|
|
179
180
|
model: options.model || 'composer-2',
|
|
180
181
|
messages: openaiMessages(options),
|
package/lib/vendors/glm.js
CHANGED
|
@@ -84,6 +84,7 @@ export async function* streamOnce({ blob, options, fetchImpl, headers, config, s
|
|
|
84
84
|
const token = blob && (blob.accessToken || blob.access_token)
|
|
85
85
|
if (!token) throw new LlmError('GLM not authenticated', 'AUTH')
|
|
86
86
|
|
|
87
|
+
/** @type {Record<string, any>} */
|
|
87
88
|
const body = {
|
|
88
89
|
model: options.model || 'glm-4-plus',
|
|
89
90
|
messages: openaiMessages(options),
|
package/lib/vendors/kimi.js
CHANGED
|
@@ -88,6 +88,7 @@ export async function* streamOnce({ blob, options, fetchImpl, headers, config, s
|
|
|
88
88
|
const token = blob && (blob.accessToken || blob.access_token)
|
|
89
89
|
if (!token) throw new LlmError('Kimi not authenticated', 'AUTH')
|
|
90
90
|
|
|
91
|
+
/** @type {Record<string, any>} */
|
|
91
92
|
const body = {
|
|
92
93
|
model: options.model || 'kimi-for-coding',
|
|
93
94
|
messages: openaiMessages(options),
|
package/lib/vendors/kiro.js
CHANGED
|
@@ -87,6 +87,7 @@ export async function* streamOnce({ blob, options, fetchImpl, headers, config, s
|
|
|
87
87
|
const token = blob && (blob.accessToken || blob.access_token)
|
|
88
88
|
if (!token) throw new LlmError('AWS Kiro not authenticated', 'AUTH')
|
|
89
89
|
|
|
90
|
+
/** @type {Record<string, any>} */
|
|
90
91
|
const body = {
|
|
91
92
|
model: options.model || 'claude-sonnet-5',
|
|
92
93
|
messages: openaiMessages(options),
|
package/lib/vendors/qwen.js
CHANGED
|
@@ -57,6 +57,7 @@ export async function* streamOnce({ blob, options, fetchImpl, headers, config, s
|
|
|
57
57
|
const key = blob && (blob.accessToken || blob.apiKey)
|
|
58
58
|
if (!key) throw new LlmError('Qwen API Key or Token is required', 'AUTH')
|
|
59
59
|
|
|
60
|
+
/** @type {Record<string, any>} */
|
|
60
61
|
const body = {
|
|
61
62
|
model: options.model || 'qwen-2.5-coder-32b-instruct',
|
|
62
63
|
messages: openaiMessages(options),
|
package/lib/wire.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
|
+
import { fetchWithTimeout } from "./http.js"
|
|
1
2
|
import { iterateSse, jsonSse } from './sse.js'
|
|
2
3
|
import { validationFromHttpError, validationRequiredError, googleRateLimitMessage, googleLicenseMessage } from './google-validation.js'
|
|
3
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @param {number} status
|
|
7
|
+
* @param {string} [bodyText]
|
|
8
|
+
* @param {string} [code]
|
|
9
|
+
* @returns {Error & { status?: number, code?: string }}
|
|
10
|
+
*/
|
|
4
11
|
export function httpError(status, bodyText, code) {
|
|
5
12
|
const snippet = String(bodyText || '').slice(0, 400)
|
|
6
|
-
const err = new Error(snippet ? `vendor http ${status}: ${snippet}` : `vendor http ${status}`)
|
|
13
|
+
const err = /** @type {Error & { status?: number, code?: string }} */ (new Error(snippet ? `vendor http ${status}: ${snippet}` : `vendor http ${status}`))
|
|
7
14
|
err.status = status
|
|
8
15
|
if (code) {
|
|
9
16
|
err.code = code
|
|
@@ -401,25 +408,19 @@ export async function* googleStream(body) {
|
|
|
401
408
|
}
|
|
402
409
|
|
|
403
410
|
export async function formTokenRequest(url, params, fetchImpl, headers, { timeoutMs = 25000 } = {}) {
|
|
404
|
-
const
|
|
405
|
-
const timeoutSignal = AbortSignal.timeout(timeoutMs)
|
|
406
|
-
const res = await impl(url, {
|
|
411
|
+
const res = await fetchWithTimeout(fetchImpl || fetch, url, {
|
|
407
412
|
method: 'POST',
|
|
408
413
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded', Accept: 'application/json', ...(headers || {}) },
|
|
409
414
|
body: new URLSearchParams(params),
|
|
410
|
-
|
|
411
|
-
})
|
|
415
|
+
}, { timeoutMs })
|
|
412
416
|
return readJson(res)
|
|
413
417
|
}
|
|
414
418
|
|
|
415
419
|
export async function jsonTokenRequest(url, body, fetchImpl, headers, { timeoutMs = 25000 } = {}) {
|
|
416
|
-
const
|
|
417
|
-
const timeoutSignal = AbortSignal.timeout(timeoutMs)
|
|
418
|
-
const res = await impl(url, {
|
|
420
|
+
const res = await fetchWithTimeout(fetchImpl || fetch, url, {
|
|
419
421
|
method: 'POST',
|
|
420
422
|
headers: { 'Content-Type': 'application/json', Accept: 'application/json', ...(headers || {}) },
|
|
421
423
|
body: JSON.stringify(body),
|
|
422
|
-
|
|
423
|
-
})
|
|
424
|
+
}, { timeoutMs })
|
|
424
425
|
return readJson(res)
|
|
425
426
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-subscriptions",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.44",
|
|
4
4
|
"description": "Use ChatGPT Codex, Claude, Grok, Antigravity, Kimi, GLM, Cursor, Kiro, Copilot, Qwen, ERNIE, Spark, JetBrains, Perplexity, Replit, and Cody subscriptions as DeepSeek Harness LLM providers via OAuth.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
57
|
-
"@deepseek-ai/dsh-credentials": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
58
|
-
"@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
59
|
-
"@deepseek-ai/dsh-llm": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
60
|
-
"@deepseek-ai/dsh-settings": "^0.1.7-rc.2 || ^0.2.0-rc.1",
|
|
57
|
+
"@deepseek-ai/dsh-credentials": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.0-rc.2",
|
|
58
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.0-rc.2",
|
|
59
|
+
"@deepseek-ai/dsh-llm": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.0-rc.2",
|
|
60
|
+
"@deepseek-ai/dsh-settings": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.0-rc.2",
|
|
61
61
|
"@deepseek-ai/schemastery": "^3.18.4"
|
|
62
62
|
},
|
|
63
63
|
"publishConfig": {
|
|
@@ -68,9 +68,14 @@
|
|
|
68
68
|
"undici": "^8.10.1"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@deepseek-ai/
|
|
71
|
+
"@deepseek-ai/cordis": "^4.0.4",
|
|
72
|
+
"@deepseek-ai/dsh-credentials": "^0.2.0-rc.2",
|
|
73
|
+
"@deepseek-ai/dsh-host-webserver": "^0.2.0-rc.2",
|
|
74
|
+
"@deepseek-ai/dsh-llm": "^0.2.0-rc.2",
|
|
75
|
+
"@deepseek-ai/dsh-settings": "^0.2.0-rc.2",
|
|
76
|
+
"@deepseek-ai/schemastery": "^3.18.4",
|
|
72
77
|
"@types/node": "^22.20.2",
|
|
73
|
-
"
|
|
74
|
-
"
|
|
78
|
+
"eslint": "^10.4.0",
|
|
79
|
+
"typescript": "^7.0.2"
|
|
75
80
|
}
|
|
76
81
|
}
|