@goodandready/dsh-subscriptions 0.4.9 → 0.4.10

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/client.js CHANGED
@@ -45,6 +45,12 @@ window.__ModuleLoader__.load({
45
45
  '.dsub-chipWarn{color:var(--dsw-alias-state-warning-primary);border-color:currentColor}' +
46
46
  '.dsub-chipDanger{color:var(--dsw-alias-state-error-primary);border-color:currentColor}' +
47
47
  '.dsub-chipDot{width:6px;height:6px;border-radius:999px;background:currentColor;flex:none}' +
48
+ '.dsub-chipActive{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 10px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2);font-size:12px;font-weight:600;line-height:1;white-space:nowrap;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-3)}' +
49
+ '.dsub-chipActiveWarn{color:var(--dsw-alias-state-warning-primary);border-color:currentColor}' +
50
+ '.dsub-chipActiveDanger{color:var(--dsw-alias-state-error-primary);border-color:currentColor}' +
51
+ '.dsub-chipActiveOk{color:var(--dsw-alias-state-success-primary);border-color:currentColor}' +
52
+ '.dsub-chipActiveBar{height:4px;width:48px;background:var(--dsw-alias-bg-layer-1);border-radius:2px;flex:none;overflow:hidden}' +
53
+ '.dsub-chipActiveFill{height:100%;border-radius:2px;background:currentColor}' +
48
54
 
49
55
  '.dsub-link{background:none;border:none;color:var(--dsw-alias-label-secondary);cursor:pointer;font-size:12px;padding:0}' +
50
56
  '.dsub-bar{position:relative;height:6px;border-radius:3px;background:var(--dsw-alias-bg-layer-1);overflow:hidden;flex:1;min-width:80px}' +
@@ -630,13 +636,14 @@ function PluginCard(props) {
630
636
  expiresAt: (data && data.expiresAt) || {},
631
637
  labels: (data && data.labels) || {},
632
638
  expiryNotifyDays: (data && data.expiryNotifyDays) || 7,
639
+ active: (data && data.active) || null,
633
640
  }
634
- } catch { return { logged: [], usage: 0, expiresAt: {}, labels: {}, expiryNotifyDays: 7 } }
641
+ } catch { return { logged: [], usage: 0, expiresAt: {}, labels: {}, expiryNotifyDays: 7, active: null } }
635
642
  }
636
643
 
637
644
  // #52: компактный чип в шапке сессии со статусом подключённых подписок.
638
645
  function HeaderChip(props) {
639
- const [state, setState] = React.useState({ loading: true, count: 0, usage: 0, expiry: null })
646
+ const [state, setState] = React.useState({ loading: true, count: 0, usage: 0, expiry: null, active: null })
640
647
  const t = (props && props.t) || ((k) => k)
641
648
  React.useEffect(() => {
642
649
  const pull = () => {
@@ -653,13 +660,36 @@ function PluginCard(props) {
653
660
  if (!expiry || at < expiry.at) expiry = { at, label: r.labels[p] || p }
654
661
  }
655
662
  }
656
- setState({ loading: false, count: r.logged.length, usage: r.usage, expiry })
657
- }).catch(() => setState({ loading: false, count: 0, usage: 0, expiry: null }))
663
+ setState({ loading: false, count: r.logged.length, usage: r.usage, expiry, active: r.active })
664
+ }).catch(() => setState({ loading: false, count: 0, usage: 0, expiry: null, active: null }))
658
665
  }
659
666
  pull()
660
667
  const id = setInterval(pull, 60 * 1000)
661
668
  return () => clearInterval(id)
662
669
  }, [])
670
+ // #69: если есть активная подписка — показываем её (провайдер + план + usage%).
671
+ if (state.active) {
672
+ const a = state.active
673
+ const u = typeof a.usagePercent === 'number' ? a.usagePercent : null
674
+ let acls = 'dsub-chipActive'
675
+ if (u != null) acls += u >= 100 ? ' dsub-chipActiveDanger' : (u >= 80 ? ' dsub-chipActiveDanger' : (u >= 50 ? ' dsub-chipActiveWarn' : ' dsub-chipActiveOk'))
676
+ const prov = t('provider' + a.provider.charAt(0).toUpperCase() + a.provider.slice(1)) || a.provider
677
+ const plan = a.plan || ''
678
+ const label = plan ? (prov + ' ' + plan) : prov
679
+ const pctText = u == null ? '' : Math.round(u) + '%'
680
+ return React.createElement('span', {
681
+ className: acls,
682
+ title: a.model ? (prov + ' · ' + a.model) : prov,
683
+ },
684
+ React.createElement('span', { className: 'dsub-chipDot' }),
685
+ label,
686
+ u != null
687
+ ? React.createElement('span', { className: 'dsub-chipActiveBar' },
688
+ React.createElement('span', { className: 'dsub-chipActiveFill', style: { width: Math.min(100, Math.max(0, u)) + '%' } }))
689
+ : null,
690
+ pctText ? React.createElement('span', null, pctText) : null,
691
+ )
692
+ }
663
693
  const on = state.count > 0
664
694
  // #66: цвет чипа по максимальному usagePercent (50/80/100).
665
695
  const u = state.usage
package/lib/index.js CHANGED
@@ -535,6 +535,31 @@ export function apply(ctx, config) {
535
535
  }
536
536
  } catch {}
537
537
  }
538
+ // #69: активная подписка = последний успешный запрос (новые сверху).
539
+ let active = null
540
+ const last = history.recent(1)
541
+ if (last.length) {
542
+ const lastRow = last[0]
543
+ const accts = await store.listAccounts(lastRow.provider)
544
+ const acct = accts.find((a) => a.ref === lastRow.ref) || accts[0]
545
+ let plan = ''
546
+ let status = 'ok'
547
+ try {
548
+ const info = await store.describeRef(lastRow.ref)
549
+ plan = info.paidTierName || ''
550
+ if (info.validationUrl) status = 'verify'
551
+ else if (info.cooldownUntil && info.cooldownUntil > Date.now()) status = 'cooldown'
552
+ } catch {}
553
+ active = {
554
+ provider: lastRow.provider,
555
+ model: lastRow.model || null,
556
+ path: lastRow.path || null,
557
+ plan,
558
+ usagePercent: usage[lastRow.provider] != null ? usage[lastRow.provider] : null,
559
+ status,
560
+ at: lastRow.ts,
561
+ }
562
+ }
538
563
  writeJson(res, 200, {
539
564
  ok: true,
540
565
  loggedIn: Object.fromEntries(PROVIDERS.map((id) => [id, logged.includes(id)])),
@@ -542,6 +567,7 @@ export function apply(ctx, config) {
542
567
  expiresAt: expires,
543
568
  labels,
544
569
  expiryNotifyDays: live().expiryNotifyDays,
570
+ active,
545
571
  })
546
572
  },
547
573
  }), 'dsh-subscriptions: /status')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-subscriptions",
3
- "version": "0.4.9",
3
+ "version": "0.4.10",
4
4
  "description": "Use ChatGPT Codex, Claude, Grok, and Antigravity subscriptions as DeepSeek Harness LLM providers via OAuth.",
5
5
  "license": "MIT",
6
6
  "type": "module",