@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/README.en.md +1 -1
- package/README.md +1 -1
- package/client.js +1 -1
- package/index.js +9 -1
- package/package.json +1 -1
- package/quota-adapters.js +89 -10
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 =
|
|
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
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 =
|
|
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
|
-
|
|
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
|
|
653
|
-
|
|
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
|
-
|
|
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')
|
|
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,
|