opencode-quotas 0.0.1
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/README.md +344 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/src/cli.d.ts +3 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +42 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/constants.d.ts +9 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +15 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/defaults.d.ts +3 -0
- package/dist/src/defaults.d.ts.map +1 -0
- package/dist/src/defaults.js +52 -0
- package/dist/src/defaults.js.map +1 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +265 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interfaces.d.ts +197 -0
- package/dist/src/interfaces.d.ts.map +1 -0
- package/dist/src/interfaces.js +2 -0
- package/dist/src/interfaces.js.map +1 -0
- package/dist/src/logger.d.ts +14 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +44 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/plugin-state.d.ts +20 -0
- package/dist/src/plugin-state.d.ts.map +1 -0
- package/dist/src/plugin-state.js +53 -0
- package/dist/src/plugin-state.js.map +1 -0
- package/dist/src/providers/antigravity/auth.d.ts +12 -0
- package/dist/src/providers/antigravity/auth.d.ts.map +1 -0
- package/dist/src/providers/antigravity/auth.js +109 -0
- package/dist/src/providers/antigravity/auth.js.map +1 -0
- package/dist/src/providers/antigravity/index.d.ts +2 -0
- package/dist/src/providers/antigravity/index.d.ts.map +1 -0
- package/dist/src/providers/antigravity/index.js +2 -0
- package/dist/src/providers/antigravity/index.js.map +1 -0
- package/dist/src/providers/antigravity/provider.d.ts +34 -0
- package/dist/src/providers/antigravity/provider.d.ts.map +1 -0
- package/dist/src/providers/antigravity/provider.js +216 -0
- package/dist/src/providers/antigravity/provider.js.map +1 -0
- package/dist/src/providers/codex.d.ts +4 -0
- package/dist/src/providers/codex.d.ts.map +1 -0
- package/dist/src/providers/codex.js +242 -0
- package/dist/src/providers/codex.js.map +1 -0
- package/dist/src/providers/github.d.ts +4 -0
- package/dist/src/providers/github.d.ts.map +1 -0
- package/dist/src/providers/github.js +139 -0
- package/dist/src/providers/github.js.map +1 -0
- package/dist/src/quota-cache.d.ts +26 -0
- package/dist/src/quota-cache.d.ts.map +1 -0
- package/dist/src/quota-cache.js +107 -0
- package/dist/src/quota-cache.js.map +1 -0
- package/dist/src/registry.d.ts +3 -0
- package/dist/src/registry.d.ts.map +1 -0
- package/dist/src/registry.js +23 -0
- package/dist/src/registry.js.map +1 -0
- package/dist/src/services/aggregation-service.d.ts +34 -0
- package/dist/src/services/aggregation-service.d.ts.map +1 -0
- package/dist/src/services/aggregation-service.js +89 -0
- package/dist/src/services/aggregation-service.js.map +1 -0
- package/dist/src/services/config-loader.d.ts +25 -0
- package/dist/src/services/config-loader.d.ts.map +1 -0
- package/dist/src/services/config-loader.js +105 -0
- package/dist/src/services/config-loader.js.map +1 -0
- package/dist/src/services/history-service.d.ts +15 -0
- package/dist/src/services/history-service.d.ts.map +1 -0
- package/dist/src/services/history-service.js +99 -0
- package/dist/src/services/history-service.js.map +1 -0
- package/dist/src/services/prediction-engine.d.ts +47 -0
- package/dist/src/services/prediction-engine.d.ts.map +1 -0
- package/dist/src/services/prediction-engine.js +94 -0
- package/dist/src/services/prediction-engine.js.map +1 -0
- package/dist/src/services/quota-service.d.ts +41 -0
- package/dist/src/services/quota-service.d.ts.map +1 -0
- package/dist/src/services/quota-service.js +257 -0
- package/dist/src/services/quota-service.js.map +1 -0
- package/dist/src/tools/quotas.d.ts +11 -0
- package/dist/src/tools/quotas.d.ts.map +1 -0
- package/dist/src/tools/quotas.js +62 -0
- package/dist/src/tools/quotas.js.map +1 -0
- package/dist/src/ui/progress-bar.d.ts +20 -0
- package/dist/src/ui/progress-bar.d.ts.map +1 -0
- package/dist/src/ui/progress-bar.js +150 -0
- package/dist/src/ui/progress-bar.js.map +1 -0
- package/dist/src/ui/quota-table.d.ts +15 -0
- package/dist/src/ui/quota-table.d.ts.map +1 -0
- package/dist/src/ui/quota-table.js +136 -0
- package/dist/src/ui/quota-table.js.map +1 -0
- package/dist/src/utils/debug.d.ts +1 -0
- package/dist/src/utils/debug.d.ts.map +1 -0
- package/dist/src/utils/debug.js +3 -0
- package/dist/src/utils/debug.js.map +1 -0
- package/dist/src/utils/paths.d.ts +7 -0
- package/dist/src/utils/paths.d.ts.map +1 -0
- package/dist/src/utils/paths.js +37 -0
- package/dist/src/utils/paths.js.map +1 -0
- package/dist/src/utils/time.d.ts +3 -0
- package/dist/src/utils/time.d.ts.map +1 -0
- package/dist/src/utils/time.js +38 -0
- package/dist/src/utils/time.js.map +1 -0
- package/dist/src/utils/validation.d.ts +6 -0
- package/dist/src/utils/validation.d.ts.map +1 -0
- package/dist/src/utils/validation.js +66 -0
- package/dist/src/utils/validation.js.map +1 -0
- package/package.json +42 -0
- package/src/cli.ts +53 -0
- package/src/constants.ts +17 -0
- package/src/defaults.ts +53 -0
- package/src/index.ts +338 -0
- package/src/interfaces.ts +258 -0
- package/src/logger.ts +55 -0
- package/src/plugin-state.ts +65 -0
- package/src/providers/antigravity/auth.ts +163 -0
- package/src/providers/antigravity/index.ts +1 -0
- package/src/providers/antigravity/provider.ts +337 -0
- package/src/providers/codex.ts +327 -0
- package/src/providers/github.ts +161 -0
- package/src/quota-cache.ts +157 -0
- package/src/registry.ts +30 -0
- package/src/services/aggregation-service.ts +116 -0
- package/src/services/config-loader.ts +124 -0
- package/src/services/history-service.ts +116 -0
- package/src/services/prediction-engine.ts +133 -0
- package/src/services/quota-service.ts +343 -0
- package/src/tools/quotas.ts +78 -0
- package/src/ui/progress-bar.ts +204 -0
- package/src/ui/quota-table.ts +173 -0
- package/src/utils/debug.ts +1 -0
- package/src/utils/paths.ts +41 -0
- package/src/utils/time.ts +40 -0
- package/src/utils/validation.ts +63 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { writeFile, readFile } from "node:fs/promises";
|
|
2
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { HISTORY_FILE } from "../utils/paths";
|
|
5
|
+
import { logger } from "../logger";
|
|
6
|
+
export class HistoryService {
|
|
7
|
+
historyPath;
|
|
8
|
+
data = {};
|
|
9
|
+
maxWindowMs = 24 * 60 * 60 * 1000; // Keep 24 hours of history
|
|
10
|
+
saveTimeout = null;
|
|
11
|
+
constructor(customPath) {
|
|
12
|
+
this.historyPath = customPath || HISTORY_FILE();
|
|
13
|
+
}
|
|
14
|
+
async init() {
|
|
15
|
+
try {
|
|
16
|
+
const dir = join(this.historyPath, "..");
|
|
17
|
+
if (!existsSync(dir)) {
|
|
18
|
+
mkdirSync(dir, { recursive: true });
|
|
19
|
+
}
|
|
20
|
+
if (existsSync(this.historyPath)) {
|
|
21
|
+
const raw = await readFile(this.historyPath, "utf-8");
|
|
22
|
+
this.data = JSON.parse(raw);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
logger.error("history-service:init_failed", { path: this.historyPath, error: e });
|
|
27
|
+
this.data = {};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async append(snapshot) {
|
|
31
|
+
const timestamp = Date.now();
|
|
32
|
+
let changed = false;
|
|
33
|
+
for (const quota of snapshot) {
|
|
34
|
+
if (!this.data[quota.id]) {
|
|
35
|
+
this.data[quota.id] = [];
|
|
36
|
+
}
|
|
37
|
+
this.data[quota.id].push({
|
|
38
|
+
timestamp,
|
|
39
|
+
used: quota.used,
|
|
40
|
+
limit: quota.limit
|
|
41
|
+
});
|
|
42
|
+
// Prune old data for this quota
|
|
43
|
+
const cutoff = timestamp - this.maxWindowMs;
|
|
44
|
+
const originalLength = this.data[quota.id].length;
|
|
45
|
+
this.data[quota.id] = this.data[quota.id].filter(p => p.timestamp >= cutoff);
|
|
46
|
+
if (this.data[quota.id].length !== originalLength || originalLength > 0) {
|
|
47
|
+
changed = true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (changed || snapshot.length > 0) {
|
|
51
|
+
this.save();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
getHistory(quotaId, windowMs) {
|
|
55
|
+
const now = Date.now();
|
|
56
|
+
const cutoff = now - windowMs;
|
|
57
|
+
const history = this.data[quotaId] || [];
|
|
58
|
+
return history.filter(p => p.timestamp >= cutoff);
|
|
59
|
+
}
|
|
60
|
+
setMaxAge(hours) {
|
|
61
|
+
this.maxWindowMs = hours * 60 * 60 * 1000;
|
|
62
|
+
}
|
|
63
|
+
async pruneAll() {
|
|
64
|
+
const now = Date.now();
|
|
65
|
+
const cutoff = now - this.maxWindowMs;
|
|
66
|
+
let changed = false;
|
|
67
|
+
for (const id in this.data) {
|
|
68
|
+
const originalLen = this.data[id].length;
|
|
69
|
+
this.data[id] = this.data[id].filter(p => p.timestamp >= cutoff);
|
|
70
|
+
if (this.data[id].length !== originalLen) {
|
|
71
|
+
changed = true;
|
|
72
|
+
}
|
|
73
|
+
// Remove key if empty to free memory
|
|
74
|
+
if (this.data[id].length === 0) {
|
|
75
|
+
delete this.data[id];
|
|
76
|
+
changed = true;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (changed) {
|
|
80
|
+
this.save();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
save() {
|
|
84
|
+
if (this.saveTimeout) {
|
|
85
|
+
clearTimeout(this.saveTimeout);
|
|
86
|
+
}
|
|
87
|
+
this.saveTimeout = setTimeout(async () => {
|
|
88
|
+
try {
|
|
89
|
+
await writeFile(this.historyPath, JSON.stringify(this.data, null, 2), "utf-8");
|
|
90
|
+
logger.debug("history-service:save_success", { path: this.historyPath });
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
logger.error("history-service:save_failed", { path: this.historyPath, error: e });
|
|
94
|
+
}
|
|
95
|
+
this.saveTimeout = null;
|
|
96
|
+
}, 5000);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=history-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-service.js","sourceRoot":"","sources":["../../../src/services/history-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type IPredictionEngine, type IHistoryService, type HistoryPoint } from "../interfaces";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration options for the prediction engine.
|
|
4
|
+
*/
|
|
5
|
+
export interface PredictionEngineConfig {
|
|
6
|
+
/**
|
|
7
|
+
* Default short time window for regression to capture spikes (minutes).
|
|
8
|
+
* Defaults to 5.
|
|
9
|
+
*/
|
|
10
|
+
predictionShortWindowMinutes?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Idle timeout in milliseconds. If the last data point is older than this,
|
|
13
|
+
* the prediction returns Infinity. Defaults to 5 minutes.
|
|
14
|
+
*/
|
|
15
|
+
idleTimeoutMs?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Prediction engine using dual-window linear regression.
|
|
19
|
+
*
|
|
20
|
+
* This implementation uses two time windows to calculate usage slopes:
|
|
21
|
+
* - Long window: Captures overall trend (default: 60 minutes)
|
|
22
|
+
* - Short window: Captures recent spikes (default: 5 minutes)
|
|
23
|
+
*
|
|
24
|
+
* The maximum of the two slopes is used for conservative estimation.
|
|
25
|
+
*/
|
|
26
|
+
export declare class LinearRegressionPredictionEngine implements IPredictionEngine {
|
|
27
|
+
private readonly historyService;
|
|
28
|
+
private readonly config;
|
|
29
|
+
constructor(historyService: IHistoryService, config?: PredictionEngineConfig);
|
|
30
|
+
/**
|
|
31
|
+
* Predicts time to limit in milliseconds using a dual-window linear regression approach.
|
|
32
|
+
* Returns Infinity if usage is decreasing, stable, or idle.
|
|
33
|
+
*/
|
|
34
|
+
predictTimeToLimit(quotaId: string, windowMinutes?: number, shortWindowMinutes?: number): number;
|
|
35
|
+
/**
|
|
36
|
+
* Calculates the slope (usage per ms) using linear regression for the given history points.
|
|
37
|
+
*/
|
|
38
|
+
calculateSlope(history: HistoryPoint[]): number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* A null prediction engine that always returns Infinity.
|
|
42
|
+
* Used when no history service is available.
|
|
43
|
+
*/
|
|
44
|
+
export declare class NullPredictionEngine implements IPredictionEngine {
|
|
45
|
+
predictTimeToLimit(_quotaId: string, _windowMinutes?: number, _shortWindowMinutes?: number): number;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=prediction-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prediction-engine.d.ts","sourceRoot":"","sources":["../../../src/services/prediction-engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAEhG;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC;;;OAGG;IACH,4BAA4B,CAAC,EAAE,MAAM,CAAC;IAEtC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,qBAAa,gCAAiC,YAAW,iBAAiB;IACtE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAkB;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmC;gBAE9C,cAAc,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,sBAAsB;IAQ5E;;;OAGG;IACH,kBAAkB,CACd,OAAO,EAAE,MAAM,EACf,aAAa,GAAE,MAAW,EAC1B,kBAAkB,CAAC,EAAE,MAAM,GAC5B,MAAM;IA8CT;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM;CAqBlD;AAED;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,iBAAiB;IAC1D,kBAAkB,CACd,QAAQ,EAAE,MAAM,EAChB,cAAc,GAAE,MAAW,EAC3B,mBAAmB,CAAC,EAAE,MAAM,GAC7B,MAAM;CAGZ"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prediction engine using dual-window linear regression.
|
|
3
|
+
*
|
|
4
|
+
* This implementation uses two time windows to calculate usage slopes:
|
|
5
|
+
* - Long window: Captures overall trend (default: 60 minutes)
|
|
6
|
+
* - Short window: Captures recent spikes (default: 5 minutes)
|
|
7
|
+
*
|
|
8
|
+
* The maximum of the two slopes is used for conservative estimation.
|
|
9
|
+
*/
|
|
10
|
+
export class LinearRegressionPredictionEngine {
|
|
11
|
+
historyService;
|
|
12
|
+
config;
|
|
13
|
+
constructor(historyService, config) {
|
|
14
|
+
this.historyService = historyService;
|
|
15
|
+
this.config = {
|
|
16
|
+
predictionShortWindowMinutes: config?.predictionShortWindowMinutes ?? 5,
|
|
17
|
+
idleTimeoutMs: config?.idleTimeoutMs ?? 5 * 60 * 1000,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Predicts time to limit in milliseconds using a dual-window linear regression approach.
|
|
22
|
+
* Returns Infinity if usage is decreasing, stable, or idle.
|
|
23
|
+
*/
|
|
24
|
+
predictTimeToLimit(quotaId, windowMinutes = 60, shortWindowMinutes) {
|
|
25
|
+
const longWindowMs = windowMinutes * 60 * 1000;
|
|
26
|
+
const shortWindowMin = shortWindowMinutes ?? this.config.predictionShortWindowMinutes;
|
|
27
|
+
const shortWindowMs = shortWindowMin * 60 * 1000;
|
|
28
|
+
const history = this.historyService.getHistory(quotaId, longWindowMs);
|
|
29
|
+
if (history.length < 2)
|
|
30
|
+
return Infinity;
|
|
31
|
+
// Idle Handling: If the last history point is older than the idle timeout,
|
|
32
|
+
// assume usage has stopped.
|
|
33
|
+
const lastPoint = history[history.length - 1];
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
if (now - lastPoint.timestamp > this.config.idleTimeoutMs) {
|
|
36
|
+
return Infinity;
|
|
37
|
+
}
|
|
38
|
+
// Long Slope
|
|
39
|
+
const mLong = this.calculateSlope(history);
|
|
40
|
+
// Short Slope: most recent data in short window or last 15% of points
|
|
41
|
+
const shortHistory = history.filter(p => p.timestamp > now - shortWindowMs);
|
|
42
|
+
// Ensure we have enough points in short history, or take the last 15%
|
|
43
|
+
let effectiveShortHistory = shortHistory;
|
|
44
|
+
if (effectiveShortHistory.length < 2) {
|
|
45
|
+
const fifteenPercentCount = Math.max(2, Math.ceil(history.length * 0.15));
|
|
46
|
+
effectiveShortHistory = history.slice(-fifteenPercentCount);
|
|
47
|
+
}
|
|
48
|
+
const mShort = this.calculateSlope(effectiveShortHistory);
|
|
49
|
+
// Conservative Estimation: use the maximum slope
|
|
50
|
+
const m = Math.max(mLong, mShort);
|
|
51
|
+
if (m <= 0)
|
|
52
|
+
return Infinity;
|
|
53
|
+
if (lastPoint.limit === null)
|
|
54
|
+
return Infinity;
|
|
55
|
+
const remaining = lastPoint.limit - lastPoint.used;
|
|
56
|
+
if (remaining <= 0)
|
|
57
|
+
return 0;
|
|
58
|
+
const msFromLastPoint = remaining / m;
|
|
59
|
+
const elapsedSinceLastPoint = now - lastPoint.timestamp;
|
|
60
|
+
return Math.max(0, msFromLastPoint - elapsedSinceLastPoint);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Calculates the slope (usage per ms) using linear regression for the given history points.
|
|
64
|
+
*/
|
|
65
|
+
calculateSlope(history) {
|
|
66
|
+
if (history.length < 2)
|
|
67
|
+
return 0;
|
|
68
|
+
let sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
|
|
69
|
+
const n = history.length;
|
|
70
|
+
const firstTimestamp = history[0].timestamp;
|
|
71
|
+
for (const p of history) {
|
|
72
|
+
const x = p.timestamp - firstTimestamp;
|
|
73
|
+
const y = p.used;
|
|
74
|
+
sumX += x;
|
|
75
|
+
sumY += y;
|
|
76
|
+
sumXY += x * y;
|
|
77
|
+
sumX2 += x * x;
|
|
78
|
+
}
|
|
79
|
+
const denominator = (n * sumX2 - sumX * sumX);
|
|
80
|
+
if (denominator === 0)
|
|
81
|
+
return 0;
|
|
82
|
+
return (n * sumXY - sumX * sumY) / denominator;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* A null prediction engine that always returns Infinity.
|
|
87
|
+
* Used when no history service is available.
|
|
88
|
+
*/
|
|
89
|
+
export class NullPredictionEngine {
|
|
90
|
+
predictTimeToLimit(_quotaId, _windowMinutes = 60, _shortWindowMinutes) {
|
|
91
|
+
return Infinity;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=prediction-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prediction-engine.js","sourceRoot":"","sources":["../../../src/services/prediction-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type QuotaConfig, type QuotaData, type IQuotaProvider, type IHistoryService, type IPredictionEngine, type IAggregationService } from "../interfaces";
|
|
2
|
+
export declare class QuotaService {
|
|
3
|
+
private config;
|
|
4
|
+
private initialized;
|
|
5
|
+
private initPromise;
|
|
6
|
+
private historyService?;
|
|
7
|
+
private predictionEngine;
|
|
8
|
+
private aggregationService;
|
|
9
|
+
constructor(initialConfig?: Partial<QuotaConfig>);
|
|
10
|
+
init(directory: string, historyService?: IHistoryService): Promise<void>;
|
|
11
|
+
private registerProviders;
|
|
12
|
+
getConfig(): QuotaConfig;
|
|
13
|
+
getProviders(): IQuotaProvider[];
|
|
14
|
+
/**
|
|
15
|
+
* Returns the prediction engine used by this service.
|
|
16
|
+
* Useful for testing or for other services that need prediction capabilities.
|
|
17
|
+
*/
|
|
18
|
+
getPredictionEngine(): IPredictionEngine;
|
|
19
|
+
/**
|
|
20
|
+
* Returns the aggregation service used by this service.
|
|
21
|
+
* Useful for testing or for other services that need aggregation capabilities.
|
|
22
|
+
*/
|
|
23
|
+
getAggregationService(): IAggregationService;
|
|
24
|
+
getQuotas(context?: {
|
|
25
|
+
providerId?: string;
|
|
26
|
+
modelId?: string;
|
|
27
|
+
}): Promise<QuotaData[]>;
|
|
28
|
+
processQuotas(data: QuotaData[], context?: {
|
|
29
|
+
providerId?: string;
|
|
30
|
+
modelId?: string;
|
|
31
|
+
}): QuotaData[];
|
|
32
|
+
private applyAggregation;
|
|
33
|
+
/**
|
|
34
|
+
* Resolves which quotas belong to an AggregatedGroup using explicit sources and patterns.
|
|
35
|
+
*/
|
|
36
|
+
private resolveGroupSources;
|
|
37
|
+
private filterQuotas;
|
|
38
|
+
private filterByModel;
|
|
39
|
+
private sortQuotas;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=quota-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quota-service.d.ts","sourceRoot":"","sources":["../../../src/services/quota-service.ts"],"names":[],"mappings":"AACA,OAAO,EACH,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAE3B,MAAM,eAAe,CAAC;AAUvB,qBAAa,YAAY;IACrB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,cAAc,CAAC,CAAkB;IACzC,OAAO,CAAC,gBAAgB,CAAoB;IAC5C,OAAO,CAAC,kBAAkB,CAAsB;gBAEpC,aAAa,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC;IAQ1C,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;YAiChE,iBAAiB;IA0B/B,SAAS,IAAI,WAAW;IAIxB,YAAY,IAAI,cAAc,EAAE;IAIhC;;;OAGG;IACH,mBAAmB,IAAI,iBAAiB;IAIxC;;;OAGG;IACH,qBAAqB,IAAI,mBAAmB;IAItC,SAAS,CAAC,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IA2C1F,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,EAAE;IA2BlG,OAAO,CAAC,gBAAgB;IA4DxB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA6C3B,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,aAAa;IA4BrB,OAAO,CAAC,UAAU;CAGrB"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { getQuotaRegistry } from "../registry";
|
|
2
|
+
import { createAntigravityProvider } from "../providers/antigravity";
|
|
3
|
+
import { createCodexProvider } from "../providers/codex";
|
|
4
|
+
import { formatDurationMs } from "../utils/time";
|
|
5
|
+
import { logger } from "../logger";
|
|
6
|
+
import { LinearRegressionPredictionEngine, NullPredictionEngine } from "./prediction-engine";
|
|
7
|
+
import { AggregationService } from "./aggregation-service";
|
|
8
|
+
import { ConfigLoader } from "./config-loader";
|
|
9
|
+
export class QuotaService {
|
|
10
|
+
config;
|
|
11
|
+
initialized = false;
|
|
12
|
+
initPromise = null;
|
|
13
|
+
historyService;
|
|
14
|
+
predictionEngine;
|
|
15
|
+
aggregationService;
|
|
16
|
+
constructor(initialConfig) {
|
|
17
|
+
this.config = ConfigLoader.createConfig(initialConfig);
|
|
18
|
+
// Initialize with null prediction engine until init() is called
|
|
19
|
+
this.predictionEngine = new NullPredictionEngine();
|
|
20
|
+
this.aggregationService = new AggregationService(this.predictionEngine);
|
|
21
|
+
}
|
|
22
|
+
async init(directory, historyService) {
|
|
23
|
+
if (this.initialized)
|
|
24
|
+
return;
|
|
25
|
+
if (this.initPromise)
|
|
26
|
+
return this.initPromise;
|
|
27
|
+
this.initPromise = (async () => {
|
|
28
|
+
this.historyService = historyService;
|
|
29
|
+
// Load config from disk
|
|
30
|
+
this.config = await ConfigLoader.loadFromDisk(directory, this.config);
|
|
31
|
+
if (this.historyService && this.config.historyMaxAgeHours !== undefined) {
|
|
32
|
+
this.historyService.setMaxAge(this.config.historyMaxAgeHours);
|
|
33
|
+
}
|
|
34
|
+
// Initialize prediction engine with history service
|
|
35
|
+
if (this.historyService) {
|
|
36
|
+
this.predictionEngine = new LinearRegressionPredictionEngine(this.historyService, { predictionShortWindowMinutes: this.config.predictionShortWindowMinutes });
|
|
37
|
+
}
|
|
38
|
+
// Re-initialize aggregation service with the new prediction engine
|
|
39
|
+
this.aggregationService = new AggregationService(this.predictionEngine);
|
|
40
|
+
// Register providers
|
|
41
|
+
await this.registerProviders();
|
|
42
|
+
this.initialized = true;
|
|
43
|
+
})();
|
|
44
|
+
return this.initPromise;
|
|
45
|
+
}
|
|
46
|
+
async registerProviders() {
|
|
47
|
+
const registry = getQuotaRegistry();
|
|
48
|
+
// Register Antigravity
|
|
49
|
+
try {
|
|
50
|
+
registry.register(createAntigravityProvider({
|
|
51
|
+
debug: !!this.config.debug,
|
|
52
|
+
}));
|
|
53
|
+
logger.debug("init:provider_registered", { id: "antigravity" });
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
logger.error("init:provider_failed", { id: "antigravity", error: e });
|
|
57
|
+
console.warn("[QuotaService] Failed to initialize Antigravity provider:", e);
|
|
58
|
+
}
|
|
59
|
+
// Register Codex
|
|
60
|
+
try {
|
|
61
|
+
registry.register(createCodexProvider());
|
|
62
|
+
logger.debug("init:provider_registered", { id: "codex" });
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
logger.error("init:provider_failed", { id: "codex", error: e });
|
|
66
|
+
console.warn("[QuotaService] Failed to initialize Codex provider:", e);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
getConfig() {
|
|
70
|
+
return this.config;
|
|
71
|
+
}
|
|
72
|
+
getProviders() {
|
|
73
|
+
return getQuotaRegistry().getAll();
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Returns the prediction engine used by this service.
|
|
77
|
+
* Useful for testing or for other services that need prediction capabilities.
|
|
78
|
+
*/
|
|
79
|
+
getPredictionEngine() {
|
|
80
|
+
return this.predictionEngine;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Returns the aggregation service used by this service.
|
|
84
|
+
* Useful for testing or for other services that need aggregation capabilities.
|
|
85
|
+
*/
|
|
86
|
+
getAggregationService() {
|
|
87
|
+
return this.aggregationService;
|
|
88
|
+
}
|
|
89
|
+
async getQuotas(context) {
|
|
90
|
+
const providers = this.getProviders();
|
|
91
|
+
logger.debug("quota_service:get_quotas_start", { providerCount: providers.length, ids: providers.map((p) => p.id) });
|
|
92
|
+
if (providers.length === 0)
|
|
93
|
+
return [];
|
|
94
|
+
const results = await Promise.all(providers.map(async (p) => {
|
|
95
|
+
const startedAt = Date.now();
|
|
96
|
+
try {
|
|
97
|
+
logger.debug("quota_service:provider_fetch_start", { id: p.id });
|
|
98
|
+
const result = await p.fetchQuota();
|
|
99
|
+
logger.debug("quota_service:provider_fetch_ok", { id: p.id, count: result.length, durationMs: Date.now() - startedAt });
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
logger.error("quota_service:provider_fetch_error", { id: p.id, durationMs: Date.now() - startedAt, error: e });
|
|
104
|
+
console.error(`Provider ${p.id} failed:`, e);
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
}));
|
|
108
|
+
const processed = this.processQuotas(results.flat(), context);
|
|
109
|
+
logger.debug("quota_service:get_quotas_end", { totalCount: processed.length });
|
|
110
|
+
return processed;
|
|
111
|
+
}
|
|
112
|
+
processQuotas(data, context) {
|
|
113
|
+
let results = [...data];
|
|
114
|
+
// 1. Enrich with predictions (before aggregation so sources have it too)
|
|
115
|
+
results = results.map(q => {
|
|
116
|
+
const time = this.predictionEngine.predictTimeToLimit(q.id, 60);
|
|
117
|
+
if (time !== Infinity) {
|
|
118
|
+
return {
|
|
119
|
+
...q,
|
|
120
|
+
predictedReset: `${formatDurationMs(time)} (predicted)`
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return q;
|
|
124
|
+
});
|
|
125
|
+
// 2. Apply Aggregation
|
|
126
|
+
results = this.applyAggregation(results);
|
|
127
|
+
// 3. Filter (Disabled & Model Mapping). If requested, perform model-strict filtering.
|
|
128
|
+
results = this.filterQuotas(results, context);
|
|
129
|
+
// 4. Sort
|
|
130
|
+
results = this.sortQuotas(results);
|
|
131
|
+
return results;
|
|
132
|
+
}
|
|
133
|
+
applyAggregation(quotas) {
|
|
134
|
+
if (!this.config.aggregatedGroups || this.config.aggregatedGroups.length === 0) {
|
|
135
|
+
return quotas;
|
|
136
|
+
}
|
|
137
|
+
const aggregatedResults = [];
|
|
138
|
+
let remainingQuotas = [...quotas];
|
|
139
|
+
for (const group of this.config.aggregatedGroups) {
|
|
140
|
+
// Resolve source quotas from explicit sources and patterns
|
|
141
|
+
const sourceQuotas = this.resolveGroupSources(remainingQuotas, group);
|
|
142
|
+
if (sourceQuotas.length === 0)
|
|
143
|
+
continue;
|
|
144
|
+
const strategy = group.strategy || "most_critical";
|
|
145
|
+
let representative = null;
|
|
146
|
+
if (strategy === "most_critical") {
|
|
147
|
+
representative = this.aggregationService.aggregateMostCritical(sourceQuotas, group.predictionWindowMinutes, group.predictionShortWindowMinutes);
|
|
148
|
+
}
|
|
149
|
+
else if (strategy === "max") {
|
|
150
|
+
representative = this.aggregationService.aggregateMax(sourceQuotas);
|
|
151
|
+
}
|
|
152
|
+
else if (strategy === "min") {
|
|
153
|
+
representative = this.aggregationService.aggregateMin(sourceQuotas);
|
|
154
|
+
}
|
|
155
|
+
else if (strategy === "mean" || strategy === "median") {
|
|
156
|
+
representative = this.aggregationService.aggregateAverage(sourceQuotas, group.name, group.id, strategy);
|
|
157
|
+
}
|
|
158
|
+
if (representative) {
|
|
159
|
+
// Create a copy for display
|
|
160
|
+
const displayQuota = {
|
|
161
|
+
...representative,
|
|
162
|
+
id: group.id,
|
|
163
|
+
providerName: group.name
|
|
164
|
+
};
|
|
165
|
+
// Remove matched sources from pool to avoid double aggregation
|
|
166
|
+
const sourceIds = new Set(sourceQuotas.map(q => q.id));
|
|
167
|
+
remainingQuotas = remainingQuotas.filter(q => !sourceIds.has(q.id));
|
|
168
|
+
aggregatedResults.push(displayQuota);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Return aggregated results.
|
|
172
|
+
// If showUnaggregated is false, only return what matched a group.
|
|
173
|
+
if (this.config.showUnaggregated === false) {
|
|
174
|
+
return aggregatedResults;
|
|
175
|
+
}
|
|
176
|
+
return [...remainingQuotas, ...aggregatedResults];
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Resolves which quotas belong to an AggregatedGroup using explicit sources and patterns.
|
|
180
|
+
*/
|
|
181
|
+
resolveGroupSources(quotas, group) {
|
|
182
|
+
const matched = [];
|
|
183
|
+
const matchedIds = new Set();
|
|
184
|
+
// 1. Explicit sources (highest priority)
|
|
185
|
+
if (group.sources && group.sources.length > 0) {
|
|
186
|
+
for (const quota of quotas) {
|
|
187
|
+
if (group.sources.includes(quota.id)) {
|
|
188
|
+
matched.push(quota);
|
|
189
|
+
matchedIds.add(quota.id);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// 2. Pattern matching
|
|
194
|
+
if (group.patterns && group.patterns.length > 0) {
|
|
195
|
+
for (const quota of quotas) {
|
|
196
|
+
// Skip if already matched by explicit source
|
|
197
|
+
if (matchedIds.has(quota.id))
|
|
198
|
+
continue;
|
|
199
|
+
// Filter by providerId if specified
|
|
200
|
+
if (group.providerId) {
|
|
201
|
+
const providerMatch = quota.providerName.toLowerCase().includes(group.providerId.toLowerCase()) ||
|
|
202
|
+
quota.id.toLowerCase().startsWith(group.providerId.toLowerCase());
|
|
203
|
+
if (!providerMatch)
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
// Check if any pattern matches
|
|
207
|
+
const matchTarget = `${quota.id} ${quota.providerName}`.toLowerCase();
|
|
208
|
+
const patternMatches = group.patterns.some(pattern => {
|
|
209
|
+
const lowerPattern = pattern.toLowerCase();
|
|
210
|
+
return matchTarget.includes(lowerPattern);
|
|
211
|
+
});
|
|
212
|
+
if (patternMatches) {
|
|
213
|
+
matched.push(quota);
|
|
214
|
+
matchedIds.add(quota.id);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return matched;
|
|
219
|
+
}
|
|
220
|
+
filterQuotas(quotas, context) {
|
|
221
|
+
let results = [...quotas];
|
|
222
|
+
// Filter out disabled quotas
|
|
223
|
+
const disabledIds = new Set(this.config.disabled || []);
|
|
224
|
+
results = results.filter((data) => !disabledIds.has(data.id));
|
|
225
|
+
// If requested, apply model-aware filtering
|
|
226
|
+
if (this.config.filterByCurrentModel && context && context.providerId && context.modelId) {
|
|
227
|
+
return this.filterByModel(results, context.providerId, context.modelId);
|
|
228
|
+
}
|
|
229
|
+
return results;
|
|
230
|
+
}
|
|
231
|
+
filterByModel(quotas, providerId, modelId) {
|
|
232
|
+
const providerLower = providerId.toLowerCase();
|
|
233
|
+
const modelIdLower = modelId.toLowerCase();
|
|
234
|
+
// Fuzzy token match with scoring
|
|
235
|
+
const tokens = modelIdLower.split(/[^a-z0-9]+/).filter(Boolean);
|
|
236
|
+
const scoredMatches = quotas
|
|
237
|
+
.map(q => {
|
|
238
|
+
const id = q.id.toLowerCase();
|
|
239
|
+
const name = q.providerName.toLowerCase();
|
|
240
|
+
const score = tokens.reduce((acc, t) => acc + (id.includes(t) || name.includes(t) ? 1 : 0), 0);
|
|
241
|
+
return { q, score };
|
|
242
|
+
})
|
|
243
|
+
.filter(m => m.score > 0)
|
|
244
|
+
.sort((a, b) => b.score - a.score);
|
|
245
|
+
if (scoredMatches.length > 0) {
|
|
246
|
+
const maxScore = scoredMatches[0].score;
|
|
247
|
+
return scoredMatches.filter(m => m.score === maxScore).map(m => m.q);
|
|
248
|
+
}
|
|
249
|
+
// 3) Provider fallback
|
|
250
|
+
const matchesProvider = quotas.filter(q => q.providerName.toLowerCase().includes(providerLower));
|
|
251
|
+
return matchesProvider.length > 0 ? matchesProvider : [];
|
|
252
|
+
}
|
|
253
|
+
sortQuotas(quotas) {
|
|
254
|
+
return quotas.sort((a, b) => a.providerName.localeCompare(b.providerName));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=quota-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quota-service.js","sourceRoot":"","sources":["../../../src/services/quota-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ToolDefinition } from "@opencode-ai/plugin";
|
|
2
|
+
import { type QuotaService } from "../services/quota-service";
|
|
3
|
+
import { type QuotaConfig } from "../interfaces";
|
|
4
|
+
/**
|
|
5
|
+
* Creates a tool definition for fetching and displaying quota information.
|
|
6
|
+
* This tool always performs a fresh fetch of quotas from all providers.
|
|
7
|
+
*
|
|
8
|
+
* @returns A ToolDefinition that can be registered under Hooks.tool
|
|
9
|
+
*/
|
|
10
|
+
export declare function createQuotaTool(quotaService: QuotaService, getConfig: () => QuotaConfig): ToolDefinition;
|
|
11
|
+
//# sourceMappingURL=quotas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quotas.d.ts","sourceRoot":"","sources":["../../../src/tools/quotas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAIjD;;;;;GAKG;AACH,wBAAgB,eAAe,CAC3B,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,MAAM,WAAW,GAC7B,cAAc,CA8DhB"}
|