@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.
@@ -114,8 +114,10 @@ export function createAdapterManager({
114
114
 
115
115
  if (adapterDisposed) return
116
116
  if (!handle && claimable.length) {
117
- handle = ctx.llm.registerAdapter(claimable, adapter)
118
- registeredByUs = new Set(claimable)
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
- handle = ctx.llm.registerAdapter(reClaimable, adapter)
152
- registeredByUs = new Set(reClaimable)
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
 
@@ -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 { ollamaHandle = ctx.llm.registerAdapter(['ollama'], ollamaAdapter) } catch { /* already registered elsewhere */ }
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.values(value)) {
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) {
@@ -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,
@@ -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.55",
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",