@goodandready/dsh-key-rotation 0.7.24 → 0.7.25
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/index.js +44 -5
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -492,9 +492,24 @@ export function apply(ctx, config = {}) {
|
|
|
492
492
|
let st = poolState.get(base);
|
|
493
493
|
if (!st) {
|
|
494
494
|
st = {
|
|
495
|
-
failedUntil: new Map(),
|
|
496
|
-
|
|
497
|
-
|
|
495
|
+
failedUntil: new Map(),
|
|
496
|
+
failCounts: new Map(),
|
|
497
|
+
authFailCounts: new Map(),
|
|
498
|
+
brokenUntil: new Map(),
|
|
499
|
+
costPerKey: new Map(),
|
|
500
|
+
lastUsedAt: new Map(),
|
|
501
|
+
usageCounts: new Map(),
|
|
502
|
+
byModel: new Map(),
|
|
503
|
+
usageDays: new Map(),
|
|
504
|
+
quotaWindows: new Map(),
|
|
505
|
+
pointer: 0,
|
|
506
|
+
lastUsed: undefined,
|
|
507
|
+
switches: 0,
|
|
508
|
+
lastReason: undefined,
|
|
509
|
+
lastSwitchAt: undefined,
|
|
510
|
+
lastExhaustionAt: undefined,
|
|
511
|
+
exhaustionCount: 0,
|
|
512
|
+
events: [],
|
|
498
513
|
};
|
|
499
514
|
poolState.set(base, st);
|
|
500
515
|
}
|
|
@@ -705,7 +720,28 @@ export function apply(ctx, config = {}) {
|
|
|
705
720
|
const switchable = !yielded && kind === 'error' &&
|
|
706
721
|
(effectiveSwitchCodes.has(code) || SWITCHABLE_MESSAGE_PATTERN.test(message));
|
|
707
722
|
if (switchable) {
|
|
708
|
-
if (pool.state.lastUsed) {
|
|
723
|
+
if (pool.state.lastUsed) {
|
|
724
|
+
const _retry = parseRetryAfter(message);
|
|
725
|
+
const _base = pool.cooldownMs ?? cooldownMs;
|
|
726
|
+
const _max = pool.maxCooldownMs ?? maxCooldownMs;
|
|
727
|
+
const _effBase = _retry !== undefined ? Math.max(_base, Math.min(_retry, _max ?? _base * 8)) : _base;
|
|
728
|
+
const _b = recordFailure(pool, pool.state.lastUsed, Date.now(), _effBase, _max);
|
|
729
|
+
pushEvent(pool, pool.state.lastUsed, code ?? 'UNKNOWN', _b);
|
|
730
|
+
// authFailCounts/brokenUntil: lazy-init if state was created by an older plugin version
|
|
731
|
+
if (!pool.state.authFailCounts) pool.state.authFailCounts = new Map();
|
|
732
|
+
if (!pool.state.brokenUntil) pool.state.brokenUntil = new Map();
|
|
733
|
+
const _code2 = String(code ?? '');
|
|
734
|
+
if (_code2 === 'AUTH' || /auth/i.test(message)) {
|
|
735
|
+
const _c2 = (pool.state.authFailCounts.get(pool.state.lastUsed) ?? 0) + 1;
|
|
736
|
+
pool.state.authFailCounts.set(pool.state.lastUsed, _c2);
|
|
737
|
+
if (_c2 >= 3) {
|
|
738
|
+
pool.state.brokenUntil.set(pool.state.lastUsed, Date.now() + 86400000*30);
|
|
739
|
+
pool.state.failedUntil.set(pool.state.lastUsed, Date.now() + 86400000*30);
|
|
740
|
+
}
|
|
741
|
+
} else {
|
|
742
|
+
pool.state.authFailCounts.delete(pool.state.lastUsed);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
709
745
|
pool.state.switches = (pool.state.switches ?? 0) + 1;
|
|
710
746
|
pool.state.lastReason = String(code ?? 'UNKNOWN');
|
|
711
747
|
pool.state.lastSwitchAt = Date.now();
|
|
@@ -717,7 +753,10 @@ export function apply(ctx, config = {}) {
|
|
|
717
753
|
// cost tracking if provider returns usage.cost
|
|
718
754
|
if (chunk.usage?.cost != null && pool.state.lastUsed) {
|
|
719
755
|
const c = Number(chunk.usage.cost);
|
|
720
|
-
if (!isNaN(c))
|
|
756
|
+
if (!isNaN(c)) {
|
|
757
|
+
if (!pool.state.costPerKey) pool.state.costPerKey = new Map();
|
|
758
|
+
pool.state.costPerKey.set(pool.state.lastUsed, (pool.state.costPerKey.get(pool.state.lastUsed) ?? 0) + c);
|
|
759
|
+
}
|
|
721
760
|
}
|
|
722
761
|
// Usage by day (#119)
|
|
723
762
|
if (pool.state.lastUsed) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-key-rotation",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.25",
|
|
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",
|