estela 0.1.39 → 0.1.40
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 +53 -0
- package/dist/cli-quota.test.d.ts +2 -0
- package/dist/cli-quota.test.d.ts.map +1 -0
- package/dist/cli-quota.test.js +216 -0
- package/dist/cli-quota.test.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +138 -0
- package/dist/cli.js.map +1 -1
- package/dist/db/store.d.ts +10 -1
- package/dist/db/store.d.ts.map +1 -1
- package/dist/db/store.js +29 -0
- package/dist/db/store.js.map +1 -1
- package/dist/demo.d.ts.map +1 -1
- package/dist/demo.js +53 -0
- package/dist/demo.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +29 -0
- package/dist/i18n/en.js.map +1 -1
- package/dist/metrics/quota.d.ts +186 -0
- package/dist/metrics/quota.d.ts.map +1 -0
- package/dist/metrics/quota.js +245 -0
- package/dist/metrics/quota.js.map +1 -0
- package/dist/metrics/quota.test.d.ts +2 -0
- package/dist/metrics/quota.test.d.ts.map +1 -0
- package/dist/metrics/quota.test.js +262 -0
- package/dist/metrics/quota.test.js.map +1 -0
- package/dist/quota.d.ts +18 -0
- package/dist/quota.d.ts.map +1 -0
- package/dist/quota.js +85 -0
- package/dist/quota.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +8 -0
- package/dist/server.js.map +1 -1
- package/dist/server.test.js +37 -0
- package/dist/server.test.js.map +1 -1
- package/package.json +1 -1
- package/web/app.css +36 -0
- package/web/app.js +61 -1
- package/web/i18n.js +28 -0
- package/web/index.html +4 -1
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HISTORY_WEEKS = exports.WINDOW_HOURS = exports.QUOTA_AGENTS = void 0;
|
|
4
|
+
exports.isQuotaAgent = isQuotaAgent;
|
|
5
|
+
exports.breakdown = breakdown;
|
|
6
|
+
exports.fiveHourWindows = fiveHourWindows;
|
|
7
|
+
exports.windowAt = windowAt;
|
|
8
|
+
exports.weekStart = weekStart;
|
|
9
|
+
exports.sameStretch = sameStretch;
|
|
10
|
+
exports.compareWithHistory = compareWithHistory;
|
|
11
|
+
exports.buildQuota = buildQuota;
|
|
12
|
+
exports.quotaRange = quotaRange;
|
|
13
|
+
exports.quotaToJson = quotaToJson;
|
|
14
|
+
/**
|
|
15
|
+
* "¿Qué proyecto se come mi cuota?"
|
|
16
|
+
*
|
|
17
|
+
* Quien paga Claude Max/Pro o Codex con suscripción agota la cuota antes de
|
|
18
|
+
* tiempo y no sabe en qué. Estela ya tiene cada turno con su carpeta, así que
|
|
19
|
+
* puede repartir el consumo por proyecto. Funciones puras, como el resto de
|
|
20
|
+
* `metrics/`: entran turnos, salen cifras, y cada cifra tiene un test.
|
|
21
|
+
*
|
|
22
|
+
* Lo que esto NO hace, a propósito: decir cuánto te queda. Ni Anthropic ni
|
|
23
|
+
* OpenAI publican los límites exactos de cada plan, y la cuota se comparte con
|
|
24
|
+
* lo que uses fuera de esta máquina (claude.ai, el móvil, otro portátil), que
|
|
25
|
+
* Estela no ve. Un "te quedan X tokens" sería inventado. Lo único que se puede
|
|
26
|
+
* defender es el consumo real y la comparación con tu propio historial.
|
|
27
|
+
*
|
|
28
|
+
* Los turnos llegan ya deduplicados: los lectores de `watchers/` descartan las
|
|
29
|
+
* filas repetidas (Claude Code por `message.id`, Codex por su ordinal sobre
|
|
30
|
+
* `last_token_usage`) y `agent_turns` los guarda con `turn_id` como clave
|
|
31
|
+
* primaria. Aquí no se repite esa lógica.
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Los agentes que cuentan para la cuota.
|
|
35
|
+
*
|
|
36
|
+
* Copilot no: guarda `promptTokens`/`completionTokens` sin caché ni nada que
|
|
37
|
+
* permita fiarse de ellos (ver `watchers/copilot.ts`), y además se paga por
|
|
38
|
+
* peticiones, no por tokens. Cursor y Gemini CLI no tienen lector todavía.
|
|
39
|
+
*
|
|
40
|
+
* Cada agente va por separado y no se suman nunca: Claude Code gasta la cuota
|
|
41
|
+
* de Anthropic y Codex la de OpenAI. Un "% del total" mezclando los dos no
|
|
42
|
+
* describiría ninguna cuota que exista.
|
|
43
|
+
*/
|
|
44
|
+
exports.QUOTA_AGENTS = ["claude-code", "codex"];
|
|
45
|
+
function isQuotaAgent(agent) {
|
|
46
|
+
return exports.QUOTA_AGENTS.includes(agent);
|
|
47
|
+
}
|
|
48
|
+
const ZERO = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 };
|
|
49
|
+
function add(u, t) {
|
|
50
|
+
const cacheWrite = t.cacheWrite5m + t.cacheWrite1h;
|
|
51
|
+
return {
|
|
52
|
+
input: u.input + t.input,
|
|
53
|
+
output: u.output + t.output,
|
|
54
|
+
cacheRead: u.cacheRead + t.cacheRead,
|
|
55
|
+
cacheWrite: u.cacheWrite + cacheWrite,
|
|
56
|
+
total: u.total + t.input + t.output + t.cacheRead + cacheWrite,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function bucketKey(b) {
|
|
60
|
+
return b.kind === "project" ? `p:${b.projectId}` : b.kind === "folder" ? `f:${b.folder}` : "-";
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Reparto por proyecto de los turnos con `from <= at < to`, de mayor a menor.
|
|
64
|
+
* Un proyecto sin actividad en el periodo no sale: una fila a cero en una
|
|
65
|
+
* tabla de "quién se come la cuota" es ruido.
|
|
66
|
+
*/
|
|
67
|
+
function breakdown(turns, from, to, bucketOf) {
|
|
68
|
+
const acc = new Map();
|
|
69
|
+
let total = ZERO;
|
|
70
|
+
for (const t of turns) {
|
|
71
|
+
if (t.at < from || t.at >= to)
|
|
72
|
+
continue;
|
|
73
|
+
const bucket = bucketOf(t.repoPath);
|
|
74
|
+
const key = bucketKey(bucket);
|
|
75
|
+
const prev = acc.get(key) ?? { bucket, usage: ZERO };
|
|
76
|
+
acc.set(key, { bucket, usage: add(prev.usage, t.tokens) });
|
|
77
|
+
total = add(total, t.tokens);
|
|
78
|
+
}
|
|
79
|
+
const rows = [...acc.values()]
|
|
80
|
+
.map(({ bucket, usage }) => ({ bucket, usage, share: total.total > 0 ? usage.total / total.total : 0 }))
|
|
81
|
+
.sort((a, b) => b.usage.total - a.usage.total);
|
|
82
|
+
return { rows, total };
|
|
83
|
+
}
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
// La ventana de 5 horas
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
exports.WINDOW_HOURS = 5;
|
|
88
|
+
const WINDOW_MS = exports.WINDOW_HOURS * 3600_000;
|
|
89
|
+
/**
|
|
90
|
+
* Las ventanas de 5 h que se deducen de unos turnos ordenados en el tiempo.
|
|
91
|
+
*
|
|
92
|
+
* Es una ESTIMACIÓN, y por eso se dice en la ayuda y en la salida:
|
|
93
|
+
*
|
|
94
|
+
* - Una ventana empieza con el primer mensaje después de que acabe la
|
|
95
|
+
* anterior, y dura 5 horas. Es lo que describen Anthropic y OpenAI, pero
|
|
96
|
+
* ninguno publica cómo redondea el inicio (ccusage, por ejemplo, lo lleva a
|
|
97
|
+
* la hora en punto). Aquí se usa la hora exacta del primer turno: no
|
|
98
|
+
* inventar un redondeo es preferible a acertar por casualidad.
|
|
99
|
+
* - La cuota se comparte con lo que uses fuera de esta máquina. Un mensaje en
|
|
100
|
+
* claude.ai puede haber abierto la ventana antes, y Estela no lo ve: la
|
|
101
|
+
* ventana real puede empezar antes, nunca después, de la que sale aquí.
|
|
102
|
+
*/
|
|
103
|
+
function fiveHourWindows(times) {
|
|
104
|
+
const sorted = [...times].sort((a, b) => a.getTime() - b.getTime());
|
|
105
|
+
const out = [];
|
|
106
|
+
for (const at of sorted) {
|
|
107
|
+
const last = out[out.length - 1];
|
|
108
|
+
if (last && at < last.end)
|
|
109
|
+
continue;
|
|
110
|
+
out.push({ start: at, end: new Date(at.getTime() + WINDOW_MS) });
|
|
111
|
+
}
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
/** La ventana abierta ahora, o null. Y si no hay, cuándo acabó la última. */
|
|
115
|
+
function windowAt(times, now) {
|
|
116
|
+
const windows = fiveHourWindows(times.filter((t) => t <= now));
|
|
117
|
+
const last = windows[windows.length - 1];
|
|
118
|
+
if (!last)
|
|
119
|
+
return { current: null, lastEnded: null };
|
|
120
|
+
return last.end > now ? { current: last, lastEnded: null } : { current: null, lastEnded: last.end };
|
|
121
|
+
}
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
// La semana y el historial
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
/**
|
|
126
|
+
* El lunes de esta semana a las 00:00, en la hora de quien pregunta.
|
|
127
|
+
*
|
|
128
|
+
* Con el calendario local (`new Date(año, mes, día)`) y no restando
|
|
129
|
+
* milisegundos: la semana del cambio de hora tiene 167 o 169 horas, y restar
|
|
130
|
+
* 7 × 24 h dejaría el "lunes" a las 23:00 del domingo.
|
|
131
|
+
*/
|
|
132
|
+
function weekStart(now) {
|
|
133
|
+
const back = (now.getDay() + 6) % 7; // lunes = 0, domingo = 6
|
|
134
|
+
return new Date(now.getFullYear(), now.getMonth(), now.getDate() - back);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* El mismo tramo de la semana, `weeksBack` semanas atrás: si hoy es miércoles a
|
|
138
|
+
* las 15:00, de lunes 00:00 a miércoles 15:00 de aquella semana. Así se compara
|
|
139
|
+
* lo comparable: un miércoles no puede llevar lo que lleva una semana entera.
|
|
140
|
+
*/
|
|
141
|
+
function sameStretch(now, weeksBack) {
|
|
142
|
+
const monday = weekStart(now);
|
|
143
|
+
const day = (now.getDay() + 6) % 7;
|
|
144
|
+
const start = new Date(monday.getFullYear(), monday.getMonth(), monday.getDate() - 7 * weeksBack);
|
|
145
|
+
const end = new Date(start.getFullYear(), start.getMonth(), start.getDate() + day, now.getHours(), now.getMinutes(), now.getSeconds(), now.getMilliseconds());
|
|
146
|
+
return { start, end };
|
|
147
|
+
}
|
|
148
|
+
/** Las semanas completas con las que se compara. */
|
|
149
|
+
exports.HISTORY_WEEKS = 4;
|
|
150
|
+
/**
|
|
151
|
+
* Esta semana frente a la media de las cuatro anteriores, en el mismo tramo.
|
|
152
|
+
*
|
|
153
|
+
* Una semana pasada solo cuenta como historial si empezó el día del primer
|
|
154
|
+
* turno de ese agente o después: antes de eso no había nada que medir, y
|
|
155
|
+
* meter un cero inventado bajaría la media y haría parecer excesiva una semana
|
|
156
|
+
* normal. Una semana posterior sin uso sí cuenta como cero: es real.
|
|
157
|
+
*/
|
|
158
|
+
function compareWithHistory(times, firstTurnAt, now) {
|
|
159
|
+
const sum = (w) => times.reduce((s, t) => (t.at >= w.start && t.at < w.end ? s + t.total : s), 0);
|
|
160
|
+
const firstDay = firstTurnAt
|
|
161
|
+
? new Date(firstTurnAt.getFullYear(), firstTurnAt.getMonth(), firstTurnAt.getDate())
|
|
162
|
+
: null;
|
|
163
|
+
const past = Array.from({ length: exports.HISTORY_WEEKS }, (_, i) => sameStretch(now, i + 1));
|
|
164
|
+
const covered = past.filter((w) => firstDay !== null && w.start >= firstDay);
|
|
165
|
+
if (covered.length < exports.HISTORY_WEEKS) {
|
|
166
|
+
return { status: "insufficient", completeWeeks: covered.length, weeks: exports.HISTORY_WEEKS };
|
|
167
|
+
}
|
|
168
|
+
const current = sum({ start: weekStart(now), end: new Date(now.getTime() + 1) });
|
|
169
|
+
const average = past.reduce((s, w) => s + sum(w), 0) / exports.HISTORY_WEEKS;
|
|
170
|
+
return { status: "ok", current, average, ratio: average > 0 ? current / average : null, weeks: exports.HISTORY_WEEKS };
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Monta el informe. `turns` debe cubrir al menos las cuatro semanas anteriores
|
|
174
|
+
* a esta (ver `quotaRange`); `firstTurnAt`, el primer turno que hay guardado de
|
|
175
|
+
* cada agente, sea de cuando sea.
|
|
176
|
+
*/
|
|
177
|
+
function buildQuota(input) {
|
|
178
|
+
const { now, bucketOf } = input;
|
|
179
|
+
const monday = weekStart(now);
|
|
180
|
+
const until = new Date(now.getTime() + 1);
|
|
181
|
+
const turns = input.turns.filter((t) => t.at <= now);
|
|
182
|
+
const agents = [];
|
|
183
|
+
for (const agent of exports.QUOTA_AGENTS) {
|
|
184
|
+
const own = turns.filter((t) => t.agent === agent);
|
|
185
|
+
const { current, lastEnded } = windowAt(own.map((t) => t.at), now);
|
|
186
|
+
const week = breakdown(own, monday, until, bucketOf);
|
|
187
|
+
if (!current && week.rows.length === 0)
|
|
188
|
+
continue;
|
|
189
|
+
agents.push({
|
|
190
|
+
agent,
|
|
191
|
+
window: current ? { ...current, ...breakdown(own, current.start, until, bucketOf) } : null,
|
|
192
|
+
lastWindowEnded: lastEnded,
|
|
193
|
+
week,
|
|
194
|
+
comparison: compareWithHistory(own.map((t) => ({ at: t.at, total: add(ZERO, t.tokens).total })), input.firstTurnAt.get(agent) ?? null, now),
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
generatedAt: now,
|
|
199
|
+
weekStart: monday,
|
|
200
|
+
agents,
|
|
201
|
+
copilotExcluded: turns.some((t) => t.agent === "copilot" && t.at >= monday),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/** Desde cuándo hay que leer turnos para montar el informe de `now`. */
|
|
205
|
+
function quotaRange(now) {
|
|
206
|
+
return { start: sameStretch(now, exports.HISTORY_WEEKS).start, end: new Date(now.getTime() + 1) };
|
|
207
|
+
}
|
|
208
|
+
// ---------------------------------------------------------------------------
|
|
209
|
+
// Salida para máquinas
|
|
210
|
+
// ---------------------------------------------------------------------------
|
|
211
|
+
/**
|
|
212
|
+
* El informe como JSON estable, para `--json` y para el panel web. Fechas en
|
|
213
|
+
* ISO, y las filas con `projectId`/`projectName`/`folder` a null cuando no
|
|
214
|
+
* aplican, para que un script no tenga que mirar de qué tipo es cada una.
|
|
215
|
+
*/
|
|
216
|
+
function quotaToJson(report) {
|
|
217
|
+
const rows = (b) => b.rows.map((r) => ({
|
|
218
|
+
projectId: r.bucket.kind === "project" ? r.bucket.projectId : null,
|
|
219
|
+
projectName: r.bucket.kind === "project" ? r.bucket.projectName : null,
|
|
220
|
+
folder: r.bucket.kind === "folder" ? r.bucket.folder : null,
|
|
221
|
+
...r.usage,
|
|
222
|
+
share: Math.round(r.share * 10_000) / 10_000,
|
|
223
|
+
}));
|
|
224
|
+
return {
|
|
225
|
+
generatedAt: report.generatedAt.toISOString(),
|
|
226
|
+
weekStart: report.weekStart.toISOString(),
|
|
227
|
+
// Para que ningún script lo trate como un dato exacto sin haberlo leído.
|
|
228
|
+
windowIsEstimate: true,
|
|
229
|
+
windowHours: exports.WINDOW_HOURS,
|
|
230
|
+
agents: report.agents.map((a) => ({
|
|
231
|
+
agent: a.agent,
|
|
232
|
+
window: a.window
|
|
233
|
+
? { start: a.window.start.toISOString(), end: a.window.end.toISOString(),
|
|
234
|
+
projects: rows(a.window), total: a.window.total }
|
|
235
|
+
: null,
|
|
236
|
+
lastWindowEnded: a.lastWindowEnded?.toISOString() ?? null,
|
|
237
|
+
week: { projects: rows(a.week), total: a.week.total },
|
|
238
|
+
comparison: a.comparison.status === "ok"
|
|
239
|
+
? { ...a.comparison, ratio: a.comparison.ratio === null ? null : Math.round(a.comparison.ratio * 1000) / 1000 }
|
|
240
|
+
: a.comparison,
|
|
241
|
+
})),
|
|
242
|
+
excluded: report.copilotExcluded ? [{ agent: "copilot", reason: "no-reliable-tokens" }] : [],
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=quota.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quota.js","sourceRoot":"","sources":["../../src/metrics/quota.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quota.test.d.ts","sourceRoot":"","sources":["../../src/metrics/quota.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
40
|
+
const node_test_1 = require("node:test");
|
|
41
|
+
const schema_js_1 = require("../db/schema.js");
|
|
42
|
+
const store = __importStar(require("../db/store.js"));
|
|
43
|
+
const quota_js_1 = require("../quota.js");
|
|
44
|
+
const quota_js_2 = require("./quota.js");
|
|
45
|
+
/**
|
|
46
|
+
* "¿Qué proyecto se come mi cuota?"
|
|
47
|
+
*
|
|
48
|
+
* Lo que no puede fallar: que un turno repetido cuente dos veces (inflaría a un
|
|
49
|
+
* proyecto), que la semana empiece donde no es, y que se compare con un
|
|
50
|
+
* historial que no existe. Todo lo demás es presentación.
|
|
51
|
+
*/
|
|
52
|
+
const tok = (total, over = {}) => ({ input: 0, output: 0, cacheRead: total, cacheWrite5m: 0, cacheWrite1h: 0, ...over });
|
|
53
|
+
const turno = (at, repoPath, total, agent = "claude-code") => ({ agent, at: new Date(at), repoPath, tokens: tok(total) });
|
|
54
|
+
const porCarpeta = (repoPath) => repoPath ? { kind: "project", projectId: repoPath, projectName: repoPath } : { kind: "none" };
|
|
55
|
+
/** Fechas en hora local: los tests no dependen de la zona de quien los corre. */
|
|
56
|
+
const local = (y, m, d, h = 0, min = 0) => new Date(y, m - 1, d, h, min);
|
|
57
|
+
// ── La semana ───────────────────────────────────────────────────────────
|
|
58
|
+
(0, node_test_1.test)("la semana empieza el lunes a las 00:00 en hora local, también un domingo por la noche", () => {
|
|
59
|
+
// 2026-10-11 es domingo; 2026-10-05, lunes.
|
|
60
|
+
strict_1.default.deepEqual((0, quota_js_2.weekStart)(local(2026, 10, 11, 23, 59)), local(2026, 10, 5));
|
|
61
|
+
strict_1.default.deepEqual((0, quota_js_2.weekStart)(local(2026, 10, 5, 0, 0)), local(2026, 10, 5), "el propio lunes a medianoche");
|
|
62
|
+
strict_1.default.deepEqual((0, quota_js_2.weekStart)(local(2026, 10, 7, 15, 0)), local(2026, 10, 5));
|
|
63
|
+
});
|
|
64
|
+
(0, node_test_1.test)("cambio de semana: lo del domingo por la noche no cuenta en la semana que empieza el lunes", () => {
|
|
65
|
+
const now = local(2026, 10, 12, 0, 30); // lunes 00:30
|
|
66
|
+
const r = (0, quota_js_2.buildQuota)({
|
|
67
|
+
turns: [
|
|
68
|
+
{ agent: "claude-code", at: local(2026, 10, 11, 23, 50), repoPath: "/a", tokens: tok(1000) },
|
|
69
|
+
{ agent: "claude-code", at: local(2026, 10, 12, 0, 10), repoPath: "/b", tokens: tok(10) },
|
|
70
|
+
],
|
|
71
|
+
firstTurnAt: new Map(), now, bucketOf: porCarpeta,
|
|
72
|
+
});
|
|
73
|
+
const semana = r.agents[0].week;
|
|
74
|
+
strict_1.default.deepEqual(semana.rows.map((x) => x.bucket.kind === "project" && x.bucket.projectId), ["/b"]);
|
|
75
|
+
strict_1.default.equal(semana.total.total, 10);
|
|
76
|
+
// Pero la ventana de 5 h sí cruza la medianoche: la cuota no sabe de semanas.
|
|
77
|
+
strict_1.default.equal(r.agents[0].window.total.total, 1010);
|
|
78
|
+
});
|
|
79
|
+
(0, node_test_1.test)("la semana del cambio de hora sigue empezando el lunes a las 00:00", () => {
|
|
80
|
+
// En Madrid, el domingo 25 de octubre de 2026 tiene 25 horas. Restar 7×24 h
|
|
81
|
+
// dejaría el "lunes" a las 23:00 del domingo.
|
|
82
|
+
const antes = process.env["TZ"];
|
|
83
|
+
process.env["TZ"] = "Europe/Madrid";
|
|
84
|
+
try {
|
|
85
|
+
const lunes = (0, quota_js_2.weekStart)(local(2026, 10, 28, 12));
|
|
86
|
+
strict_1.default.equal(lunes.getDay(), 1);
|
|
87
|
+
strict_1.default.equal(lunes.getHours(), 0);
|
|
88
|
+
const atras = (0, quota_js_2.sameStretch)(local(2026, 10, 28, 12), 1);
|
|
89
|
+
strict_1.default.equal(atras.start.getDay(), 1);
|
|
90
|
+
strict_1.default.equal(atras.start.getHours(), 0, "el lunes anterior, a medianoche y no a las 23:00 del domingo");
|
|
91
|
+
strict_1.default.equal(atras.end.getDay(), 3);
|
|
92
|
+
strict_1.default.equal(atras.end.getHours(), 12);
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
if (antes === undefined)
|
|
96
|
+
delete process.env["TZ"];
|
|
97
|
+
else
|
|
98
|
+
process.env["TZ"] = antes;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
(0, node_test_1.test)("el mismo tramo de semanas anteriores: de lunes 00:00 al mismo día y hora", () => {
|
|
102
|
+
const t = (0, quota_js_2.sameStretch)(local(2026, 10, 7, 15, 0), 2); // miércoles 15:00, dos semanas atrás
|
|
103
|
+
strict_1.default.deepEqual(t.start, local(2026, 9, 21));
|
|
104
|
+
strict_1.default.deepEqual(t.end, local(2026, 9, 23, 15, 0));
|
|
105
|
+
});
|
|
106
|
+
// ── La ventana de 5 h ───────────────────────────────────────────────────
|
|
107
|
+
(0, node_test_1.test)("una ventana empieza con el primer turno después de que acabe la anterior y dura 5 h", () => {
|
|
108
|
+
const w = (0, quota_js_2.fiveHourWindows)([
|
|
109
|
+
local(2026, 10, 7, 9, 0), local(2026, 10, 7, 13, 59), // misma ventana
|
|
110
|
+
local(2026, 10, 7, 14, 0), // justo al cerrar: nueva
|
|
111
|
+
local(2026, 10, 7, 18, 30), // dentro de la segunda
|
|
112
|
+
]);
|
|
113
|
+
strict_1.default.deepEqual(w.map((x) => [x.start.getHours(), x.end.getHours()]), [[9, 14], [14, 19]]);
|
|
114
|
+
});
|
|
115
|
+
(0, node_test_1.test)("ventana abierta ahora, o la hora en que acabó la última", () => {
|
|
116
|
+
const veces = [local(2026, 10, 7, 9, 0), local(2026, 10, 7, 10, 0)];
|
|
117
|
+
const abierta = (0, quota_js_2.windowAt)(veces, local(2026, 10, 7, 12, 0));
|
|
118
|
+
strict_1.default.deepEqual(abierta.current?.start, local(2026, 10, 7, 9, 0));
|
|
119
|
+
strict_1.default.equal(abierta.lastEnded, null);
|
|
120
|
+
const cerrada = (0, quota_js_2.windowAt)(veces, local(2026, 10, 7, 16, 0));
|
|
121
|
+
strict_1.default.equal(cerrada.current, null);
|
|
122
|
+
strict_1.default.deepEqual(cerrada.lastEnded, local(2026, 10, 7, 14, 0));
|
|
123
|
+
strict_1.default.deepEqual((0, quota_js_2.windowAt)([], local(2026, 10, 7, 16, 0)), { current: null, lastEnded: null });
|
|
124
|
+
});
|
|
125
|
+
// ── Reparto ─────────────────────────────────────────────────────────────
|
|
126
|
+
(0, node_test_1.test)("el reparto va de mayor a menor, con su porcentaje, y suma bien los cinco campos", () => {
|
|
127
|
+
const now = local(2026, 10, 7, 12);
|
|
128
|
+
const r = (0, quota_js_2.buildQuota)({
|
|
129
|
+
turns: [
|
|
130
|
+
{ agent: "claude-code", at: local(2026, 10, 7, 10), repoPath: "/a",
|
|
131
|
+
tokens: { input: 1, output: 2, cacheRead: 3, cacheWrite5m: 4, cacheWrite1h: 5 } },
|
|
132
|
+
turno("2026-10-06T10:00:00", "/b", 45),
|
|
133
|
+
],
|
|
134
|
+
firstTurnAt: new Map(), now, bucketOf: porCarpeta,
|
|
135
|
+
});
|
|
136
|
+
const w = r.agents[0].week;
|
|
137
|
+
strict_1.default.deepEqual(w.rows.map((x) => x.usage.total), [45, 15]);
|
|
138
|
+
strict_1.default.deepEqual(w.rows[1].usage, { input: 1, output: 2, cacheRead: 3, cacheWrite: 9, total: 15 });
|
|
139
|
+
strict_1.default.equal(w.rows[0].share, 0.75);
|
|
140
|
+
strict_1.default.equal(w.total.total, 60);
|
|
141
|
+
});
|
|
142
|
+
(0, node_test_1.test)("un proyecto sin actividad en el periodo no sale en la tabla", () => {
|
|
143
|
+
const db = (0, schema_js_1.openDatabase)(":memory:");
|
|
144
|
+
try {
|
|
145
|
+
store.upsertClient(db, { id: "c", name: "C", currency: "EUR" });
|
|
146
|
+
for (const [id, repo] of [["activo", "/repos/activo"], ["parado", "/repos/parado"]]) {
|
|
147
|
+
store.upsertProject(db, { id, clientId: "c", name: id, repoPaths: [repo], billable: true,
|
|
148
|
+
roundingMinutes: 0, aiCostPolicy: "absorbed", kind: "client" });
|
|
149
|
+
}
|
|
150
|
+
store.saveTurns(db, [turnoGuardado("t1", "/repos/activo", "2026-10-07T10:00:00")]);
|
|
151
|
+
const r = (0, quota_js_1.loadQuotaReport)(db, local(2026, 10, 7, 12));
|
|
152
|
+
const ids = r.agents[0].week.rows.map((x) => x.bucket.kind === "project" ? x.bucket.projectId : "?");
|
|
153
|
+
strict_1.default.deepEqual(ids, ["activo"]);
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
db.close();
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
(0, node_test_1.test)("un turno fuera de cualquier proyecto cuenta, a nombre de su carpeta, y uno sin carpeta también", () => {
|
|
160
|
+
const db = (0, schema_js_1.openDatabase)(":memory:");
|
|
161
|
+
try {
|
|
162
|
+
store.saveTurns(db, [
|
|
163
|
+
turnoGuardado("t1", "/home/yo/notas", "2026-10-07T10:00:00"),
|
|
164
|
+
{ ...turnoGuardado("t2", null, "2026-10-07T10:05:00") },
|
|
165
|
+
]);
|
|
166
|
+
const filas = (0, quota_js_1.loadQuotaReport)(db, local(2026, 10, 7, 12)).agents[0].week.rows.map((x) => x.bucket);
|
|
167
|
+
strict_1.default.deepEqual(filas, [{ kind: "folder", folder: "notas" }, { kind: "none" }]);
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
db.close();
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
(0, node_test_1.test)("deduplicación: el mismo turno leído dos veces cuenta una sola vez", () => {
|
|
174
|
+
// Es la garantía de los lectores (por message.id en Claude Code) y de la
|
|
175
|
+
// clave primaria de agent_turns. La cuota no la repite: la hereda.
|
|
176
|
+
const db = (0, schema_js_1.openDatabase)(":memory:");
|
|
177
|
+
try {
|
|
178
|
+
const t = turnoGuardado("msg_01ABC", "/repo", "2026-10-07T10:00:00", 1000);
|
|
179
|
+
store.saveTurns(db, [t, t]);
|
|
180
|
+
store.saveTurns(db, [t]);
|
|
181
|
+
const r = (0, quota_js_1.loadQuotaReport)(db, local(2026, 10, 7, 12));
|
|
182
|
+
strict_1.default.equal(r.agents[0].week.total.total, 1000);
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
db.close();
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
// ── Agentes ─────────────────────────────────────────────────────────────
|
|
189
|
+
(0, node_test_1.test)("Claude Code y Codex van por separado; Copilot queda fuera y se dice", () => {
|
|
190
|
+
const now = local(2026, 10, 7, 12);
|
|
191
|
+
const r = (0, quota_js_2.buildQuota)({
|
|
192
|
+
turns: [
|
|
193
|
+
turno("2026-10-07T10:00:00", "/a", 100, "claude-code"),
|
|
194
|
+
turno("2026-10-07T10:00:00", "/a", 7, "codex"),
|
|
195
|
+
turno("2026-10-07T10:00:00", "/a", 999_999, "copilot"),
|
|
196
|
+
],
|
|
197
|
+
firstTurnAt: new Map(), now, bucketOf: porCarpeta,
|
|
198
|
+
});
|
|
199
|
+
strict_1.default.deepEqual(r.agents.map((a) => [a.agent, a.week.total.total]), [["claude-code", 100], ["codex", 7]]);
|
|
200
|
+
strict_1.default.equal(r.copilotExcluded, true);
|
|
201
|
+
});
|
|
202
|
+
(0, node_test_1.test)("un agente sin actividad no aparece; sin Copilot no se menciona", () => {
|
|
203
|
+
const r = (0, quota_js_2.buildQuota)({
|
|
204
|
+
turns: [turno("2026-10-07T10:00:00", "/a", 100, "claude-code")],
|
|
205
|
+
firstTurnAt: new Map(), now: local(2026, 10, 7, 12), bucketOf: porCarpeta,
|
|
206
|
+
});
|
|
207
|
+
strict_1.default.deepEqual(r.agents.map((a) => a.agent), ["claude-code"]);
|
|
208
|
+
strict_1.default.equal(r.copilotExcluded, false);
|
|
209
|
+
});
|
|
210
|
+
// ── Historial ───────────────────────────────────────────────────────────
|
|
211
|
+
const semanal = (n) => Array.from({ length: n }, (_, i) => ({ at: (0, quota_js_2.sameStretch)(local(2026, 10, 7, 15), i + 1).start, total: 100 }));
|
|
212
|
+
(0, node_test_1.test)("semana sin historial: no se compara, y se dice cuántas semanas hay", () => {
|
|
213
|
+
const now = local(2026, 10, 7, 15);
|
|
214
|
+
// El primer turno es de hace 10 días: solo una semana completa anterior.
|
|
215
|
+
const c = (0, quota_js_2.compareWithHistory)([], local(2026, 9, 28, 9), now);
|
|
216
|
+
strict_1.default.deepEqual(c, { status: "insufficient", completeWeeks: 1, weeks: 4 });
|
|
217
|
+
// Sin ningún turno guardado, ninguna.
|
|
218
|
+
strict_1.default.deepEqual((0, quota_js_2.compareWithHistory)([], null, now), { status: "insufficient", completeWeeks: 0, weeks: 4 });
|
|
219
|
+
});
|
|
220
|
+
(0, node_test_1.test)("con cuatro semanas de historial, media del mismo tramo; una semana vacía cuenta como cero", () => {
|
|
221
|
+
const now = local(2026, 10, 7, 15); // miércoles
|
|
222
|
+
const veces = [
|
|
223
|
+
...semanal(3), // 100 en cada una de las tres últimas
|
|
224
|
+
{ at: local(2026, 10, 6, 10), total: 150 }, // esta semana
|
|
225
|
+
{ at: local(2026, 10, 1, 9), total: 9999 }, // jueves de la semana pasada: fuera del tramo
|
|
226
|
+
];
|
|
227
|
+
// La cuarta semana atrás está cubierta (el primer turno es anterior) pero vacía.
|
|
228
|
+
const c = (0, quota_js_2.compareWithHistory)(veces, local(2026, 8, 1), now);
|
|
229
|
+
strict_1.default.equal(c.status, "ok");
|
|
230
|
+
if (c.status !== "ok")
|
|
231
|
+
return;
|
|
232
|
+
strict_1.default.equal(c.current, 150);
|
|
233
|
+
strict_1.default.equal(c.average, 75, "(100+100+100+0)/4: el jueves pasado no entra en un tramo que acaba el miércoles");
|
|
234
|
+
strict_1.default.equal(c.ratio, 2);
|
|
235
|
+
});
|
|
236
|
+
(0, node_test_1.test)("una media de cero no divide: el ratio va a null", () => {
|
|
237
|
+
const c = (0, quota_js_2.compareWithHistory)([{ at: local(2026, 10, 6, 10), total: 5 }], local(2026, 1, 1), local(2026, 10, 7, 15));
|
|
238
|
+
strict_1.default.equal(c.status, "ok");
|
|
239
|
+
if (c.status === "ok")
|
|
240
|
+
strict_1.default.equal(c.ratio, null);
|
|
241
|
+
});
|
|
242
|
+
// ── JSON ────────────────────────────────────────────────────────────────
|
|
243
|
+
(0, node_test_1.test)("el JSON lleva fechas en ISO, filas homogéneas y avisa de que la ventana es una estimación", () => {
|
|
244
|
+
const r = (0, quota_js_2.buildQuota)({
|
|
245
|
+
turns: [turno("2026-10-07T10:00:00", "/a", 100), turno("2026-10-07T10:30:00", null, 100)],
|
|
246
|
+
firstTurnAt: new Map(), now: local(2026, 10, 7, 12), bucketOf: porCarpeta,
|
|
247
|
+
});
|
|
248
|
+
const j = (0, quota_js_2.quotaToJson)(r);
|
|
249
|
+
strict_1.default.equal(j.windowIsEstimate, true);
|
|
250
|
+
strict_1.default.deepEqual(Object.keys(j.agents[0].week.projects[0]).sort(), ["cacheRead", "cacheWrite", "folder", "input", "output", "projectId", "projectName", "share", "total"]);
|
|
251
|
+
strict_1.default.equal(j.agents[0].week.projects[1]["projectId"], null);
|
|
252
|
+
strict_1.default.deepEqual(j.excluded, []);
|
|
253
|
+
strict_1.default.doesNotThrow(() => JSON.parse(JSON.stringify(j)));
|
|
254
|
+
});
|
|
255
|
+
// ---------------------------------------------------------------------------
|
|
256
|
+
function turnoGuardado(turnId, repoPath, at, cacheRead = 100) {
|
|
257
|
+
return {
|
|
258
|
+
agent: "claude-code", turnId, sessionId: "s", at: new Date(at), model: "claude-sonnet-4-6",
|
|
259
|
+
repoPath, branch: "main", tokens: tok(cacheRead), producerVersion: null,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=quota.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quota.test.js","sourceRoot":"","sources":["../../src/metrics/quota.test.ts"],"names":[],"mappings":"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"}
|
package/dist/quota.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DatabaseSync } from "node:sqlite";
|
|
2
|
+
import { type QuotaReport } from "./metrics/quota.js";
|
|
3
|
+
/**
|
|
4
|
+
* La cuota sobre la base: lo que comparten `estela quota` y el panel web.
|
|
5
|
+
* El cálculo vive en `metrics/quota.ts`; aquí solo se leen los datos.
|
|
6
|
+
*/
|
|
7
|
+
export declare function loadQuotaReport(db: DatabaseSync, now?: Date): QuotaReport;
|
|
8
|
+
/**
|
|
9
|
+
* Trae los turnos de esta semana antes de calcular.
|
|
10
|
+
*
|
|
11
|
+
* Sin esto, la "ventana actual" sería la de la última vez que alguien ejecutó
|
|
12
|
+
* `estela import`, que puede ser de ayer. Solo se leen los transcripts desde el
|
|
13
|
+
* lunes, y solo se guardan turnos: `INSERT OR IGNORE` sobre el `turn_id` hace
|
|
14
|
+
* que repetirlo no duplique nada, y el siguiente `import` reconstruye las horas
|
|
15
|
+
* con lo que lee él mismo, así que no se le quita trabajo.
|
|
16
|
+
*/
|
|
17
|
+
export declare function refreshQuotaTurns(db: DatabaseSync, since: Date): Promise<number>;
|
|
18
|
+
//# sourceMappingURL=quota.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quota.d.ts","sourceRoot":"","sources":["../src/quota.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,EAA4C,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGhG;;;GAGG;AAEH,wBAAgB,eAAe,CAAC,EAAE,EAAE,YAAY,EAAE,GAAG,GAAE,IAAiB,GAAG,WAAW,CA0BrF;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAGtF"}
|