@goodandready/dsh-key-rotation 0.8.83 → 0.8.84
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 +10 -5
- package/lib/lifecycle.js +2 -2
- package/lib/plugin-updater.js +4 -1
- package/lib/routes/balance.js +2 -1
- package/lib/routes/config.js +3 -2
- package/lib/routes/guard.js +23 -0
- package/lib/routes/keys.js +8 -7
- package/lib/routes/metrics.js +2 -1
- package/lib/routes/quick-action.js +2 -1
- package/lib/routes/status.js +3 -2
- package/lib/routes/telemetry.js +6 -5
- package/lib/routes/testing.js +4 -3
- package/lib/routes/webhook.js +2 -1
- package/package.json +4 -4
package/lib/index.js
CHANGED
|
@@ -36,6 +36,7 @@ import { CircuitBreaker } from './circuit-breaker.js';
|
|
|
36
36
|
import { NotifyQueue } from './notify-queue.js';
|
|
37
37
|
import { classifyFailure } from './error-taxonomy.js';
|
|
38
38
|
import { registerOpsRoutes } from './routes-ops.js';
|
|
39
|
+
import { getWebServer } from './routes/guard.js';
|
|
39
40
|
import { registerPluginUpdater } from './plugin-updater.js';
|
|
40
41
|
import { notifySwitch, notifyExhaustion, notifyEarlyWarning, pushEvent } from './notify-events.js';
|
|
41
42
|
import { QUOTA_WINDOW_TYPES } from './quota-window.js';
|
|
@@ -178,7 +179,7 @@ export const Config = typeof Schema.number().volatile === 'function'
|
|
|
178
179
|
: SettingsSchema;
|
|
179
180
|
|
|
180
181
|
function registerConfigBridge(ctx, getCloneIds) {
|
|
181
|
-
return ctx.
|
|
182
|
+
return getWebServer(ctx).register({
|
|
182
183
|
kind: 'exact',
|
|
183
184
|
path: CONFIG_PATH,
|
|
184
185
|
handler: (req, res) => {
|
|
@@ -246,9 +247,11 @@ export function apply(ctx, config = {}) {
|
|
|
246
247
|
|
|
247
248
|
setupAutoUnbreakEffect(ctx, getConfig, buildRuntime, ensureSandboxRunner, logger);
|
|
248
249
|
|
|
249
|
-
// Dynamic webServer registration (#528)
|
|
250
|
+
// Dynamic webServer registration (#528, #567)
|
|
250
251
|
const setupWebRoutes = (webCtx = ctx) => {
|
|
251
|
-
const target = webCtx
|
|
252
|
+
const target = getWebServer(webCtx) ? webCtx : ctx;
|
|
253
|
+
const ws = getWebServer(target);
|
|
254
|
+
if (!ws) return;
|
|
252
255
|
registerConfigBridge(target, () => buildRuntime().cloneIds);
|
|
253
256
|
registerOpsRoutes(target, {
|
|
254
257
|
buildRuntime,
|
|
@@ -265,7 +268,7 @@ export function apply(ctx, config = {}) {
|
|
|
265
268
|
selectionTraceStore,
|
|
266
269
|
diagBuffer,
|
|
267
270
|
});
|
|
268
|
-
if (typeof
|
|
271
|
+
if (typeof ws?.register === 'function') {
|
|
269
272
|
registerPluginUpdater(target, {
|
|
270
273
|
endpoint: '/api/dsh-key-rotation/update',
|
|
271
274
|
packageName: '@goodandready/dsh-key-rotation',
|
|
@@ -274,10 +277,12 @@ export function apply(ctx, config = {}) {
|
|
|
274
277
|
}
|
|
275
278
|
};
|
|
276
279
|
|
|
277
|
-
if (ctx.webServer) {
|
|
280
|
+
if (Object.prototype.hasOwnProperty.call(ctx, 'webServer') && ctx.webServer) {
|
|
278
281
|
setupWebRoutes(ctx);
|
|
279
282
|
} else if (typeof ctx.inject === 'function') {
|
|
280
283
|
ctx.inject(['webServer'], setupWebRoutes);
|
|
284
|
+
} else if (getWebServer(ctx)) {
|
|
285
|
+
setupWebRoutes(ctx);
|
|
281
286
|
}
|
|
282
287
|
|
|
283
288
|
// Periodic sweep of expired cooldowns
|
package/lib/lifecycle.js
CHANGED
|
@@ -45,7 +45,7 @@ export function setupAutoUnbreakEffect(ctx, getConfig, buildRuntime, ensureSandb
|
|
|
45
45
|
await autoUnbreakBrokenKeys(pools, async (ref) => {
|
|
46
46
|
// A rotating resolver can substitute a healthy neighbor for this
|
|
47
47
|
// quarantined ref, falsely proving that the broken key recovered.
|
|
48
|
-
const credentials = ctx.get
|
|
48
|
+
const credentials = (typeof ctx?.get === 'function' ? ctx.get('credentials') : undefined) ?? (ctx && Object.prototype.hasOwnProperty.call(ctx, 'credentials') ? ctx.credentials : undefined);
|
|
49
49
|
const resolve = credentials?.__dshKeyRotationOriginalResolve ?? credentials?.resolve;
|
|
50
50
|
const hit = await resolve?.call(credentials, ref);
|
|
51
51
|
const raw = typeof hit?.value === 'string' && hit.value.length > 0
|
|
@@ -197,7 +197,7 @@ export function setupProactiveHealthProbeEffect(ctx, getConfig, buildRuntime, en
|
|
|
197
197
|
for (const ref of candidates) {
|
|
198
198
|
if (disposed) break;
|
|
199
199
|
try {
|
|
200
|
-
const credentials = ctx.get
|
|
200
|
+
const credentials = (typeof ctx?.get === 'function' ? ctx.get('credentials') : undefined) ?? (ctx && Object.prototype.hasOwnProperty.call(ctx, 'credentials') ? ctx.credentials : undefined);
|
|
201
201
|
const resolve = credentials?.__dshKeyRotationOriginalResolve ?? credentials?.resolve;
|
|
202
202
|
const hit = await resolve?.call(credentials, ref);
|
|
203
203
|
const raw = typeof hit?.value === 'string' && hit.value.length > 0 ? hit.value : envValue(ref);
|
package/lib/plugin-updater.js
CHANGED
|
@@ -314,7 +314,10 @@ function json(response, statusCode, value) {
|
|
|
314
314
|
|
|
315
315
|
export function registerPluginUpdater(ctx, options) {
|
|
316
316
|
let installing = false
|
|
317
|
-
|
|
317
|
+
const viaOwn = ctx && Object.prototype.hasOwnProperty.call(ctx, 'webServer') && typeof ctx.webServer?.register === 'function' ? ctx.webServer : undefined
|
|
318
|
+
const viaGet = typeof ctx?.get === 'function' ? ctx.get('webServer') : undefined
|
|
319
|
+
const ws = viaOwn ?? (typeof viaGet?.register === 'function' ? viaGet : undefined) ?? ctx?.webServer
|
|
320
|
+
return ws.register({
|
|
318
321
|
kind: 'exact',
|
|
319
322
|
path: options.endpoint,
|
|
320
323
|
handler: async (request, response) => {
|
package/lib/routes/balance.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getWebServer } from './guard.js';
|
|
1
2
|
// lib/ops-balance.js — operational HTTP routes for balance inspection (#495).
|
|
2
3
|
|
|
3
4
|
import {
|
|
@@ -18,7 +19,7 @@ export function registerBalanceRoutes(ctx, deps) {
|
|
|
18
19
|
buildRuntime,
|
|
19
20
|
} = deps;
|
|
20
21
|
|
|
21
|
-
ctx.effect(() => ctx.
|
|
22
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
22
23
|
kind: 'exact',
|
|
23
24
|
path: BALANCE_PATH,
|
|
24
25
|
handler: async (req, res) => {
|
package/lib/routes/config.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getWebServer } from './guard.js';
|
|
1
2
|
// lib/ops-config-io.js — full configuration export and import (#504).
|
|
2
3
|
import crypto from 'node:crypto';
|
|
3
4
|
import { readFileSync } from 'node:fs';
|
|
@@ -187,7 +188,7 @@ export function diffConfigs(currentConfig, incomingConfig, mode = 'merge') {
|
|
|
187
188
|
|
|
188
189
|
export function registerConfigIoRoutes(ctx, deps) {
|
|
189
190
|
// ── GET & POST /dsh-key-rotation/export (#552: support POST for safe passphrase transmission) ──
|
|
190
|
-
ctx.effect(() => ctx.
|
|
191
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
191
192
|
kind: 'exact',
|
|
192
193
|
path: CONFIG_EXPORT_PATH,
|
|
193
194
|
handler: async (req, res) => {
|
|
@@ -448,7 +449,7 @@ export function registerConfigIoRoutes(ctx, deps) {
|
|
|
448
449
|
});
|
|
449
450
|
};
|
|
450
451
|
|
|
451
|
-
ctx.effect(() => ctx.
|
|
452
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
452
453
|
kind: 'exact',
|
|
453
454
|
path: CONFIG_IMPORT_PATH,
|
|
454
455
|
handler: handleImport,
|
package/lib/routes/guard.js
CHANGED
|
@@ -11,3 +11,26 @@ export {
|
|
|
11
11
|
json,
|
|
12
12
|
readJson,
|
|
13
13
|
} from '../http-bridge.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Safely resolve webServer from a Cordis context or test mock without
|
|
17
|
+
* triggering Cordis's Proxy trap (`cannot get property "webServer" without inject`)
|
|
18
|
+
* when `webServer` is provided by a sibling plugin and not in static `inject`.
|
|
19
|
+
*/
|
|
20
|
+
export function getWebServer(ctx) {
|
|
21
|
+
if (!ctx) return undefined;
|
|
22
|
+
if (Object.prototype.hasOwnProperty.call(ctx, 'webServer') && typeof ctx.webServer?.register === 'function') {
|
|
23
|
+
return ctx.webServer;
|
|
24
|
+
}
|
|
25
|
+
if (typeof ctx.get === 'function') {
|
|
26
|
+
const viaGet = ctx.get('webServer');
|
|
27
|
+
if (typeof viaGet?.register === 'function') return viaGet;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const ws = ctx.webServer;
|
|
31
|
+
if (typeof ws?.register === 'function') return ws;
|
|
32
|
+
} catch {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
package/lib/routes/keys.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getWebServer } from './guard.js';
|
|
1
2
|
import { decryptSecret, encryptSecret } from '../crypto-storage.js';
|
|
2
3
|
// lib/ops-keys.js — key store + cooldown reset + import routes (#312 split from routes-ops.js).
|
|
3
4
|
import {
|
|
@@ -156,7 +157,7 @@ export async function discoverUnconfiguredKeys(ctx, runtimePools = []) {
|
|
|
156
157
|
|
|
157
158
|
export function registerKeyRoutes(ctx, deps) {
|
|
158
159
|
|
|
159
|
-
ctx.effect(() => ctx.
|
|
160
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
160
161
|
kind: 'exact',
|
|
161
162
|
path: DRAIN_PATH,
|
|
162
163
|
handler: async (req, res) => {
|
|
@@ -219,7 +220,7 @@ ctx.effect(() => ctx.webServer.register({
|
|
|
219
220
|
// it is never sent back, only its last few characters are (see the status
|
|
220
221
|
// route) — and the route is loopback- and same-origin-gated like the config
|
|
221
222
|
// bridge next to it.
|
|
222
|
-
ctx.effect(() => ctx.
|
|
223
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
223
224
|
kind: 'exact',
|
|
224
225
|
path: KEY_PATH,
|
|
225
226
|
handler: async (req, res) => {
|
|
@@ -289,7 +290,7 @@ ctx.effect(() => ctx.webServer.register({
|
|
|
289
290
|
|
|
290
291
|
|
|
291
292
|
// ── reset route: clear cooldown for a provider (or a single ref) ──
|
|
292
|
-
ctx.effect(() => ctx.
|
|
293
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
293
294
|
kind: 'exact',
|
|
294
295
|
path: RESET_PATH,
|
|
295
296
|
handler: async (req, res) => {
|
|
@@ -374,7 +375,7 @@ ctx.effect(() => ctx.webServer.register({
|
|
|
374
375
|
}), 'dsh-key-rotation: reset route');
|
|
375
376
|
|
|
376
377
|
|
|
377
|
-
ctx.effect(() => ctx.
|
|
378
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
378
379
|
kind: 'exact',
|
|
379
380
|
path: IMPORT_PATH,
|
|
380
381
|
handler: async (req, res) => {
|
|
@@ -411,7 +412,7 @@ ctx.effect(() => ctx.webServer.register({
|
|
|
411
412
|
// Health for external panels (Beszel/Uptime)
|
|
412
413
|
|
|
413
414
|
// ── discover unconfigured keys route (#491) ──
|
|
414
|
-
ctx.effect(() => ctx.
|
|
415
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
415
416
|
kind: 'exact',
|
|
416
417
|
path: DISCOVER_PATH,
|
|
417
418
|
handler: async (req, res) => {
|
|
@@ -434,7 +435,7 @@ ctx.effect(() => ctx.webServer.register({
|
|
|
434
435
|
}), 'dsh-key-rotation: discover route');
|
|
435
436
|
|
|
436
437
|
// ── auto-import discovered keys into pools (#491) ──
|
|
437
|
-
ctx.effect(() => ctx.
|
|
438
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
438
439
|
kind: 'exact',
|
|
439
440
|
path: AUTO_IMPORT_PATH,
|
|
440
441
|
handler: async (req, res) => {
|
|
@@ -528,7 +529,7 @@ ctx.effect(() => ctx.webServer.register({
|
|
|
528
529
|
},
|
|
529
530
|
}), 'dsh-key-rotation: auto-import route');
|
|
530
531
|
|
|
531
|
-
ctx.effect(() => ctx.
|
|
532
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
532
533
|
kind: 'exact',
|
|
533
534
|
path: PRESET_LIMITS_PATH,
|
|
534
535
|
handler: async (req, res) => {
|
package/lib/routes/metrics.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getWebServer } from './guard.js';
|
|
1
2
|
// lib/ops-metrics.js — Prometheus / OpenMetrics export route (#373).
|
|
2
3
|
import { METRICS_PATH } from './paths.js';
|
|
3
4
|
import { isTrustedBridgeRequest, isKeyPaused, isKeyRevoked } from '../pool.js';
|
|
@@ -10,7 +11,7 @@ import { hasModelQuotaConfig, isModelQuotaAvailable } from '../model-quota.js';
|
|
|
10
11
|
export function registerMetricsRoutes(ctx, deps) {
|
|
11
12
|
const { buildRuntime, poolState } = deps;
|
|
12
13
|
|
|
13
|
-
ctx.effect(() => ctx.
|
|
14
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
14
15
|
kind: 'exact',
|
|
15
16
|
path: METRICS_PATH,
|
|
16
17
|
handler: async (req, res) => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getWebServer } from './guard.js';
|
|
1
2
|
import { json, readJson, isTrustedBridgeRequest } from '../http-bridge.js';
|
|
2
3
|
import { QUICK_ACTION_PATH } from './paths.js';
|
|
3
4
|
import { keyTail, isKeyPaused } from '../pool.js';
|
|
@@ -9,7 +10,7 @@ import { keyTail, isKeyPaused } from '../pool.js';
|
|
|
9
10
|
export function registerQuickActionRoutes(ctx, deps) {
|
|
10
11
|
const { buildRuntime, pushEvent, circuitBreaker } = deps;
|
|
11
12
|
|
|
12
|
-
ctx.effect(() => ctx.
|
|
13
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
13
14
|
kind: 'exact',
|
|
14
15
|
path: QUICK_ACTION_PATH,
|
|
15
16
|
handler: async (req, res) => {
|
package/lib/routes/status.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getWebServer } from './guard.js';
|
|
1
2
|
import { getModelQuotaStatus, isModelQuotaAvailable, hasModelQuotaConfig } from '../model-quota.js';
|
|
2
3
|
import { providerOfBase, basePoolForBase, modelPoolsForRef } from '../pool-index.js';
|
|
3
4
|
import { decryptSecret } from '../crypto-storage.js';
|
|
@@ -44,7 +45,7 @@ export function registerStatusRoutes(ctx, deps) {
|
|
|
44
45
|
// (a typo is otherwise silent), and how often rotation has fired.
|
|
45
46
|
//
|
|
46
47
|
// Key VALUES never leave the host — only the boolean fact that one exists.
|
|
47
|
-
ctx.effect(() => ctx.
|
|
48
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
48
49
|
kind: 'exact',
|
|
49
50
|
path: STATUS_PATH,
|
|
50
51
|
handler: async (req, res) => {
|
|
@@ -204,7 +205,7 @@ ctx.effect(() => ctx.webServer.register({
|
|
|
204
205
|
// #209: usage report - per-key requests/cost over the last N days.
|
|
205
206
|
// ?format=csv returns text/csv; ?days=N window (1..90, default 7).
|
|
206
207
|
|
|
207
|
-
ctx.effect(() => ctx.
|
|
208
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
208
209
|
kind: 'exact',
|
|
209
210
|
path: HEALTH_PATH,
|
|
210
211
|
handler: async (req, res) => {
|
package/lib/routes/telemetry.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getWebServer } from './guard.js';
|
|
1
2
|
// lib/ops-telemetry.js — usage + snapshot operational routes (#312 split from routes-ops.js).
|
|
2
3
|
import {
|
|
3
4
|
json,
|
|
@@ -71,7 +72,7 @@ export function registerTelemetryRoutes(ctx, deps) {
|
|
|
71
72
|
buildRuntime,
|
|
72
73
|
} = deps;
|
|
73
74
|
|
|
74
|
-
ctx.effect(() => ctx.
|
|
75
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
75
76
|
kind: 'exact',
|
|
76
77
|
path: USAGE_PATH,
|
|
77
78
|
handler: (req, res) => {
|
|
@@ -116,7 +117,7 @@ ctx.effect(() => ctx.webServer.register({
|
|
|
116
117
|
// Secret values never travel: only credential/env names. Token fields are
|
|
117
118
|
// exported as empty strings; on import they keep existing values when empty.
|
|
118
119
|
|
|
119
|
-
ctx.effect(() => ctx.
|
|
120
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
120
121
|
kind: 'exact',
|
|
121
122
|
path: SNAPSHOT_PATH,
|
|
122
123
|
handler: async (req, res) => {
|
|
@@ -162,7 +163,7 @@ ctx.effect(() => ctx.webServer.register({
|
|
|
162
163
|
}), 'dsh-key-rotation: snapshot route');
|
|
163
164
|
|
|
164
165
|
|
|
165
|
-
ctx.effect(() => ctx.
|
|
166
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
166
167
|
kind: 'exact',
|
|
167
168
|
path: TRACE_PATH,
|
|
168
169
|
handler: (req, res) => {
|
|
@@ -187,7 +188,7 @@ ctx.effect(() => ctx.webServer.register({
|
|
|
187
188
|
}), 'dsh-key-rotation: trace route');
|
|
188
189
|
|
|
189
190
|
|
|
190
|
-
ctx.effect(() => ctx.
|
|
191
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
191
192
|
kind: 'exact',
|
|
192
193
|
path: SIMULATE_PATH,
|
|
193
194
|
handler: async (req, res) => {
|
|
@@ -243,7 +244,7 @@ ctx.effect(() => ctx.webServer.register({
|
|
|
243
244
|
},
|
|
244
245
|
}), 'dsh-key-rotation: simulate route');
|
|
245
246
|
|
|
246
|
-
ctx.effect(() => ctx.
|
|
247
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
247
248
|
kind: 'exact',
|
|
248
249
|
path: DIAG_PATH,
|
|
249
250
|
handler: async (req, res) => {
|
package/lib/routes/testing.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getWebServer } from './guard.js';
|
|
1
2
|
// lib/ops-test.js — sandbox test + sandbox cache routes (#312 split from routes-ops.js).
|
|
2
3
|
import {
|
|
3
4
|
json,
|
|
@@ -29,7 +30,7 @@ export function registerTestRoutes(ctx, deps) {
|
|
|
29
30
|
} = deps;
|
|
30
31
|
|
|
31
32
|
// ── test route: dry-run a single key without rotation ──
|
|
32
|
-
ctx.effect(() => ctx.
|
|
33
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
33
34
|
kind: 'exact',
|
|
34
35
|
path: TEST_PATH,
|
|
35
36
|
handler: async (req, res) => {
|
|
@@ -105,7 +106,7 @@ ctx.effect(() => ctx.webServer.register({
|
|
|
105
106
|
// straight through.
|
|
106
107
|
// Read-only cache snapshot for clients (badge polling).
|
|
107
108
|
|
|
108
|
-
ctx.effect(() => ctx.
|
|
109
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
109
110
|
kind: 'exact',
|
|
110
111
|
path: SANDBOX_CACHE_PATH,
|
|
111
112
|
handler: (req, res) => {
|
|
@@ -125,7 +126,7 @@ ctx.effect(() => ctx.webServer.register({
|
|
|
125
126
|
// cannot be same-origin, so a shared secret is the gate).
|
|
126
127
|
|
|
127
128
|
// ── test matrix route: batch probe all configured keys (#490) ──
|
|
128
|
-
ctx.effect(() => ctx.
|
|
129
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
129
130
|
kind: 'exact',
|
|
130
131
|
path: TEST_MATRIX_PATH,
|
|
131
132
|
handler: async (req, res) => {
|
package/lib/routes/webhook.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getWebServer } from './guard.js';
|
|
1
2
|
import crypto from 'node:crypto';
|
|
2
3
|
// lib/ops-webhook.js — webhook interactive action route (#312 split from routes-ops.js, #388 telegram secret-token & answerCallbackQuery).
|
|
3
4
|
import {
|
|
@@ -36,7 +37,7 @@ export function registerWebhookActionRoute(ctx, deps) {
|
|
|
36
37
|
circuitBreaker,
|
|
37
38
|
} = deps;
|
|
38
39
|
|
|
39
|
-
ctx.effect(() => ctx.
|
|
40
|
+
ctx.effect(() => getWebServer(ctx).register({
|
|
40
41
|
kind: 'exact',
|
|
41
42
|
path: WEBHOOK_ACTION_PATH,
|
|
42
43
|
handler: async (req, res) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-key-rotation",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.84",
|
|
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": [
|
|
@@ -63,9 +63,9 @@
|
|
|
63
63
|
"node": ">=18"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
|
-
"@deepseek-ai/cordis": "^4.0.1",
|
|
67
|
-
"@deepseek-ai/dsh-llm": "^0.1.7-rc.2 || >=0.2.0-rc.1 <0.2.1-0 || >=0.2.1-alpha.1 <0.2.2-0",
|
|
68
|
-
"@deepseek-ai/schemastery": "^3.18.4"
|
|
66
|
+
"@deepseek-ai/cordis": "^4.0.1 || >=4.0.6-alpha.1 <5.0.0-0",
|
|
67
|
+
"@deepseek-ai/dsh-llm": "^0.1.7-rc.2 || >=0.2.0-rc.1 <0.2.1-0 || >=0.2.1-alpha.1 <0.2.2-0 || >=0.2.2-alpha.1 <0.2.3-0",
|
|
68
|
+
"@deepseek-ai/schemastery": "^3.18.4 || >=3.18.6-alpha.1 <4.0.0-0"
|
|
69
69
|
},
|
|
70
70
|
"scripts": {
|
|
71
71
|
"test": "node tools/test.mjs",
|