@statforge/claudestat 1.4.0 → 1.5.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 +130 -547
- package/dist/cost-projector.d.ts +24 -0
- package/dist/cost-projector.js +133 -0
- package/dist/daemon.js +1 -1
- package/dist/db.d.ts +4 -0
- package/dist/db.js +14 -6
- package/dist/enricher.d.ts +18 -26
- package/dist/enricher.js +113 -333
- package/dist/index.js +23 -2
- package/dist/insights.js +0 -2
- package/dist/meta-stats.js +1 -1
- package/dist/middleware/rate-limiter.js +1 -1
- package/dist/paths.d.ts +17 -0
- package/dist/paths.js +44 -0
- package/dist/quota-tracker.js +0 -1
- package/dist/roast.js +0 -2
- package/dist/routes/events.js +5 -5
- package/dist/routes/misc.js +3 -21
- package/dist/routes/stream.d.ts +1 -1
- package/dist/routes/stream.js +3 -3
- package/dist/service.js +11 -7
- package/dist/watchers/adapter.d.ts +37 -0
- package/dist/watchers/adapter.js +31 -0
- package/dist/watchers/amp.d.ts +8 -0
- package/dist/watchers/amp.js +42 -0
- package/dist/watchers/claude-code.d.ts +17 -0
- package/dist/watchers/claude-code.js +300 -0
- package/dist/watchers/codebuff.d.ts +8 -0
- package/dist/watchers/codebuff.js +42 -0
- package/dist/watchers/codex.d.ts +9 -0
- package/dist/watchers/codex.js +43 -0
- package/dist/watchers/droid.d.ts +8 -0
- package/dist/watchers/droid.js +42 -0
- package/dist/watchers/opencode.d.ts +9 -0
- package/dist/watchers/opencode.js +43 -0
- package/package.json +10 -2
package/dist/paths.js
CHANGED
|
@@ -16,6 +16,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
16
16
|
};
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.isWindows = void 0;
|
|
19
|
+
exports.isBinary = isBinary;
|
|
20
|
+
exports.getBinaryDir = getBinaryDir;
|
|
21
|
+
exports.getDashboardDir = getDashboardDir;
|
|
19
22
|
exports.getClaudeDir = getClaudeDir;
|
|
20
23
|
exports.getClaudestatDir = getClaudestatDir;
|
|
21
24
|
exports.getPidFile = getPidFile;
|
|
@@ -28,7 +31,48 @@ exports.whichAllCmd = whichAllCmd;
|
|
|
28
31
|
exports.portCheckCmd = portCheckCmd;
|
|
29
32
|
const os_1 = __importDefault(require("os"));
|
|
30
33
|
const path_1 = __importDefault(require("path"));
|
|
34
|
+
const fs_1 = __importDefault(require("fs"));
|
|
31
35
|
const isWin = process.platform === 'win32';
|
|
36
|
+
// ─── Binary detection ──────────────────────────────────────────────────────────
|
|
37
|
+
/**
|
|
38
|
+
* Detecta si claudestat está corriendo como binario standalone (Bun compile)
|
|
39
|
+
* vs desde npm (node dist/index.js).
|
|
40
|
+
*/
|
|
41
|
+
function isBinary() {
|
|
42
|
+
const arg1 = process.argv[1] ?? '';
|
|
43
|
+
return !arg1.includes('node_modules') && !arg1.includes('dist/index.js')
|
|
44
|
+
&& !arg1.includes('tsx') && arg1.includes('claudestat');
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Retorna el directorio base del binario o del proyecto.
|
|
48
|
+
* En binario: directorio donde está el ejecutable.
|
|
49
|
+
* En npm: root del proyecto (unimos dist/..).
|
|
50
|
+
*/
|
|
51
|
+
function getBinaryDir() {
|
|
52
|
+
if (isBinary()) {
|
|
53
|
+
return path_1.default.dirname(process.argv[1]);
|
|
54
|
+
}
|
|
55
|
+
return path_1.default.join(__dirname, '..');
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Retorna el directorio del dashboard build (dashboard/dist/).
|
|
59
|
+
* En binario: busca relativo al binario o en CLAUDESTAT_DATA_DIR.
|
|
60
|
+
* En npm: usa __dirname para encontrar dist/.
|
|
61
|
+
*/
|
|
62
|
+
function getDashboardDir() {
|
|
63
|
+
if (isBinary()) {
|
|
64
|
+
const candidates = [
|
|
65
|
+
path_1.default.join(getBinaryDir(), 'dashboard'),
|
|
66
|
+
path_1.default.join(getClaudestatDir(), 'dashboard'),
|
|
67
|
+
path_1.default.join(getBinaryDir(), '..', 'dashboard', 'dist'),
|
|
68
|
+
];
|
|
69
|
+
for (const c of candidates) {
|
|
70
|
+
if (fs_1.default.existsSync(path_1.default.join(c, 'index.html')))
|
|
71
|
+
return c;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return path_1.default.join(__dirname, '..', 'dashboard', 'dist');
|
|
75
|
+
}
|
|
32
76
|
// ─── Claude Code data directory ────────────────────────────────────────────────
|
|
33
77
|
/**
|
|
34
78
|
* Returns the Claude Code data directory (~/.claude on all platforms).
|
package/dist/quota-tracker.js
CHANGED
|
@@ -298,7 +298,6 @@ function computeQuota(forcePlan) {
|
|
|
298
298
|
const cycleEntries = entries.filter(e => e.ts >= fiveHAgo);
|
|
299
299
|
const cycleTokens = cycleEntries.reduce((sum, e) => sum + (e.inputTokens ?? 0) + (e.outputTokens ?? 0), 0);
|
|
300
300
|
const cyclePct = Math.min(100, Math.round(cycleTokens / limits.tokens5h * 100));
|
|
301
|
-
const cycleResetMs = Math.max(0, cycleResetAt - now);
|
|
302
301
|
// ─ Semanal por modelo: ventanas de 5 min con actividad ─
|
|
303
302
|
// Contamos ventanas de 5 min distintas con al menos 1 respuesta por modelo
|
|
304
303
|
const sonnetWindows = new Set();
|
package/dist/roast.js
CHANGED
|
@@ -79,8 +79,6 @@ async function runRoast(opts) {
|
|
|
79
79
|
const D = '\x1b[2m';
|
|
80
80
|
const G = '\x1b[32m';
|
|
81
81
|
const Y = '\x1b[33m';
|
|
82
|
-
const C = '\x1b[36m';
|
|
83
|
-
const M = '\x1b[35m';
|
|
84
82
|
const bar = (pct, width = 20) => {
|
|
85
83
|
const filled = Math.round(Math.min(pct, 100) / 100 * width);
|
|
86
84
|
const color = pct >= 90 ? '\x1b[31m' : pct >= 70 ? '\x1b[33m' : '\x1b[32m';
|
package/dist/routes/events.js
CHANGED
|
@@ -75,14 +75,14 @@ exports.eventsRouter.post('/event', (req, res) => {
|
|
|
75
75
|
res.status(429).json({ error: 'Too many requests — wait 1 minute' });
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
78
|
-
const { type, session_id, tool_name, tool_input, tool_response, ts, cwd, transcript_path } = req.body;
|
|
78
|
+
const { type, session_id, tool_name, tool_input, tool_response, ts, cwd, transcript_path, source } = req.body;
|
|
79
79
|
if (!session_id || !type) {
|
|
80
80
|
res.status(400).json({ error: 'Missing session_id or type' });
|
|
81
81
|
return;
|
|
82
82
|
}
|
|
83
83
|
const resolvedCwd = cwd
|
|
84
84
|
?? (transcript_path ? path_1.default.dirname(transcript_path) || undefined : undefined);
|
|
85
|
-
db_1.dbOps.upsertSession({ id: session_id, cwd: resolvedCwd, started_at: ts, last_event_at: ts });
|
|
85
|
+
db_1.dbOps.upsertSession({ id: session_id, cwd: resolvedCwd, started_at: ts, last_event_at: ts, source });
|
|
86
86
|
// Skill grouping: get current parent BEFORE processing this event
|
|
87
87
|
// (the Skill Done event itself is NOT tagged — only its subsequent sub-calls are)
|
|
88
88
|
const skillParent = (tool_name !== 'Skill' && type !== 'Stop')
|
|
@@ -112,7 +112,7 @@ exports.eventsRouter.post('/event', (req, res) => {
|
|
|
112
112
|
session_id, type,
|
|
113
113
|
tool_name: tool_name ?? undefined,
|
|
114
114
|
tool_input: tool_input ? JSON.stringify(tool_input) : undefined,
|
|
115
|
-
ts, cwd: resolvedCwd, skill_parent: skillParent
|
|
115
|
+
ts, cwd: resolvedCwd, skill_parent: skillParent, source
|
|
116
116
|
});
|
|
117
117
|
(0, stream_1.broadcast)({ type: 'event', payload: { ...req.body, skill_parent: skillParent } });
|
|
118
118
|
// Stop limpia el skill activo para esta sesión
|
|
@@ -208,12 +208,12 @@ exports.eventsRouter.post('/event', (req, res) => {
|
|
|
208
208
|
* 2. Guarda el coste + score en DB
|
|
209
209
|
* 3. Hace broadcast vía SSE para que el watch muestre el coste actualizado
|
|
210
210
|
*/
|
|
211
|
-
const onCostUpdate = (sessionId, cost) => {
|
|
211
|
+
const onCostUpdate = (sessionId, cost, source) => {
|
|
212
212
|
// Ensure session row exists — sub-agent JSONLs arrive from the enricher without a
|
|
213
213
|
// prior hook event (Claude Code does not fire hooks for sub-agent sessions).
|
|
214
214
|
let sessionRow = db_1.dbOps.getSession(sessionId);
|
|
215
215
|
if (!sessionRow) {
|
|
216
|
-
db_1.dbOps.upsertSession({ id: sessionId, cwd: undefined, started_at: cost.firstTs ?? Date.now(), last_event_at: cost.firstTs ?? Date.now() });
|
|
216
|
+
db_1.dbOps.upsertSession({ id: sessionId, cwd: undefined, started_at: cost.firstTs ?? Date.now(), last_event_at: cost.firstTs ?? Date.now(), source });
|
|
217
217
|
sessionRow = db_1.dbOps.getSession(sessionId);
|
|
218
218
|
}
|
|
219
219
|
// Sub-agent detection: first time we see a session, check if its firstTs falls after
|
package/dist/routes/misc.js
CHANGED
|
@@ -9,7 +9,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
9
9
|
exports.miscRouter = void 0;
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
11
|
const fs_1 = __importDefault(require("fs"));
|
|
12
|
-
const os_1 = __importDefault(require("os"));
|
|
13
12
|
const express_1 = require("express");
|
|
14
13
|
const db_1 = require("../db");
|
|
15
14
|
const intelligence_1 = require("../intelligence");
|
|
@@ -23,6 +22,7 @@ const projects_1 = require("./projects");
|
|
|
23
22
|
const session_state_1 = require("../session-state");
|
|
24
23
|
const stream_1 = require("./stream");
|
|
25
24
|
const paths_1 = require("../paths");
|
|
25
|
+
const cost_projector_1 = require("../cost-projector");
|
|
26
26
|
exports.miscRouter = (0, express_1.Router)();
|
|
27
27
|
// ─── GET /git?path=... — git info para un proyecto ────────────────────────────
|
|
28
28
|
exports.miscRouter.get('/git', (req, res) => {
|
|
@@ -135,7 +135,6 @@ exports.miscRouter.get('/system-config', (_req, res) => {
|
|
|
135
135
|
return;
|
|
136
136
|
}
|
|
137
137
|
try {
|
|
138
|
-
const home = os_1.default.homedir();
|
|
139
138
|
const claudeDir = (0, paths_1.getClaudeDir)();
|
|
140
139
|
let hooks = {};
|
|
141
140
|
try {
|
|
@@ -257,24 +256,7 @@ exports.miscRouter.put('/config', (req, res) => {
|
|
|
257
256
|
res.status(500).json({ error: String(e) });
|
|
258
257
|
}
|
|
259
258
|
});
|
|
260
|
-
// ─── GET /cost-projection —
|
|
259
|
+
// ─── GET /cost-projection — linear regression cost projection ───────────────
|
|
261
260
|
exports.miscRouter.get('/cost-projection', (_req, res) => {
|
|
262
|
-
|
|
263
|
-
const month = db_1.dbOps.getCostProjection(30);
|
|
264
|
-
const weekSpan = week.latest && week.earliest ? (week.latest - week.earliest) / 86400000 : 0;
|
|
265
|
-
const monthSpan = month.latest && month.earliest ? (month.latest - month.earliest) / 86400000 : 0;
|
|
266
|
-
const weeklyProjected = weekSpan > 0.5 ? (week.total_cost_usd ?? 0) / weekSpan * 7 : 0;
|
|
267
|
-
const monthlyProjected = monthSpan > 1 ? (month.total_cost_usd ?? 0) / monthSpan * 30 : 0;
|
|
268
|
-
res.json({
|
|
269
|
-
weekly: {
|
|
270
|
-
daysWithData: Math.round(weekSpan * 10) / 10,
|
|
271
|
-
costSoFar: week.total_cost_usd ?? 0,
|
|
272
|
-
projected: Math.round(weeklyProjected * 100) / 100,
|
|
273
|
-
},
|
|
274
|
-
monthly: {
|
|
275
|
-
daysWithData: Math.round(monthSpan * 10) / 10,
|
|
276
|
-
costSoFar: month.total_cost_usd ?? 0,
|
|
277
|
-
projected: Math.round(monthlyProjected * 100) / 100,
|
|
278
|
-
},
|
|
279
|
-
});
|
|
261
|
+
res.json((0, cost_projector_1.computeProjection)(90));
|
|
280
262
|
});
|
package/dist/routes/stream.d.ts
CHANGED
|
@@ -5,4 +5,4 @@ export declare const sessionLastEvent: Map<string, {
|
|
|
5
5
|
}>;
|
|
6
6
|
export declare function broadcast(msg: object): void;
|
|
7
7
|
export declare function getSseClientsSize(): number;
|
|
8
|
-
export declare function setOnCostUpdateRef(cb: (sessionId: string, cost: any) => void): void;
|
|
8
|
+
export declare function setOnCostUpdateRef(cb: (sessionId: string, cost: any, source?: string) => void): void;
|
package/dist/routes/stream.js
CHANGED
|
@@ -54,13 +54,13 @@ exports.streamRouter.get('/stream', (req, res) => {
|
|
|
54
54
|
: allEvents;
|
|
55
55
|
const lastEvt = exports.sessionLastEvent.get(latestSession.id);
|
|
56
56
|
const state = (0, session_state_1.deriveSessionState)(lastEvt?.type, lastEvt?.ts ?? latestSession.last_event_at ?? latestSession.started_at);
|
|
57
|
-
(0, enricher_1.getAllBlockCostsForSession)(latestSession.id).then(blockCosts => {
|
|
57
|
+
(0, enricher_1.getAllBlockCostsForSession)(latestSession.id).then((blockCosts) => {
|
|
58
58
|
const subAgentSessions = db_1.dbOps.getChildSessions(latestSession.id);
|
|
59
59
|
res.write(`data: ${JSON.stringify({ type: 'init', session: { ...latestSession, state }, events, blockCosts, subAgentSessions })}\n\n`);
|
|
60
60
|
if (_onCostUpdateRef) {
|
|
61
|
-
(0, enricher_1.processLatestForSession)(latestSession.id, _onCostUpdateRef).catch(err => console.error('[stream] Error processing latest session:', err));
|
|
61
|
+
(0, enricher_1.processLatestForSession)(latestSession.id, _onCostUpdateRef).catch((err) => console.error('[stream] Error processing latest session:', err));
|
|
62
62
|
}
|
|
63
|
-
}).catch(err => {
|
|
63
|
+
}).catch((err) => {
|
|
64
64
|
console.error('[stream] Error loading block costs:', err);
|
|
65
65
|
const subAgentSessions = db_1.dbOps.getChildSessions(latestSession.id);
|
|
66
66
|
res.write(`data: ${JSON.stringify({ type: 'init', session: { ...latestSession, state }, events, blockCosts: [], subAgentSessions })}\n\n`);
|
package/dist/service.js
CHANGED
|
@@ -12,9 +12,16 @@ const PLIST_LABEL = 'com.statforge.claudestat';
|
|
|
12
12
|
const PLIST_PATH = path_1.default.join(process.env.HOME ?? '~', 'Library', 'LaunchAgents', `${PLIST_LABEL}.plist`);
|
|
13
13
|
const SYSTEMD_DIR = path_1.default.join(process.env.HOME ?? '~', '.config', 'systemd', 'user');
|
|
14
14
|
const SYSTEMD_PATH = path_1.default.join(SYSTEMD_DIR, 'claudestat.service');
|
|
15
|
+
function isBinary() {
|
|
16
|
+
return process.argv[1]?.includes('claudestat') && !process.argv[1]?.includes('node_modules')
|
|
17
|
+
&& !process.argv[1]?.includes('dist/index.js');
|
|
18
|
+
}
|
|
19
|
+
function serviceCommand() {
|
|
20
|
+
if (isBinary())
|
|
21
|
+
return process.argv[1];
|
|
22
|
+
return `${process.execPath} ${process.argv[1]}`;
|
|
23
|
+
}
|
|
15
24
|
function makePlist() {
|
|
16
|
-
const node = process.execPath;
|
|
17
|
-
const script = process.argv[1];
|
|
18
25
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
19
26
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
20
27
|
<plist version="1.0">
|
|
@@ -23,8 +30,7 @@ function makePlist() {
|
|
|
23
30
|
<string>${PLIST_LABEL}</string>
|
|
24
31
|
<key>ProgramArguments</key>
|
|
25
32
|
<array>
|
|
26
|
-
<string>${
|
|
27
|
-
<string>${script}</string>
|
|
33
|
+
<string>${serviceCommand()}</string>
|
|
28
34
|
<string>start</string>
|
|
29
35
|
</array>
|
|
30
36
|
<key>EnvironmentVariables</key>
|
|
@@ -40,15 +46,13 @@ function makePlist() {
|
|
|
40
46
|
</plist>`;
|
|
41
47
|
}
|
|
42
48
|
function makeUnit() {
|
|
43
|
-
const node = process.execPath;
|
|
44
|
-
const script = process.argv[1];
|
|
45
49
|
return `[Unit]
|
|
46
50
|
Description=ClaudeStat daemon — real-time Claude Code monitor
|
|
47
51
|
After=default.target
|
|
48
52
|
|
|
49
53
|
[Service]
|
|
50
54
|
Type=simple
|
|
51
|
-
ExecStart=${
|
|
55
|
+
ExecStart=${serviceCommand()} start
|
|
52
56
|
Restart=on-failure
|
|
53
57
|
RestartSec=5
|
|
54
58
|
Environment=CLAUDESTAT_DAEMON=1
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* adapter.ts — WatcherAdapter interface + factory para Multi-CLI support
|
|
3
|
+
*
|
|
4
|
+
* Cada CLI coding (Claude Code, Codex, OpenCode, etc.) tiene su propio
|
|
5
|
+
* formato de trazas y ubicación de archivos. Este adapter pattern permite
|
|
6
|
+
* que claudestat las soporte todas con una interfaz común.
|
|
7
|
+
*/
|
|
8
|
+
import type { CostUpdate } from '../db';
|
|
9
|
+
export interface ParsedEvent {
|
|
10
|
+
sessionId: string;
|
|
11
|
+
type: string;
|
|
12
|
+
toolName?: string;
|
|
13
|
+
toolInput?: string;
|
|
14
|
+
ts: number;
|
|
15
|
+
cwd?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface WatcherAdapter {
|
|
18
|
+
/** Nombre único del CLI (claude-code, codex, opencode, etc.) */
|
|
19
|
+
readonly name: string;
|
|
20
|
+
/** Label legible mostrado en UI */
|
|
21
|
+
readonly label: string;
|
|
22
|
+
/** Detecta si este CLI está instalado y tiene trazas disponibles */
|
|
23
|
+
detect(): boolean;
|
|
24
|
+
/** Directorios/glob a observar con chokidar */
|
|
25
|
+
getWatchPaths(): string[];
|
|
26
|
+
/** Parsea una línea de traza en un ParsedEvent */
|
|
27
|
+
parseEvent(raw: string, filePath: string): ParsedEvent | null;
|
|
28
|
+
/** Lee y calcula costos acumulados de un archivo de sesión */
|
|
29
|
+
getSessionCost(filePath: string): Promise<CostUpdate | null>;
|
|
30
|
+
/** Nombre amigable para el badge de la CLI (ej: "CC", "Codex") */
|
|
31
|
+
get shortName(): string;
|
|
32
|
+
}
|
|
33
|
+
export declare function registerAdapter(adapter: WatcherAdapter): void;
|
|
34
|
+
export declare function getAdapter(name: string): WatcherAdapter | undefined;
|
|
35
|
+
export declare function getAllAdapters(): WatcherAdapter[];
|
|
36
|
+
export declare function getActiveAdapters(): WatcherAdapter[];
|
|
37
|
+
export declare function getAdapterNames(): string[];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* adapter.ts — WatcherAdapter interface + factory para Multi-CLI support
|
|
4
|
+
*
|
|
5
|
+
* Cada CLI coding (Claude Code, Codex, OpenCode, etc.) tiene su propio
|
|
6
|
+
* formato de trazas y ubicación de archivos. Este adapter pattern permite
|
|
7
|
+
* que claudestat las soporte todas con una interfaz común.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.registerAdapter = registerAdapter;
|
|
11
|
+
exports.getAdapter = getAdapter;
|
|
12
|
+
exports.getAllAdapters = getAllAdapters;
|
|
13
|
+
exports.getActiveAdapters = getActiveAdapters;
|
|
14
|
+
exports.getAdapterNames = getAdapterNames;
|
|
15
|
+
// ─── Factory ───────────────────────────────────────────────────────────────────
|
|
16
|
+
const registry = new Map();
|
|
17
|
+
function registerAdapter(adapter) {
|
|
18
|
+
registry.set(adapter.name, adapter);
|
|
19
|
+
}
|
|
20
|
+
function getAdapter(name) {
|
|
21
|
+
return registry.get(name);
|
|
22
|
+
}
|
|
23
|
+
function getAllAdapters() {
|
|
24
|
+
return Array.from(registry.values());
|
|
25
|
+
}
|
|
26
|
+
function getActiveAdapters() {
|
|
27
|
+
return getAllAdapters().filter(a => a.detect());
|
|
28
|
+
}
|
|
29
|
+
function getAdapterNames() {
|
|
30
|
+
return Array.from(registry.keys());
|
|
31
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* amp.ts — WatcherAdapter para Amp (coding CLI agent)
|
|
3
|
+
*
|
|
4
|
+
* Amp stores traces in ~/.amp/logs/ as JSONL files.
|
|
5
|
+
* This is a scaffold — fill in parseEvent/getSessionCost with sample traces.
|
|
6
|
+
*/
|
|
7
|
+
import { type WatcherAdapter } from './adapter';
|
|
8
|
+
export declare const ampAdapter: WatcherAdapter;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* amp.ts — WatcherAdapter para Amp (coding CLI agent)
|
|
4
|
+
*
|
|
5
|
+
* Amp stores traces in ~/.amp/logs/ as JSONL files.
|
|
6
|
+
* This is a scaffold — fill in parseEvent/getSessionCost with sample traces.
|
|
7
|
+
*/
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.ampAdapter = void 0;
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const os_1 = __importDefault(require("os"));
|
|
15
|
+
const fs_1 = __importDefault(require("fs"));
|
|
16
|
+
const adapter_1 = require("./adapter");
|
|
17
|
+
const AMP_DIR = path_1.default.join(os_1.default.homedir(), '.amp', 'logs');
|
|
18
|
+
exports.ampAdapter = {
|
|
19
|
+
name: 'amp',
|
|
20
|
+
label: 'Amp',
|
|
21
|
+
get shortName() { return 'Amp'; },
|
|
22
|
+
detect() {
|
|
23
|
+
try {
|
|
24
|
+
return fs_1.default.existsSync(AMP_DIR);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
getWatchPaths() {
|
|
31
|
+
return [`${AMP_DIR}/**/*.jsonl`];
|
|
32
|
+
},
|
|
33
|
+
parseEvent(_raw, _filePath) {
|
|
34
|
+
// TODO: implement when Amp trace format is known
|
|
35
|
+
return null;
|
|
36
|
+
},
|
|
37
|
+
async getSessionCost(_filePath) {
|
|
38
|
+
// TODO: implement when Amp trace format is known
|
|
39
|
+
return null;
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
(0, adapter_1.registerAdapter)(exports.ampAdapter);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* claude-code.ts — WatcherAdapter para Claude Code
|
|
3
|
+
*
|
|
4
|
+
* Claude Code escribe trazas JSONL en ~/.claude/projects/{hash}/{session-id}.jsonl
|
|
5
|
+
* Cada línea "assistant" contiene usage tokens y modelo.
|
|
6
|
+
*/
|
|
7
|
+
import { type WatcherAdapter } from './adapter';
|
|
8
|
+
import type { BlockCostEntry } from '../db';
|
|
9
|
+
export declare function getContextWindow(model: string): number;
|
|
10
|
+
export declare const claudeCodeAdapter: WatcherAdapter;
|
|
11
|
+
export declare function getAllBlockCostsForSession(sessionId: string): Promise<BlockCostEntry[]>;
|
|
12
|
+
export interface SessionPrompt {
|
|
13
|
+
index: number;
|
|
14
|
+
ts: number;
|
|
15
|
+
text: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function getSessionPrompts(sessionId: string): Promise<SessionPrompt[]>;
|