@goodandready/dsh-key-rotation 0.5.4 → 0.6.0
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 +27 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -80,7 +80,7 @@ export const Config = Schema.object({
|
|
|
80
80
|
providers: Schema.array(Schema.object({
|
|
81
81
|
provider: Schema.string().required(),
|
|
82
82
|
keys: Schema.array(Schema.string()).default([]),
|
|
83
|
-
cooldownMs: Schema.number()
|
|
83
|
+
cooldownMs: Schema.number(),
|
|
84
84
|
})).default([...DEFAULT_PROVIDERS]),
|
|
85
85
|
});
|
|
86
86
|
|
|
@@ -617,6 +617,32 @@ export function apply(ctx, config = {}) {
|
|
|
617
617
|
return rotate(options, pool);
|
|
618
618
|
});
|
|
619
619
|
|
|
620
|
+
// Safety net for non-stream requests (agent/request-error waterfall).
|
|
621
|
+
// llm/stream covers streaming calls; sync calls (embeddings, batch) go
|
|
622
|
+
// through agent/request and surface errors here. If the error is
|
|
623
|
+
// switchable, mark the key and ask the agent loop to retry.
|
|
624
|
+
ctx.on('agent/request-error', async (payload, next) => {
|
|
625
|
+
const provider = payload?.provider ?? payload?.failure?.provider ?? '';
|
|
626
|
+
if (!provider) return next();
|
|
627
|
+
const { providerToPool, switchCodes } = buildRuntime();
|
|
628
|
+
const pool = providerToPool.get(provider);
|
|
629
|
+
if (!pool) return next();
|
|
630
|
+
const code = String(payload?.failure?.code ?? payload?.code ?? '');
|
|
631
|
+
const message = String(payload?.failure?.message ?? payload?.message ?? '');
|
|
632
|
+
const switchable = switchCodes.has(code) || SWITCHABLE_MESSAGE_PATTERN.test(message);
|
|
633
|
+
if (!switchable) return next();
|
|
634
|
+
const ref = pool.state.lastUsed;
|
|
635
|
+
if (ref) {
|
|
636
|
+
const backoff = recordFailure(pool, ref, Date.now(), pool.cooldownMs ?? 60000);
|
|
637
|
+
pushEvent(pool, ref, code || 'UNKNOWN', backoff);
|
|
638
|
+
pool.state.switches = (pool.state.switches ?? 0) + 1;
|
|
639
|
+
pool.state.lastReason = code || 'UNKNOWN';
|
|
640
|
+
pool.state.lastSwitchAt = Date.now();
|
|
641
|
+
console.warn(`[dsh-key-rotation] ${provider}: key ${String(ref)} failed via agent/request-error (${String(code)} ${String(message).slice(0, 80)}) — retry`);
|
|
642
|
+
}
|
|
643
|
+
return { kind: 'retry' };
|
|
644
|
+
});
|
|
645
|
+
|
|
620
646
|
ctx.inject(['settings'], (sctx) => {
|
|
621
647
|
const scope = sctx.settings.register(NS, Config, { base: config });
|
|
622
648
|
getConfig = () => scope.get() ?? config;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-key-rotation",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
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",
|