@goodandready/dsh-subscriptions 0.6.55 → 0.6.57
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-manager.js +8 -4
- package/lib/config-schema.js +16 -0
- package/lib/index.js +5 -1
- package/lib/usage.js +8 -6
- package/lib/vendor-factory.js +10 -0
- package/lib/vendors/claude.js +32 -1
- package/package.json +1 -1
package/lib/adapter-manager.js
CHANGED
|
@@ -114,8 +114,10 @@ export function createAdapterManager({
|
|
|
114
114
|
|
|
115
115
|
if (adapterDisposed) return
|
|
116
116
|
if (!handle && claimable.length) {
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
if (ctx.llm && typeof ctx.llm.registerAdapter === 'function') {
|
|
118
|
+
handle = ctx.llm.registerAdapter(claimable, adapter)
|
|
119
|
+
registeredByUs = new Set(claimable)
|
|
120
|
+
}
|
|
119
121
|
return
|
|
120
122
|
}
|
|
121
123
|
if (!handle) {
|
|
@@ -148,8 +150,10 @@ export function createAdapterManager({
|
|
|
148
150
|
const currentGlobal = new Set((ctx.llm && typeof ctx.llm.listProviders === 'function' ? ctx.llm.listProviders() : []).map((p) => p.id))
|
|
149
151
|
const reClaimable = desired.filter((p) => !currentGlobal.has(p))
|
|
150
152
|
if (reClaimable.length) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
+
if (ctx.llm && typeof ctx.llm.registerAdapter === 'function') {
|
|
154
|
+
handle = ctx.llm.registerAdapter(reClaimable, adapter)
|
|
155
|
+
registeredByUs = new Set(reClaimable)
|
|
156
|
+
}
|
|
153
157
|
}
|
|
154
158
|
}
|
|
155
159
|
|
package/lib/config-schema.js
CHANGED
|
@@ -84,6 +84,22 @@ export const Config = z.object({
|
|
|
84
84
|
.description('Grok CLI identity version header. Empty uses the built-in default.'),
|
|
85
85
|
antigravityClientId: z.string().volatile().default(''),
|
|
86
86
|
antigravityRedirectUri: z.string().volatile().default(''),
|
|
87
|
+
antigravityModels: z.array(z.any()).volatile().default([])
|
|
88
|
+
.description('Custom model catalog for Antigravity.'),
|
|
89
|
+
codexOriginator: z.string().volatile().default('')
|
|
90
|
+
.description('Originator header for Codex API requests (e.g. codex_cli_rs).'),
|
|
91
|
+
codexSystemPrefix: z.string().volatile().default('')
|
|
92
|
+
.description('System prompt prefix for Codex.'),
|
|
93
|
+
codexModels: z.array(z.any()).volatile().default([])
|
|
94
|
+
.description('Custom model catalog for Codex.'),
|
|
95
|
+
claudeSystemPrefix: z.string().volatile().default('')
|
|
96
|
+
.description('System prompt prefix for Claude.'),
|
|
97
|
+
claudeCcVersion: z.string().volatile().default('')
|
|
98
|
+
.description('Claude Code version header for billing attribution (default: 2.1.289.7e2).'),
|
|
99
|
+
claudeModels: z.array(z.any()).volatile().default([])
|
|
100
|
+
.description('Custom model catalog for Claude.'),
|
|
101
|
+
grokModels: z.array(z.any()).volatile().default([])
|
|
102
|
+
.description('Custom model catalog for Grok.'),
|
|
87
103
|
cascadingFallback: z.boolean().volatile().default(false)
|
|
88
104
|
.description('#349 Opt-in cross-vendor fallback when all accounts of a provider are exhausted or rate limited.'),
|
|
89
105
|
cascadingChain: z.any().volatile().default({})
|
package/lib/index.js
CHANGED
|
@@ -260,7 +260,11 @@ export function apply(ctx, rawConfig) {
|
|
|
260
260
|
const cfg = live()
|
|
261
261
|
const alive = !!cfg.ollamaFallback && await ollamaAlive(ollamaBase(cfg), fetch)
|
|
262
262
|
if (alive && !ollamaHandle) {
|
|
263
|
-
try {
|
|
263
|
+
try {
|
|
264
|
+
if (ctx.llm && typeof ctx.llm.registerAdapter === 'function') {
|
|
265
|
+
ollamaHandle = ctx.llm.registerAdapter(['ollama'], ollamaAdapter)
|
|
266
|
+
}
|
|
267
|
+
} catch { /* already registered elsewhere */ }
|
|
264
268
|
} else if (!alive && ollamaHandle) {
|
|
265
269
|
try { ollamaHandle() } catch { /* already gone */ }
|
|
266
270
|
ollamaHandle = undefined
|
package/lib/usage.js
CHANGED
|
@@ -3,8 +3,9 @@ export function numberOrNull(value) {
|
|
|
3
3
|
return Number.isFinite(n) ? n : null
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
export function windowPercent(obj) {
|
|
6
|
+
export function windowPercent(obj, key) {
|
|
7
7
|
if (!obj || typeof obj !== 'object') return null
|
|
8
|
+
if (key === 'extra_usage' || (obj.monthly_limit != null && obj.used_credits != null)) return null
|
|
8
9
|
return numberOrNull(
|
|
9
10
|
obj.utilization ?? obj.used_percent ?? obj.usedPercent ?? obj.creditUsagePercent ?? obj.used_percentage,
|
|
10
11
|
)
|
|
@@ -12,9 +13,9 @@ export function windowPercent(obj) {
|
|
|
12
13
|
|
|
13
14
|
export function deepestUsedPercent(obj) {
|
|
14
15
|
let max = null
|
|
15
|
-
function walk(value, depth) {
|
|
16
|
+
function walk(value, key, depth) {
|
|
16
17
|
if (!value || typeof value !== 'object' || depth > 8) return
|
|
17
|
-
const here = windowPercent(value)
|
|
18
|
+
const here = windowPercent(value, key)
|
|
18
19
|
if (here != null) max = max == null ? here : Math.max(max, here)
|
|
19
20
|
const remaining = numberOrNull(value.remainingFraction)
|
|
20
21
|
if (remaining != null) {
|
|
@@ -26,11 +27,11 @@ export function deepestUsedPercent(obj) {
|
|
|
26
27
|
const used = usedFrac * 100
|
|
27
28
|
max = max == null ? used : Math.max(max, used)
|
|
28
29
|
}
|
|
29
|
-
for (const child of Object.
|
|
30
|
-
if (child && typeof child === 'object') walk(child, depth + 1)
|
|
30
|
+
for (const [k, child] of Object.entries(value)) {
|
|
31
|
+
if (child && typeof child === 'object') walk(child, k, depth + 1)
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
|
-
walk(obj, 0)
|
|
34
|
+
walk(obj, '', 0)
|
|
34
35
|
return max
|
|
35
36
|
}
|
|
36
37
|
|
|
@@ -81,6 +82,7 @@ const WINDOW_LABELS = {
|
|
|
81
82
|
secondary_window: { zh: "7天", en: "7d" },
|
|
82
83
|
monthly: { zh: "月度", en: "month" },
|
|
83
84
|
credits: { zh: "点数", en: "credits" },
|
|
85
|
+
extra_usage: { zh: "额外用量", en: "extra" },
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
export function windowLabel(id) {
|
package/lib/vendor-factory.js
CHANGED
|
@@ -139,6 +139,16 @@ export function validateProfile(raw) {
|
|
|
139
139
|
}
|
|
140
140
|
if (!/^[a-z][a-z0-9_]*$/.test(p.id)) throw new Error(`customVendors: id "${p.id}" must match [a-z][a-z0-9_]*`)
|
|
141
141
|
if (p.tokenStyle && !["form", "json"].includes(p.tokenStyle)) throw new Error(`customVendors[${p.id}]: tokenStyle must be form|json`)
|
|
142
|
+
for (const key of ["authUrl", "tokenUrl", "baseUrl"]) {
|
|
143
|
+
try {
|
|
144
|
+
const u = new URL(p[key])
|
|
145
|
+
if (u.protocol !== "https:" && u.protocol !== "http:") {
|
|
146
|
+
throw new Error("protocol must be http: or https:")
|
|
147
|
+
}
|
|
148
|
+
} catch (e) {
|
|
149
|
+
throw new Error(`customVendors[${p.id}]: field ${key} must be a valid http(s) URL (${e.message || e})`)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
142
152
|
return {
|
|
143
153
|
id: p.id,
|
|
144
154
|
displayName: p.displayName || p.id,
|
package/lib/vendors/claude.js
CHANGED
|
@@ -56,6 +56,7 @@ export function defaults() {
|
|
|
56
56
|
return {
|
|
57
57
|
clientId: '9d1c250a-e61b-44d9-88ed-5944d1962f5e',
|
|
58
58
|
redirectUri: 'https://console.anthropic.com/oauth/code/callback',
|
|
59
|
+
claudeCcVersion: '2.1.289.7e2',
|
|
59
60
|
models: [
|
|
60
61
|
{ id: 'claude-opus-5', name: 'Claude Opus 5' },
|
|
61
62
|
{ id: 'claude-sonnet-5', name: 'Claude Sonnet 5' },
|
|
@@ -137,7 +138,9 @@ export async function listModels(blob, cfg, fetchImpl) {
|
|
|
137
138
|
"Accept": "application/json",
|
|
138
139
|
"anthropic-version": "2023-06-01",
|
|
139
140
|
}
|
|
140
|
-
if (blob.accessToken.startsWith("sk-ant-")) {
|
|
141
|
+
if (blob.accessToken.startsWith("sk-ant-oat") || blob.accessToken.startsWith("sk-ant-ort")) {
|
|
142
|
+
headers["Authorization"] = `Bearer ${blob.accessToken}`
|
|
143
|
+
} else if (blob.accessToken.startsWith("sk-ant-")) {
|
|
141
144
|
headers["x-api-key"] = blob.accessToken
|
|
142
145
|
} else {
|
|
143
146
|
headers["Authorization"] = `Bearer ${blob.accessToken}`
|
|
@@ -200,9 +203,37 @@ export async function usage(blob, _cfg, fetchImpl) {
|
|
|
200
203
|
}
|
|
201
204
|
}
|
|
202
205
|
|
|
206
|
+
export function makeClaudeBillingHeader(cfg) {
|
|
207
|
+
const ccVersion = (cfg && cfg.claudeCcVersion) || '2.1.289.7e2'
|
|
208
|
+
const cch = (globalThis.__DSH_CC_H__ || (() => {
|
|
209
|
+
globalThis.__DSH_CC_H__ = Math.random().toString(16).slice(2, 6)
|
|
210
|
+
return globalThis.__DSH_CC_H__
|
|
211
|
+
})())
|
|
212
|
+
const turnIndex = (globalThis.__DSH_CC_TURN__ = (globalThis.__DSH_CC_TURN__ || 0) + 1)
|
|
213
|
+
return `x-anthropic-billing-header: cc_version=${ccVersion}; cc_entrypoint=sdk-cli; cch=${cch}; cc_turn_origin=sdk; cc_prompt_index=0; cc_turn_index=${turnIndex};`
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function applyClaudeBillingHeader(payload, cfg) {
|
|
217
|
+
if (process.env.CLAUDE_CODE_ATTRIBUTION_HEADER === '0') return payload
|
|
218
|
+
if (!payload) return payload
|
|
219
|
+
const headerText = makeClaudeBillingHeader(cfg)
|
|
220
|
+
const headerBlock = { type: 'text', text: headerText }
|
|
221
|
+
if (Array.isArray(payload.system)) {
|
|
222
|
+
if (!payload.system.some((b) => typeof b === 'object' && b && typeof b.text === 'string' && b.text.startsWith('x-anthropic-billing-header:'))) {
|
|
223
|
+
payload.system = [headerBlock, ...payload.system]
|
|
224
|
+
}
|
|
225
|
+
} else if (typeof payload.system === 'string' && payload.system.trim()) {
|
|
226
|
+
payload.system = [headerBlock, { type: 'text', text: payload.system }]
|
|
227
|
+
} else if (!payload.system) {
|
|
228
|
+
payload.system = [headerBlock]
|
|
229
|
+
}
|
|
230
|
+
return payload
|
|
231
|
+
}
|
|
232
|
+
|
|
203
233
|
export async function* streamOnce({ blob, options, fetchImpl, headers, config, signal }) {
|
|
204
234
|
const payload = anthropicPayload(options, config.systemPrefix || IDENTITY)
|
|
205
235
|
applyClaudeThinking(payload, options)
|
|
236
|
+
applyClaudeBillingHeader(payload, config)
|
|
206
237
|
const res = await fetchImpl(API, {
|
|
207
238
|
method: 'POST',
|
|
208
239
|
headers: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-subscriptions",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.57",
|
|
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",
|