@goodandready/dsh-subscriptions 0.7.35 → 0.7.36

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.
Files changed (2) hide show
  1. package/lib/client.js +89 -1
  2. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -313,6 +313,13 @@ window.__ModuleLoader__.load({
313
313
  "save": "Save",
314
314
  "saved": "Saved",
315
315
  "cancel": "Cancel",
316
+ "checkAllAccounts": "⚡ Check all",
317
+ "refreshAllQuotas": "🔄 Refresh quotas",
318
+ "importAllCli": "📥 Import all CLI",
319
+ "batchProgress": "{done}/{total} done",
320
+ "moveUp": "Move up",
321
+ "moveDown": "Move down",
322
+ "copyRef": "Copy account ref",
316
323
  "unsavedChanges": "Unsaved changes",
317
324
  "accountLabel": "Account",
318
325
  "usageRemaining": "Remaining quota",
@@ -712,6 +719,13 @@ window.__ModuleLoader__.load({
712
719
  "save": "保存",
713
720
  "saved": "已保存",
714
721
  "cancel": "取消",
722
+ "checkAllAccounts": "⚡ 全部检查",
723
+ "refreshAllQuotas": "🔄 刷新配额",
724
+ "importAllCli": "📥 导入全部 CLI",
725
+ "batchProgress": "已完成 {done}/{total}",
726
+ "moveUp": "上移",
727
+ "moveDown": "下移",
728
+ "copyRef": "复制账户引用",
715
729
  "unsavedChanges": "有未保存的更改",
716
730
  "accountLabel": "账户",
717
731
  "usageRemaining": "剩余配额",
@@ -1443,6 +1457,8 @@ window.__ModuleLoader__.load({
1443
1457
  }
1444
1458
  }
1445
1459
  const [checking, setChecking] = React.useState({})
1460
+ const [batch, setBatch] = React.useState(null)
1461
+ const batchCancelRef = React.useRef(false)
1446
1462
  const [saved, setSaved] = React.useState(false)
1447
1463
  const [savedSnapshot, setSavedSnapshot] = React.useState(null)
1448
1464
  const [tokenDraft, setTokenDraft] = React.useState({})
@@ -1555,6 +1571,21 @@ window.__ModuleLoader__.load({
1555
1571
  const updateSlot = (provider, index, patch) => setSlots((prev) => prev.map((s) => (
1556
1572
  s && s.provider === provider && Number(s.index) === Number(index) ? Object.assign({}, s, patch) : s
1557
1573
  )))
1574
+ const moveSlot = (provider, index, delta) => setSlots((prev) => {
1575
+ const positions = prev
1576
+ .map((slot, position) => ({ slot, position }))
1577
+ .filter((row) => row.slot && row.slot.provider === provider)
1578
+ const from = positions.findIndex((row) => Number(row.slot.index) === Number(index))
1579
+ const to = from + delta
1580
+ if (from < 0 || to < 0 || to >= positions.length) return prev
1581
+ const next = prev.slice()
1582
+ const a = positions[from].position
1583
+ const b = positions[to].position
1584
+ const tmp = next[a]
1585
+ next[a] = next[b]
1586
+ next[b] = tmp
1587
+ return next
1588
+ })
1558
1589
  const accountOf = (provider, index) => accounts.find((a) => a.provider === provider && a.index === index) || {}
1559
1590
 
1560
1591
  const save = async () => {
@@ -1773,6 +1804,34 @@ window.__ModuleLoader__.load({
1773
1804
  later(() => setInfo(''), 3000)
1774
1805
  }
1775
1806
 
1807
+ const runBatch = async (kind, provider) => {
1808
+ if (batch) return
1809
+ const rows = slots.filter((slot) => slot && slot.provider === provider)
1810
+ if (!rows.length) return
1811
+ batchCancelRef.current = false
1812
+ setBatch({ kind, provider, done: 0, total: rows.length })
1813
+ const queue = rows.slice()
1814
+ const worker = async () => {
1815
+ while (queue.length && !batchCancelRef.current) {
1816
+ const slot = queue.shift()
1817
+ try {
1818
+ if (kind === 'import') await importLocalCli(slot.provider, slot.index)
1819
+ else await doCheck(slot.provider, slot.index)
1820
+ } catch (e) {
1821
+ setErr(cleanErrorMessage(e.message || e))
1822
+ } finally {
1823
+ setBatch((b) => b ? Object.assign({}, b, { done: b.done + 1 }) : b)
1824
+ }
1825
+ }
1826
+ }
1827
+ await Promise.all([worker(), worker()])
1828
+ setBatch(null)
1829
+ }
1830
+ const cancelBatch = () => {
1831
+ batchCancelRef.current = true
1832
+ setBatch((b) => b ? Object.assign({}, b, { cancelled: true }) : b)
1833
+ }
1834
+
1776
1835
  const importToken = async (provider, index) => {
1777
1836
  setErr('')
1778
1837
  const tok = (tokenDraft[provider + ':' + index] || '').trim()
@@ -2860,10 +2919,22 @@ h('div', { className: 'dsub-row' },
2860
2919
  .map((slot, i) => ({ slot: slot, i: i }))
2861
2920
  .filter((row) => row.slot.provider === prov.id)
2862
2921
  return h('div', { className: 'dsub-block', key: prov.id },
2863
- h('div', { className: 'dsub-h' }, prov.name),
2922
+ h('div', { className: 'dsub-h', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 6, flexWrap: 'wrap' } },
2923
+ h('span', null, prov.name),
2924
+ h('div', { className: 'dsub-row', style: { marginTop: 0, gap: 4, flexWrap: 'wrap' } },
2925
+ h('button', { type: 'button', className: 'dsub-mini', disabled: Boolean(batch), onClick: () => runBatch('check', prov.id).catch((e) => setErr(cleanErrorMessage(e.message || e))) }, t('checkAllAccounts')),
2926
+ h('button', { type: 'button', className: 'dsub-mini', disabled: Boolean(batch), onClick: () => runBatch('check', prov.id).catch((e) => setErr(cleanErrorMessage(e.message || e))) }, t('refreshAllQuotas')),
2927
+ h('button', { type: 'button', className: 'dsub-mini', disabled: Boolean(batch), onClick: () => runBatch('import', prov.id).catch((e) => setErr(cleanErrorMessage(e.message || e))) }, t('importAllCli')),
2928
+ batch && batch.provider === prov.id ? h(React.Fragment, null,
2929
+ h('span', { className: 'dsub-sub' }, t('batchProgress').replace('{done}', String(batch.done)).replace('{total}', String(batch.total))),
2930
+ h('button', { type: 'button', className: 'dsub-mini', onClick: cancelBatch }, t('cancel'))
2931
+ ) : null,
2932
+ ),
2933
+ ),
2864
2934
  rows.map((row) => {
2865
2935
  const account = accountOf(row.slot.provider, row.slot.index)
2866
2936
  const key = row.slot.provider + ':' + row.slot.index
2937
+ const rowPosition = rows.findIndex((candidate) => candidate.i === row.i)
2867
2938
  const on = !!account.configured
2868
2939
  const poolEnabled = row.slot.poolEnabled !== false
2869
2940
  const poolModels = Array.isArray(row.slot.poolModels) ? row.slot.poolModels : null
@@ -2914,6 +2985,9 @@ h('div', { className: 'dsub-row' },
2914
2985
  },
2915
2986
  }),
2916
2987
  h('span', { className: 'dsub-badge' + (account.isRevoked ? ' dsub-badge-bad' : (account.validationUrl ? ' dsub-badge-warn' : (on ? ' dsub-badge-on' : ''))) }, badgeFor(account, t)),
2988
+ account.capabilities && account.capabilities.vision ? h('span', { className: 'dsub-model-tag', title: 'Vision' }, '👁') : null,
2989
+ account.capabilities && account.capabilities.tools ? h('span', { className: 'dsub-model-tag', title: 'Tools' }, '🔧') : null,
2990
+ account.capabilities && account.capabilities.thinking ? h('span', { className: 'dsub-model-tag', title: 'Thinking' }, '🧠') : null,
2917
2991
  normalizePlanBadge(row.slot.provider, account.plan || account.paidTierName || (account.quota && account.quota.plan)),
2918
2992
  h('button', {
2919
2993
  type: 'button', className: 'dsub-mini',
@@ -2979,6 +3053,20 @@ h('div', { className: 'dsub-row' },
2979
3053
  type: 'button', className: 'dsub-mini', title: t('quarantineParkTitle'),
2980
3054
  onClick: () => doParkQuarantine(row.slot.provider, row.slot.index, 3600000),
2981
3055
  }, ('⏸ ' + t('quarantinePark'))) : null)),
3056
+ h('button', {
3057
+ type: 'button', className: 'dsub-mini', title: t('moveUp'),
3058
+ disabled: rowPosition <= 0,
3059
+ onClick: () => moveSlot(row.slot.provider, row.slot.index, -1),
3060
+ }, '↑'),
3061
+ h('button', {
3062
+ type: 'button', className: 'dsub-mini', title: t('moveDown'),
3063
+ disabled: rowPosition < 0 || rowPosition >= rows.length - 1,
3064
+ onClick: () => moveSlot(row.slot.provider, row.slot.index, 1),
3065
+ }, '↓'),
3066
+ h('button', {
3067
+ type: 'button', className: 'dsub-mini', title: t('copyRef'),
3068
+ onClick: () => copyText(row.slot.ref || key),
3069
+ }, '📋'),
2982
3070
  h('button', {
2983
3071
  type: 'button', className: 'dsub-mini', title: t('removeSlot'),
2984
3072
  onClick: () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-subscriptions",
3
- "version": "0.7.35",
3
+ "version": "0.7.36",
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",