@goodandready/dsh-key-rotation 0.7.7 → 0.7.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.
Files changed (2) hide show
  1. package/lib/client.js +44 -7
  2. package/package.json +4 -1
package/lib/client.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // dsh-key-rotation — Settings section ("Key Rotation" / "Ротация ключей").
2
- // Renders in the harness Settings sidebar via the settings.section slot and
2
+ // Renders in Settings Plugins Plugin settings via the settings.plugin.item slot and
3
3
  // edits the plugin's `dsh-key-rotation` settings namespace through the
4
4
  // loopback-fenced config bridge at /dsh-key-rotation/config.
5
5
  //
@@ -27,6 +27,8 @@ window.__ModuleLoader__.load({
27
27
  // -------------------------------------------------------------- i18n
28
28
  const en = {
29
29
  title: 'Key Rotation',
30
+ subtitle: 'Per-provider API key rotation: pools of keys, automatic failover on quota/rate-limit errors, cooldown and recovery.',
31
+ cardDesc: 'Per-provider API key rotation: pools of keys, automatic failover on quota/rate-limit errors, cooldown and recovery.',
30
32
  loading: 'Loading…',
31
33
  notRegistered: 'not registered',
32
34
  removeKey: 'Remove key',
@@ -78,6 +80,8 @@ window.__ModuleLoader__.load({
78
80
  };
79
81
  const ru = {
80
82
  title: 'Ротация ключей',
83
+ subtitle: 'Ротация API-ключей по провайдерам: пулы ключей, автоматическое переключение при исчерпании квоты или лимита, кулдаун и восстановление.',
84
+ cardDesc: 'Ротация API-ключей по провайдерам: пулы ключей, автоматическое переключение при исчерпании квоты или лимита, кулдаун и восстановление.',
81
85
  loading: 'Загрузка…',
82
86
  notRegistered: 'не зарегистрирован',
83
87
  removeKey: 'Удалить ключ',
@@ -198,6 +202,13 @@ window.__ModuleLoader__.load({
198
202
  '.krot-btn:not(:disabled):hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l3,var(--dsw-alias-border-l2))}',
199
203
  '.krot-foot{display:flex;gap:8px;align-items:center}',
200
204
  '.krot-save{background:var(--dsw-alias-button-info-fill);border-color:var(--dsw-alias-button-info-fill);color:var(--dsw-alias-label-primary-foreground);padding:5px 14px;font-size:13px}',
205
+ '.krot-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none}',
206
+ '.krot-card-header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;display:flex;align-items:center;gap:12px;padding:14px 16px}',
207
+ '.krot-card-head-text{display:flex;flex-direction:column;gap:2px;min-width:0}',
208
+ '.krot-card-name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}',
209
+ '.krot-card-description{color:var(--dsw-alias-label-secondary);font-size:13px}',
210
+ '.krot-card-chevron{flex:none;opacity:.6}',
211
+ '.krot-card-body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}',
201
212
  ].join('');
202
213
  const CARD_CSS_ID = 'dsh-key-rotation/section.module.css';
203
214
  if (typeof document !== 'undefined' && !document.querySelector('style[data-plugin-css="' + CARD_CSS_ID + '"]')) {
@@ -656,12 +667,38 @@ window.__ModuleLoader__.load({
656
667
  function useLocale() {
657
668
  return useActiveLocale(ctx);
658
669
  }
659
- ctx.slots.inject('settings.section', () => ctx.slots.register({
660
- name: 'settings.section',
661
- id: 'dsh-key-rotation',
662
- order: 20,
663
- label: () => 'Key Rotation',
664
- }, (props) => React.createElement(KeyRotationSection, { ...props, locale: useLocale() })));
670
+ // Collapsible card in Settings -> Plugins -> Plugin settings
671
+ // (settings.plugin.item), matching Model Sync / Spendmeter / Vision Bridge.
672
+ // key MUST equal the settings namespace (NS), else the tab silently skips it.
673
+ function KeyRotationCard(props) {
674
+ const locale = useLocale();
675
+ const t = makeT(locale === 'ru' ? ru : en, en);
676
+ const [open, setOpen] = React.useState(false);
677
+ return h('div', { className: 'krot-card' + (open ? ' krot-card-open' : '') },
678
+ h('button', { type: 'button', className: 'krot-card-header', 'aria-expanded': open, onClick: () => setOpen((v) => !v) },
679
+ h('span', { className: 'krot-card-head-text' },
680
+ h('span', { className: 'krot-card-name' }, t('title')),
681
+ h('span', { className: 'krot-card-description' }, t('subtitle'))),
682
+ h('span', { className: 'krot-card-chevron', 'aria-hidden': 'true' }, open ? '▴' : '▾')),
683
+ open ? h('div', { className: 'krot-card-body' }, h(KeyRotationSection, { ...props, locale })) : null);
684
+ }
685
+ const tryPluginItem = () => {
686
+ try {
687
+ ctx.slots.inject('settings.plugin.item', () =>
688
+ ctx.slots.register(
689
+ { name: 'settings.plugin.item', key: NS, locale: NS, inject: () => ({ ctx }) },
690
+ KeyRotationCard,
691
+ ));
692
+ return true;
693
+ } catch { return false; }
694
+ };
695
+ if (!tryPluginItem()) {
696
+ // Fallback for builds without the Plugins tab slot: keep the sidebar section.
697
+ ctx.slots.inject('settings.section', () => ctx.slots.register(
698
+ { name: 'settings.section', id: 'dsh-key-rotation', order: 20, label: () => 'Key Rotation' },
699
+ (props) => h(KeyRotationSection, { ...props, locale: useLocale() }),
700
+ ));
701
+ }
665
702
  }
666
703
 
667
704
  module.exports = { apply, inject: ['slots', 'locale'] };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-key-rotation",
3
- "version": "0.7.7",
3
+ "version": "0.7.10",
4
4
  "description": "Per-provider API key rotation for DeepSeek Harness: a key pool per provider, auto-created clone routes, and switching to the next key on quota/rate-limit errors. Includes a Settings section (Key Rotation) to edit the key pools, cooldown and switch codes.",
5
5
  "keywords": [
6
6
  "deepseek-harness",
@@ -54,5 +54,8 @@
54
54
  },
55
55
  "scripts": {
56
56
  "test": "node --test test/*.test.js"
57
+ },
58
+ "publishConfig": {
59
+ "access": "public"
57
60
  }
58
61
  }