@goodandready/dsh-subscriptions 0.6.45 → 0.6.47
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/adapter.js +13 -1
- package/lib/subscriptions.js +5 -3
- package/lib/tools-normalizer.js +22 -2
- package/lib/vendors/codex.js +6 -6
- package/lib/wire.js +4 -3
- package/package.json +1 -1
package/lib/adapter.js
CHANGED
|
@@ -309,7 +309,19 @@ export class SubscriptionAdapter extends LlmAdapter {
|
|
|
309
309
|
}
|
|
310
310
|
throw err
|
|
311
311
|
} finally {
|
|
312
|
-
|
|
312
|
+
const isFinishError = finishReason && (
|
|
313
|
+
finishReason.kind === 'error' ||
|
|
314
|
+
finishReason === 'error' ||
|
|
315
|
+
(typeof finishReason === 'object' && Boolean(finishReason.failure))
|
|
316
|
+
)
|
|
317
|
+
if (errorCaught || isFinishError) {
|
|
318
|
+
if (!errorCaught && isFinishError) {
|
|
319
|
+
errorCaught = new Error(
|
|
320
|
+
typeof finishReason === 'object' && finishReason.failure
|
|
321
|
+
? (finishReason.failure.message || finishReason.failure.code || 'stream finished with error')
|
|
322
|
+
: 'stream finished with error'
|
|
323
|
+
)
|
|
324
|
+
}
|
|
313
325
|
finalizeOnce('error')
|
|
314
326
|
} else if (opts && opts._runawayState && opts._runawayState.tripped) {
|
|
315
327
|
finalizeOnce('runaway')
|
package/lib/subscriptions.js
CHANGED
|
@@ -2,6 +2,7 @@ import { isProvider } from "./refs.js"
|
|
|
2
2
|
import { pickAccount, markCooldown, isSwitchableError, modelFamily } from "./rotate.js"
|
|
3
3
|
import { quotaSnapshot } from "./ratelimit.js"
|
|
4
4
|
import { pickFetch } from "./proxy.js"
|
|
5
|
+
import { fetchWithTimeout } from "./http.js"
|
|
5
6
|
|
|
6
7
|
// ponytail: allowlist per provider — add path to extend without touching request logic
|
|
7
8
|
export const ALLOWLIST = {
|
|
@@ -75,7 +76,7 @@ export function createSubscriptionsService(deps) {
|
|
|
75
76
|
}
|
|
76
77
|
return out
|
|
77
78
|
},
|
|
78
|
-
async request({ provider, path, method = "GET", headers = {}, body, signal }) {
|
|
79
|
+
async request({ provider, path, method = "GET", headers = {}, body, signal, timeoutMs }) {
|
|
79
80
|
if (!isProvider(provider)) {
|
|
80
81
|
const err = new Error("unknown provider: " + provider)
|
|
81
82
|
err.code = "PROVIDER"
|
|
@@ -144,8 +145,9 @@ export function createSubscriptionsService(deps) {
|
|
|
144
145
|
const url = p
|
|
145
146
|
const extraHeaders = headersFor(provider, blob, cfg)
|
|
146
147
|
const fetchImpl = pickFetch(deps, account.ref)
|
|
148
|
+
const requestTimeoutMs = Number(timeoutMs) > 0 ? Number(timeoutMs) : 30000
|
|
147
149
|
const t0 = Date.now()
|
|
148
|
-
const res = await fetchImpl
|
|
150
|
+
const res = await fetchWithTimeout(fetchImpl, url, {
|
|
149
151
|
method,
|
|
150
152
|
headers: {
|
|
151
153
|
Authorization: "Bearer " + blob.accessToken,
|
|
@@ -156,7 +158,7 @@ export function createSubscriptionsService(deps) {
|
|
|
156
158
|
},
|
|
157
159
|
body: body && typeof body === "object" && !(body instanceof Uint8Array) && typeof body !== "string" ? JSON.stringify(body) : body,
|
|
158
160
|
signal,
|
|
159
|
-
})
|
|
161
|
+
}, { timeoutMs: requestTimeoutMs })
|
|
160
162
|
// capture quota
|
|
161
163
|
try {
|
|
162
164
|
const snap = quotaSnapshot(provider, res.headers, null, Date.now())
|
package/lib/tools-normalizer.js
CHANGED
|
@@ -35,8 +35,8 @@ export function normalizeJsonSchema(schema, depth = 0) {
|
|
|
35
35
|
out.type = "object"
|
|
36
36
|
} else if (schema.items) {
|
|
37
37
|
out.type = "array"
|
|
38
|
-
} else if (schema.anyOf || schema.oneOf || schema.allOf) {
|
|
39
|
-
// Schema combinator without explicit type
|
|
38
|
+
} else if (schema.anyOf || schema.oneOf || schema.allOf || schema.$ref || schema.const !== undefined) {
|
|
39
|
+
// Schema combinator, reference, or const without explicit type
|
|
40
40
|
} else {
|
|
41
41
|
out.type = depth === 0 ? "object" : "string"
|
|
42
42
|
}
|
|
@@ -53,6 +53,26 @@ export function normalizeJsonSchema(schema, depth = 0) {
|
|
|
53
53
|
out.default = schema.default
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
if (typeof schema.$ref === "string") {
|
|
57
|
+
out.$ref = schema.$ref
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (schema.const !== undefined) {
|
|
61
|
+
out.const = schema.const
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const defs = schema.$defs || schema.definitions
|
|
65
|
+
if (defs && typeof defs === "object" && !Array.isArray(defs)) {
|
|
66
|
+
const normDefs = {}
|
|
67
|
+
for (const [k, v] of Object.entries(defs)) {
|
|
68
|
+
if (typeof k === "string" && k) {
|
|
69
|
+
normDefs[k] = normalizeJsonSchema(v, depth + 1)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (schema.$defs) out.$defs = normDefs
|
|
73
|
+
if (schema.definitions) out.definitions = normDefs
|
|
74
|
+
}
|
|
75
|
+
|
|
56
76
|
if (out.type === "object" || (!out.type && (schema.properties || schema.required || schema.additionalProperties !== undefined))) {
|
|
57
77
|
if (schema.properties && typeof schema.properties === "object" && !Array.isArray(schema.properties)) {
|
|
58
78
|
out.properties = {}
|
package/lib/vendors/codex.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isTimeoutError } from "../http.js"
|
|
1
|
+
import { isTimeoutError, fetchWithTimeout } from "../http.js"
|
|
2
2
|
import { randomUUID, createHash } from 'node:crypto'
|
|
3
3
|
import { buildAuthorizeUrl } from '../oauth.js'
|
|
4
4
|
import { codexResponsesBody, modelCatalog } from '../messages.js'
|
|
@@ -152,9 +152,9 @@ export async function listModels(blob, cfg, fetchImpl) {
|
|
|
152
152
|
try {
|
|
153
153
|
const base = (cfg.baseUrl || defaults().baseUrl).replace(/\/$/, '')
|
|
154
154
|
const version = cfg.clientVersion || defaults().clientVersion
|
|
155
|
-
const res = await impl
|
|
155
|
+
const res = await fetchWithTimeout(impl, `${base}/models?client_version=${encodeURIComponent(version)}`, {
|
|
156
156
|
headers: identityHeaders(blob, cfg, { Accept: 'application/json' }),
|
|
157
|
-
})
|
|
157
|
+
}, { timeoutMs: 15000 })
|
|
158
158
|
const json = await readJson(res)
|
|
159
159
|
const rows = []
|
|
160
160
|
for (const entry of json.models || json.data || []) {
|
|
@@ -186,9 +186,9 @@ export async function check(blob, cfg, fetchImpl) {
|
|
|
186
186
|
const base = (cfg.baseUrl || defaults().baseUrl).replace(/\/$/, "")
|
|
187
187
|
const version = cfg.clientVersion || defaults().clientVersion
|
|
188
188
|
const impl = fetchImpl || fetch
|
|
189
|
-
const res = await impl
|
|
189
|
+
const res = await fetchWithTimeout(impl, base + "/models?client_version=" + encodeURIComponent(version), {
|
|
190
190
|
headers: identityHeaders(blob, cfg, { Accept: "application/json" }),
|
|
191
|
-
})
|
|
191
|
+
}, { timeoutMs: 15000 })
|
|
192
192
|
if (!res.ok) throw httpError(res.status, await res.text())
|
|
193
193
|
const json = await readJson(res)
|
|
194
194
|
// quota headers may contain limits
|
|
@@ -197,7 +197,7 @@ export async function check(blob, cfg, fetchImpl) {
|
|
|
197
197
|
|
|
198
198
|
export async function usage(blob, cfg, fetchImpl) {
|
|
199
199
|
try {
|
|
200
|
-
const res = await (fetchImpl || fetch
|
|
200
|
+
const res = await fetchWithTimeout(fetchImpl || fetch, USAGE, {
|
|
201
201
|
headers: identityHeaders(blob, cfg, { Accept: 'application/json' }),
|
|
202
202
|
})
|
|
203
203
|
const json = await readJson(res)
|
package/lib/wire.js
CHANGED
|
@@ -88,7 +88,7 @@ export function toTokenUsage(raw) {
|
|
|
88
88
|
"inputTokens" in raw || "input_tokens" in raw || "promptTokens" in raw || "prompt_tokens" in raw || "input" in raw ||
|
|
89
89
|
"outputTokens" in raw || "output_tokens" in raw || "completionTokens" in raw || "completion_tokens" in raw || "output" in raw ||
|
|
90
90
|
"totalTokens" in raw || "total_tokens" in raw || "totalTokenCount" in raw ||
|
|
91
|
-
"promptTokenCount" in raw || "candidatesTokenCount" in raw
|
|
91
|
+
"promptTokenCount" in raw || "candidatesTokenCount" in raw || "thoughtsTokenCount" in raw
|
|
92
92
|
)
|
|
93
93
|
if (!hasKnownField) return null
|
|
94
94
|
|
|
@@ -135,7 +135,8 @@ export function toTokenUsage(raw) {
|
|
|
135
135
|
raw.reasoningTokens ??
|
|
136
136
|
raw.output_token_details?.reasoning_tokens ??
|
|
137
137
|
raw.completion_tokens_details?.reasoning_tokens ??
|
|
138
|
-
raw.reasoning_tokens
|
|
138
|
+
raw.reasoning_tokens ??
|
|
139
|
+
raw.thoughtsTokenCount
|
|
139
140
|
)
|
|
140
141
|
const rawTotal = toCount(raw.totalTokens ?? raw.total_tokens ?? raw.totalTokenCount)
|
|
141
142
|
|
|
@@ -150,7 +151,7 @@ export function toTokenUsage(raw) {
|
|
|
150
151
|
if (cacheWriteTokens > 0 || raw.cacheWriteTokens !== undefined || raw.cache_creation_input_tokens !== undefined) {
|
|
151
152
|
out.cacheWriteTokens = cacheWriteTokens
|
|
152
153
|
}
|
|
153
|
-
if (reasoningTokens > 0 || raw.reasoningTokens !== undefined || raw.output_token_details?.reasoning_tokens !== undefined || raw.completion_tokens_details?.reasoning_tokens !== undefined) {
|
|
154
|
+
if (reasoningTokens > 0 || raw.reasoningTokens !== undefined || raw.output_token_details?.reasoning_tokens !== undefined || raw.completion_tokens_details?.reasoning_tokens !== undefined || raw.thoughtsTokenCount !== undefined) {
|
|
154
155
|
out.reasoningTokens = reasoningTokens
|
|
155
156
|
}
|
|
156
157
|
if (rawTotal > 0 || raw.totalTokens !== undefined || raw.total_tokens !== undefined || raw.totalTokenCount !== undefined) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-subscriptions",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.47",
|
|
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",
|