@goodandready/dsh-key-rotation 0.8.19 → 0.8.20

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/CHANGELOG.md CHANGED
@@ -3,6 +3,11 @@
3
3
  All notable changes to `@goodandready/dsh-key-rotation` are documented here.
4
4
  User-facing feature notes also appear in README (en is source of truth).
5
5
 
6
+ ## 0.8.20 - 2026-09-22
7
+
8
+ ### Fixed
9
+ - **Settings card on current DSH** (#345): the client reads its settings namespace through `configForms` instead of the removed `settingsScope` service. The package manifest declares the settings and slots providers the card injects, so the fiber activates and the card mounts again.
10
+
6
11
  ## 0.8.19 - 2026-09-22
7
12
 
8
13
  ### Fixed
package/lib/client.js CHANGED
@@ -644,7 +644,7 @@ window.__ModuleLoader__.load({
644
644
  );
645
645
  }
646
646
 
647
- // Provider registration is not part of settingsScope's value. Fetch it
647
+ // Provider registration is not part of configForms's value. Fetch it
648
648
  // independently, and never turn an unavailable catalog into proof of absence.
649
649
  function useProviderCatalog() {
650
650
  const [catalog, setCatalog] = React.useState({ status: 'loading', providers: [] });
@@ -687,10 +687,10 @@ window.__ModuleLoader__.load({
687
687
 
688
688
  function KeyRotationSection(props) {
689
689
  const t = resolveT(props);
690
- const settingsScope = React.useMemo(() => {
690
+ const configForms = React.useMemo(() => {
691
691
  try {
692
- if (props.ctx && props.ctx.settingsScope) {
693
- return props.ctx.settingsScope.bind({ namespace: NS });
692
+ if (props.ctx && props.ctx.configForms) {
693
+ return props.ctx.configForms.get(NS);
694
694
  }
695
695
  } catch (_) {
696
696
  return null;
@@ -700,10 +700,10 @@ window.__ModuleLoader__.load({
700
700
  // #273: getSnapshot must be referentially stable or React 18 unmounts the tree
701
701
  const scopeCacheRef = React.useRef({ has: false, value: null });
702
702
  const getScopeSnapshot = React.useCallback(() => {
703
- if (!settingsScope || typeof settingsScope.getSnapshot !== 'function') return null;
703
+ if (!configForms || typeof configForms.getSnapshot !== 'function') return null;
704
704
  let next = null;
705
705
  try {
706
- next = settingsScope.getSnapshot();
706
+ next = configForms.getSnapshot();
707
707
  } catch (_) {
708
708
  return null;
709
709
  }
@@ -718,21 +718,21 @@ window.__ModuleLoader__.load({
718
718
  }
719
719
  scopeCacheRef.current = { has: true, value: next };
720
720
  return next;
721
- }, [settingsScope]);
721
+ }, [configForms]);
722
722
  const scopeSnapshot = React.useSyncExternalStore(
723
- React.useMemo(() => (cb) => (settingsScope && typeof settingsScope.subscribe === 'function' ? settingsScope.subscribe(cb) : () => {}), [settingsScope]),
723
+ React.useMemo(() => (cb) => (configForms && typeof configForms.subscribe === 'function' ? configForms.subscribe(cb) : () => {}), [configForms]),
724
724
  getScopeSnapshot
725
725
  );
726
726
  const [state, setState] = React.useState({ status: 'loading', value: null, revision: 0, error: '', providers: [] });
727
727
  const catalog = useProviderCatalog();
728
728
  const latestScopeSnapshot = React.useRef(scopeSnapshot);
729
729
  latestScopeSnapshot.current = scopeSnapshot;
730
- // #290: surface settingsScope availability as card state
730
+ // #290: surface configForms availability as card state
731
731
  React.useEffect(() => {
732
- if (!settingsScope) {
732
+ if (!configForms) {
733
733
  setState((s) => (s.status === 'unavailable' ? s : { ...s, status: 'unavailable' }));
734
734
  }
735
- }, [settingsScope]);
735
+ }, [configForms]);
736
736
  const [draft, setDraft] = React.useState(null);
737
737
  // ── all hooks live ABOVE any early return (React error 310 otherwise) ──
738
738
  const [search, setSearch] = React.useState('');
@@ -1014,7 +1014,7 @@ window.__ModuleLoader__.load({
1014
1014
  React.createElement('button', { type: 'button', className: 'krot-btn', onClick: () => load() }, t('retry'))
1015
1015
  );
1016
1016
  }
1017
- if (state.status === 'unavailable' || !settingsScope) {
1017
+ if (state.status === 'unavailable' || !configForms) {
1018
1018
  return React.createElement('div', { className: 'krot-state-block', role: 'status', style: { padding: '12px 0', display: 'flex', flexDirection: 'column', gap: '6px' } },
1019
1019
  React.createElement('p', { style: { fontSize: 14, fontWeight: 600, color: 'var(--dsw-alias-label-primary)', margin: 0 } }, t('unavailableTitle')),
1020
1020
  React.createElement('p', { className: 'krot-hint', style: { margin: 0 } }, t('unavailableDesc'))
@@ -1127,11 +1127,11 @@ window.__ModuleLoader__.load({
1127
1127
  })
1128
1128
  .catch((e) => setState((s) => ({ ...s, status: 'error', error: String(e) })));
1129
1129
  };
1130
- if (settingsScope && typeof settingsScope.set === 'function') {
1130
+ if (configForms && typeof configForms.set === 'function') {
1131
1131
  (async () => {
1132
1132
  try {
1133
1133
  for (const [k, v] of Object.entries(draft)) {
1134
- await settingsScope.set(k, v);
1134
+ await configForms.set(k, v);
1135
1135
  }
1136
1136
  setState((s) => ({ ...s, status: 'ready', value: draft, error: '' }));
1137
1137
  setDraft(null);
@@ -1936,7 +1936,7 @@ window.__ModuleLoader__.load({
1936
1936
  }
1937
1937
  }
1938
1938
 
1939
- module.exports = { apply, inject: ['slots', 'locale', 'settingsScope'] };
1939
+ module.exports = { apply, inject: ['slots', 'locale', 'configForms'] };
1940
1940
  return module.exports;
1941
1941
  },
1942
1942
  updateCheck: 'Check for updates',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-key-rotation",
3
- "version": "0.8.19",
3
+ "version": "0.8.20",
4
4
  "packageManager": "pnpm@10.33.2",
5
5
  "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.",
6
6
  "keywords": [
@@ -46,7 +46,8 @@
46
46
  "platform": "web",
47
47
  "inject": [
48
48
  "@deepseek-ai/dsh-client-locale",
49
- "@deepseek-ai/dsh-client-ui-settings"
49
+ "@deepseek-ai/dsh-client-ui-settings",
50
+ "@deepseek-ai/dsh-client-ui-slots"
50
51
  ]
51
52
  }
52
53
  },