@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.
@@ -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 json = await req(profile.tokenUrl, params, fetchImpl)
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 json = await req(profile.tokenUrl, params, fetchImpl)
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)(`${base}/responses`, {
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
@@ -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
@@ -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),
@@ -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),
@@ -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),
@@ -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),
@@ -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),
@@ -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 impl = fetchImpl || fetch
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
- signal: timeoutSignal,
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 impl = fetchImpl || fetch
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
- signal: timeoutSignal,
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.41",
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/dsh-llm": "0.1.0-rc.8",
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
- "typescript": "^7.0.2",
74
- "@deepseek-ai/schemastery": "^3.18.4"
78
+ "eslint": "^10.4.0",
79
+ "typescript": "^7.0.2"
75
80
  }
76
81
  }