@vymalo/opencode-ratelimit 0.11.0 → 0.14.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/dist/config.d.ts +14 -14
- package/dist/config.js +103 -108
- package/dist/config.js.map +1 -1
- package/dist/headers.d.ts +15 -15
- package/dist/headers.js +71 -70
- package/dist/headers.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib.js +1 -0
- package/dist/lib.js.map +1 -1
- package/dist/logging.d.ts +6 -6
- package/dist/logging.js +58 -62
- package/dist/logging.js.map +1 -1
- package/dist/opencode.d.ts +4 -4
- package/dist/opencode.js +51 -56
- package/dist/opencode.js.map +1 -1
- package/dist/plugin.d.ts +49 -49
- package/dist/plugin.js +442 -423
- package/dist/plugin.js.map +1 -1
- package/dist/types.d.ts +53 -53
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
package/dist/logging.js
CHANGED
|
@@ -1,72 +1,68 @@
|
|
|
1
1
|
export const LOG_LEVEL_PRIORITY = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
trace: 5,
|
|
3
|
+
debug: 10,
|
|
4
|
+
info: 20,
|
|
5
|
+
warn: 30,
|
|
6
|
+
error: 40
|
|
7
7
|
};
|
|
8
8
|
export const DEFAULT_LOG_LEVEL = "info";
|
|
9
9
|
function redactFields(fields) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
10
|
+
if (!fields) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
const redacted = {};
|
|
14
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
15
|
+
if (/token|secret|password|authorization/i.test(key)) {
|
|
16
|
+
redacted[key] = "[redacted]";
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
redacted[key] = value;
|
|
20
|
+
}
|
|
21
|
+
return redacted;
|
|
22
22
|
}
|
|
23
23
|
export function createJsonConsoleLogger(minLevel = DEFAULT_LOG_LEVEL) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
24
|
+
const minPriority = LOG_LEVEL_PRIORITY[minLevel];
|
|
25
|
+
const write = (level, event, fields) => {
|
|
26
|
+
if (LOG_LEVEL_PRIORITY[level] < minPriority) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const payload = {
|
|
30
|
+
ts: new Date().toISOString(),
|
|
31
|
+
level,
|
|
32
|
+
event,
|
|
33
|
+
...redactFields(fields) ?? {}
|
|
34
|
+
};
|
|
35
|
+
const line = JSON.stringify(payload);
|
|
36
|
+
if (level === "error") {
|
|
37
|
+
console.error(line);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (level === "warn") {
|
|
41
|
+
console.warn(line);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
console.log(line);
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
trace: (event, fields) => write("trace", event, fields),
|
|
48
|
+
debug: (event, fields) => write("debug", event, fields),
|
|
49
|
+
info: (event, fields) => write("info", event, fields),
|
|
50
|
+
warn: (event, fields) => write("warn", event, fields),
|
|
51
|
+
error: (event, fields) => write("error", event, fields)
|
|
52
|
+
};
|
|
53
53
|
}
|
|
54
54
|
export function fromOpenCodeLogLevel(value) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
case "ERROR":
|
|
67
|
-
return "error";
|
|
68
|
-
default:
|
|
69
|
-
return undefined;
|
|
70
|
-
}
|
|
55
|
+
if (typeof value !== "string") {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
switch (value.toUpperCase()) {
|
|
59
|
+
// DEBUG unlocks the most-verbose `trace` tier (host has no finer level).
|
|
60
|
+
case "DEBUG": return "trace";
|
|
61
|
+
case "INFO": return "info";
|
|
62
|
+
case "WARN": return "warn";
|
|
63
|
+
case "ERROR": return "error";
|
|
64
|
+
default: return undefined;
|
|
65
|
+
}
|
|
71
66
|
}
|
|
67
|
+
|
|
72
68
|
//# sourceMappingURL=logging.js.map
|
package/dist/logging.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"
|
|
1
|
+
{"mappings":"AAIA,OAAO,MAAM,qBAA+C;CAC1D,OAAO;CACP,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;AACT;AAEA,OAAO,MAAM,oBAA8B;AAc3C,SAAS,aAAa,QAA2C;CAC/D,IAAI,CAAC,QAAQ;EACX,OAAO;CACT;CACA,MAAM,WAAsB,CAAC;CAC7B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAAG;EACjD,IAAI,uCAAuC,KAAK,GAAG,GAAG;GACpD,SAAS,OAAO;GAChB;EACF;EACA,SAAS,OAAO;CAClB;CACA,OAAO;AACT;AAEA,OAAO,SAAS,wBAAwB,WAAqB,mBAA2B;CACtF,MAAM,cAAc,mBAAmB;CAEvC,MAAM,SAAS,OAAiB,OAAe,WAA6B;EAC1E,IAAI,mBAAmB,SAAS,aAAa;GAC3C;EACF;EACA,MAAM,UAAU;GACd,IAAI,IAAI,KAAK,CAAC,CAAC,YAAY;GAC3B;GACA;GACA,GAAI,aAAa,MAAM,KAAK,CAAC;EAC/B;EACA,MAAM,OAAO,KAAK,UAAU,OAAO;EACnC,IAAI,UAAU,SAAS;GACrB,QAAQ,MAAM,IAAI;GAClB;EACF;EACA,IAAI,UAAU,QAAQ;GACpB,QAAQ,KAAK,IAAI;GACjB;EACF;EACA,QAAQ,IAAI,IAAI;CAClB;CAEA,OAAO;EACL,QAAQ,OAAO,WAAW,MAAM,SAAS,OAAO,MAAM;EACtD,QAAQ,OAAO,WAAW,MAAM,SAAS,OAAO,MAAM;EACtD,OAAO,OAAO,WAAW,MAAM,QAAQ,OAAO,MAAM;EACpD,OAAO,OAAO,WAAW,MAAM,QAAQ,OAAO,MAAM;EACpD,QAAQ,OAAO,WAAW,MAAM,SAAS,OAAO,MAAM;CACxD;AACF;AAEA,OAAO,SAAS,qBAAqB,OAAsC;CACzE,IAAI,OAAO,UAAU,UAAU;EAC7B,OAAO;CACT;CACA,QAAQ,MAAM,YAAY,GAA1B;;EAEE,KAAK,SACH,OAAO;EACT,KAAK,QACH,OAAO;EACT,KAAK,QACH,OAAO;EACT,KAAK,SACH,OAAO;EACT,SACE,OAAO;CACX;AACF","names":[],"sources":["../src/logging.ts"],"version":3,"file":"logging.js","sourceRoot":""}
|
package/dist/opencode.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { Plugin } from "@opencode-ai/plugin";
|
|
2
2
|
import { type Logger } from "./logging.js";
|
|
3
3
|
export interface OpenCodePluginFactoryOptions {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
logger?: Logger;
|
|
5
|
+
fetchImpl?: typeof fetch;
|
|
6
|
+
now?: () => number;
|
|
7
|
+
sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
|
|
8
8
|
}
|
|
9
9
|
export declare function createOpencodeRatelimitPlugin(factoryOptions?: OpenCodePluginFactoryOptions): Plugin;
|
|
10
10
|
export declare const OpencodeRatelimitPlugin: Plugin;
|
package/dist/opencode.js
CHANGED
|
@@ -2,66 +2,61 @@ import { createJsonConsoleLogger, DEFAULT_LOG_LEVEL, fromOpenCodeLogLevel, LOG_L
|
|
|
2
2
|
import { installRateLimiter } from "./plugin.js";
|
|
3
3
|
const PLUGIN_SERVICE_NAME = "opencode-ratelimit-plugin";
|
|
4
4
|
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
* Pipe plugin logs through OpenCode's `client.app.log` so they show up in the
|
|
6
|
+
* host's structured log stream, with the JSON console as a reliable fallback.
|
|
7
|
+
* Mirrors the pattern used by `@vymalo/opencode-oauth2` and `-models-info`.
|
|
8
|
+
*/
|
|
9
9
|
function createOpenCodeLogger(client, getMinLevel) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
info: (event, fields) => write("info", event, fields),
|
|
44
|
-
warn: (event, fields) => write("warn", event, fields),
|
|
45
|
-
error: (event, fields) => write("error", event, fields)
|
|
46
|
-
};
|
|
10
|
+
const fallback = createJsonConsoleLogger("debug");
|
|
11
|
+
// OpenCode already captures plugin logs via client.app.log (and filters them
|
|
12
|
+
// by its own log level). Mirroring every event to stdout on top of that just
|
|
13
|
+
// floods the terminal, so only mirror warn/error to the JSON console by
|
|
14
|
+
// default; set VYMALO_PLUGIN_CONSOLE_LOG=1 to restore full console output.
|
|
15
|
+
const consoleAll = /^(1|true|yes|on)$/i.test(process.env.VYMALO_PLUGIN_CONSOLE_LOG ?? "");
|
|
16
|
+
const write = (level, event, fields) => {
|
|
17
|
+
if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[getMinLevel()]) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (consoleAll || level === "warn" || level === "error") {
|
|
21
|
+
fallback[level](event, fields);
|
|
22
|
+
}
|
|
23
|
+
// The host's log API has no `trace` level — fold it onto `debug` so the most
|
|
24
|
+
// verbose tier still reaches the structured stream (it's already gated above
|
|
25
|
+
// by `getMinLevel`, which DEBUG maps to `trace`).
|
|
26
|
+
const hostLevel = level === "trace" ? "debug" : level;
|
|
27
|
+
void client.app.log({ body: {
|
|
28
|
+
service: PLUGIN_SERVICE_NAME,
|
|
29
|
+
level: hostLevel,
|
|
30
|
+
message: event,
|
|
31
|
+
extra: fields
|
|
32
|
+
} }).catch(() => {
|
|
33
|
+
/* best-effort */
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
trace: (event, fields) => write("trace", event, fields),
|
|
38
|
+
debug: (event, fields) => write("debug", event, fields),
|
|
39
|
+
info: (event, fields) => write("info", event, fields),
|
|
40
|
+
warn: (event, fields) => write("warn", event, fields),
|
|
41
|
+
error: (event, fields) => write("error", event, fields)
|
|
42
|
+
};
|
|
47
43
|
}
|
|
48
44
|
export function createOpencodeRatelimitPlugin(factoryOptions = {}) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
};
|
|
63
|
-
};
|
|
45
|
+
return async ({ client }) => {
|
|
46
|
+
let currentLogLevel = DEFAULT_LOG_LEVEL;
|
|
47
|
+
const logger = factoryOptions.logger ?? createOpenCodeLogger(client, () => currentLogLevel);
|
|
48
|
+
return { config: async (config) => {
|
|
49
|
+
currentLogLevel = fromOpenCodeLogLevel(config.logLevel) ?? DEFAULT_LOG_LEVEL;
|
|
50
|
+
installRateLimiter(config, {
|
|
51
|
+
logger,
|
|
52
|
+
fetchImpl: factoryOptions.fetchImpl,
|
|
53
|
+
now: factoryOptions.now,
|
|
54
|
+
sleep: factoryOptions.sleep
|
|
55
|
+
});
|
|
56
|
+
} };
|
|
57
|
+
};
|
|
64
58
|
}
|
|
65
59
|
export const OpencodeRatelimitPlugin = createOpencodeRatelimitPlugin();
|
|
66
60
|
export default OpencodeRatelimitPlugin;
|
|
61
|
+
|
|
67
62
|
//# sourceMappingURL=opencode.js.map
|
package/dist/opencode.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"
|
|
1
|
+
{"mappings":"AAEA,SACE,yBACA,mBACA,sBAEA,0BAGK;AACP,SAAkC,0BAA0B;AAE5D,MAAM,sBAAsB;;;;;;AAgB5B,SAAS,qBAAqB,QAA+B,aAAqC;CAChG,MAAM,WAAW,wBAAwB,OAAO;;;;;CAKhD,MAAM,aAAa,qBAAqB,KAAK,QAAQ,IAAI,6BAA6B,EAAE;CAExF,MAAM,SAAS,OAAiB,OAAe,WAAuB;EACpE,IAAI,mBAAmB,SAAS,mBAAmB,YAAY,IAAI;GACjE;EACF;EACA,IAAI,cAAc,UAAU,UAAU,UAAU,SAAS;GACvD,SAAS,MAAM,CAAC,OAAO,MAAM;EAC/B;;;;EAIA,MAAM,YAAY,UAAU,UAAU,UAAU;EAChD,KAAK,OAAO,IACT,IAAI,EACH,MAAM;GACJ,SAAS;GACT,OAAO;GACP,SAAS;GACT,OAAO;EACT,EACF,CAAC,CAAC,CACD,YAAY;;EAEb,CAAC;CACL;CAEA,OAAO;EACL,QAAQ,OAAO,WAAW,MAAM,SAAS,OAAO,MAAM;EACtD,QAAQ,OAAO,WAAW,MAAM,SAAS,OAAO,MAAM;EACtD,OAAO,OAAO,WAAW,MAAM,QAAQ,OAAO,MAAM;EACpD,OAAO,OAAO,WAAW,MAAM,QAAQ,OAAO,MAAM;EACpD,QAAQ,OAAO,WAAW,MAAM,SAAS,OAAO,MAAM;CACxD;AACF;AAEA,OAAO,SAAS,8BACd,iBAA+C,CAAC,GACxC;CACR,OAAO,OAAO,EAAE,aAAa;EAC3B,IAAI,kBAA4B;EAChC,MAAM,SAAS,eAAe,UAAU,qBAAqB,cAAc,eAAe;EAE1F,OAAO,EACL,QAAQ,OAAO,WAA2B;GACxC,kBAAkB,qBAAqB,OAAO,QAAQ,KAAK;GAC3D,mBAAmB,QAA8B;IAC/C;IACA,WAAW,eAAe;IAC1B,KAAK,eAAe;IACpB,OAAO,eAAe;GACxB,CAAC;EACH,EACF;CACF;AACF;AAEA,OAAO,MAAM,0BAAkC,8BAA8B;AAE7E,eAAe","names":[],"sources":["../src/opencode.ts"],"version":3,"file":"opencode.js","sourceRoot":""}
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,68 +1,68 @@
|
|
|
1
1
|
import type { Logger } from "./logging.js";
|
|
2
2
|
import type { RateLimitOptions } from "./types.js";
|
|
3
3
|
/** Fallback backoff when a 429 carries no `x-ratelimit-reset` and no `Retry-After`. */
|
|
4
|
-
export declare const DEFAULT_BACKOFF_MS =
|
|
4
|
+
export declare const DEFAULT_BACKOFF_MS = 1e3;
|
|
5
5
|
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
* Mutable, in-memory rate-limit state for a single bucket (a provider, or a
|
|
7
|
+
* `(provider, model)` pair when `scope: "model"`). Lives for the process
|
|
8
|
+
* lifetime in the provider's state store. Never persisted — a reset window is
|
|
9
|
+
* measured in seconds, so survival across process boots is pointless.
|
|
10
|
+
*/
|
|
11
11
|
export interface ProviderRateState {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Epoch ms until which new requests should be held back. 0 = no cooldown.
|
|
14
|
+
* The sole gate driver — set from a response's `x-ratelimit-reset` (when
|
|
15
|
+
* `remaining` hits 0, and the matched tier is `"wait"`) or from a 429 backoff.
|
|
16
|
+
*/
|
|
17
|
+
cooldownUntilMs: number;
|
|
18
|
+
/** The `maxWaitMs` of the tier that armed the current cooldown (0 = unlimited). */
|
|
19
|
+
cooldownMaxWaitMs: number;
|
|
20
|
+
/** A single in-flight wait shared by every caller during a cooldown window. */
|
|
21
|
+
cooldownPromise?: Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Epoch ms at which {@link cooldownPromise} is scheduled to resolve. Lets a
|
|
24
|
+
* caller that needs a shorter wait detect a too-long shared timer and fall
|
|
25
|
+
* back to its own sleep, so it never waits past its required time / `maxWaitMs`.
|
|
26
|
+
*/
|
|
27
|
+
cooldownPromiseUntilMs?: number;
|
|
28
28
|
}
|
|
29
29
|
export declare function createProviderState(): ProviderRateState;
|
|
30
30
|
export interface RateLimitDeps {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
logger: Logger;
|
|
32
|
+
/** Defaults to `Date.now`. */
|
|
33
|
+
now?: () => number;
|
|
34
|
+
/** Defaults to a real `setTimeout`-based, abort-aware sleep. */
|
|
35
|
+
sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
|
|
36
|
+
/** Underlying fetch when a provider has no pre-existing `options.fetch`. Defaults to `globalThis.fetch`. */
|
|
37
|
+
fetchImpl?: typeof fetch;
|
|
38
38
|
}
|
|
39
39
|
export interface ProviderConfigLike {
|
|
40
|
-
|
|
40
|
+
options?: Record<string, unknown>;
|
|
41
41
|
}
|
|
42
42
|
export interface InstallConfigInput {
|
|
43
|
-
|
|
43
|
+
provider?: Record<string, ProviderConfigLike | undefined>;
|
|
44
44
|
}
|
|
45
45
|
/** A per-bucket state store (key = provider id, or `${providerId}\0${model}`). */
|
|
46
46
|
export type RateStateStore = Map<string, ProviderRateState>;
|
|
47
47
|
/**
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
* Walk every provider in the assembled OpenCode config; for each one that has
|
|
49
|
+
* opted in via `options.meta.rateLimit`, wrap its `options.fetch` with a
|
|
50
|
+
* rate-limit-aware fetch. Synchronous — all real work happens lazily inside the
|
|
51
|
+
* wrapper at request time.
|
|
52
|
+
*/
|
|
53
53
|
export declare function installRateLimiter(input: InstallConfigInput, deps: RateLimitDeps): void;
|
|
54
54
|
/**
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
55
|
+
* Build the fetch wrapper for one provider. The wrapper:
|
|
56
|
+
* 1. Resolves the bucket (provider, or `(provider, model)` under `scope: "model"`).
|
|
57
|
+
* 2. Pre-request gate: if that bucket's cooldown is armed, waits until it clears.
|
|
58
|
+
* 3. Sends the request via the underlying fetch.
|
|
59
|
+
* 4. Reads the rate-limit headers; selects the policy tier by reset magnitude.
|
|
60
|
+
* On `remaining: 0` it arms the gate for the next callers (only when the
|
|
61
|
+
* matched tier is `"wait"`).
|
|
62
|
+
* 5. On a 429: a `"wait"` tier waits the reset window and retries (up to the
|
|
63
|
+
* tier's `maxRetries`); an `"error"` tier surfaces the 429 immediately.
|
|
64
|
+
*
|
|
65
|
+
* The Response is returned untouched (no `.clone()`) — we only read `status`
|
|
66
|
+
* and `headers`, so the body stream is delivered to OpenCode intact.
|
|
67
|
+
*/
|
|
68
68
|
export declare function makeRateLimitFetch(providerId: string, opts: RateLimitOptions, store: RateStateStore, deps: RateLimitDeps, delegate?: typeof fetch): typeof fetch;
|