@goodandready/dsh-subscriptions 0.6.87 → 0.6.88
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 +4 -0
- package/lib/client.js +57 -145
- package/lib/config-schema.js +8 -0
- package/lib/http.js +16 -1
- package/lib/vendor-factory.js +3 -3
- package/lib/vendors/codex.js +5 -5
- package/lib/vendors/cody.js +1 -4
- package/lib/vendors/copilot.js +4 -0
- package/lib/vendors/ernie.js +0 -1
- package/lib/vendors/perplexity.js +3 -2
- package/lib/vendors/replit.js +1 -4
- package/package.json +1 -1
package/lib/accounts.js
CHANGED
|
@@ -380,6 +380,10 @@ export function createAccountStore({ credentials, getConfig, fetchImpl, fetchFor
|
|
|
380
380
|
pacePerHour: info.pacePerHour || 0,
|
|
381
381
|
maxConcurrency: slot.maxConcurrency !== undefined ? slot.maxConcurrency : (curConfig.accountMaxConcurrency || 1),
|
|
382
382
|
maxQueueSize: slot.maxQueueSize > 0 ? Number(slot.maxQueueSize) : (curConfig.maxQueueSize || 20),
|
|
383
|
+
vipOnly: !!slot.vipOnly,
|
|
384
|
+
tags: Array.isArray(slot.tags) ? slot.tags : [],
|
|
385
|
+
weight: Number(slot.weight) || 0,
|
|
386
|
+
isPro: !!slot.isPro,
|
|
383
387
|
})
|
|
384
388
|
}
|
|
385
389
|
return out
|
package/lib/client.js
CHANGED
|
@@ -83,18 +83,13 @@ window.__ModuleLoader__.load({
|
|
|
83
83
|
"syncModels": "Sync Models",
|
|
84
84
|
"syncModelsTitle": "Discover and synchronize available models from vendor API",
|
|
85
85
|
"modelsSynced": "Models synchronized",
|
|
86
|
-
"doctorDiagnosis": "Doctor Verdict",
|
|
87
86
|
"recommendation": "Recommendation",
|
|
88
|
-
"pingTitle": "Measure network latency to provider API",
|
|
89
87
|
"notConnected": "Not connected",
|
|
90
88
|
"verifyAccount": "Verify account",
|
|
91
89
|
"coolingDown": "Cooling down",
|
|
92
90
|
"usageFull": "Usage 100%",
|
|
93
91
|
"connected": "Connected",
|
|
94
92
|
"title": "Subscriptions",
|
|
95
|
-
"cardIntro": "Subscription accounts, rotation and limits.",
|
|
96
|
-
"show": "Show",
|
|
97
|
-
"hide": "Hide",
|
|
98
93
|
"intro": "Log in with a consumer subscription. Tokens stay on the host credentials store. The browser never reads them back. After Connect, if the provider lands on localhost or a vendor page, paste the redirected URL or the code here.",
|
|
99
94
|
"useOrigin": "Use this Web UI origin as OAuth redirect_uri",
|
|
100
95
|
"useOriginHint": "Leave off unless you registered your own OAuth client for this origin. Vendor CLI clients usually require their published redirect URI plus the paste step.",
|
|
@@ -135,8 +130,6 @@ window.__ModuleLoader__.load({
|
|
|
135
130
|
"copilotCliPathHint": "Optional path to copilot or github-copilot-cli binary.",
|
|
136
131
|
"ollamaFallback": "Ollama local fallback",
|
|
137
132
|
"ollamaFallbackHint": "Automatically route queries to a local Ollama instance when cloud quota is exhausted.",
|
|
138
|
-
"ollamaBaseUrl": "Ollama Base URL",
|
|
139
|
-
"ollamaFallbackModel": "Ollama Fallback Model",
|
|
140
133
|
"advancedSettings": "Advanced Settings & Monitoring",
|
|
141
134
|
"cooldownMs": "Failure cooldown (minutes)",
|
|
142
135
|
"cooldownMsHint": "How long to pause a failing or rate-limited account before retrying.",
|
|
@@ -146,12 +139,10 @@ window.__ModuleLoader__.load({
|
|
|
146
139
|
"notifyLimitsHint": "Show notification alerts when account usage reaches quota ceiling.",
|
|
147
140
|
"hostOnline": "Host online",
|
|
148
141
|
"hostOffline": "Host unreachable",
|
|
149
|
-
"statsTitle": "Session Telemetry",
|
|
150
142
|
"statsRequests": "Successful / Total Requests",
|
|
151
143
|
"statsLatency": "Avg Response Latency",
|
|
152
144
|
"statsSuccessRate": "Session Success Rate",
|
|
153
145
|
"statsLastActivity": "Last Activity",
|
|
154
|
-
"smokeTitle": "Connection Smoke Test (Ping)",
|
|
155
146
|
"smokeDesc": "Test live upstream connectivity and measure round-trip latency to the subscription provider.",
|
|
156
147
|
"runSmoke": "⚡ Run Smoke Test (Ping)",
|
|
157
148
|
"smokeTesting": "Pinging…",
|
|
@@ -189,10 +180,7 @@ window.__ModuleLoader__.load({
|
|
|
189
180
|
"capabilitiesHint": "Subscription capabilities, context window and model features",
|
|
190
181
|
"orPasteVaultPayload": "or paste vault payload below",
|
|
191
182
|
"workspaceTitle": "Organization / Workspace",
|
|
192
|
-
"workspaceSelect": "Select active organization/workspace",
|
|
193
|
-
"personalWorkspace": "Personal Default",
|
|
194
183
|
"windowResetsAt": "Window resets at",
|
|
195
|
-
"quotaRecovery": "Quota recovery",
|
|
196
184
|
"toastCooldownRecovered": "is now available (cooldown expired)",
|
|
197
185
|
"modelsCatalogTitle": "Curated Subscription Models",
|
|
198
186
|
"modelsCatalogDesc": "Available model catalog across active subscriptions in DeepSeek Harness.",
|
|
@@ -211,7 +199,6 @@ window.__ModuleLoader__.load({
|
|
|
211
199
|
"resetCreditsHint": "ChatGPT reset cards: emergency reset for the 5-hour window. Requires a 5s confirmation.",
|
|
212
200
|
"resetCreditsAction": "Reset ChatGPT Limit",
|
|
213
201
|
"usageLimitsTitle": "Usage Limits",
|
|
214
|
-
"slotDetailsTitle": "Slot Details",
|
|
215
202
|
"resetAvailable": "Reset attempts available",
|
|
216
203
|
"resetExpires": "earliest expires",
|
|
217
204
|
"resetAck": "I understand one attempt will be consumed",
|
|
@@ -232,23 +219,17 @@ window.__ModuleLoader__.load({
|
|
|
232
219
|
"tokensSaved": "Saved Tokens",
|
|
233
220
|
"subsPill": "SUBS",
|
|
234
221
|
"subsModalTitle": "Subscription Hub",
|
|
235
|
-
"subsActiveHero": "Active Subscription",
|
|
236
222
|
"subsPoolTitle": "Provider Accounts",
|
|
237
223
|
"subsRefresh": "Refresh",
|
|
238
224
|
"subsOpenSettings": "All Settings →",
|
|
239
|
-
"subsFastMode": "Fast Mode 1.5x",
|
|
240
|
-
"subsHealthy": "Healthy",
|
|
241
225
|
"subsFree": "free",
|
|
242
226
|
"subsUsed": "used",
|
|
243
|
-
"subsModalClose": "Close",
|
|
244
227
|
"subsLogged": "connected",
|
|
245
228
|
"subsNotLogged": "not connected",
|
|
246
229
|
"subsCooldown": "cooldown",
|
|
247
|
-
"hudTitle": "Subscription balance",
|
|
248
230
|
"settingsLoading": "Loading settings…",
|
|
249
231
|
"settingsUnavailable": "Settings are unavailable",
|
|
250
232
|
"settingsRetry": "Retry",
|
|
251
|
-
"hudHint": "drag · edge docks · click refresh",
|
|
252
233
|
"fcCalibrating": "calibrating…",
|
|
253
234
|
"fcIdle": "no usage",
|
|
254
235
|
"fcHours": "h",
|
|
@@ -276,23 +257,14 @@ window.__ModuleLoader__.load({
|
|
|
276
257
|
"addAccount": "+ Add account",
|
|
277
258
|
"save": "Save",
|
|
278
259
|
"saved": "Saved",
|
|
279
|
-
"loading": "Loading…",
|
|
280
|
-
"unavailable": "Settings are unavailable",
|
|
281
260
|
"accountLabel": "Account",
|
|
282
261
|
"plan": "Plan",
|
|
283
262
|
"storedAs": "Stored as",
|
|
284
|
-
"switchLabel": "Provider",
|
|
285
|
-
"chipActive": "Subscriptions",
|
|
286
|
-
"expiryLabel": "expires",
|
|
287
263
|
"slashLogin": "Login to a subscription provider",
|
|
288
264
|
"slashLogout": "Log out a subscription provider",
|
|
289
|
-
"slashStatus": "Subscription status",
|
|
290
|
-
"none": "none",
|
|
291
265
|
"forecast": "≈",
|
|
292
266
|
"windowPrimary": "Primary window",
|
|
293
267
|
"windowSecondary": "Secondary window",
|
|
294
|
-
"resetLabel": "reset",
|
|
295
|
-
"check": "Check",
|
|
296
268
|
"checking": "Checking…",
|
|
297
269
|
"importToken": "Save token",
|
|
298
270
|
"importTokenPlace": "Paste token or API key",
|
|
@@ -302,7 +274,12 @@ window.__ModuleLoader__.load({
|
|
|
302
274
|
"howToGetToken": "❓ Instructions",
|
|
303
275
|
"howToGetTokenTitle": "How to get token / API key for this provider",
|
|
304
276
|
"instructionsTitle": "How to obtain token",
|
|
305
|
-
"
|
|
277
|
+
"lang": "en",
|
|
278
|
+
"cardIntro": "Subscription accounts, rotation and limits.",
|
|
279
|
+
"loading": "Loading…",
|
|
280
|
+
"unavailable": "Settings are unavailable",
|
|
281
|
+
"error": "Error",
|
|
282
|
+
"settingsError": "Settings error",
|
|
306
283
|
"cancel": "Cancel",
|
|
307
284
|
"quota": "Quota",
|
|
308
285
|
"subs5hWindow": "5h window",
|
|
@@ -313,8 +290,6 @@ window.__ModuleLoader__.load({
|
|
|
313
290
|
"sessionRevokedBadge": "Revoked / Expired",
|
|
314
291
|
"sessionRevokedWarning": "Session expired / revoked — re-authorization required",
|
|
315
292
|
"manualTitle": "If the browser did not come back",
|
|
316
|
-
"updateChecking": "Checking updates…",
|
|
317
|
-
"updateUpToDate": "Up to date",
|
|
318
293
|
"updateAvailable": "Update available",
|
|
319
294
|
"updateNow": "Update",
|
|
320
295
|
"updating": "Updating…",
|
|
@@ -339,7 +314,6 @@ window.__ModuleLoader__.load({
|
|
|
339
314
|
"backupImportAction": "Import",
|
|
340
315
|
"backupPassphrase": "Vault Passphrase (min 12 chars)",
|
|
341
316
|
"backupExportHint": "Encrypt connected subscription accounts and slots with AES-256-GCM. ⚠️ Contains sensitive OAuth refresh tokens; use a strong password (min 12 chars).",
|
|
342
|
-
"vaultTokenWarning": "⚠️ Contains sensitive OAuth refresh tokens",
|
|
343
317
|
"backupImportHint": "Restore encrypted subscription accounts and credentials from a vault payload.",
|
|
344
318
|
"backupPayloadPlaceholder": "Paste DSHE... encrypted string here",
|
|
345
319
|
"backupExportOk": "Backup exported successfully",
|
|
@@ -354,10 +328,7 @@ window.__ModuleLoader__.load({
|
|
|
354
328
|
"resetsIn": "Resets in",
|
|
355
329
|
"toastQuarantined": "Account placed in quarantine",
|
|
356
330
|
"toastReleased": "Account active and healthy",
|
|
357
|
-
"toastQuotaWarning": "Quota threshold exceeded",
|
|
358
|
-
"enableToasts": "In-app toast alerts",
|
|
359
331
|
"headlessTip": "Headless / Remote Server?",
|
|
360
|
-
"headlessSshCommand": "SSH Port Forward Command:",
|
|
361
332
|
"headlessCopySsh": "Copy SSH Command",
|
|
362
333
|
"headlessCopied": "Copied!",
|
|
363
334
|
"headlessScanQr": "Scan with Mobile to Authenticate:",
|
|
@@ -395,23 +366,14 @@ window.__ModuleLoader__.load({
|
|
|
395
366
|
"wizardAll": "Account Wizard",
|
|
396
367
|
"wizardIncludeNetwork": "Include active network checks (proxy ping & model catalog discovery)",
|
|
397
368
|
"wizardRunning": "Running diagnostic checklist...",
|
|
398
|
-
"wizardStepCreds": "Credentials & Expiry",
|
|
399
|
-
"wizardStepProxy": "Proxy & Gateway",
|
|
400
|
-
"wizardStepToken": "Token Validation",
|
|
401
|
-
"wizardStepCatalog": "Model Catalog Reachability",
|
|
402
369
|
"wizardHealthy": "Healthy",
|
|
403
370
|
"wizardDegraded": "Degraded / Warnings",
|
|
404
371
|
"wizardFailing": "Issues Detected",
|
|
405
372
|
"wizardRecommendations": "Recommendations & Next Steps",
|
|
406
373
|
"wizardCopy": "Copy Masked Diagnostic Report",
|
|
407
374
|
"cachePinnedBadge": "Cache Pinned",
|
|
408
|
-
"field.enableToasts": "Show popup toast notifications on quarantine or quota events",
|
|
409
375
|
"reasoningEffortTitle": "Reasoning Effort Control",
|
|
410
376
|
"reasoningEffortDesc": "Configure reasoning depth for models with extended thinking capabilities.",
|
|
411
|
-
"reasoningLevelLow": "Low",
|
|
412
|
-
"reasoningLevelMed": "Medium",
|
|
413
|
-
"reasoningLevelHigh": "High",
|
|
414
|
-
"reasoningLevelMax": "Max",
|
|
415
377
|
"reasoningLevelOff": "Off"
|
|
416
378
|
};
|
|
417
379
|
|
|
@@ -419,18 +381,13 @@ window.__ModuleLoader__.load({
|
|
|
419
381
|
"syncModels": "同步模型",
|
|
420
382
|
"syncModelsTitle": "从服务商 API 实时发现并同步可用模型列表",
|
|
421
383
|
"modelsSynced": "模型已同步",
|
|
422
|
-
"doctorDiagnosis": "诊断结论",
|
|
423
384
|
"recommendation": "修复建议",
|
|
424
|
-
"pingTitle": "测试到服务商 API 的网络往返延迟",
|
|
425
385
|
"notConnected": "未连接",
|
|
426
386
|
"verifyAccount": "需要验证账户",
|
|
427
387
|
"coolingDown": "冷却等待中",
|
|
428
388
|
"usageFull": "用量已达 100%",
|
|
429
389
|
"connected": "已连接",
|
|
430
390
|
"title": "个人订阅管理",
|
|
431
|
-
"cardIntro": "AI 服务订阅账户、自动轮换与速率限制管理。",
|
|
432
|
-
"show": "展开",
|
|
433
|
-
"hide": "收起",
|
|
434
391
|
"intro": "通过个人订阅登录。凭据安全保存在服务器端凭据库中,浏览器不回读敏感令牌。点击“连接”后,若页面跳转至 localhost 或服务商页面,请将重定向网址或授权代码粘贴到下方。",
|
|
435
392
|
"useOrigin": "将当前 Web UI 地址作为 OAuth 重定向地址 (redirect_uri)",
|
|
436
393
|
"useOriginHint": "除非您为当前域名申请了专属 OAuth 客户端,否则请保持关闭。官方 CLI 客户端通常需使用其公开重定向地址并配合粘贴代码流程。",
|
|
@@ -471,8 +428,6 @@ window.__ModuleLoader__.load({
|
|
|
471
428
|
"copilotCliPathHint": "可选的 copilot 或 github-copilot-cli 二进制文件路径。",
|
|
472
429
|
"ollamaFallback": "Ollama 本地模型自动兜底",
|
|
473
430
|
"ollamaFallbackHint": "当云端配额耗尽或服务商故障时,自动将请求转发给本地 Ollama 实例。",
|
|
474
|
-
"ollamaBaseUrl": "Ollama 服务基础 URL",
|
|
475
|
-
"ollamaFallbackModel": "Ollama 兜底模型名称",
|
|
476
431
|
"advancedSettings": "高级配置与监控",
|
|
477
432
|
"cooldownMs": "故障与限流冷却时间(分钟)",
|
|
478
433
|
"cooldownMsHint": "当账户遇到 429 或故障时暂停该账户的分钟数。",
|
|
@@ -482,12 +437,10 @@ window.__ModuleLoader__.load({
|
|
|
482
437
|
"notifyLimitsHint": "当账户使用量达到上限时触发系统通知提醒。",
|
|
483
438
|
"hostOnline": "主机在线",
|
|
484
439
|
"hostOffline": "主机无法连接",
|
|
485
|
-
"statsTitle": "会话遥测统计",
|
|
486
440
|
"statsRequests": "成功 / 总请求数",
|
|
487
441
|
"statsLatency": "平均响应延迟",
|
|
488
442
|
"statsSuccessRate": "会话成功率",
|
|
489
443
|
"statsLastActivity": "最近活跃时间",
|
|
490
|
-
"smokeTitle": "链路连通性冒烟测试 (Ping)",
|
|
491
444
|
"smokeDesc": "向当前订阅服务商发起实时探活并测量双向网络往返延迟 (RTT)。",
|
|
492
445
|
"runSmoke": "⚡ 执行冒烟探活 (Ping)",
|
|
493
446
|
"smokeTesting": "正在探活…",
|
|
@@ -525,10 +478,7 @@ window.__ModuleLoader__.load({
|
|
|
525
478
|
"capabilitiesHint": "订阅账号模型上下文窗口与特权特性",
|
|
526
479
|
"orPasteVaultPayload": "或在下方粘贴保险库文本",
|
|
527
480
|
"workspaceTitle": "工作区与组织",
|
|
528
|
-
"workspaceSelect": "选择生效的工作区或组织",
|
|
529
|
-
"personalWorkspace": "个人默认",
|
|
530
481
|
"windowResetsAt": "额度重置于",
|
|
531
|
-
"quotaRecovery": "额度恢复",
|
|
532
482
|
"toastCooldownRecovered": "已解除冷却恢复可用",
|
|
533
483
|
"modelsCatalogTitle": "精选订阅模型",
|
|
534
484
|
"modelsCatalogDesc": "当前 DeepSeek Harness 活跃订阅下可用模型一览。",
|
|
@@ -547,7 +497,6 @@ window.__ModuleLoader__.load({
|
|
|
547
497
|
"resetCreditsHint": "ChatGPT 重置卡:紧急重置 5 小时额度窗口。扣除前需等待 5 秒倒计时确认。",
|
|
548
498
|
"resetCreditsAction": "重置 ChatGPT 限制",
|
|
549
499
|
"usageLimitsTitle": "用量限制",
|
|
550
|
-
"slotDetailsTitle": "槽位详情",
|
|
551
500
|
"resetAvailable": "可用重置次数",
|
|
552
501
|
"resetExpires": "最早到期时间",
|
|
553
502
|
"resetAck": "我确认将消耗一次重置机会",
|
|
@@ -568,23 +517,17 @@ window.__ModuleLoader__.load({
|
|
|
568
517
|
"tokensSaved": "已节省 Token",
|
|
569
518
|
"subsPill": "订阅",
|
|
570
519
|
"subsModalTitle": "订阅管理中心",
|
|
571
|
-
"subsActiveHero": "当前主用订阅",
|
|
572
520
|
"subsPoolTitle": "服务商账户池",
|
|
573
521
|
"subsRefresh": "刷新",
|
|
574
522
|
"subsOpenSettings": "全部设置 →",
|
|
575
|
-
"subsFastMode": "加速模式 1.5x",
|
|
576
|
-
"subsHealthy": "健康运行中",
|
|
577
523
|
"subsFree": "空闲可用",
|
|
578
524
|
"subsUsed": "已用",
|
|
579
|
-
"subsModalClose": "关闭",
|
|
580
525
|
"subsLogged": "已连接",
|
|
581
526
|
"subsNotLogged": "未连接",
|
|
582
527
|
"subsCooldown": "冷却中",
|
|
583
|
-
"hudTitle": "订阅额度余量",
|
|
584
528
|
"settingsLoading": "正在加载设置…",
|
|
585
529
|
"settingsUnavailable": "设置加载失败",
|
|
586
530
|
"settingsRetry": "重试",
|
|
587
|
-
"hudHint": "可拖拽 · 边缘停靠 · 点击刷新",
|
|
588
531
|
"fcCalibrating": "校准中…",
|
|
589
532
|
"fcIdle": "暂无消耗",
|
|
590
533
|
"fcHours": "小时",
|
|
@@ -612,23 +555,14 @@ window.__ModuleLoader__.load({
|
|
|
612
555
|
"addAccount": "+ 添加账户",
|
|
613
556
|
"save": "保存",
|
|
614
557
|
"saved": "已保存",
|
|
615
|
-
"loading": "加载中…",
|
|
616
|
-
"unavailable": "设置不可用",
|
|
617
558
|
"accountLabel": "账户",
|
|
618
559
|
"plan": "套餐方案",
|
|
619
560
|
"storedAs": "存储标识",
|
|
620
|
-
"switchLabel": "切换服务商",
|
|
621
|
-
"chipActive": "已启用订阅",
|
|
622
|
-
"expiryLabel": "到期时间",
|
|
623
561
|
"slashLogin": "登录订阅服务商",
|
|
624
562
|
"slashLogout": "登出订阅服务商",
|
|
625
|
-
"slashStatus": "查看订阅状态",
|
|
626
|
-
"none": "无",
|
|
627
563
|
"forecast": "≈",
|
|
628
564
|
"windowPrimary": "主配额窗口",
|
|
629
565
|
"windowSecondary": "次配额窗口",
|
|
630
|
-
"resetLabel": "重置倒计时",
|
|
631
|
-
"check": "检测",
|
|
632
566
|
"checking": "检测中…",
|
|
633
567
|
"importToken": "保存令牌",
|
|
634
568
|
"importTokenPlace": "粘贴令牌或 API Key",
|
|
@@ -638,7 +572,12 @@ window.__ModuleLoader__.load({
|
|
|
638
572
|
"howToGetToken": "❓ 获取指引",
|
|
639
573
|
"howToGetTokenTitle": "如何获取此服务商的令牌或 API 密钥",
|
|
640
574
|
"instructionsTitle": "获取令牌指引",
|
|
641
|
-
"
|
|
575
|
+
"lang": "zh",
|
|
576
|
+
"cardIntro": "AI 服务订阅账户、自动轮换与速率限制管理。",
|
|
577
|
+
"loading": "加载中…",
|
|
578
|
+
"unavailable": "设置不可用",
|
|
579
|
+
"error": "错误",
|
|
580
|
+
"settingsError": "设置错误",
|
|
642
581
|
"cancel": "取消",
|
|
643
582
|
"quota": "配额",
|
|
644
583
|
"subs5hWindow": "5小时窗口",
|
|
@@ -649,8 +588,6 @@ window.__ModuleLoader__.load({
|
|
|
649
588
|
"sessionRevokedBadge": "已失效 / 过期",
|
|
650
589
|
"sessionRevokedWarning": "会话已过期或失效 — 需要重新授权",
|
|
651
590
|
"manualTitle": "若浏览器未能自动跳转回调",
|
|
652
|
-
"updateChecking": "检查更新中…",
|
|
653
|
-
"updateUpToDate": "已是最新版本",
|
|
654
591
|
"updateAvailable": "有新版本可用",
|
|
655
592
|
"updateNow": "立即更新",
|
|
656
593
|
"updating": "正在更新…",
|
|
@@ -675,7 +612,6 @@ window.__ModuleLoader__.load({
|
|
|
675
612
|
"backupImportAction": "导入",
|
|
676
613
|
"backupPassphrase": "凭据库密码(至少 12 位)",
|
|
677
614
|
"backupExportHint": "使用 AES-256-GCM 安全加密导出所有订阅账户与配置。⚠️ 包含敏感的 OAuth 刷新令牌,请使用至少 12 位的强密码保护。",
|
|
678
|
-
"vaultTokenWarning": "⚠️ 包含敏感的 OAuth 刷新令牌",
|
|
679
615
|
"backupImportHint": "从已加密的备份内容中导入并恢复订阅账户与凭据。",
|
|
680
616
|
"backupPayloadPlaceholder": "在此粘贴 DSHE... 加密内容",
|
|
681
617
|
"backupExportOk": "备份导出成功",
|
|
@@ -690,7 +626,6 @@ window.__ModuleLoader__.load({
|
|
|
690
626
|
"resetsIn": "重置倒计时",
|
|
691
627
|
"toastQuarantined": "账户进入隔离期",
|
|
692
628
|
"headlessTip": "无头环境 / 远程服务器?",
|
|
693
|
-
"headlessSshCommand": "SSH 端口转发命令:",
|
|
694
629
|
"headlessCopySsh": "复制 SSH 命令",
|
|
695
630
|
"headlessCopied": "已复制!",
|
|
696
631
|
"headlessScanQr": "使用手机扫描以登录:",
|
|
@@ -703,8 +638,6 @@ window.__ModuleLoader__.load({
|
|
|
703
638
|
"vaultSyncLastPush": "上次推送:",
|
|
704
639
|
"vaultSyncLastPull": "上次拉取:",
|
|
705
640
|
"toastReleased": "账户已解除隔离恢复使用",
|
|
706
|
-
"toastQuotaWarning": "额度预警",
|
|
707
|
-
"enableToasts": "应用内弹窗提醒",
|
|
708
641
|
"groupQueue": "并发限制与请求队列",
|
|
709
642
|
"enableQueue": "启用并发请求排队",
|
|
710
643
|
"enableQueueHint": "当账户达到并发上限时将多余请求排队等待,避免直接触发 429 报错",
|
|
@@ -731,23 +664,14 @@ window.__ModuleLoader__.load({
|
|
|
731
664
|
"wizardAll": "诊断向导",
|
|
732
665
|
"wizardIncludeNetwork": "包含活跃网络探测(代理连通性与模型目录探测)",
|
|
733
666
|
"wizardRunning": "正在执行诊断检查清单...",
|
|
734
|
-
"wizardStepCreds": "凭据完整性与有效期",
|
|
735
|
-
"wizardStepProxy": "网络代理与网关",
|
|
736
|
-
"wizardStepToken": "令牌有效性验证",
|
|
737
|
-
"wizardStepCatalog": "模型目录可达性",
|
|
738
667
|
"wizardHealthy": "健康正常",
|
|
739
668
|
"wizardDegraded": "降级预警",
|
|
740
669
|
"wizardFailing": "发现故障",
|
|
741
670
|
"wizardRecommendations": "排查建议与修复步骤",
|
|
742
671
|
"wizardCopy": "复制脱敏诊断报告",
|
|
743
672
|
"cachePinnedBadge": "缓存粘性",
|
|
744
|
-
"field.enableToasts": "当账户发生隔离或额度达到警戒线时显示即时弹窗提醒",
|
|
745
673
|
"reasoningEffortTitle": "推理强度控制",
|
|
746
674
|
"reasoningEffortDesc": "为具备扩展思考能力的模型配置推理深度与思考预算。",
|
|
747
|
-
"reasoningLevelLow": "低",
|
|
748
|
-
"reasoningLevelMed": "中",
|
|
749
|
-
"reasoningLevelHigh": "高",
|
|
750
|
-
"reasoningLevelMax": "最高",
|
|
751
675
|
"reasoningLevelOff": "关闭"
|
|
752
676
|
};
|
|
753
677
|
// #51: live countdown to the quota window reset (account.quota.resetAt).
|
|
@@ -1009,7 +933,7 @@ window.__ModuleLoader__.load({
|
|
|
1009
933
|
fetch('/dsh-subscriptions/vault/sync/status')
|
|
1010
934
|
.then((r) => r.json())
|
|
1011
935
|
.then((d) => { if (d && d.ok) setVaultSyncInfo(d.status) })
|
|
1012
|
-
.catch(() =>
|
|
936
|
+
.catch((e) => setBackupErr(cleanErrorMessage(e && e.message ? e.message : e)))
|
|
1013
937
|
}
|
|
1014
938
|
|
|
1015
939
|
const doVaultSyncPush = async () => {
|
|
@@ -2622,7 +2546,7 @@ window.__ModuleLoader__.load({
|
|
|
2622
2546
|
stepsEn: ['Paste your token or API key into the field above and click "Save token".'],
|
|
2623
2547
|
};
|
|
2624
2548
|
// Determine language safely from current locale (fallback to zh if Chinese or en)
|
|
2625
|
-
const isZh = t('
|
|
2549
|
+
const isZh = t('lang') === 'zh';
|
|
2626
2550
|
const steps = (isZh && info.stepsZh) ? info.stepsZh : (info.stepsEn || []);
|
|
2627
2551
|
return h('div', { className: 'dsub-helpBox' },
|
|
2628
2552
|
h('div', { className: 'dsub-helpHead' },
|
|
@@ -2888,7 +2812,7 @@ window.__ModuleLoader__.load({
|
|
|
2888
2812
|
var agoStr = null
|
|
2889
2813
|
if (at) {
|
|
2890
2814
|
var m = Math.round((Date.now() - at) / 60000)
|
|
2891
|
-
if (m >= 1) agoStr = m + 'm ' + (t('
|
|
2815
|
+
if (m >= 1) agoStr = m + 'm ' + (t('lang') === 'zh' ? '前' : 'ago')
|
|
2892
2816
|
}
|
|
2893
2817
|
|
|
2894
2818
|
return h('div', { className: 'dsub-panel-box' },
|
|
@@ -3164,47 +3088,9 @@ window.__ModuleLoader__.load({
|
|
|
3164
3088
|
expiryNotifyDays: (data && data.expiryNotifyDays) || 7,
|
|
3165
3089
|
composerQuota: (data && data.composerQuota) || 'off',
|
|
3166
3090
|
active: (data && data.active) || null,
|
|
3091
|
+
error: null,
|
|
3167
3092
|
}
|
|
3168
|
-
} catch { return { logged: [], usage: 0, expiresAt: {}, labels: {}, expiryNotifyDays: 7, fastMode: false, composerQuota: 'off', active: null } }
|
|
3169
|
-
}
|
|
3170
|
-
|
|
3171
|
-
// #84: compact quota indicator of the active subscription in the input area.
|
|
3172
|
-
// The runway forecast uses a rolling window of /status samples.
|
|
3173
|
-
const fcSamples = { windows: {} }
|
|
3174
|
-
|
|
3175
|
-
function fcObserve(key, remaining, now) {
|
|
3176
|
-
const windows = fcSamples.windows
|
|
3177
|
-
const prev = windows[key]
|
|
3178
|
-
const samples = (prev && prev.samples) || []
|
|
3179
|
-
const last = samples[samples.length - 1]
|
|
3180
|
-
if (!last || (now > last.at && (Math.abs(remaining - last.pct) >= 0.1 || now - last.at >= 15 * 60 * 1000))) {
|
|
3181
|
-
samples.push({ at: now, pct: remaining })
|
|
3182
|
-
}
|
|
3183
|
-
windows[key] = { samples: samples.filter((x) => x.at >= now - 24 * 60 * 60 * 1000).slice(-192) }
|
|
3184
|
-
}
|
|
3185
|
-
|
|
3186
|
-
function fcEstimate(key, remaining) {
|
|
3187
|
-
const rec = fcSamples.windows[key]
|
|
3188
|
-
if (!rec) return { status: 'calibrating' }
|
|
3189
|
-
const samples = rec.samples
|
|
3190
|
-
if (samples.length < 3) return { status: 'calibrating' }
|
|
3191
|
-
const first = samples[0]
|
|
3192
|
-
const last = samples[samples.length - 1]
|
|
3193
|
-
const span = last.at - first.at
|
|
3194
|
-
const consumed = first.pct - last.pct
|
|
3195
|
-
if (span < 30 * 60 * 1000 || consumed < 1) return { status: 'calibrating' }
|
|
3196
|
-
const t0 = first.at
|
|
3197
|
-
let sw = 0, sx = 0, sy = 0, sxx = 0, sxy = 0
|
|
3198
|
-
for (const x of samples) {
|
|
3199
|
-
const wx = (x.at - t0) / 3600000
|
|
3200
|
-
const wy = first.pct - x.pct
|
|
3201
|
-
const w = Math.exp((x.at - last.at) / (6 * 3600000))
|
|
3202
|
-
sw += w; sx += w * wx; sy += w * wy; sxx += w * wx * wx; sxy += w * wx * wy
|
|
3203
|
-
}
|
|
3204
|
-
const den = sw * sxx - sx * sx
|
|
3205
|
-
const pace = den > 0 ? (sw * sxy - sx * sy) / den : 0
|
|
3206
|
-
if (!Number.isFinite(pace) || pace < 0.02) return { status: 'idle' }
|
|
3207
|
-
return { status: 'ready', runwaySeconds: Math.round((remaining / pace) * 3600) }
|
|
3093
|
+
} catch { return { logged: [], usage: 0, expiresAt: {}, labels: {}, expiryNotifyDays: 7, fastMode: false, composerQuota: 'off', active: null, error: 'status unavailable' } }
|
|
3208
3094
|
}
|
|
3209
3095
|
|
|
3210
3096
|
function ComposerQuota(props) {
|
|
@@ -3213,15 +3099,25 @@ window.__ModuleLoader__.load({
|
|
|
3213
3099
|
React.useEffect(() => {
|
|
3214
3100
|
let alive = true
|
|
3215
3101
|
const pull = () => {
|
|
3216
|
-
|
|
3102
|
+
Promise.all([
|
|
3103
|
+
refreshLoggedIn(),
|
|
3104
|
+
fetch('/dsh-subscriptions/analytics', { cache: 'no-store' })
|
|
3105
|
+
.then((res) => res.json())
|
|
3106
|
+
.catch(() => ({})),
|
|
3107
|
+
]).then(([r, analyticsPayload]) => {
|
|
3217
3108
|
if (!alive) return
|
|
3218
3109
|
const mode = r.composerQuota || 'off'
|
|
3219
3110
|
const a = r.active
|
|
3220
3111
|
if (mode !== 'off' && a && a.provider && a.provider !== 'ollama' && a.usagePercent != null) {
|
|
3221
3112
|
const remaining = Math.max(0, 100 - a.usagePercent)
|
|
3222
|
-
const
|
|
3223
|
-
|
|
3224
|
-
|
|
3113
|
+
const forecast = (analyticsPayload && analyticsPayload.analytics && analyticsPayload.analytics.forecast) || []
|
|
3114
|
+
const row = forecast.find((f) => f.provider === a.provider && (!f.ref || !a.ref || f.ref === a.ref))
|
|
3115
|
+
let est = { status: 'calibrating' }
|
|
3116
|
+
if (row) {
|
|
3117
|
+
est = row.hoursToExhaustion == null
|
|
3118
|
+
? { status: 'idle' }
|
|
3119
|
+
: { status: 'forecast', runwaySeconds: Math.max(0, Number(row.hoursToExhaustion) * 3600) }
|
|
3120
|
+
}
|
|
3225
3121
|
setState({ mode, active: a, remaining, est })
|
|
3226
3122
|
} else {
|
|
3227
3123
|
setState({ mode, active: a, remaining: null, est: null })
|
|
@@ -3329,9 +3225,15 @@ window.__ModuleLoader__.load({
|
|
|
3329
3225
|
return false
|
|
3330
3226
|
}
|
|
3331
3227
|
|
|
3228
|
+
let pluginSettingsGeneration = 0
|
|
3332
3229
|
function openPluginSettings(doc = document, schedule = (run, ms) => window.setTimeout(run, ms), navCtx) {
|
|
3333
3230
|
try {
|
|
3334
3231
|
if (findAndClickCard(doc)) return
|
|
3232
|
+
const generation = ++pluginSettingsGeneration
|
|
3233
|
+
const runIfCurrent = (fn, ms) => schedule(() => {
|
|
3234
|
+
if (generation !== pluginSettingsGeneration) return
|
|
3235
|
+
fn()
|
|
3236
|
+
}, ms)
|
|
3335
3237
|
|
|
3336
3238
|
const activeLabels = resolvePluginLabels(navCtx)
|
|
3337
3239
|
const checkEl = (el) => matchesPluginLabel(el, activeLabels)
|
|
@@ -3342,9 +3244,9 @@ window.__ModuleLoader__.load({
|
|
|
3342
3244
|
panel.click()
|
|
3343
3245
|
const poll = (left) => {
|
|
3344
3246
|
if (findAndClickCard(doc)) return
|
|
3345
|
-
if (left > 0)
|
|
3247
|
+
if (left > 0) runIfCurrent(() => poll(left - 1), 100)
|
|
3346
3248
|
}
|
|
3347
|
-
|
|
3249
|
+
runIfCurrent(() => poll(40), 100)
|
|
3348
3250
|
return
|
|
3349
3251
|
}
|
|
3350
3252
|
|
|
@@ -3360,15 +3262,15 @@ window.__ModuleLoader__.load({
|
|
|
3360
3262
|
section.click()
|
|
3361
3263
|
const poll = (cLeft) => {
|
|
3362
3264
|
if (findAndClickCard(doc)) return
|
|
3363
|
-
if (cLeft > 0)
|
|
3265
|
+
if (cLeft > 0) runIfCurrent(() => poll(cLeft - 1), 100)
|
|
3364
3266
|
}
|
|
3365
|
-
|
|
3267
|
+
runIfCurrent(() => poll(40), 100)
|
|
3366
3268
|
return
|
|
3367
3269
|
}
|
|
3368
3270
|
} catch { /* bestEffort */ }
|
|
3369
|
-
if (left > 0)
|
|
3271
|
+
if (left > 0) runIfCurrent(() => pollSection(left - 1), 80)
|
|
3370
3272
|
}
|
|
3371
|
-
|
|
3273
|
+
runIfCurrent(() => pollSection(20), 80)
|
|
3372
3274
|
}
|
|
3373
3275
|
}
|
|
3374
3276
|
} catch { /* bestEffort */ }
|
|
@@ -3382,6 +3284,13 @@ window.__ModuleLoader__.load({
|
|
|
3382
3284
|
const dismissToast = (id) => {
|
|
3383
3285
|
setToasts((prev) => prev.filter((t) => t.id !== id))
|
|
3384
3286
|
}
|
|
3287
|
+
const reportError = (message) => {
|
|
3288
|
+
const text = cleanErrorMessage(message)
|
|
3289
|
+
if (!text) return
|
|
3290
|
+
setToasts((prev) => prev.some((toast) => toast.message === text)
|
|
3291
|
+
? prev
|
|
3292
|
+
: [{ id: 'err_' + Date.now(), message: text, cls: 'dsub-toast-bad' }, ...prev].slice(0, 3))
|
|
3293
|
+
}
|
|
3385
3294
|
|
|
3386
3295
|
const pollAlerts = () => {
|
|
3387
3296
|
fetch('/dsh-subscriptions/alerts?limit=5', { cache: 'no-store' })
|
|
@@ -3401,22 +3310,25 @@ window.__ModuleLoader__.load({
|
|
|
3401
3310
|
}
|
|
3402
3311
|
}
|
|
3403
3312
|
})
|
|
3404
|
-
.catch(() =>
|
|
3313
|
+
.catch((e) => reportError(t('hostOffline') + ': ' + String(e && e.message || e)))
|
|
3405
3314
|
}
|
|
3406
3315
|
|
|
3407
3316
|
const pull = () => {
|
|
3408
3317
|
setState((s) => Object.assign({}, s, { loading: true }))
|
|
3409
3318
|
refreshLoggedIn().then((r) => {
|
|
3319
|
+
if (r.error) reportError(t('hostOffline') + ': ' + r.error)
|
|
3410
3320
|
const logged = r.logged || []
|
|
3411
3321
|
fetch('/dsh-subscriptions/config', { cache: 'no-store' })
|
|
3412
3322
|
.then((res) => res.json())
|
|
3413
3323
|
.then((cfg) => {
|
|
3414
3324
|
setState((s) => Object.assign({}, s, { logged, usage: r.usage, accounts: (cfg && cfg.accounts) || [], active: r.active, loading: false }))
|
|
3415
3325
|
})
|
|
3416
|
-
.catch(() => {
|
|
3326
|
+
.catch((e) => {
|
|
3327
|
+
reportError(t('hostOffline') + ': ' + String(e && e.message || e))
|
|
3417
3328
|
setState((s) => Object.assign({}, s, { logged, usage: r.usage, accounts: [], active: r.active, loading: false }))
|
|
3418
3329
|
})
|
|
3419
|
-
}).catch(() => {
|
|
3330
|
+
}).catch((e) => {
|
|
3331
|
+
reportError(t('hostOffline') + ': ' + String(e && e.message || e))
|
|
3420
3332
|
setState((s) => Object.assign({}, s, { loading: false }))
|
|
3421
3333
|
})
|
|
3422
3334
|
}
|
|
@@ -3767,7 +3679,7 @@ window.__ModuleLoader__.load({
|
|
|
3767
3679
|
}, 'dsh-subscriptions: slash commands')
|
|
3768
3680
|
}
|
|
3769
3681
|
|
|
3770
|
-
exports.inject = ['slots', 'locale'
|
|
3682
|
+
exports.inject = ['slots', 'locale']
|
|
3771
3683
|
exports.apply = function apply(ctx) {
|
|
3772
3684
|
if (typeof window !== 'undefined') {
|
|
3773
3685
|
window.__dshCtx = ctx
|
package/lib/config-schema.js
CHANGED
|
@@ -26,6 +26,14 @@ export const Slot = z.object({
|
|
|
26
26
|
.description('#590 Optional monthly subscription cost in USD for analytics. Defaults to 20.'),
|
|
27
27
|
maxQueueSize: z.number().default(0)
|
|
28
28
|
.description('#592 Per-account queue depth before overflow. 0 = use the global maxQueueSize.'),
|
|
29
|
+
vipOnly: z.boolean().default(false)
|
|
30
|
+
.description('#175 Reserve this account for VIP requests only.'),
|
|
31
|
+
tags: z.array(z.string()).default([])
|
|
32
|
+
.description('#173 Tags used by tag-filtered rotation.'),
|
|
33
|
+
weight: z.number().default(0)
|
|
34
|
+
.description('#171 Weighted rotation priority. 0 = derive from isPro.'),
|
|
35
|
+
isPro: z.boolean().default(false)
|
|
36
|
+
.description('#171 Treat this account as Pro for weighted rotation.'),
|
|
29
37
|
})
|
|
30
38
|
|
|
31
39
|
export const defaultSlots = PROVIDERS.map((provider) => ({ provider, index: 1, label: '' }))
|
package/lib/http.js
CHANGED
|
@@ -282,8 +282,23 @@ export function isSameOrigin(url1, url2) {
|
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
export function headerSafeValue(value) {
|
|
286
|
+
return String(value == null ? '' : value)
|
|
287
|
+
.replace(/[\r\n]+/g, ' ')
|
|
288
|
+
.replace(/[^\t\x20-\x7e\x80-\xff]/g, '')
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export function sanitizeHeaderValues(headers) {
|
|
292
|
+
const out = {}
|
|
293
|
+
for (const [key, value] of Object.entries(headers || {})) {
|
|
294
|
+
if (value === undefined || value === null) continue
|
|
295
|
+
out[key] = headerSafeValue(value)
|
|
296
|
+
}
|
|
297
|
+
return out
|
|
298
|
+
}
|
|
299
|
+
|
|
285
300
|
export function sanitizeRequestHeaders(url, init = {}, options = {}) {
|
|
286
|
-
const headers =
|
|
301
|
+
const headers = sanitizeHeaderValues(init.headers || {})
|
|
287
302
|
if (!url) return headers
|
|
288
303
|
try {
|
|
289
304
|
const parsed = new URL(url)
|
package/lib/vendor-factory.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchWithTimeout } from "./http.js"
|
|
1
|
+
import { fetchWithTimeout, sanitizeHeaderValues } from "./http.js"
|
|
2
2
|
// Vendor factory from a declarative profile.
|
|
3
3
|
//
|
|
4
4
|
// Covers the OpenAI-Responses-compatible subscription family: PKCE auth,
|
|
@@ -30,11 +30,11 @@ export function createVendorFromProfile(profile) {
|
|
|
30
30
|
const tokenStyle = profile.tokenStyle === "json" ? "json" : "form"
|
|
31
31
|
|
|
32
32
|
function identityHeaders(blob, extra) {
|
|
33
|
-
return {
|
|
33
|
+
return sanitizeHeaderValues({
|
|
34
34
|
Authorization: `Bearer ${blob.accessToken}`,
|
|
35
35
|
...(profile.headers || {}),
|
|
36
36
|
...(extra || {}),
|
|
37
|
-
}
|
|
37
|
+
})
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
return {
|
package/lib/vendors/codex.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isTimeoutError, fetchWithTimeout } from "../http.js"
|
|
1
|
+
import { isTimeoutError, fetchWithTimeout, headerSafeValue } from "../http.js"
|
|
2
2
|
import { randomUUID, createHash } from 'node:crypto'
|
|
3
3
|
import { buildAuthorizeUrl } from '../oauth.js'
|
|
4
4
|
import { codexResponsesBody, modelCatalog } from '../messages.js'
|
|
@@ -61,10 +61,10 @@ export function authorizeUrl(cfg, pkce) {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
function identityHeaders(blob, config, extra) {
|
|
64
|
-
const originator = config.originator || 'codex_cli_rs'
|
|
65
|
-
const activeOrgId = blob.selectedOrgId || blob.accountId || ''
|
|
64
|
+
const originator = headerSafeValue(config.originator || 'codex_cli_rs')
|
|
65
|
+
const activeOrgId = headerSafeValue(blob.selectedOrgId || blob.accountId || '')
|
|
66
66
|
return {
|
|
67
|
-
Authorization: `Bearer ${blob.accessToken}`,
|
|
67
|
+
Authorization: `Bearer ${headerSafeValue(blob.accessToken)}`,
|
|
68
68
|
originator,
|
|
69
69
|
'chatgpt-account-id': activeOrgId,
|
|
70
70
|
'ChatGPT-Account-ID': activeOrgId,
|
|
@@ -260,7 +260,7 @@ export async function* streamOnce({ blob, options, fetchImpl, headers, config, s
|
|
|
260
260
|
Accept: 'text/event-stream',
|
|
261
261
|
'session-id': sessionId,
|
|
262
262
|
'x-client-request-id': sessionId,
|
|
263
|
-
...(isFast ? { 'x-codex-routing-hint': `model=${(options && options.model) || 'gpt-5.6-luna'};tier=priority` } : {}),
|
|
263
|
+
...(isFast ? { 'x-codex-routing-hint': `model=${headerSafeValue((options && options.model) || 'gpt-5.6-luna')};tier=priority` } : {}),
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
const res = await fetchImpl(`${base}/responses`, {
|
package/lib/vendors/cody.js
CHANGED
|
@@ -39,10 +39,7 @@ export async function listModels() {
|
|
|
39
39
|
return CODY_MODELS
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
export async function usage(
|
|
43
|
-
if (blob && (blob.accessToken || blob.token)) {
|
|
44
|
-
return { usedPercent: null, plan: 'Cody Pro', timestamp: Date.now() }
|
|
45
|
-
}
|
|
42
|
+
export async function usage() {
|
|
46
43
|
return null
|
|
47
44
|
}
|
|
48
45
|
|
package/lib/vendors/copilot.js
CHANGED
|
@@ -81,6 +81,7 @@ export async function listModels(blob, cfg, fetchImpl) {
|
|
|
81
81
|
const impl = fetchImpl || fetch
|
|
82
82
|
const fallback = modelCatalog(id, (cfg && cfg.models) || COPILOT_MODELS)
|
|
83
83
|
if (!blob) return fallback
|
|
84
|
+
blob = { ...blob }
|
|
84
85
|
const githubToken = blob.refreshToken || blob.githubToken
|
|
85
86
|
let copilotToken = blob.accessToken
|
|
86
87
|
try {
|
|
@@ -279,6 +280,8 @@ export async function usage(blob, config, fetchImpl) {
|
|
|
279
280
|
const usedPercent = user && typeof user.used_percent === "number" && Number.isFinite(user.used_percent)
|
|
280
281
|
? user.used_percent
|
|
281
282
|
: null
|
|
283
|
+
|
|
284
|
+
if (usedPercent == null) return null
|
|
282
285
|
return {
|
|
283
286
|
usedPercent,
|
|
284
287
|
plan: user && user.plan ? (user.plan.name || String(user.plan)) : "Copilot",
|
|
@@ -290,6 +293,7 @@ export async function usage(blob, config, fetchImpl) {
|
|
|
290
293
|
}
|
|
291
294
|
|
|
292
295
|
export async function* streamOnce({ blob, options, fetchImpl, headers, config, signal, spawnImpl }) {
|
|
296
|
+
blob = blob ? { ...blob } : blob
|
|
293
297
|
const mode = (config && config.copilotMode) || (blob && blob.copilotMode) || 'auto'
|
|
294
298
|
const customPath = (config && config.copilotCliPath) || (blob && blob.copilotCliPath) || ''
|
|
295
299
|
|
package/lib/vendors/ernie.js
CHANGED
|
@@ -74,7 +74,6 @@ export async function* streamOnce({ blob, options, fetchImpl, headers, config, s
|
|
|
74
74
|
const auth = await refreshErnieToken(blob.apiKey, blob.secretKey, impl)
|
|
75
75
|
if (auth && auth.access_token) {
|
|
76
76
|
token = auth.access_token
|
|
77
|
-
blob.accessToken = token
|
|
78
77
|
}
|
|
79
78
|
}
|
|
80
79
|
if (!token) throw new LlmError('Baidu ERNIE requires access token or API Key + Secret Key', 'AUTH')
|
|
@@ -171,15 +171,16 @@ export async function usage(blob, _cfg, fetchImpl) {
|
|
|
171
171
|
})
|
|
172
172
|
if (res.ok) {
|
|
173
173
|
const d = await readJson(res)
|
|
174
|
+
if (typeof d.used_percent !== 'number') return null
|
|
174
175
|
return {
|
|
175
|
-
usedPercent:
|
|
176
|
+
usedPercent: d.used_percent,
|
|
176
177
|
plan: d.plan || blob.plan || 'Perplexity Pro',
|
|
177
178
|
timestamp: Date.now(),
|
|
178
179
|
quota: d.quota ? { used: d.quota.used, limit: d.quota.limit, resetAt: d.quota.reset_at } : undefined,
|
|
179
180
|
}
|
|
180
181
|
}
|
|
181
182
|
} catch { /* usage endpoint is optional */ }
|
|
182
|
-
return
|
|
183
|
+
return null
|
|
183
184
|
}
|
|
184
185
|
|
|
185
186
|
export async function* streamOnce({ blob, options, fetchImpl, headers, config, signal }) {
|
package/lib/vendors/replit.js
CHANGED
|
@@ -34,10 +34,7 @@ export async function listModels() {
|
|
|
34
34
|
return REPLIT_MODELS
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
export async function usage(
|
|
38
|
-
if (blob && (blob.accessToken || blob.token)) {
|
|
39
|
-
return { usedPercent: null, plan: 'Replit Core', timestamp: Date.now() }
|
|
40
|
-
}
|
|
37
|
+
export async function usage() {
|
|
41
38
|
return null
|
|
42
39
|
}
|
|
43
40
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-subscriptions",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.88",
|
|
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",
|