@kunkun.sh/kuota 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +130 -2
- package/bin/kuota.mjs +3 -0
- package/dist/bin.d.mts +1 -0
- package/dist/bin.mjs +1303 -0
- package/dist/dist-CIjerpSd.mjs +576 -0
- package/dist/history-G4o4HVvW.d.mts +36 -0
- package/dist/history-oOXsjdWR.mjs +236 -0
- package/dist/history.d.mts +3 -0
- package/dist/history.mjs +3 -0
- package/dist/index-2k6FkhpT.d.mts +81 -0
- package/dist/index-NHzh2TGn.d.mts +168 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.mjs +7 -0
- package/dist/main-B-hZbKK1.mjs +340 -0
- package/dist/metrics-Bzmrfgn-.mjs +307 -0
- package/dist/metrics-D7oNul_9.d.mts +30 -0
- package/dist/metrics.d.mts +3 -0
- package/dist/metrics.mjs +3 -0
- package/dist/parsers.d.mts +13 -0
- package/dist/parsers.mjs +19 -0
- package/dist/providers.d.mts +2 -0
- package/dist/providers.mjs +1 -0
- package/dist/src-C48Ew_L9.mjs +707 -0
- package/dist/src-y_QKmTyj.mjs +309 -0
- package/dist/web/assets/index-ihoe7C_u.js +27 -0
- package/dist/web/index.html +30 -0
- package/dist/web-server-DkdA5Ixj.mjs +154 -0
- package/package.json +73 -4
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
// ../core/src/types.ts
|
|
3
|
+
const ProviderIdSchema = Schema.Literal("codex", "claude", "antigravity");
|
|
4
|
+
const QuotaStatusSchema = Schema.Literal("ok", "partial", "unauthenticated", "unavailable", "unsupported", "error");
|
|
5
|
+
const QuotaWindowSchema = Schema.Struct({
|
|
6
|
+
windowId: Schema.String,
|
|
7
|
+
usedPercent: Schema.NullOr(Schema.Number),
|
|
8
|
+
remainingPercent: Schema.NullOr(Schema.Number),
|
|
9
|
+
resetAt: Schema.NullOr(Schema.String)
|
|
10
|
+
});
|
|
11
|
+
const QuotaSnapshotSchema = Schema.Struct({
|
|
12
|
+
provider: ProviderIdSchema,
|
|
13
|
+
status: QuotaStatusSchema,
|
|
14
|
+
fetchedAt: Schema.String,
|
|
15
|
+
source: Schema.String,
|
|
16
|
+
windows: Schema.Array(QuotaWindowSchema),
|
|
17
|
+
errorCode: Schema.NullOr(Schema.String)
|
|
18
|
+
});
|
|
19
|
+
// ../core/src/hash.ts
|
|
20
|
+
const K = new Uint32Array([
|
|
21
|
+
1116352408,
|
|
22
|
+
1899447441,
|
|
23
|
+
3049323471,
|
|
24
|
+
3921009573,
|
|
25
|
+
961987163,
|
|
26
|
+
1508970993,
|
|
27
|
+
2453635748,
|
|
28
|
+
2870763221,
|
|
29
|
+
3624381080,
|
|
30
|
+
310598401,
|
|
31
|
+
607225278,
|
|
32
|
+
1426881987,
|
|
33
|
+
1925078388,
|
|
34
|
+
2162078206,
|
|
35
|
+
2614888103,
|
|
36
|
+
3248222580,
|
|
37
|
+
3835390401,
|
|
38
|
+
4022224774,
|
|
39
|
+
264347078,
|
|
40
|
+
604807628,
|
|
41
|
+
770255983,
|
|
42
|
+
1249150122,
|
|
43
|
+
1555081692,
|
|
44
|
+
1996064986,
|
|
45
|
+
2554220882,
|
|
46
|
+
2821834349,
|
|
47
|
+
2952996808,
|
|
48
|
+
3210313671,
|
|
49
|
+
3336571891,
|
|
50
|
+
3584528711,
|
|
51
|
+
113926993,
|
|
52
|
+
338241895,
|
|
53
|
+
666307205,
|
|
54
|
+
773529912,
|
|
55
|
+
1294757372,
|
|
56
|
+
1396182291,
|
|
57
|
+
1695183700,
|
|
58
|
+
1986661051,
|
|
59
|
+
2177026350,
|
|
60
|
+
2456956037,
|
|
61
|
+
2730485921,
|
|
62
|
+
2820302411,
|
|
63
|
+
3259730800,
|
|
64
|
+
3345764771,
|
|
65
|
+
3516065817,
|
|
66
|
+
3600352804,
|
|
67
|
+
4094571909,
|
|
68
|
+
275423344,
|
|
69
|
+
430227734,
|
|
70
|
+
506948616,
|
|
71
|
+
659060556,
|
|
72
|
+
883997877,
|
|
73
|
+
958139571,
|
|
74
|
+
1322822218,
|
|
75
|
+
1537002063,
|
|
76
|
+
1747873779,
|
|
77
|
+
1955562222,
|
|
78
|
+
2024104815,
|
|
79
|
+
2227730452,
|
|
80
|
+
2361852424,
|
|
81
|
+
2428436474,
|
|
82
|
+
2756734187,
|
|
83
|
+
3204031479,
|
|
84
|
+
3329325298
|
|
85
|
+
]);
|
|
86
|
+
const rotr = (x, n) => x >>> n | x << 32 - n;
|
|
87
|
+
/** Dependency-free SHA-256 (hex). Keeps @kuota/core free of node:crypto so it stays browser-safe. */
|
|
88
|
+
function sha256Hex(text) {
|
|
89
|
+
const data = new TextEncoder().encode(text);
|
|
90
|
+
const bitLength = data.length * 8;
|
|
91
|
+
const padded = new Uint8Array(data.length + 9 + 63 >> 6 << 6);
|
|
92
|
+
padded.set(data);
|
|
93
|
+
padded[data.length] = 128;
|
|
94
|
+
const view = new DataView(padded.buffer);
|
|
95
|
+
view.setUint32(padded.length - 8, Math.floor(bitLength / 2 ** 32));
|
|
96
|
+
view.setUint32(padded.length - 4, bitLength >>> 0);
|
|
97
|
+
const h = new Uint32Array([
|
|
98
|
+
1779033703,
|
|
99
|
+
3144134277,
|
|
100
|
+
1013904242,
|
|
101
|
+
2773480762,
|
|
102
|
+
1359893119,
|
|
103
|
+
2600822924,
|
|
104
|
+
528734635,
|
|
105
|
+
1541459225
|
|
106
|
+
]);
|
|
107
|
+
const w = /* @__PURE__ */ new Uint32Array(64);
|
|
108
|
+
for (let offset = 0; offset < padded.length; offset += 64) {
|
|
109
|
+
for (let i = 0; i < 16; i++) w[i] = view.getUint32(offset + i * 4);
|
|
110
|
+
for (let i = 16; i < 64; i++) {
|
|
111
|
+
const s0 = rotr(w[i - 15], 7) ^ rotr(w[i - 15], 18) ^ w[i - 15] >>> 3;
|
|
112
|
+
const s1 = rotr(w[i - 2], 17) ^ rotr(w[i - 2], 19) ^ w[i - 2] >>> 10;
|
|
113
|
+
w[i] = w[i - 16] + s0 + w[i - 7] + s1 >>> 0;
|
|
114
|
+
}
|
|
115
|
+
let [a, b, c, d, e, f, g, hh] = h;
|
|
116
|
+
for (let i = 0; i < 64; i++) {
|
|
117
|
+
const s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
|
|
118
|
+
const ch = e & f ^ ~e & g;
|
|
119
|
+
const t1 = hh + s1 + ch + K[i] + w[i] >>> 0;
|
|
120
|
+
const t2 = (rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22)) + (a & b ^ a & c ^ b & c) >>> 0;
|
|
121
|
+
hh = g;
|
|
122
|
+
g = f;
|
|
123
|
+
f = e;
|
|
124
|
+
e = d + t1 >>> 0;
|
|
125
|
+
d = c;
|
|
126
|
+
c = b;
|
|
127
|
+
b = a;
|
|
128
|
+
a = t1 + t2 >>> 0;
|
|
129
|
+
}
|
|
130
|
+
const next = [
|
|
131
|
+
a,
|
|
132
|
+
b,
|
|
133
|
+
c,
|
|
134
|
+
d,
|
|
135
|
+
e,
|
|
136
|
+
f,
|
|
137
|
+
g,
|
|
138
|
+
hh
|
|
139
|
+
];
|
|
140
|
+
for (let i = 0; i < 8; i++) h[i] = h[i] + next[i] >>> 0;
|
|
141
|
+
}
|
|
142
|
+
return Array.from(h, (x) => x.toString(16).padStart(8, "0")).join("");
|
|
143
|
+
}
|
|
144
|
+
// ../core/src/history/schema.ts
|
|
145
|
+
const HOUR = 36e5;
|
|
146
|
+
/**
|
|
147
|
+
* Window cadence heuristics, derived from window ids the adapters emit. Only cadences named in
|
|
148
|
+
* the id (5h / weekly / daily) are trusted; everything else stays `unknown` rather than guessed.
|
|
149
|
+
* Codex `primary` / `secondary` follow the documented 5h / weekly convention of its app-server.
|
|
150
|
+
*/
|
|
151
|
+
function windowProfile(provider, windowId, resetAt, now = /* @__PURE__ */ new Date()) {
|
|
152
|
+
if (provider === "codex") {
|
|
153
|
+
if (windowId === "primary") {
|
|
154
|
+
if (resetAt) {
|
|
155
|
+
const resetMs = new Date(resetAt).getTime();
|
|
156
|
+
const nowMs = now.getTime();
|
|
157
|
+
if (Number.isFinite(resetMs) && resetMs - nowMs > 5 * HOUR) return {
|
|
158
|
+
semantics: "fixed",
|
|
159
|
+
durationMs: 168 * HOUR
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
semantics: "fixed",
|
|
164
|
+
durationMs: 5 * HOUR
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (windowId === "secondary") return {
|
|
168
|
+
semantics: "fixed",
|
|
169
|
+
durationMs: 168 * HOUR
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const id = windowId.toLowerCase();
|
|
173
|
+
const has = (re) => re.test(id);
|
|
174
|
+
if (has(/(^|[.:_-])(5h|five-hour)([.:_-]|$)/)) return {
|
|
175
|
+
semantics: "fixed",
|
|
176
|
+
durationMs: 5 * HOUR
|
|
177
|
+
};
|
|
178
|
+
if (has(/(^|[.:_-])(weekly|7d|seven-day)([.:_-]|$)/)) return {
|
|
179
|
+
semantics: "fixed",
|
|
180
|
+
durationMs: 168 * HOUR
|
|
181
|
+
};
|
|
182
|
+
if (has(/(^|[.:_-])(daily|24h)([.:_-]|$)/)) return {
|
|
183
|
+
semantics: "fixed",
|
|
184
|
+
durationMs: 24 * HOUR
|
|
185
|
+
};
|
|
186
|
+
return {
|
|
187
|
+
semantics: "unknown",
|
|
188
|
+
durationMs: null
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
const IsoDate = Schema.String.pipe(Schema.filter((value) => Number.isFinite(Date.parse(value)) || "must be an ISO timestamp"));
|
|
192
|
+
const Percent = Schema.Number.pipe(Schema.filter((value) => Number.isFinite(value) && value >= 0 && value <= 100 || "0..100"));
|
|
193
|
+
const QuotaHistoryEventV1Schema = Schema.Struct({
|
|
194
|
+
schemaVersion: Schema.Literal(1),
|
|
195
|
+
kind: Schema.Literal("quota_observed", "quota_unavailable", "usage_observed"),
|
|
196
|
+
eventId: Schema.String,
|
|
197
|
+
observedAt: IsoDate,
|
|
198
|
+
recordedAt: IsoDate,
|
|
199
|
+
provider: Schema.String,
|
|
200
|
+
accountScope: Schema.NullOr(Schema.String),
|
|
201
|
+
deviceId: Schema.String,
|
|
202
|
+
windowId: Schema.String,
|
|
203
|
+
epochId: Schema.NullOr(Schema.String),
|
|
204
|
+
semantics: Schema.Literal("fixed", "rolling", "first_use", "unknown"),
|
|
205
|
+
startAt: Schema.NullOr(IsoDate),
|
|
206
|
+
resetAt: Schema.NullOr(IsoDate),
|
|
207
|
+
usedPercent: Schema.NullOr(Percent),
|
|
208
|
+
remainingPercent: Schema.NullOr(Percent),
|
|
209
|
+
source: Schema.String,
|
|
210
|
+
state: Schema.Literal("ok", "partial", "stale", "error", "unauthenticated"),
|
|
211
|
+
errorCode: Schema.NullOr(Schema.String),
|
|
212
|
+
usage: Schema.optional(Schema.Struct({
|
|
213
|
+
inputTokens: Schema.optional(Schema.Number),
|
|
214
|
+
outputTokens: Schema.optional(Schema.Number),
|
|
215
|
+
cacheReadTokens: Schema.optional(Schema.Number),
|
|
216
|
+
cacheWriteTokens: Schema.optional(Schema.Number),
|
|
217
|
+
model: Schema.optional(Schema.String),
|
|
218
|
+
estimatedUsd: Schema.optional(Schema.Number)
|
|
219
|
+
}))
|
|
220
|
+
});
|
|
221
|
+
const decode = Schema.decodeUnknownEither(QuotaHistoryEventV1Schema, { onExcessProperty: "error" });
|
|
222
|
+
/** Strict decode: unknown (possibly secret-bearing) fields are rejected, not silently kept. */
|
|
223
|
+
function decodeHistoryEvent(input) {
|
|
224
|
+
return decode(input);
|
|
225
|
+
}
|
|
226
|
+
const validPercent = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 && v <= 100;
|
|
227
|
+
const minuteIso = (ms) => (/* @__PURE__ */ new Date(Math.round(ms / 6e4) * 6e4)).toISOString();
|
|
228
|
+
function makeId(parts) {
|
|
229
|
+
return sha256Hex(parts.map((part) => part === null ? "\0" : String(part)).join(""));
|
|
230
|
+
}
|
|
231
|
+
/** Pure normalization: one event per measurable window, or one sanitized unavailable event. */
|
|
232
|
+
function historyEventsFromSnapshot(snapshot, options) {
|
|
233
|
+
const observedMs = Date.parse(snapshot.fetchedAt);
|
|
234
|
+
if (!Number.isFinite(observedMs)) return [];
|
|
235
|
+
const observedAt = new Date(observedMs).toISOString();
|
|
236
|
+
const base = {
|
|
237
|
+
schemaVersion: 1,
|
|
238
|
+
observedAt,
|
|
239
|
+
recordedAt: options.recordedAt,
|
|
240
|
+
provider: snapshot.provider,
|
|
241
|
+
accountScope: options.accountScope,
|
|
242
|
+
deviceId: options.deviceId,
|
|
243
|
+
source: snapshot.source
|
|
244
|
+
};
|
|
245
|
+
const measurable = snapshot.windows.filter((w) => validPercent(w.usedPercent));
|
|
246
|
+
if (!(snapshot.status === "ok" || snapshot.status === "partial") || measurable.length === 0) {
|
|
247
|
+
const state = snapshot.status === "unauthenticated" ? "unauthenticated" : "error";
|
|
248
|
+
const errorCode = snapshot.errorCode ?? snapshot.status.toUpperCase();
|
|
249
|
+
return [{
|
|
250
|
+
...base,
|
|
251
|
+
kind: "quota_unavailable",
|
|
252
|
+
eventId: makeId([
|
|
253
|
+
"quota_unavailable",
|
|
254
|
+
snapshot.provider,
|
|
255
|
+
options.accountScope,
|
|
256
|
+
options.deviceId,
|
|
257
|
+
observedAt,
|
|
258
|
+
state,
|
|
259
|
+
errorCode
|
|
260
|
+
]),
|
|
261
|
+
windowId: "*",
|
|
262
|
+
epochId: null,
|
|
263
|
+
semantics: "unknown",
|
|
264
|
+
startAt: null,
|
|
265
|
+
resetAt: null,
|
|
266
|
+
usedPercent: null,
|
|
267
|
+
remainingPercent: null,
|
|
268
|
+
state,
|
|
269
|
+
errorCode
|
|
270
|
+
}];
|
|
271
|
+
}
|
|
272
|
+
const state = options.stale ? "stale" : snapshot.status === "partial" ? "partial" : "ok";
|
|
273
|
+
return measurable.map((window) => {
|
|
274
|
+
const profile = windowProfile(snapshot.provider, window.windowId, window.resetAt);
|
|
275
|
+
const semantics = options.semanticsForWindow?.(window.windowId) ?? profile.semantics;
|
|
276
|
+
const resetMs = window.resetAt === null ? NaN : Date.parse(window.resetAt);
|
|
277
|
+
const hasReset = Number.isFinite(resetMs);
|
|
278
|
+
const epochId = hasReset ? minuteIso(resetMs) : null;
|
|
279
|
+
const providedStart = options.startForWindow?.(window.windowId) ?? null;
|
|
280
|
+
const startAt = providedStart !== null && Number.isFinite(Date.parse(providedStart)) ? new Date(providedStart).toISOString() : hasReset && profile.durationMs !== null ? new Date(resetMs - profile.durationMs).toISOString() : null;
|
|
281
|
+
const usedPercent = window.usedPercent;
|
|
282
|
+
const remaining = validPercent(window.remainingPercent) ? window.remainingPercent : Math.max(0, Math.min(100, 100 - usedPercent));
|
|
283
|
+
return {
|
|
284
|
+
...base,
|
|
285
|
+
kind: "quota_observed",
|
|
286
|
+
eventId: makeId([
|
|
287
|
+
"quota_observed",
|
|
288
|
+
snapshot.provider,
|
|
289
|
+
options.accountScope,
|
|
290
|
+
options.deviceId,
|
|
291
|
+
window.windowId,
|
|
292
|
+
epochId,
|
|
293
|
+
observedAt,
|
|
294
|
+
usedPercent,
|
|
295
|
+
state
|
|
296
|
+
]),
|
|
297
|
+
windowId: window.windowId,
|
|
298
|
+
epochId,
|
|
299
|
+
semantics,
|
|
300
|
+
startAt,
|
|
301
|
+
resetAt: hasReset ? new Date(resetMs).toISOString() : null,
|
|
302
|
+
usedPercent,
|
|
303
|
+
remainingPercent: remaining,
|
|
304
|
+
state,
|
|
305
|
+
errorCode: snapshot.status === "partial" ? snapshot.errorCode : null
|
|
306
|
+
};
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
export { sha256Hex as a, QuotaStatusSchema as c, windowProfile as i, QuotaWindowSchema as l, decodeHistoryEvent as n, ProviderIdSchema as o, historyEventsFromSnapshot as r, QuotaSnapshotSchema as s, QuotaHistoryEventV1Schema as t };
|