estela 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/README.md +138 -0
- package/dist/billing/amortize.d.ts +44 -0
- package/dist/billing/amortize.d.ts.map +1 -0
- package/dist/billing/amortize.js +83 -0
- package/dist/billing/amortize.js.map +1 -0
- package/dist/billing/amortize.test.d.ts +2 -0
- package/dist/billing/amortize.test.d.ts.map +1 -0
- package/dist/billing/amortize.test.js +121 -0
- package/dist/billing/amortize.test.js.map +1 -0
- package/dist/billing/format.test.d.ts +2 -0
- package/dist/billing/format.test.d.ts.map +1 -0
- package/dist/billing/format.test.js +110 -0
- package/dist/billing/format.test.js.map +1 -0
- package/dist/billing/invoice.d.ts +52 -0
- package/dist/billing/invoice.d.ts.map +1 -0
- package/dist/billing/invoice.js +148 -0
- package/dist/billing/invoice.js.map +1 -0
- package/dist/billing/invoice.test.d.ts +2 -0
- package/dist/billing/invoice.test.d.ts.map +1 -0
- package/dist/billing/invoice.test.js +200 -0
- package/dist/billing/invoice.test.js.map +1 -0
- package/dist/billing/sessionize.d.ts +104 -0
- package/dist/billing/sessionize.d.ts.map +1 -0
- package/dist/billing/sessionize.js +0 -0
- package/dist/billing/sessionize.js.map +1 -0
- package/dist/billing/sessionize.test.d.ts +2 -0
- package/dist/billing/sessionize.test.d.ts.map +1 -0
- package/dist/billing/sessionize.test.js +67 -0
- package/dist/billing/sessionize.test.js.map +1 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1091 -0
- package/dist/cli.js.map +1 -0
- package/dist/cloud/auth.d.ts +4 -0
- package/dist/cloud/auth.d.ts.map +1 -0
- package/dist/cloud/auth.js +98 -0
- package/dist/cloud/auth.js.map +1 -0
- package/dist/cloud/client.d.ts +12 -0
- package/dist/cloud/client.d.ts.map +1 -0
- package/dist/cloud/client.js +34 -0
- package/dist/cloud/client.js.map +1 -0
- package/dist/db/schema.d.ts +11 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +424 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/schema.test.d.ts +2 -0
- package/dist/db/schema.test.d.ts.map +1 -0
- package/dist/db/schema.test.js +335 -0
- package/dist/db/schema.test.js.map +1 -0
- package/dist/db/store.d.ts +113 -0
- package/dist/db/store.d.ts.map +1 -0
- package/dist/db/store.js +550 -0
- package/dist/db/store.js.map +1 -0
- package/dist/doctor.d.ts +24 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +229 -0
- package/dist/doctor.js.map +1 -0
- package/dist/export/csv.d.ts +9 -0
- package/dist/export/csv.d.ts.map +1 -0
- package/dist/export/csv.js +81 -0
- package/dist/export/csv.js.map +1 -0
- package/dist/export/invoice-pdf.d.ts +21 -0
- package/dist/export/invoice-pdf.d.ts.map +1 -0
- package/dist/export/invoice-pdf.js +135 -0
- package/dist/export/invoice-pdf.js.map +1 -0
- package/dist/export/panel.d.ts +78 -0
- package/dist/export/panel.d.ts.map +1 -0
- package/dist/export/panel.js +693 -0
- package/dist/export/panel.js.map +1 -0
- package/dist/export/panel.test.d.ts +2 -0
- package/dist/export/panel.test.d.ts.map +1 -0
- package/dist/export/panel.test.js +273 -0
- package/dist/export/panel.test.js.map +1 -0
- package/dist/export/pdf.d.ts +32 -0
- package/dist/export/pdf.d.ts.map +1 -0
- package/dist/export/pdf.js +229 -0
- package/dist/export/pdf.js.map +1 -0
- package/dist/export/pdf.test.d.ts +2 -0
- package/dist/export/pdf.test.d.ts.map +1 -0
- package/dist/export/pdf.test.js +151 -0
- package/dist/export/pdf.test.js.map +1 -0
- package/dist/export/share.d.ts +42 -0
- package/dist/export/share.d.ts.map +1 -0
- package/dist/export/share.js +181 -0
- package/dist/export/share.js.map +1 -0
- package/dist/export/share.test.d.ts +2 -0
- package/dist/export/share.test.d.ts.map +1 -0
- package/dist/export/share.test.js +116 -0
- package/dist/export/share.test.js.map +1 -0
- package/dist/metrics/index.d.ts +101 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +221 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/metrics.test.d.ts +2 -0
- package/dist/metrics/metrics.test.d.ts.map +1 -0
- package/dist/metrics/metrics.test.js +162 -0
- package/dist/metrics/metrics.test.js.map +1 -0
- package/dist/metrics/people.d.ts +46 -0
- package/dist/metrics/people.d.ts.map +1 -0
- package/dist/metrics/people.js +126 -0
- package/dist/metrics/people.js.map +1 -0
- package/dist/metrics/people.test.d.ts +2 -0
- package/dist/metrics/people.test.d.ts.map +1 -0
- package/dist/metrics/people.test.js +84 -0
- package/dist/metrics/people.test.js.map +1 -0
- package/dist/metrics/team.d.ts +41 -0
- package/dist/metrics/team.d.ts.map +1 -0
- package/dist/metrics/team.js +0 -0
- package/dist/metrics/team.js.map +1 -0
- package/dist/metrics/team.test.d.ts +2 -0
- package/dist/metrics/team.test.d.ts.map +1 -0
- package/dist/metrics/team.test.js +90 -0
- package/dist/metrics/team.test.js.map +1 -0
- package/dist/pricing/catalog.d.ts +39 -0
- package/dist/pricing/catalog.d.ts.map +1 -0
- package/dist/pricing/catalog.js +59 -0
- package/dist/pricing/catalog.js.map +1 -0
- package/dist/pricing/cost.d.ts +25 -0
- package/dist/pricing/cost.d.ts.map +1 -0
- package/dist/pricing/cost.js +50 -0
- package/dist/pricing/cost.js.map +1 -0
- package/dist/pricing/cost.test.d.ts +2 -0
- package/dist/pricing/cost.test.d.ts.map +1 -0
- package/dist/pricing/cost.test.js +74 -0
- package/dist/pricing/cost.test.js.map +1 -0
- package/dist/server.d.ts +15 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1141 -0
- package/dist/server.js.map +1 -0
- package/dist/setup.d.ts +70 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +223 -0
- package/dist/setup.js.map +1 -0
- package/dist/setup.test.d.ts +2 -0
- package/dist/setup.test.d.ts.map +1 -0
- package/dist/setup.test.js +131 -0
- package/dist/setup.test.js.map +1 -0
- package/dist/watchers/claude.d.ts +34 -0
- package/dist/watchers/claude.d.ts.map +1 -0
- package/dist/watchers/claude.js +235 -0
- package/dist/watchers/claude.js.map +1 -0
- package/dist/watchers/claude.test.d.ts +2 -0
- package/dist/watchers/claude.test.d.ts.map +1 -0
- package/dist/watchers/claude.test.js +180 -0
- package/dist/watchers/claude.test.js.map +1 -0
- package/dist/watchers/git.d.ts +42 -0
- package/dist/watchers/git.d.ts.map +1 -0
- package/dist/watchers/git.js +218 -0
- package/dist/watchers/git.js.map +1 -0
- package/dist/watchers/git.test.d.ts +2 -0
- package/dist/watchers/git.test.d.ts.map +1 -0
- package/dist/watchers/git.test.js +73 -0
- package/dist/watchers/git.test.js.map +1 -0
- package/dist/watchers/identity.d.ts +34 -0
- package/dist/watchers/identity.d.ts.map +1 -0
- package/dist/watchers/identity.js +85 -0
- package/dist/watchers/identity.js.map +1 -0
- package/dist/watchers/identity.test.d.ts +2 -0
- package/dist/watchers/identity.test.d.ts.map +1 -0
- package/dist/watchers/identity.test.js +48 -0
- package/dist/watchers/identity.test.js.map +1 -0
- package/dist/web-ui.test.d.ts +2 -0
- package/dist/web-ui.test.d.ts.map +1 -0
- package/dist/web-ui.test.js +312 -0
- package/dist/web-ui.test.js.map +1 -0
- package/node_modules/@estela/shared/dist/index.d.ts +3 -0
- package/node_modules/@estela/shared/dist/index.d.ts.map +1 -0
- package/node_modules/@estela/shared/dist/index.js +19 -0
- package/node_modules/@estela/shared/dist/index.js.map +1 -0
- package/node_modules/@estela/shared/dist/money.d.ts +71 -0
- package/node_modules/@estela/shared/dist/money.d.ts.map +1 -0
- package/node_modules/@estela/shared/dist/money.js +171 -0
- package/node_modules/@estela/shared/dist/money.js.map +1 -0
- package/node_modules/@estela/shared/dist/types.d.ts +365 -0
- package/node_modules/@estela/shared/dist/types.d.ts.map +1 -0
- package/node_modules/@estela/shared/dist/types.js +24 -0
- package/node_modules/@estela/shared/dist/types.js.map +1 -0
- package/node_modules/@estela/shared/package.json +5 -0
- package/package.json +41 -0
- package/web/app.css +749 -0
- package/web/app.js +1257 -0
- package/web/apple-touch-icon.png +0 -0
- package/web/favicon.png +0 -0
- package/web/index.html +132 -0
- package/web/lib.js +94 -0
- package/web/logo-mark.png +0 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scanClaudeCode = scanClaudeCode;
|
|
4
|
+
exports.resolveScratchpads = resolveScratchpads;
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const promises_1 = require("node:fs/promises");
|
|
7
|
+
const node_os_1 = require("node:os");
|
|
8
|
+
const node_path_1 = require("node:path");
|
|
9
|
+
const node_readline_1 = require("node:readline");
|
|
10
|
+
/**
|
|
11
|
+
* Adaptador de Claude Code.
|
|
12
|
+
*
|
|
13
|
+
* El `.jsonl` que escribe Claude Code es un formato interno no documentado, así
|
|
14
|
+
* que se trata como un feed externo no confiable, no como una API:
|
|
15
|
+
*
|
|
16
|
+
* 1. Se leen ocho campos y se ignora todo lo demás. Los `type` desconocidos
|
|
17
|
+
* (`atis-latch`, `bridge-session`, `ai-title`, `queue-operation`...) son
|
|
18
|
+
* maquinaria interna: se cuentan para el canario y se descartan.
|
|
19
|
+
* 2. Una clave nueva jamás rompe el parseo.
|
|
20
|
+
* 3. Se deduplica por `message.id`. Medido sobre transcripts reales, el mismo
|
|
21
|
+
* turno aparece hasta cinco veces con el mismo `usage`: sumar por fila
|
|
22
|
+
* multiplica el coste por ~2.9x.
|
|
23
|
+
* 4. Lo que no cuadra se cuenta y se reporta. Nunca se degrada en silencio.
|
|
24
|
+
*/
|
|
25
|
+
const CLAUDE_HOME = (0, node_path_1.join)((0, node_os_1.homedir)(), ".claude", "projects");
|
|
26
|
+
async function scanClaudeCode(options = {}) {
|
|
27
|
+
const root = options.root ?? CLAUDE_HOME;
|
|
28
|
+
const files = await listTranscripts(root);
|
|
29
|
+
const turns = [];
|
|
30
|
+
const seenTurnIds = new Set();
|
|
31
|
+
const producerVersions = new Set();
|
|
32
|
+
const warnings = [];
|
|
33
|
+
let recordsSeen = 0;
|
|
34
|
+
let duplicatesDropped = 0;
|
|
35
|
+
let unknownRecords = 0;
|
|
36
|
+
let malformedRecords = 0;
|
|
37
|
+
for (const file of files) {
|
|
38
|
+
for await (const line of readLines(file)) {
|
|
39
|
+
if (!line.trim())
|
|
40
|
+
continue;
|
|
41
|
+
recordsSeen++;
|
|
42
|
+
let raw;
|
|
43
|
+
try {
|
|
44
|
+
raw = JSON.parse(line);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Una línea a medio escribir mientras la sesión está viva es normal.
|
|
48
|
+
malformedRecords++;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (raw.type !== "assistant") {
|
|
52
|
+
unknownRecords++;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const turn = toTurn(raw);
|
|
56
|
+
if (!turn) {
|
|
57
|
+
malformedRecords++;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (seenTurnIds.has(turn.turnId)) {
|
|
61
|
+
duplicatesDropped++;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
seenTurnIds.add(turn.turnId);
|
|
65
|
+
if (options.since && turn.at < options.since)
|
|
66
|
+
continue;
|
|
67
|
+
if (options.repoPaths?.length && !matchesRepo(turn.repoPath, options.repoPaths))
|
|
68
|
+
continue;
|
|
69
|
+
if (turn.producerVersion)
|
|
70
|
+
producerVersions.add(turn.producerVersion);
|
|
71
|
+
turns.push(turn);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// El canario. Un salto brusco aquí significa que el formato cambió.
|
|
75
|
+
const classifiable = recordsSeen - unknownRecords;
|
|
76
|
+
if (classifiable > 0 && malformedRecords / classifiable > 0.02) {
|
|
77
|
+
warnings.push(`${malformedRecords} de ${classifiable} registros de tipo conocido venían malformados ` +
|
|
78
|
+
`(${((malformedRecords / classifiable) * 100).toFixed(1)}%). ` +
|
|
79
|
+
`Claude Code puede haber cambiado su formato: revisa los totales antes de facturar.`);
|
|
80
|
+
}
|
|
81
|
+
turns.sort((a, b) => a.at.getTime() - b.at.getTime());
|
|
82
|
+
return {
|
|
83
|
+
turns,
|
|
84
|
+
report: {
|
|
85
|
+
filesRead: files.length,
|
|
86
|
+
recordsSeen,
|
|
87
|
+
turnsAccepted: turns.length,
|
|
88
|
+
duplicatesDropped,
|
|
89
|
+
unknownRecords,
|
|
90
|
+
malformedRecords,
|
|
91
|
+
producerVersions: [...producerVersions].sort(),
|
|
92
|
+
warnings,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function toTurn(raw) {
|
|
97
|
+
const id = raw.message?.id;
|
|
98
|
+
const model = raw.message?.model;
|
|
99
|
+
const timestamp = raw.timestamp;
|
|
100
|
+
if (typeof id !== "string" || typeof model !== "string" || typeof timestamp !== "string") {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
const at = new Date(timestamp);
|
|
104
|
+
if (Number.isNaN(at.getTime()))
|
|
105
|
+
return null;
|
|
106
|
+
return {
|
|
107
|
+
agent: "claude-code",
|
|
108
|
+
turnId: id,
|
|
109
|
+
sessionId: typeof raw.sessionId === "string" ? raw.sessionId : id,
|
|
110
|
+
at,
|
|
111
|
+
model,
|
|
112
|
+
repoPath: typeof raw.cwd === "string" ? raw.cwd : null,
|
|
113
|
+
branch: typeof raw.gitBranch === "string" && raw.gitBranch ? raw.gitBranch : null,
|
|
114
|
+
tokens: readUsage(raw.message?.usage),
|
|
115
|
+
producerVersion: typeof raw.version === "string" ? raw.version : null,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Lee el objeto `usage`.
|
|
120
|
+
*
|
|
121
|
+
* Los TTL de escritura de caché viven en `cache_creation.ephemeral_{5m,1h}`, y
|
|
122
|
+
* cuestan distinto (1.25x frente a 2x). Cuando ese desglose no está, se cae a
|
|
123
|
+
* `cache_creation_input_tokens` y se imputa al TTL de 5 minutos: es el
|
|
124
|
+
* multiplicador más bajo, así que ante la duda el coste se subestima en vez de
|
|
125
|
+
* inflar una factura.
|
|
126
|
+
*/
|
|
127
|
+
function readUsage(usage) {
|
|
128
|
+
if (!usage)
|
|
129
|
+
return { input: 0, output: 0, cacheRead: 0, cacheWrite5m: 0, cacheWrite1h: 0 };
|
|
130
|
+
const creation = usage["cache_creation"];
|
|
131
|
+
const detailed5m = num(creation?.["ephemeral_5m_input_tokens"]);
|
|
132
|
+
const detailed1h = num(creation?.["ephemeral_1h_input_tokens"]);
|
|
133
|
+
const totalWrite = num(usage["cache_creation_input_tokens"]);
|
|
134
|
+
const hasDetail = creation !== undefined && (detailed5m > 0 || detailed1h > 0);
|
|
135
|
+
return {
|
|
136
|
+
input: num(usage["input_tokens"]),
|
|
137
|
+
output: num(usage["output_tokens"]),
|
|
138
|
+
cacheRead: num(usage["cache_read_input_tokens"]),
|
|
139
|
+
cacheWrite5m: hasDetail ? detailed5m : totalWrite,
|
|
140
|
+
cacheWrite1h: hasDetail ? detailed1h : 0,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function num(value) {
|
|
144
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Devuelve al repositorio de origen los turnos ocurridos en un scratchpad.
|
|
148
|
+
*
|
|
149
|
+
* Claude Code trabaja parte del tiempo en un directorio temporal cuyo `cwd` es
|
|
150
|
+
* algo como:
|
|
151
|
+
*
|
|
152
|
+
* /private/tmp/claude-502/-Users-ana-Proyectos-mi-repo/<sesión>/scratchpad
|
|
153
|
+
*
|
|
154
|
+
* Ese trabajo es del proyecto, pero su ruta no es la del repositorio, así que
|
|
155
|
+
* se quedaba sin imputar: horas reales que desaparecían del parte. En una
|
|
156
|
+
* jornada medida, casi la mitad de los turnos de un proyecto estaban ahí.
|
|
157
|
+
*
|
|
158
|
+
* El segmento intermedio es la ruta original con las barras convertidas en
|
|
159
|
+
* guiones. La conversión pierde información —una barra, un guion y un guion
|
|
160
|
+
* bajo acaban todos como "-"—, así que no se puede invertir; lo que sí se puede
|
|
161
|
+
* es generar ese mismo identificador para cada repositorio conocido y ver cuál
|
|
162
|
+
* coincide.
|
|
163
|
+
*/
|
|
164
|
+
function resolveScratchpads(turns) {
|
|
165
|
+
const realPaths = new Set();
|
|
166
|
+
for (const turn of turns) {
|
|
167
|
+
if (turn.repoPath && !isScratchpad(turn.repoPath))
|
|
168
|
+
realPaths.add(turn.repoPath);
|
|
169
|
+
}
|
|
170
|
+
const bySlug = new Map();
|
|
171
|
+
for (const path of realPaths)
|
|
172
|
+
bySlug.set(slugOfPath(path), path);
|
|
173
|
+
return turns.map((turn) => {
|
|
174
|
+
if (!turn.repoPath || !isScratchpad(turn.repoPath))
|
|
175
|
+
return turn;
|
|
176
|
+
const slug = scratchpadSlug(turn.repoPath);
|
|
177
|
+
const real = slug ? bySlug.get(slug) : undefined;
|
|
178
|
+
return real ? { ...turn, repoPath: real } : turn;
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
function isScratchpad(path) {
|
|
182
|
+
return path.includes("/claude-") && path.endsWith("/scratchpad");
|
|
183
|
+
}
|
|
184
|
+
/** El segmento con forma de identificador dentro de la ruta del scratchpad. */
|
|
185
|
+
function scratchpadSlug(path) {
|
|
186
|
+
const parts = path.split("/");
|
|
187
|
+
// …/claude-<uid>/<slug>/<sesión>/scratchpad
|
|
188
|
+
const index = parts.findIndex((p) => p.startsWith("claude-"));
|
|
189
|
+
const slug = index >= 0 ? parts[index + 1] : undefined;
|
|
190
|
+
return slug?.startsWith("-") ? slug : null;
|
|
191
|
+
}
|
|
192
|
+
/** Mismo identificador que usa Claude Code para nombrar la carpeta del proyecto. */
|
|
193
|
+
function slugOfPath(path) {
|
|
194
|
+
return path.replace(/[/_.]/g, "-");
|
|
195
|
+
}
|
|
196
|
+
function matchesRepo(repoPath, roots) {
|
|
197
|
+
if (!repoPath)
|
|
198
|
+
return false;
|
|
199
|
+
return roots.some((root) => repoPath === root || repoPath.startsWith(root + "/"));
|
|
200
|
+
}
|
|
201
|
+
async function listTranscripts(root) {
|
|
202
|
+
let entries;
|
|
203
|
+
try {
|
|
204
|
+
entries = await (0, promises_1.readdir)(root);
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return [];
|
|
208
|
+
}
|
|
209
|
+
const files = [];
|
|
210
|
+
for (const entry of entries) {
|
|
211
|
+
const dir = (0, node_path_1.join)(root, entry);
|
|
212
|
+
try {
|
|
213
|
+
if (!(await (0, promises_1.stat)(dir)).isDirectory())
|
|
214
|
+
continue;
|
|
215
|
+
for (const name of await (0, promises_1.readdir)(dir)) {
|
|
216
|
+
if (name.endsWith(".jsonl"))
|
|
217
|
+
files.push((0, node_path_1.join)(dir, name));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
// Un proyecto ilegible no debe tumbar el escaneo de los demás.
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return files.sort();
|
|
225
|
+
}
|
|
226
|
+
async function* readLines(file) {
|
|
227
|
+
const stream = (0, node_fs_1.createReadStream)(file, { encoding: "utf8" });
|
|
228
|
+
try {
|
|
229
|
+
yield* (0, node_readline_1.createInterface)({ input: stream, crlfDelay: Infinity });
|
|
230
|
+
}
|
|
231
|
+
finally {
|
|
232
|
+
stream.destroy();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/watchers/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.test.d.ts","sourceRoot":"","sources":["../../src/watchers/claude.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
8
|
+
const node_os_1 = require("node:os");
|
|
9
|
+
const node_path_1 = require("node:path");
|
|
10
|
+
const node_test_1 = require("node:test");
|
|
11
|
+
const claude_js_1 = require("./claude.js");
|
|
12
|
+
/** Monta un store de transcripts falso con las líneas dadas. */
|
|
13
|
+
function fixture(lines) {
|
|
14
|
+
const root = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "estela-test-"));
|
|
15
|
+
const project = (0, node_path_1.join)(root, "-Users-test-proyecto");
|
|
16
|
+
(0, node_fs_1.mkdirSync)(project, { recursive: true });
|
|
17
|
+
(0, node_fs_1.writeFileSync)((0, node_path_1.join)(project, "session.jsonl"), lines.map((l) => (typeof l === "string" ? l : JSON.stringify(l))).join("\n"));
|
|
18
|
+
return root;
|
|
19
|
+
}
|
|
20
|
+
function assistant(id, overrides = {}) {
|
|
21
|
+
return {
|
|
22
|
+
type: "assistant",
|
|
23
|
+
timestamp: "2026-08-21T12:00:00.000Z",
|
|
24
|
+
cwd: "/Users/test/proyecto",
|
|
25
|
+
gitBranch: "main",
|
|
26
|
+
version: "2.1.238",
|
|
27
|
+
sessionId: "sess-1",
|
|
28
|
+
message: {
|
|
29
|
+
id,
|
|
30
|
+
model: "claude-opus-5",
|
|
31
|
+
usage: {
|
|
32
|
+
input_tokens: 10,
|
|
33
|
+
output_tokens: 100,
|
|
34
|
+
cache_read_input_tokens: 1000,
|
|
35
|
+
cache_creation_input_tokens: 500,
|
|
36
|
+
cache_creation: { ephemeral_5m_input_tokens: 0, ephemeral_1h_input_tokens: 500 },
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
...overrides,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
(0, node_test_1.test)("deduplica por message.id: el mismo turno repetido cuenta una vez", async () => {
|
|
43
|
+
// Reproduce lo observado en transcripts reales: el mismo turno hasta 5 veces.
|
|
44
|
+
const root = fixture([
|
|
45
|
+
assistant("msg_A"), assistant("msg_A"), assistant("msg_A"),
|
|
46
|
+
assistant("msg_A"), assistant("msg_A"),
|
|
47
|
+
assistant("msg_B"),
|
|
48
|
+
]);
|
|
49
|
+
const { turns, report } = await (0, claude_js_1.scanClaudeCode)({ root });
|
|
50
|
+
strict_1.default.equal(turns.length, 2, "deben quedar 2 turnos únicos");
|
|
51
|
+
strict_1.default.equal(report.duplicatesDropped, 4);
|
|
52
|
+
strict_1.default.equal(report.recordsSeen, 6);
|
|
53
|
+
});
|
|
54
|
+
(0, node_test_1.test)("los registros internos se ignoran sin contarse como error", async () => {
|
|
55
|
+
const root = fixture([
|
|
56
|
+
assistant("msg_A"),
|
|
57
|
+
{ type: "atis-latch", sessionId: "s" },
|
|
58
|
+
{ type: "bridge-session", sessionId: "s" },
|
|
59
|
+
{ type: "ai-title", aiTitle: "x", sessionId: "s" },
|
|
60
|
+
{ type: "queue-operation", operation: "x", sessionId: "s" },
|
|
61
|
+
{ type: "file-history-snapshot", snapshot: {} },
|
|
62
|
+
{ type: "user", message: {} },
|
|
63
|
+
]);
|
|
64
|
+
const { turns, report } = await (0, claude_js_1.scanClaudeCode)({ root });
|
|
65
|
+
strict_1.default.equal(turns.length, 1);
|
|
66
|
+
strict_1.default.equal(report.unknownRecords, 6);
|
|
67
|
+
strict_1.default.equal(report.malformedRecords, 0, "lo interno no es un error");
|
|
68
|
+
});
|
|
69
|
+
(0, node_test_1.test)("una clave nueva desconocida no rompe el parseo", async () => {
|
|
70
|
+
const root = fixture([
|
|
71
|
+
assistant("msg_A", { campoDelFuturo: { anidado: true }, otraCosa: [1, 2, 3] }),
|
|
72
|
+
]);
|
|
73
|
+
const { turns, report } = await (0, claude_js_1.scanClaudeCode)({ root });
|
|
74
|
+
strict_1.default.equal(turns.length, 1);
|
|
75
|
+
strict_1.default.equal(report.malformedRecords, 0);
|
|
76
|
+
strict_1.default.equal(turns[0].tokens.output, 100);
|
|
77
|
+
});
|
|
78
|
+
(0, node_test_1.test)("desglosa los TTL de caché, que cuestan distinto", async () => {
|
|
79
|
+
const root = fixture([assistant("msg_A")]);
|
|
80
|
+
const { turns } = await (0, claude_js_1.scanClaudeCode)({ root });
|
|
81
|
+
strict_1.default.equal(turns[0].tokens.cacheWrite1h, 500);
|
|
82
|
+
strict_1.default.equal(turns[0].tokens.cacheWrite5m, 0);
|
|
83
|
+
});
|
|
84
|
+
(0, node_test_1.test)("sin desglose de TTL, imputa al multiplicador más bajo", async () => {
|
|
85
|
+
// Ante la duda subestimar: inflar una factura es peor que quedarse corto.
|
|
86
|
+
const root = fixture([
|
|
87
|
+
assistant("msg_A", {
|
|
88
|
+
message: {
|
|
89
|
+
id: "msg_A", model: "claude-opus-5",
|
|
90
|
+
usage: { input_tokens: 0, output_tokens: 0, cache_read_input_tokens: 0,
|
|
91
|
+
cache_creation_input_tokens: 800 },
|
|
92
|
+
},
|
|
93
|
+
}),
|
|
94
|
+
]);
|
|
95
|
+
const { turns } = await (0, claude_js_1.scanClaudeCode)({ root });
|
|
96
|
+
strict_1.default.equal(turns[0].tokens.cacheWrite5m, 800);
|
|
97
|
+
strict_1.default.equal(turns[0].tokens.cacheWrite1h, 0);
|
|
98
|
+
});
|
|
99
|
+
(0, node_test_1.test)("una línea a medio escribir se cuenta pero no rompe el escaneo", async () => {
|
|
100
|
+
const root = fixture([
|
|
101
|
+
assistant("msg_A"),
|
|
102
|
+
'{"type":"assistant","message":{"id":"msg_trunc"', // sesión viva
|
|
103
|
+
assistant("msg_B"),
|
|
104
|
+
]);
|
|
105
|
+
const { turns, report } = await (0, claude_js_1.scanClaudeCode)({ root });
|
|
106
|
+
strict_1.default.equal(turns.length, 2);
|
|
107
|
+
strict_1.default.equal(report.malformedRecords, 1);
|
|
108
|
+
});
|
|
109
|
+
(0, node_test_1.test)("un registro sin timestamp o sin modelo se descarta como malformado", async () => {
|
|
110
|
+
const root = fixture([
|
|
111
|
+
{ type: "assistant", message: { id: "x", model: "claude-opus-5" } }, // sin timestamp
|
|
112
|
+
{ type: "assistant", timestamp: "2026-08-21T12:00:00Z", message: { id: "y" } }, // sin modelo
|
|
113
|
+
assistant("msg_ok"),
|
|
114
|
+
]);
|
|
115
|
+
const { turns, report } = await (0, claude_js_1.scanClaudeCode)({ root });
|
|
116
|
+
strict_1.default.equal(turns.length, 1);
|
|
117
|
+
strict_1.default.equal(report.malformedRecords, 2);
|
|
118
|
+
});
|
|
119
|
+
(0, node_test_1.test)("filtra por fecha y por repositorio", async () => {
|
|
120
|
+
const root = fixture([
|
|
121
|
+
assistant("msg_viejo", { timestamp: "2026-01-01T00:00:00.000Z" }),
|
|
122
|
+
assistant("msg_nuevo", { timestamp: "2026-08-21T00:00:00.000Z" }),
|
|
123
|
+
assistant("msg_otro", { cwd: "/Users/test/otro-proyecto" }),
|
|
124
|
+
]);
|
|
125
|
+
const porFecha = await (0, claude_js_1.scanClaudeCode)({ root, since: new Date("2026-06-01T00:00:00Z") });
|
|
126
|
+
strict_1.default.equal(porFecha.turns.length, 2);
|
|
127
|
+
const porRepo = await (0, claude_js_1.scanClaudeCode)({ root, repoPaths: ["/Users/test/otro-proyecto"] });
|
|
128
|
+
strict_1.default.equal(porRepo.turns.length, 1);
|
|
129
|
+
strict_1.default.equal(porRepo.turns[0].turnId, "msg_otro");
|
|
130
|
+
});
|
|
131
|
+
(0, node_test_1.test)("registra las versiones que escribieron el store", async () => {
|
|
132
|
+
const root = fixture([
|
|
133
|
+
assistant("msg_A", { version: "2.1.183" }),
|
|
134
|
+
assistant("msg_B", { version: "2.1.238" }),
|
|
135
|
+
]);
|
|
136
|
+
const { report } = await (0, claude_js_1.scanClaudeCode)({ root });
|
|
137
|
+
strict_1.default.deepEqual(report.producerVersions, ["2.1.183", "2.1.238"]);
|
|
138
|
+
});
|
|
139
|
+
(0, node_test_1.test)("un store inexistente devuelve vacío en vez de lanzar", async () => {
|
|
140
|
+
const { turns, report } = await (0, claude_js_1.scanClaudeCode)({ root: "/ruta/que/no/existe" });
|
|
141
|
+
strict_1.default.equal(turns.length, 0);
|
|
142
|
+
strict_1.default.equal(report.filesRead, 0);
|
|
143
|
+
});
|
|
144
|
+
// ── Scratchpads ────────────────────────────────────────────────────────
|
|
145
|
+
(0, node_test_1.test)("devuelve al repositorio el trabajo hecho en un scratchpad", async () => {
|
|
146
|
+
// El fallo que esto previene: Claude Code trabaja parte del tiempo en un
|
|
147
|
+
// directorio temporal cuyo cwd no es el repositorio. Ese trabajo se quedaba
|
|
148
|
+
// sin imputar — en una jornada medida, casi la mitad de los turnos.
|
|
149
|
+
const root = fixture([
|
|
150
|
+
assistant("msg_repo", { cwd: "/Users/ana/Proyectos/mi_repo" }),
|
|
151
|
+
assistant("msg_scratch", {
|
|
152
|
+
cwd: "/private/tmp/claude-502/-Users-ana-Proyectos-mi-repo/abc-123/scratchpad",
|
|
153
|
+
}),
|
|
154
|
+
]);
|
|
155
|
+
const { turns } = await (0, claude_js_1.scanClaudeCode)({ root });
|
|
156
|
+
const fixed = (0, claude_js_1.resolveScratchpads)(turns);
|
|
157
|
+
strict_1.default.equal(fixed.length, 2);
|
|
158
|
+
for (const turn of fixed) {
|
|
159
|
+
strict_1.default.equal(turn.repoPath, "/Users/ana/Proyectos/mi_repo", "los dos turnos deben apuntar al mismo repositorio");
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
(0, node_test_1.test)("un scratchpad sin repositorio conocido se queda como está", async () => {
|
|
163
|
+
// Mejor sin imputar que imputado al proyecto equivocado: una hora en la
|
|
164
|
+
// factura de otro cliente es peor que una hora que falta.
|
|
165
|
+
const root = fixture([
|
|
166
|
+
assistant("msg_a", { cwd: "/Users/ana/Proyectos/otro_repo" }),
|
|
167
|
+
assistant("msg_b", {
|
|
168
|
+
cwd: "/private/tmp/claude-502/-Users-ana-Proyectos-desconocido/x/scratchpad",
|
|
169
|
+
}),
|
|
170
|
+
]);
|
|
171
|
+
const fixed = (0, claude_js_1.resolveScratchpads)((await (0, claude_js_1.scanClaudeCode)({ root })).turns);
|
|
172
|
+
const scratch = fixed.find((t) => t.turnId === "msg_b");
|
|
173
|
+
strict_1.default.ok(scratch.repoPath.includes("scratchpad"), "sin cambios");
|
|
174
|
+
});
|
|
175
|
+
(0, node_test_1.test)("las rutas normales no se tocan", async () => {
|
|
176
|
+
const root = fixture([assistant("msg_a", { cwd: "/Users/ana/Proyectos/repo" })]);
|
|
177
|
+
const fixed = (0, claude_js_1.resolveScratchpads)((await (0, claude_js_1.scanClaudeCode)({ root })).turns);
|
|
178
|
+
strict_1.default.equal(fixed[0].repoPath, "/Users/ana/Proyectos/repo");
|
|
179
|
+
});
|
|
180
|
+
//# sourceMappingURL=claude.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.test.js","sourceRoot":"","sources":["../../src/watchers/claude.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { CommitRecord } from "@estela/shared";
|
|
2
|
+
export declare function readCommits(repoPath: string, options?: {
|
|
3
|
+
since?: Date;
|
|
4
|
+
authorEmail?: string;
|
|
5
|
+
authorEmails?: readonly string[];
|
|
6
|
+
}): Promise<CommitRecord[]>;
|
|
7
|
+
/**
|
|
8
|
+
* Raíz del repositorio.
|
|
9
|
+
*
|
|
10
|
+
* `git rev-parse --show-toplevel` en vez de comprobar si existe un directorio
|
|
11
|
+
* `.git`: en un `git worktree` el `.git` es un *archivo*, no un directorio, y la
|
|
12
|
+
* comprobación ingenua devuelve falso en un repo perfectamente válido.
|
|
13
|
+
*/
|
|
14
|
+
export declare function repoRoot(path: string): Promise<string | null>;
|
|
15
|
+
/**
|
|
16
|
+
* Ramas ya integradas en la rama de integración.
|
|
17
|
+
*
|
|
18
|
+
* Lo que queda fuera es trabajo abierto, que es la señal de riesgo que un jefe
|
|
19
|
+
* de proyecto no tiene hoy: no la ve hasta que estalla al integrar.
|
|
20
|
+
*
|
|
21
|
+
* La rama base se detecta porque varía por equipo —unos integran en `main`,
|
|
22
|
+
* otros en `develop`— y equivocarse la marcaría todo como abierto.
|
|
23
|
+
*/
|
|
24
|
+
export declare function mergedBranches(path: string): Promise<Set<string>>;
|
|
25
|
+
/** Rama donde el equipo integra. `develop` gana a `main` si existe. */
|
|
26
|
+
export declare function integrationBranch(root: string): Promise<string | null>;
|
|
27
|
+
/** Rama activa del repositorio. Ya no se usa para etiquetar commits. */
|
|
28
|
+
export declare function currentBranch(root: string): Promise<string | null>;
|
|
29
|
+
/**
|
|
30
|
+
* Autores que han commiteado en un repositorio, de más a menos reciente.
|
|
31
|
+
*
|
|
32
|
+
* Sirve para preguntar "¿cuál de estos eres tú?" en vez de adivinarlo: en el
|
|
33
|
+
* repositorio de un cliente hay cinco compañeros y tu correo global no aparece
|
|
34
|
+
* por ningún lado.
|
|
35
|
+
*/
|
|
36
|
+
export declare function repoAuthors(path: string, limit?: number): Promise<{
|
|
37
|
+
email: string;
|
|
38
|
+
commits: number;
|
|
39
|
+
lastAt: string;
|
|
40
|
+
}[]>;
|
|
41
|
+
export declare function gitUserEmail(path: string): Promise<string | null>;
|
|
42
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/watchers/git.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAgBnD,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,IAAI,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAO,GACrF,OAAO,CAAC,YAAY,EAAE,CAAC,CAiFzB;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOnE;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAqBvE;AAED,uEAAuE;AACvE,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQ5E;AAED,wEAAwE;AACxE,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOxE;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EAAE,KAAK,SAAK,GACvB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAyB/D;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOvE"}
|