@goodandready/dsh-subscriptions 0.5.1 → 0.5.3

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
@@ -32,7 +32,8 @@ window.__ModuleLoader__.load({
32
32
  '.dsub-mini{appearance:none;font:inherit;font-size:12px;cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;padding:3px 8px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);transition:all .15s}' +
33
33
  '.dsub-mini:hover{background:var(--dsw-alias-bg-layer-1);border-color:var(--dsw-alias-label-dimmed)}' +
34
34
  '.dsub-ok{font-size:12px;color:var(--dsw-alias-state-success-primary)}' +
35
- '.dsub-bad{font-size:12px;color:var(--dsw-alias-state-error-primary)}' +
35
+ '.dsub-bad{font-size:12px;color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere;word-break:break-word;max-width:100%}' +
36
+ '.dsub-hint{overflow-wrap:anywhere;word-break:break-word;max-width:100%}' +
36
37
  '.dsub-btn{appearance:none;font:inherit;cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:5px 12px;font-size:12.5px;font-weight:500;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);transition:all .15s}' +
37
38
  '.dsub-btn:hover{background:var(--dsw-alias-bg-layer-1);border-color:var(--dsw-alias-label-dimmed)}' +
38
39
  '.dsub-inp{height:30px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);border-radius:6px;padding:0 8px;font-size:12px;min-width:180px}' +
@@ -83,6 +84,8 @@ window.__ModuleLoader__.load({
83
84
  '.dsub-brandOllama{background:rgba(107,114,128,.15);color:#9ca3af;border:1px solid rgba(107,114,128,.3)}' +
84
85
  '.dsub-brandKimi{background:rgba(236,72,153,.15);color:#f472b6;border:1px solid rgba(236,72,153,.3)}' +
85
86
  '.dsub-brandGlm{background:rgba(20,184,166,.15);color:#2dd4bf;border:1px solid rgba(20,184,166,.3)}' +
87
+ '.dsub-planBadge{display:inline-flex;align-items:center;padding:1px 6px;border-radius:4px;font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px;background:rgba(99,102,241,.15);color:#818cf8;border:1px solid rgba(99,102,241,.3);margin-left:6px}' +
88
+
86
89
  '.dsub-accInfo{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}' +
87
90
  '.dsub-accNameRow{display:flex;align-items:center;justify-content:space-between;gap:8px}' +
88
91
  '.dsub-accName{font-size:13px;font-weight:600}' +
@@ -322,7 +325,49 @@ const cssId = 'dsh-subscriptions/settings.module.css'
322
325
  }
323
326
 
324
327
  // #51: live countdown to the quota window reset (account.quota.resetAt).
325
- function formatRelativeReset(resetAt, lang, now) {
328
+ function cleanErrorMessage(raw) {
329
+ if (!raw) return ''
330
+ var text = typeof raw === 'string' ? raw : (raw.message || String(raw))
331
+ text = text.trim()
332
+ if (text.charAt(0) === '{' && text.charAt(text.length - 1) === '}') {
333
+ try {
334
+ var parsed = JSON.parse(text)
335
+ if (parsed.error && parsed.error.message) text = parsed.error.message
336
+ else if (parsed.message) text = parsed.message
337
+ else if (parsed.code) text = parsed.code
338
+ } catch (e) {}
339
+ }
340
+ var firstLine = text.split('\n')[0].trim()
341
+ if (firstLine.length > 160) return firstLine.slice(0, 157) + '...'
342
+ return firstLine
343
+ }
344
+
345
+ function normalizePlanBadge(provider, plan) {
346
+ if (!plan && provider !== 'kimi' && provider !== 'glm') return null
347
+ var p = String(plan || '').toLowerCase().replace(/[^a-z0-9]/g, '')
348
+ var label = plan
349
+ if (provider === 'codex') {
350
+ if (p.indexOf('pro20') >= 0 || p === 'pro') label = 'Pro 20x'
351
+ else if (p.indexOf('pro5') >= 0 || p.indexOf('prolite') >= 0) label = 'Pro 5x'
352
+ else if (p.indexOf('team') >= 0) label = 'Team'
353
+ else if (p.indexOf('plus') >= 0) label = 'Plus'
354
+ else if (p.indexOf('enterp') >= 0) label = 'Enterprise'
355
+ } else if (provider === 'grok') {
356
+ if (p.indexOf('super') >= 0) label = 'SuperGrok'
357
+ else if (p.indexOf('plus') >= 0) label = 'X Premium+'
358
+ else if (p.indexOf('premium') >= 0) label = 'X Premium'
359
+ } else if (provider === 'antigravity') {
360
+ if (p.indexOf('ultra') >= 0) label = 'Ultra'
361
+ else if (p.indexOf('pro') >= 0) label = 'Pro'
362
+ } else if (provider === 'kimi') {
363
+ label = 'Coding Plan'
364
+ } else if (provider === 'glm') {
365
+ label = '150% Boost'
366
+ }
367
+ return label ? React.createElement('span', { className: 'dsub-planBadge' }, label) : null
368
+ }
369
+
370
+ function formatRelativeReset(resetAt, lang, now) {
326
371
  if (!resetAt || !Number.isFinite(resetAt) || resetAt <= 0) return ''
327
372
  var delta = resetAt - (now || Date.now())
328
373
  var isRu = lang !== 'en'
@@ -596,7 +641,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
596
641
  })
597
642
  const data = await res.json().catch(() => ({}))
598
643
  setProxyRes((m) => Object.assign({}, m, { [key]: data }))
599
- } catch (e) { setErr(String(e.message || e)) }
644
+ } catch (e) { setErr(cleanErrorMessage(e.message || e)) }
600
645
  setChecking((c) => Object.assign({}, c, { ['proxy:' + key]: false }))
601
646
  }
602
647
 
@@ -616,7 +661,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
616
661
  if (data && data.quota) {
617
662
  setAccounts((prev) => prev.map((a) => a.provider===provider && a.index===index ? Object.assign({}, a, { quota: data.quota }) : a))
618
663
  }
619
- } catch (e) { setErr(String(e.message || e)) }
664
+ } catch (e) { setErr(cleanErrorMessage(e.message || e)) }
620
665
  setChecking((c) => Object.assign({}, c, { [key]: false }))
621
666
  }
622
667
 
@@ -737,23 +782,24 @@ const cssId = 'dsh-subscriptions/settings.module.css'
737
782
  },
738
783
  }),
739
784
  React.createElement('span', { className: 'dsub-badge' + (account.validationUrl ? ' dsub-badge-warn' : (on ? ' dsub-badge-on' : '')) }, badgeFor(account, t)),
785
+ normalizePlanBadge(row.slot.provider, account.plan || (account.quota && account.quota.plan)),
740
786
  React.createElement('button', {
741
787
  type: 'button', className: 'dsub-mini',
742
- onClick: () => connect(row.slot.provider, row.slot.index).catch((e) => setErr(String(e.message || e))),
788
+ onClick: () => connect(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
743
789
  }, on ? t('reconnect') : t('connect')),
744
790
  (row.slot.provider === 'codex' ? React.createElement('button', {
745
791
  type: 'button', className: 'dsub-mini',
746
- onClick: () => deviceStartLogin(row.slot.provider, row.slot.index).catch((e) => setErr(String(e.message || e))),
792
+ onClick: () => deviceStartLogin(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
747
793
  }, t('deviceLogin')) : null),
748
794
  React.createElement('button', {
749
795
  type: 'button', className: 'dsub-mini',
750
796
  disabled: !on,
751
- onClick: () => logout(row.slot.provider, row.slot.index).catch((e) => setErr(String(e.message || e))),
797
+ onClick: () => logout(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
752
798
  }, t('disconnect')),
753
799
  React.createElement('button', {
754
800
  type: 'button', className: 'dsub-mini',
755
801
  disabled: checking[key],
756
- onClick: () => doCheck(row.slot.provider, row.slot.index).catch((e) => setErr(String(e.message || e))),
802
+ onClick: () => doCheck(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
757
803
  }, checking[key] ? t('checking') : t('check')),
758
804
  React.createElement('button', {
759
805
  type: 'button', className: 'dsub-mini', title: t('removeSlot'),
@@ -761,7 +807,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
761
807
  const slot = row.slot
762
808
  Promise.resolve(on ? logout(slot.provider, slot.index) : null)
763
809
  .then(() => setSlots(slots.filter((_, k) => k !== row.i)))
764
- .catch((e) => setErr(String(e.message || e)))
810
+ .catch((e) => setErr(cleanErrorMessage(e.message || e)))
765
811
  },
766
812
  }, '\u00d7'),
767
813
  ),
@@ -776,7 +822,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
776
822
  }),
777
823
  React.createElement('button', {
778
824
  type: 'button', className: 'dsub-mini',
779
- onClick: () => complete(row.slot.provider, row.slot.index).catch((e) => setErr(String(e.message || e))),
825
+ onClick: () => complete(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
780
826
  }, t('submitCode')),
781
827
  ),
782
828
  React.createElement('div', { className: 'dsub-row' },
@@ -788,12 +834,12 @@ const cssId = 'dsh-subscriptions/settings.module.css'
788
834
  }),
789
835
  React.createElement('button', {
790
836
  type: 'button', className: 'dsub-mini',
791
- onClick: () => importToken(row.slot.provider, row.slot.index).catch((e) => setErr(String(e.message || e))),
837
+ onClick: () => importToken(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
792
838
  }, t('importToken')),
793
839
  React.createElement('button', {
794
840
  type: 'button', className: 'dsub-mini',
795
841
  title: t('importLocalCli'),
796
- onClick: () => importLocalCli(row.slot.provider, row.slot.index).catch((e) => setErr(String(e.message || e))),
842
+ onClick: () => importLocalCli(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
797
843
  }, '📥 CLI'),
798
844
  ),
799
845
  React.createElement('div', { className: 'dsub-row' },
@@ -810,7 +856,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
810
856
  React.createElement('button', {
811
857
  type: 'button', className: 'dsub-mini',
812
858
  disabled: checking['proxy:' + key],
813
- onClick: () => doProxyCheck(row.slot.provider, row.slot.index).catch((e) => setErr(String(e.message || e))),
859
+ onClick: () => doProxyCheck(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
814
860
  }, checking['proxy:' + key] ? '\u2026' : t('proxyCheck')),
815
861
  ),
816
862
  (function(){
@@ -956,7 +1002,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
956
1002
  React.createElement('div', { className: 'dsub-foot' },
957
1003
  React.createElement('button', {
958
1004
  type: 'button', className: 'dsub-save',
959
- onClick: () => save().catch((e) => setErr(String(e.message || e))),
1005
+ onClick: () => save().catch((e) => setErr(cleanErrorMessage(e.message || e))),
960
1006
  }, t('save')),
961
1007
  saved ? React.createElement('span', { className: 'dsub-ok' }, t('saved')) : null,
962
1008
  err ? React.createElement('span', { className: 'dsub-bad' }, err) : null,
package/lib/mask.js CHANGED
@@ -19,3 +19,22 @@ const EMAIL_RE = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g
19
19
  export function maskText(value) {
20
20
  return String(value || '').replace(EMAIL_RE, (m) => maskEmail(m))
21
21
  }
22
+
23
+ export function cleanErrorMessage(raw) {
24
+ if (!raw) return ''
25
+ let text = typeof raw === 'string' ? raw : (raw.message || String(raw))
26
+ text = text.trim()
27
+ if (text.startsWith('{') && text.endsWith('}')) {
28
+ try {
29
+ const parsed = JSON.parse(text)
30
+ if (parsed.error && parsed.error.message) text = parsed.error.message
31
+ else if (parsed.message) text = parsed.message
32
+ else if (parsed.code) text = parsed.code
33
+ } catch {}
34
+ }
35
+ const firstLine = text.split('\n')[0].trim()
36
+ if (firstLine.length > 160) {
37
+ return firstLine.slice(0, 157) + '...'
38
+ }
39
+ return firstLine
40
+ }
package/lib/plan.js ADDED
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Normalize and pretty-print subscription plans.
3
+ */
4
+
5
+ export function normalizePlanName(provider, rawPlan) {
6
+ if (!rawPlan || typeof rawPlan !== 'string') {
7
+ if (provider === 'kimi') return 'Coding Plan'
8
+ if (provider === 'glm') return 'Coding Plan 150%'
9
+ return ''
10
+ }
11
+ const key = rawPlan.trim().toLowerCase().replace(/[^a-z0-9]/g, '')
12
+ if (provider === 'codex') {
13
+ if (key.includes('pro20') || key === 'pro') return 'Pro 20x'
14
+ if (key.includes('pro5') || key.includes('prolite')) return 'Pro 5x'
15
+ if (key.includes('team')) return 'Team'
16
+ if (key.includes('plus')) return 'Plus'
17
+ if (key.includes('enterp')) return 'Enterprise'
18
+ if (key.includes('edu')) return 'Edu'
19
+ if (key.includes('free')) return 'Free'
20
+ }
21
+ if (provider === 'grok') {
22
+ if (key.includes('super')) return 'SuperGrok'
23
+ if (key.includes('plus') || key.includes('premiumplus')) return 'X Premium+'
24
+ if (key.includes('premium')) return 'X Premium'
25
+ if (key.includes('basic')) return 'X Basic'
26
+ if (key.includes('free')) return 'Free'
27
+ }
28
+ if (provider === 'claude') {
29
+ if (key.includes('team')) return 'Team'
30
+ if (key.includes('enterp')) return 'Enterprise'
31
+ if (key.includes('pro')) return 'Pro'
32
+ if (key.includes('free')) return 'Free'
33
+ }
34
+ if (provider === 'antigravity') {
35
+ if (key.includes('ultra')) return 'Ultra'
36
+ if (key.includes('pro')) return 'Pro'
37
+ if (key.includes('free')) return 'Free'
38
+ }
39
+ if (provider === 'kimi') return 'Coding Plan'
40
+ if (provider === 'glm') return 'Coding Plan 150%'
41
+ return rawPlan
42
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-subscriptions",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
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",