i18n-ai-translate
Version:
AI-powered localization CLI, Node library, and GitHub Action. Translate i18next JSON, Gettext PO, Java .properties, and iOS .strings with ChatGPT, Claude, Gemini, or local Ollama models.
78 lines • 2.96 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("./utils");
/**
* Usage pattern
* -------------
* await limiter.wait(estimatedTokens); // BEFORE the request
* ... make API request ...
* limiter.apiCalled(actualTokens); // AFTER the request
*/
class TokenRateLimiter {
lastAPICall;
delayBetweenCallsMs; // optional-legacy
maxTokensPerMinute = 200_000;
windowStart;
tokensThisWindow;
verboseLogging;
constructor(delayBetweenCallsMs, verboseLogging) {
this.lastAPICall = null;
this.delayBetweenCallsMs = delayBetweenCallsMs; // keep for backwards-compat
this.windowStart = null;
this.tokensThisWindow = 0;
this.verboseLogging = verboseLogging;
}
/**
* Call immediately **after** a successful request.
* @param tokenCount Prompt + completion tokens the request actually consumed
*/
apiCalled(tokenCount) {
const now = Date.now();
// Rollover the 60 s token window if it has expired
if (!this.windowStart || now - this.windowStart >= 60_000) {
this.windowStart = now;
this.tokensThisWindow = 0;
}
this.tokensThisWindow += tokenCount;
this.lastAPICall = now;
}
/**
* Call immediately **before** you send a request.
* It sleeps long enough so that:
* • you do not exceed 200 000 tokens in any 60 s window
* • you respect `delayBetweenCallsMs` (if you were using that before)
*
* @param tokenCount Expected token usage for the upcoming request
*/
async wait(tokenCount) {
const now = Date.now();
// Reset rolling window if needed
if (!this.windowStart || now - this.windowStart >= 60_000) {
this.windowStart = now;
this.tokensThisWindow = 0;
}
// How long must we wait for the token budget?
let timeToWait = this.tokensThisWindow + tokenCount > this.maxTokensPerMinute
? 60_000 - (now - this.windowStart)
: 0;
// Respect a fixed inter-call delay, if configured
if (this.lastAPICall !== null) {
const gap = this.delayBetweenCallsMs - (now - this.lastAPICall);
if (gap > timeToWait)
timeToWait = gap;
}
if (timeToWait > 0) {
if (this.verboseLogging) {
const tokenMsg = `${this.tokensThisWindow}/${this.maxTokensPerMinute} tokens used`;
const gapMsg = this.delayBetweenCallsMs
? `, ${this.delayBetweenCallsMs} ms min-gap`
: "";
(0, utils_1.printInfo)(`\nRateLimiter | Waiting ${timeToWait} ms (` +
`${tokenMsg}${gapMsg})`);
}
await (0, utils_1.delay)(timeToWait);
}
}
}
exports.default = TokenRateLimiter;
//# sourceMappingURL=token_rate_limiter.js.map