@gehennawu/dsh-service 1.4.3 → 1.4.4

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/index.js CHANGED
@@ -27,6 +27,7 @@ import {
27
27
  fetchStepFunStepPlanUsage as fetchStepFunStepPlanAdapterUsage,
28
28
  fetchXiaomiTokenPlanUsage as fetchXiaomiTokenPlanAdapterUsage,
29
29
  normalizeAntigravityModels as normalizeAntigravityModelsAdapter,
30
+ normalizeAntigravityQuotaSummary as normalizeAntigravityQuotaSummaryAdapter,
30
31
  normalizeCodexRateLimit as normalizeCodexRateLimitAdapter,
31
32
  normalizeDeepseekBalance as normalizeDeepseekBalanceAdapter,
32
33
  normalizeGeminiBuckets as normalizeGeminiBucketsAdapter,
@@ -166,7 +167,7 @@ const QUOTA_BACKOFF_BASE_MS = 30000
166
167
  const QUOTA_BACKOFF_MAX_MS = 15 * 60 * 1000
167
168
  const QUOTA_CONFIG_STAT_TTL_MS = 5000
168
169
  const QUOTA_MAX_CONCURRENCY = 4
169
- const MAX_QUOTA_RESPONSE_BYTES = 64 * 1024
170
+ const MAX_QUOTA_RESPONSE_BYTES = 1024 * 1024
170
171
  const MAX_QUOTA_CONFIG_BYTES = 256 * 1024
171
172
  const MAX_QUOTA_PROVIDERS = 256
172
173
  const MAX_QUOTA_PROVIDER_NAME = 128
@@ -1311,6 +1312,11 @@ function normalizeAntigravityModels(models) {
1311
1312
  return normalizeAntigravityModelsAdapter(models)
1312
1313
  }
1313
1314
 
1315
+ /** Antigravity retrieveUserQuotaSummary 的 groups[] → 窗口(池化配额已用 %)。 */
1316
+ function normalizeAntigravityQuotaSummary(groups) {
1317
+ return normalizeAntigravityQuotaSummaryAdapter(groups)
1318
+ }
1319
+
1314
1320
  /** api-call 信封解包:{status_code:int, body:string|object} → {statusCode, payload}。 */
1315
1321
  function unwrapCliproxyApiCallEnvelope(envelope) {
1316
1322
  return unwrapCliproxyApiCallEnvelopeAdapter(envelope)
@@ -5468,6 +5474,7 @@ export {
5468
5474
  locateSkillFrontmatter,
5469
5475
  name,
5470
5476
  normalizeAntigravityModels,
5477
+ normalizeAntigravityQuotaSummary,
5471
5478
  normalizeCodexRateLimit,
5472
5479
  normalizeDeepseekBalance,
5473
5480
  normalizeGeminiBuckets,
@@ -5536,6 +5543,7 @@ export default {
5536
5543
  locateSkillFrontmatter,
5537
5544
  name,
5538
5545
  normalizeAntigravityModels,
5546
+ normalizeAntigravityQuotaSummary,
5539
5547
  normalizeCodexRateLimit,
5540
5548
  normalizeDeepseekBalance,
5541
5549
  normalizeGeminiBuckets,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gehennawu/dsh-service",
3
- "version": "1.4.3",
3
+ "version": "1.4.4",
4
4
  "description": "DSH Web 运维面板:安全重启、健康监控、备份和 Linux 权限维护。",
5
5
  "type": "module",
6
6
  "scripts": {
package/quota-adapters.js CHANGED
@@ -11,7 +11,7 @@ const MAX_QUOTA_ERROR_DETAIL = 256
11
11
  const MAX_QUOTA_CPA_ACCOUNTS = 8
12
12
  const MAX_QUOTA_CPA_CALLS = 12
13
13
  const QUOTA_CPA_CONCURRENCY = 3
14
- const MAX_QUOTA_CPA_WINDOWS = 32
14
+ const MAX_QUOTA_CPA_WINDOWS = 64
15
15
 
16
16
  function quotaErrorCode(error) {
17
17
  const raw = typeof error?.message === 'string' && error.message.length > 0 ? error.message : String(error ?? '')
@@ -543,8 +543,10 @@ async function fetchStepFunStepPlanUsage({ credential, signal, requestJson }) {
543
543
  const CLIPROXY_CODEX_USAGE_URL = 'https://chatgpt.com/backend-api/wham/usage'
544
544
  const CLIPROXY_GEMINI_QUOTA_URL = 'https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuota'
545
545
  const CLIPROXY_ANTIGRAVITY_QUOTA_URLS = [
546
+ 'https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuotaSummary',
547
+ 'https://daily-cloudcode-pa.googleapis.com/v1internal:retrieveUserQuotaSummary',
548
+ 'https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuota',
546
549
  'https://daily-cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels',
547
- 'https://daily-cloudcode-pa.sandbox.googleapis.com/v1internal:fetchAvailableModels',
548
550
  'https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels',
549
551
  ]
550
552
  const CLIPROXY_SUPPORTED_ACCOUNT_KINDS = new Set(['codex', 'gemini', 'gemini-cli', 'antigravity'])
@@ -556,6 +558,12 @@ const CODEX_WINDOW_ORDER = new Map([
556
558
  ['codex-primary', 4],
557
559
  ['codex-secondary', 5],
558
560
  ])
561
+ const ANTIGRAVITY_WINDOW_ORDER = new Map([
562
+ ['gemini-5h', 0],
563
+ ['gemini-week', 1],
564
+ ['claude-5h', 2],
565
+ ['claude-week', 3],
566
+ ])
559
567
 
560
568
  function safeCliproxyOrigin(baseURL, pinnedHosts) {
561
569
  if (!Array.isArray(pinnedHosts) || pinnedHosts.length === 0) return undefined
@@ -623,6 +631,23 @@ function normalizeCodexRateLimit(rateLimit) {
623
631
  return sortCodexWindows(windows)
624
632
  }
625
633
 
634
+ function parseCodexSignals(quota) {
635
+ const signals = quota?.signals
636
+ if (signals === null || typeof signals !== 'object') return []
637
+ const windows = []
638
+ const pUsed = normalizePercentValue(signals['X-Codex-Primary-Used-Percent'] ?? signals['x-codex-primary-used-percent'])
639
+ const pReset = normalizeResetTimestamp(signals['X-Codex-Primary-Reset-At'] ?? signals['x-codex-primary-reset-at'])
640
+ if (pUsed !== null) {
641
+ windows.push({ id: 'codex-5h', kindKey: 'codex-5h', percent: pUsed, ...(pReset !== undefined ? { resetsAt: pReset } : {}) })
642
+ }
643
+ const sUsed = normalizePercentValue(signals['X-Codex-Secondary-Used-Percent'] ?? signals['x-codex-secondary-used-percent'])
644
+ const sReset = normalizeResetTimestamp(signals['X-Codex-Secondary-Reset-At'] ?? signals['x-codex-secondary-reset-at'])
645
+ if (sUsed !== null) {
646
+ windows.push({ id: 'codex-week', kindKey: 'codex-week', percent: sUsed, ...(sReset !== undefined ? { resetsAt: sReset } : {}) })
647
+ }
648
+ return sortCodexWindows(windows)
649
+ }
650
+
626
651
  function normalizeGeminiBuckets(buckets) {
627
652
  const windows = []
628
653
  if (!Array.isArray(buckets)) return windows
@@ -643,18 +668,56 @@ function normalizeGeminiBuckets(buckets) {
643
668
  return windows.sort((a, b) => b.percent - a.percent)
644
669
  }
645
670
 
671
+ function normalizeAntigravityQuotaSummary(groups) {
672
+ const windows = []
673
+ if (!Array.isArray(groups)) return windows
674
+ for (const group of groups) {
675
+ if (group === null || typeof group !== 'object' || !Array.isArray(group.buckets)) continue
676
+ const isGemini = String(group.displayName ?? '').toLowerCase().includes('gemini')
677
+ for (const bucket of group.buckets) {
678
+ if (bucket === null || typeof bucket !== 'object') continue
679
+ const windowType = String(bucket.window ?? bucket.bucketId ?? '').toLowerCase()
680
+ const is5h = windowType.includes('5h')
681
+ const code = isGemini
682
+ ? (is5h ? 'gemini-5h' : 'gemini-week')
683
+ : (is5h ? 'claude-5h' : 'claude-week')
684
+ const remaining = Number(bucket.remainingFraction)
685
+ if (!Number.isFinite(remaining)) continue
686
+ const fraction = Math.max(0, Math.min(1, remaining))
687
+ const resetsAt = normalizeResetTimestamp(bucket.resetTime)
688
+ windows.push({
689
+ id: code,
690
+ kindKey: code,
691
+ percent: Math.round((1 - fraction) * 100),
692
+ ...(resetsAt !== undefined ? { resetsAt } : {}),
693
+ })
694
+ }
695
+ }
696
+ return windows.sort((a, b) => {
697
+ const rankA = ANTIGRAVITY_WINDOW_ORDER.get(a.id) ?? 99
698
+ const rankB = ANTIGRAVITY_WINDOW_ORDER.get(b.id) ?? 99
699
+ return rankA - rankB
700
+ })
701
+ }
702
+
646
703
  function normalizeAntigravityModels(models) {
647
704
  const windows = []
648
705
  if (models === null || typeof models !== 'object') return windows
649
- for (const [modelId, entry] of Object.entries(models)) {
706
+ const entries = Array.isArray(models)
707
+ ? models.map((item) => [String(item?.name ?? item?.modelId ?? item?.id ?? item?.model ?? ''), item])
708
+ : Object.entries(models)
709
+ for (const [rawModelId, entry] of entries) {
650
710
  if (entry === null || typeof entry !== 'object') continue
711
+ if (entry.isInternal === true || entry.is_internal === true) continue
712
+ const modelId = String(rawModelId || entry.name || entry.modelId || entry.id || entry.model || '').trim()
713
+ if (modelId === '') continue
651
714
  const info = entry.quotaInfo !== null && typeof entry.quotaInfo === 'object' ? entry.quotaInfo
652
- : entry.quota_info !== null && typeof entry.quota_info === 'object' ? entry.quota_info : null
653
- if (info === null) continue
654
- const remaining = Number(info.remainingFraction ?? info.remaining_fraction)
715
+ : entry.quota_info !== null && typeof entry.quota_info === 'object' ? entry.quota_info
716
+ : entry
717
+ const remaining = Number(info.remainingFraction ?? info.remaining_fraction ?? entry.remainingFraction ?? entry.remaining_fraction)
655
718
  if (!Number.isFinite(remaining)) continue
656
719
  const fraction = Math.max(0, Math.min(1, remaining))
657
- const resetsAt = normalizeResetTimestamp(info.resetTime ?? info.reset_time)
720
+ const resetsAt = normalizeResetTimestamp(info.resetTime ?? info.reset_time ?? entry.resetTime ?? entry.reset_time)
658
721
  windows.push({
659
722
  id: String(modelId).toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'model',
660
723
  kindKey: modelId,
@@ -717,6 +780,8 @@ function buildCliproxyAccountPlan(entry) {
717
780
  function parseCliproxyUpstream(provider, payload) {
718
781
  if (provider === 'codex') return normalizeCodexRateLimit(payload?.rate_limit)
719
782
  if (provider === 'antigravity') {
783
+ if (Array.isArray(payload?.groups)) return normalizeAntigravityQuotaSummary(payload.groups)
784
+ if (Array.isArray(payload?.buckets)) return normalizeGeminiBuckets(payload.buckets)
720
785
  const models = payload?.models
721
786
  return models !== null && typeof models === 'object' ? normalizeAntigravityModels(models) : []
722
787
  }
@@ -747,7 +812,8 @@ async function fetchCliproxyUsage({ profile, config, credential, signal, request
747
812
  : typeof entry.name === 'string' && entry.name.trim() !== '' ? entry.name.trim() : ''
748
813
  const slugSource = `${label !== '' ? label : plan.provider}-${accounts.length}`
749
814
  const slug = slugSource.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 48) || `acct-${accounts.length}`
750
- accounts.push({ authIndex: entry.auth_index, provider: plan.provider, label, slug, calls: plan.calls })
815
+ const fallbackWindows = plan.provider === 'codex' ? parseCodexSignals(entry.quota) : []
816
+ accounts.push({ authIndex: entry.auth_index, provider: plan.provider, label, slug, calls: plan.calls, fallbackWindows })
751
817
  if (accounts.length >= MAX_QUOTA_CPA_ACCOUNTS) break
752
818
  }
753
819
  if (accounts.length === 0) return []
@@ -769,6 +835,9 @@ async function fetchCliproxyUsage({ profile, config, credential, signal, request
769
835
  })
770
836
  } catch (error) {
771
837
  failures.push({ index: accountIndex, code: quotaErrorCode(error) })
838
+ if (account.fallbackWindows?.length > 0) {
839
+ accountResults.set(accountIndex, account.fallbackWindows)
840
+ }
772
841
  return
773
842
  }
774
843
  const { statusCode, payload } = unwrapCliproxyApiCallEnvelope(envelope)
@@ -778,9 +847,18 @@ async function fetchCliproxyUsage({ profile, config, credential, signal, request
778
847
  return
779
848
  }
780
849
  failures.push({ index: accountIndex, code: statusCode === 200 ? 'bad-payload:shape' : `upstream-status:${statusCode}` })
781
- if (account.provider !== 'antigravity') return
850
+ if (account.provider !== 'antigravity') {
851
+ if (account.fallbackWindows?.length > 0) {
852
+ accountResults.set(accountIndex, account.fallbackWindows)
853
+ }
854
+ return
855
+ }
856
+ }
857
+ if (account.fallbackWindows?.length > 0) {
858
+ accountResults.set(accountIndex, account.fallbackWindows)
859
+ } else {
860
+ accountResults.set(accountIndex, [])
782
861
  }
783
- accountResults.set(accountIndex, [])
784
862
  }
785
863
  const queue = accounts.map((account, index) => ({ account, index }))
786
864
  await Promise.all(Array.from({ length: Math.min(QUOTA_CPA_CONCURRENCY, queue.length) }, async () => {
@@ -946,6 +1024,7 @@ export {
946
1024
  fetchXiaomiTokenPlanUsage,
947
1025
  findQuotaAdapter,
948
1026
  normalizeAntigravityModels,
1027
+ normalizeAntigravityQuotaSummary,
949
1028
  normalizeCodexRateLimit,
950
1029
  normalizeDeepseekBalance,
951
1030
  normalizeGeminiBuckets,