@goodandready/dsh-subscriptions 0.7.47 → 0.7.48

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 CHANGED
@@ -51,6 +51,7 @@ import { recordSwitch, recordExhaust, recordBroken, computeHealthScore, healthBa
51
51
  import { executeWithRetry } from './backoff.js'
52
52
  import { getVendor } from './vendors/index.js'
53
53
  import { versionForProvider } from './client-version-service.js'
54
+ import { writeClaudeKeychain } from './claude-keychain.js'
54
55
 
55
56
  const SKEW_MS = 60 * 1000
56
57
  const USAGE_TTL_MS = 2 * 60 * 1000
@@ -508,6 +509,9 @@ export function createAccountStore({ credentials, getConfig, fetchImpl, fetchFor
508
509
  accountId: next.accountId || blob.accountId,
509
510
  }
510
511
  if (ref) await saveBlob(ref, merged)
512
+ if (ref && provider === 'claude' && blob.accessToken && merged.accessToken !== blob.accessToken) {
513
+ writeClaudeKeychain(merged, blob.accessToken).catch(() => {})
514
+ }
511
515
  if (ref) refreshFailures.delete(ref)
512
516
  return merged
513
517
  } catch (e) {
@@ -56,6 +56,7 @@ export function createAdapterManager({
56
56
  switchAtRemaining: () => live().switchAtRemaining,
57
57
  rotationStrategy: () => live().rotationStrategy,
58
58
  modelAccountRules: () => live().modelAccountRules || [],
59
+ subagentSpeed: () => live().codexSubagentSpeed,
59
60
  rateLimitWait: () => live().rateLimitWait,
60
61
  rateLimitMaxWaitMs: () => live().rateLimitMaxWaitMs,
61
62
  enableSoftFailureSentinel: () => live().enableSoftFailureSentinel,
package/lib/adapter.js CHANGED
@@ -6,6 +6,7 @@ import { LlmAdapter, LlmError, attributionHeaders } from '@deepseek-ai/dsh-llm'
6
6
  import { displayName } from './refs.js'
7
7
  import { applyModelSettings, bestAccountPlan } from './model-settings.js'
8
8
  import { getSpeedMode } from './speed-mode.js'
9
+ import { resolveSpeed } from './account-features.js'
9
10
  import { getVendor } from './vendors/index.js'
10
11
  import { modelCatalog } from './messages.js'
11
12
  import { streamWithRotation } from './stream-rotate.js'
@@ -205,7 +206,11 @@ export class SubscriptionAdapter extends LlmAdapter {
205
206
  const defaultRef = typeof deps.defaultAccountRef === 'function' ? deps.defaultAccountRef(provider) : null
206
207
  const streamOptions = {
207
208
  ...hydratedOptions,
208
- ...(provider === 'codex' && getSpeedMode(sessionId) === 'fast' ? { service_tier: 'priority' } : {}),
209
+ ...(provider === 'codex' && resolveSpeed({
210
+ childSpeed: options.speed,
211
+ sessionSpeed: getSpeedMode(sessionId),
212
+ subagentSpeed: (options.subagent || options.parentSessionId) && typeof deps.subagentSpeed === 'function' ? deps.subagentSpeed() : undefined,
213
+ }) === 'fast' ? { service_tier: 'priority' } : {}),
209
214
  ...(effectiveReasoning.effort ? { reasoningEffort: effectiveReasoning.effort } : {}),
210
215
  ...(effectiveReasoning.budgetTokens ? { thinkingBudget: effectiveReasoning.budgetTokens } : {}),
211
216
  // #830: kill switch. With no default account, use a sentinel that
package/lib/images.js CHANGED
@@ -28,7 +28,7 @@ const GROK_ASPECT = {
28
28
  auto: 'auto',
29
29
  }
30
30
 
31
- export function codexBody({ prompt, size, quality }) {
31
+ export function codexBody({ prompt, size, quality, referenceImages = [] }) {
32
32
  const text = String(prompt || '').trim()
33
33
  if (!text) throw new Error('prompt must be a non-empty string')
34
34
  return {
@@ -36,10 +36,13 @@ export function codexBody({ prompt, size, quality }) {
36
36
  model: CODEX_MODEL,
37
37
  ...(size ? { size } : {}),
38
38
  ...(quality ? { quality } : {}),
39
+ ...(Array.isArray(referenceImages) && referenceImages.length
40
+ ? { images: referenceImages.map((ref) => ({ image_url: ref })) }
41
+ : {}),
39
42
  }
40
43
  }
41
44
 
42
- export function grokBody({ prompt, size, quality }) {
45
+ export function grokBody({ prompt, size, quality, referenceImages = [] }) {
43
46
  const text = String(prompt || '').trim()
44
47
  if (!text) throw new Error('prompt must be a non-empty string')
45
48
  // Grok has only two quality tiers: high is composed from medium.
@@ -52,6 +55,7 @@ export function grokBody({ prompt, size, quality }) {
52
55
  response_format: 'b64_json',
53
56
  ...(size && GROK_ASPECT[size] ? { aspect_ratio: GROK_ASPECT[size] } : {}),
54
57
  ...(level ? { quality: level } : {}),
58
+ ...(Array.isArray(referenceImages) && referenceImages.length ? { image_urls: referenceImages } : {}),
55
59
  }
56
60
  }
57
61
 
package/lib/index.js CHANGED
@@ -471,6 +471,7 @@ export function apply(ctx, rawConfig) {
471
471
  prompt: request.prompt,
472
472
  size: request.size,
473
473
  quality: request.quality,
474
+ referenceImages: request.referenceImages,
474
475
  session,
475
476
  fetchImpl: fetchFn,
476
477
  signal: request.signal,
@@ -1,5 +1,6 @@
1
1
  import { mkdir, writeFile } from 'node:fs/promises'
2
2
  import path from 'node:path'
3
+ import { validateReferenceImages } from './media-reference.js'
3
4
 
4
5
  const TOOL_OUTPUT = {
5
6
  schema: {
@@ -86,12 +87,15 @@ export function registerSubscriptionTools(ctx, deps, options = {}) {
86
87
  provider: { type: 'string', enum: ['gpt', 'codex', 'grok'], description: 'Preferred provider' },
87
88
  size: { type: 'string', description: 'Image size, e.g. 1024x1024' },
88
89
  quality: { type: 'string', description: 'low, medium or high' },
90
+ referenceImages: { type: 'array', items: { type: 'string' }, maxItems: 5, description: '1–5 attachment refs for image editing' },
89
91
  },
90
92
  required: ['prompt'],
91
93
  },
92
94
  async execute(args, exec) {
93
95
  const images = deps.images && deps.images()
94
96
  if (!images || typeof images.generate !== 'function') throw new Error('subscription image service is unavailable')
97
+ const references = validateReferenceImages(args && args.referenceImages)
98
+ if (!references.ok) throw new Error(references.error)
95
99
  const preferred = String((args && args.provider) || 'gpt').toLowerCase()
96
100
  const order = preferred === 'grok' ? ['grok', 'codex'] : ['codex', 'grok']
97
101
  let lastError = null
@@ -102,6 +106,7 @@ export function registerSubscriptionTools(ctx, deps, options = {}) {
102
106
  prompt: args && args.prompt,
103
107
  size: args && args.size,
104
108
  quality: args && args.quality,
109
+ referenceImages: references.refs,
105
110
  signal: exec && exec.signal,
106
111
  })
107
112
  const files = await saveImages(rows, exec)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-subscriptions",
3
- "version": "0.7.47",
3
+ "version": "0.7.48",
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",