@goodandready/dsh-key-rotation 0.8.81 → 0.8.82
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 +8 -0
- package/lib/client-src/40-components.js +21 -15
- package/lib/client-src/52-card-pool-rows.js +1 -1
- package/lib/client-src/60-header-chip.js +61 -53
- package/lib/client.js +2567 -2329
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.8.82 (2026-10-30)
|
|
4
|
+
|
|
5
|
+
### Modernized UI Builder & JSX Pipeline (Block 10 Release)
|
|
6
|
+
- **Modern JSX/TSX Build Pipeline via esbuild (Issue #523)**: Replaced mechanical text concatenation with modern compiler-based build pipeline (`scripts/build-client.mjs`) using `esbuild`. Supports native JSX syntax with `React.createElement` transpilation.
|
|
7
|
+
- **Component JSX Modernization**: Migrated key client components (such as `Sparkline` and `KeyRotationHeaderChip`) to idiomatic JSX, improving clarity and maintainability while preserving strict modular scoping and zero runtime overhead.
|
|
8
|
+
- **Deterministic & Compliant Bundle Assembly**: Automated atomic output writing with size verification (< 256 KiB DSH Store limit, actual: ~207 KiB), UTF-8 charset preservation for multi-language localization (en, zh, ru), inline legal comments, and syntax verification (`node --check`).
|
|
9
|
+
- **CI/CD Drift Prevention**: Built-in `--check` mode in `build-client.mjs` ensuring `lib/client.js` is always strictly in sync with `lib/client-src/`.
|
|
10
|
+
|
|
3
11
|
## 0.8.81 (2026-10-30)
|
|
4
12
|
|
|
5
13
|
### Direct Extension Pipeline & Pure Key Resolution (Block 9 Release)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
function Sparkline({ points = [], width = 120, height = 22, stroke = 'var(--dsw-alias-brand-primary, currentColor)' }) {
|
|
2
2
|
if (!Array.isArray(points) || points.length < 2) {
|
|
3
|
-
return
|
|
4
|
-
|
|
3
|
+
return (
|
|
4
|
+
<svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} style={{ opacity: 0.3 }}>
|
|
5
|
+
<line x1={0} y1={height / 2} x2={width} y2={height / 2} stroke={stroke} strokeWidth={1} strokeDasharray="3 3" />
|
|
6
|
+
</svg>
|
|
5
7
|
);
|
|
6
8
|
}
|
|
7
9
|
const min = Math.min(...points);
|
|
@@ -14,19 +16,23 @@
|
|
|
14
16
|
return `${x},${y}`;
|
|
15
17
|
}).join(' ');
|
|
16
18
|
|
|
17
|
-
return
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
return (
|
|
20
|
+
<svg
|
|
21
|
+
width={width}
|
|
22
|
+
height={height}
|
|
23
|
+
viewBox={`0 0 ${width} ${height}`}
|
|
24
|
+
style={{ display: 'inline-block', verticalAlign: 'middle', overflow: 'visible' }}
|
|
25
|
+
>
|
|
26
|
+
<polyline
|
|
27
|
+
points={coords}
|
|
28
|
+
fill="none"
|
|
29
|
+
stroke={stroke}
|
|
30
|
+
strokeWidth={2}
|
|
31
|
+
strokeLinecap="round"
|
|
32
|
+
strokeLinejoin="round"
|
|
33
|
+
/>
|
|
34
|
+
</svg>
|
|
35
|
+
);
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
function parseBulkKeys(text) {
|
|
@@ -339,7 +339,7 @@
|
|
|
339
339
|
);
|
|
340
340
|
})();
|
|
341
341
|
|
|
342
|
-
|
|
342
|
+
/*! ── per-model sub-pools: keys + token quotas, plus live usage meters ── */
|
|
343
343
|
const modelPools = (() => {
|
|
344
344
|
const models = modelEntriesOf(entry);
|
|
345
345
|
const statusFor = (model) => status[entry.provider + '::' + model] ?? null;
|
|
@@ -80,58 +80,66 @@
|
|
|
80
80
|
const color = !poolEntries.length ? 'var(--dsw-alias-label-tertiary)' : anyExhausted ? 'var(--dsw-alias-state-error-primary)' : healthy < total ? 'var(--dsw-alias-state-warn-primary)' : 'var(--dsw-alias-state-success-primary)';
|
|
81
81
|
const label = poolEntries.length ? `${healthy}/${total} rot` : 'rot';
|
|
82
82
|
|
|
83
|
-
return
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
83
|
+
return (
|
|
84
|
+
<div ref={ref} style={{ position: 'relative', display: 'inline-flex' }}>
|
|
85
|
+
<button
|
|
86
|
+
type="button"
|
|
87
|
+
className="krot-header-chip"
|
|
88
|
+
title={t('title')}
|
|
89
|
+
onClick={() => setOpen((v) => !v)}
|
|
90
|
+
>
|
|
91
|
+
<span style={{ width: '8px', height: '8px', borderRadius: '50%', background: color, flex: 'none', boxShadow: `0 0 6px ${color}` }} />
|
|
92
|
+
{label}
|
|
93
|
+
<span style={{ fontSize: '9px', opacity: 0.6 }}>{open ? '▲' : '▼'}</span>
|
|
94
|
+
</button>
|
|
95
|
+
{open ? (
|
|
96
|
+
<div className="krot-popover" style={{ minWidth: '220px' }}>
|
|
97
|
+
<div className="krot-pop-title">{t('headerPoolsTitle')}</div>
|
|
98
|
+
{!poolEntries.length ? (
|
|
99
|
+
<div style={{ fontSize: '12px', color: 'var(--dsw-alias-label-tertiary)' }}>{t('noActivePools')}</div>
|
|
100
|
+
) : null}
|
|
101
|
+
{poolEntries.map(([name, p]) => {
|
|
102
|
+
const c = p.exhausted ? 'var(--dsw-alias-state-error-primary)' : (p.healthy < p.total ? 'var(--dsw-alias-state-warn-primary)' : 'var(--dsw-alias-state-success-primary)');
|
|
103
|
+
const provName = p.providerName || name;
|
|
104
|
+
const tail = p.lastUsedTail;
|
|
105
|
+
return (
|
|
106
|
+
<div key={name} className="krot-pop-row" style={{ display: 'flex', flexDirection: 'column', gap: '4px', padding: '6px 0', borderBottom: '1px solid var(--dsw-alias-border-subtle)' }}>
|
|
107
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
108
|
+
<div className="krot-pop-name">
|
|
109
|
+
<span style={{ width: '7px', height: '7px', borderRadius: '50%', background: c, flex: 'none' }} />
|
|
110
|
+
{name}
|
|
111
|
+
{tail ? <span style={{ marginLeft: '6px', fontSize: '11px', color: 'var(--dsw-alias-label-tertiary)', fontFeatureSettings: '"tnum"', fontFamily: 'monospace' }}>{`...${tail}`}</span> : null}
|
|
112
|
+
</div>
|
|
113
|
+
<div className="krot-pop-count" style={{ color: c, fontWeight: 600 }}>{`${p.healthy}/${p.total}`}</div>
|
|
114
|
+
</div>
|
|
115
|
+
<div style={{ display: 'flex', gap: '4px', marginTop: '2px' }}>
|
|
116
|
+
<button
|
|
117
|
+
type="button"
|
|
118
|
+
disabled={busy}
|
|
119
|
+
onClick={(e) => { e.stopPropagation(); runAction('skip', provName, p.lastUsed); }}
|
|
120
|
+
title={t('quickSkipTitle')}
|
|
121
|
+
style={{ padding: '2px 6px', fontSize: '11px', borderRadius: '4px', border: '1px solid var(--dsw-alias-border-subtle)', background: 'transparent', cursor: 'pointer', color: 'inherit' }}
|
|
122
|
+
>{`⏭️ ${t('quickSkip')}`}</button>
|
|
123
|
+
<button
|
|
124
|
+
type="button"
|
|
125
|
+
disabled={busy}
|
|
126
|
+
onClick={(e) => { e.stopPropagation(); runAction('reset', provName, p.lastUsed); }}
|
|
127
|
+
title={t('quickResetTitle')}
|
|
128
|
+
style={{ padding: '2px 6px', fontSize: '11px', borderRadius: '4px', border: '1px solid var(--dsw-alias-border-subtle)', background: 'transparent', cursor: 'pointer', color: 'inherit' }}
|
|
129
|
+
>{`🔄 ${t('quickReset')}`}</button>
|
|
130
|
+
<button
|
|
131
|
+
type="button"
|
|
132
|
+
disabled={busy || !p.lastUsed}
|
|
133
|
+
onClick={(e) => { e.stopPropagation(); runAction('pause', provName, p.lastUsed); }}
|
|
134
|
+
title={t('quickPauseTitle')}
|
|
135
|
+
style={{ padding: '2px 6px', fontSize: '11px', borderRadius: '4px', border: '1px solid var(--dsw-alias-border-subtle)', background: 'transparent', cursor: 'pointer', color: 'inherit' }}
|
|
136
|
+
>{`⏸️ ${t('quickPause')}`}</button>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
);
|
|
140
|
+
})}
|
|
141
|
+
</div>
|
|
142
|
+
) : null}
|
|
143
|
+
</div>
|
|
136
144
|
);
|
|
137
145
|
}
|