@usevalt/cli 0.7.3 → 0.7.4
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/dist/index.js +94 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1035,7 +1035,7 @@ proxyCommand.command("stop").description("Stop the MCP proxy").action(() => {
|
|
|
1035
1035
|
|
|
1036
1036
|
// src/commands/hook.ts
|
|
1037
1037
|
import { Command as Command13 } from "commander";
|
|
1038
|
-
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, unlinkSync as unlinkSync2, existsSync as existsSync3, readdirSync } from "fs";
|
|
1038
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, unlinkSync as unlinkSync2, existsSync as existsSync3, readdirSync, statSync, openSync, readSync, closeSync } from "fs";
|
|
1039
1039
|
import { createReadStream } from "fs";
|
|
1040
1040
|
import { createInterface } from "readline";
|
|
1041
1041
|
import { execSync } from "child_process";
|
|
@@ -1311,6 +1311,51 @@ async function parseTranscript(transcriptPath) {
|
|
|
1311
1311
|
}
|
|
1312
1312
|
return result;
|
|
1313
1313
|
}
|
|
1314
|
+
function parseTranscriptIncremental(transcriptPath, fromByteOffset, model) {
|
|
1315
|
+
const result = {
|
|
1316
|
+
deltaPromptTokens: 0,
|
|
1317
|
+
deltaCompletionTokens: 0,
|
|
1318
|
+
deltaCacheReadTokens: 0,
|
|
1319
|
+
deltaCostUsd: 0,
|
|
1320
|
+
newByteOffset: fromByteOffset
|
|
1321
|
+
};
|
|
1322
|
+
try {
|
|
1323
|
+
const fileSize = statSync(transcriptPath).size;
|
|
1324
|
+
if (fileSize <= fromByteOffset) return result;
|
|
1325
|
+
const bytesToRead = fileSize - fromByteOffset;
|
|
1326
|
+
const buffer = Buffer.alloc(bytesToRead);
|
|
1327
|
+
const fd = openSync(transcriptPath, "r");
|
|
1328
|
+
try {
|
|
1329
|
+
readSync(fd, buffer, 0, bytesToRead, fromByteOffset);
|
|
1330
|
+
} finally {
|
|
1331
|
+
closeSync(fd);
|
|
1332
|
+
}
|
|
1333
|
+
const chunk = buffer.toString("utf-8");
|
|
1334
|
+
const lines = chunk.split("\n");
|
|
1335
|
+
for (const line of lines) {
|
|
1336
|
+
if (!line.trim()) continue;
|
|
1337
|
+
try {
|
|
1338
|
+
const entry = JSON.parse(line);
|
|
1339
|
+
const usage = entry.message?.usage ?? entry.usage;
|
|
1340
|
+
if (usage) {
|
|
1341
|
+
result.deltaPromptTokens += usage.input_tokens ?? 0;
|
|
1342
|
+
result.deltaCompletionTokens += usage.output_tokens ?? 0;
|
|
1343
|
+
result.deltaCacheReadTokens += usage.cache_read_input_tokens ?? 0;
|
|
1344
|
+
}
|
|
1345
|
+
} catch {
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
result.newByteOffset = fileSize;
|
|
1349
|
+
result.deltaCostUsd = calculateCost(
|
|
1350
|
+
model,
|
|
1351
|
+
result.deltaPromptTokens,
|
|
1352
|
+
result.deltaCompletionTokens,
|
|
1353
|
+
result.deltaCacheReadTokens
|
|
1354
|
+
);
|
|
1355
|
+
} catch {
|
|
1356
|
+
}
|
|
1357
|
+
return result;
|
|
1358
|
+
}
|
|
1314
1359
|
var sessionStartCommand = new Command13("session-start").description("Hook: called when a Claude Code session starts").action(async () => {
|
|
1315
1360
|
try {
|
|
1316
1361
|
const { apiKey, endpoint, apiEndpoint } = resolveConfig();
|
|
@@ -1322,6 +1367,7 @@ var sessionStartCommand = new Command13("session-start").description("Hook: call
|
|
|
1322
1367
|
const model = hookData["model"] || process.env["CLAUDE_MODEL"] || "unknown";
|
|
1323
1368
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1324
1369
|
const cwd = hookData["cwd"] || process.cwd();
|
|
1370
|
+
const transcriptPath = hookData["transcript_path"] || void 0;
|
|
1325
1371
|
const state = {
|
|
1326
1372
|
sessionId,
|
|
1327
1373
|
claudeSessionId,
|
|
@@ -1331,7 +1377,8 @@ var sessionStartCommand = new Command13("session-start").description("Hook: call
|
|
|
1331
1377
|
apiEndpoint,
|
|
1332
1378
|
projectSlug,
|
|
1333
1379
|
model,
|
|
1334
|
-
cwd
|
|
1380
|
+
cwd,
|
|
1381
|
+
transcriptPath
|
|
1335
1382
|
};
|
|
1336
1383
|
writeFileSync3(getSessionFile(claudeSessionId), JSON.stringify(state, null, 2), { mode: 384 });
|
|
1337
1384
|
let gitCommitBefore;
|
|
@@ -1500,6 +1547,45 @@ var postToolUseCommand = new Command13("post-tool-use").description("Hook: calle
|
|
|
1500
1547
|
}
|
|
1501
1548
|
}
|
|
1502
1549
|
}
|
|
1550
|
+
try {
|
|
1551
|
+
const tPath = hookData["transcript_path"] ?? session.transcriptPath;
|
|
1552
|
+
if (tPath && existsSync3(tPath)) {
|
|
1553
|
+
if (!session.transcriptPath) session.transcriptPath = tPath;
|
|
1554
|
+
const deltas = parseTranscriptIncremental(
|
|
1555
|
+
tPath,
|
|
1556
|
+
session.transcriptByteOffset ?? 0,
|
|
1557
|
+
session.model ?? "unknown"
|
|
1558
|
+
);
|
|
1559
|
+
if (deltas.deltaPromptTokens > 0 || deltas.deltaCompletionTokens > 0) {
|
|
1560
|
+
events.push({
|
|
1561
|
+
event_id: crypto.randomUUID(),
|
|
1562
|
+
session_id: session.sessionId,
|
|
1563
|
+
event_type: "cost",
|
|
1564
|
+
timestamp,
|
|
1565
|
+
tool: "claude-code",
|
|
1566
|
+
tokens_prompt: deltas.deltaPromptTokens,
|
|
1567
|
+
tokens_completion: deltas.deltaCompletionTokens,
|
|
1568
|
+
cost_usd: deltas.deltaCostUsd,
|
|
1569
|
+
metadata: {
|
|
1570
|
+
model: session.model,
|
|
1571
|
+
source: "incremental",
|
|
1572
|
+
cache_read_tokens: deltas.deltaCacheReadTokens
|
|
1573
|
+
}
|
|
1574
|
+
});
|
|
1575
|
+
}
|
|
1576
|
+
session.transcriptByteOffset = deltas.newByteOffset;
|
|
1577
|
+
session.runningPromptTokens = (session.runningPromptTokens ?? 0) + deltas.deltaPromptTokens;
|
|
1578
|
+
session.runningCompletionTokens = (session.runningCompletionTokens ?? 0) + deltas.deltaCompletionTokens;
|
|
1579
|
+
session.runningCacheReadTokens = (session.runningCacheReadTokens ?? 0) + deltas.deltaCacheReadTokens;
|
|
1580
|
+
session.runningCostUsd = (session.runningCostUsd ?? 0) + deltas.deltaCostUsd;
|
|
1581
|
+
writeFileSync3(
|
|
1582
|
+
getSessionFile(session.claudeSessionId),
|
|
1583
|
+
JSON.stringify(session, null, 2),
|
|
1584
|
+
{ mode: 384 }
|
|
1585
|
+
);
|
|
1586
|
+
}
|
|
1587
|
+
} catch {
|
|
1588
|
+
}
|
|
1503
1589
|
await sendEvents(session.endpoint, session.apiKey, events);
|
|
1504
1590
|
} catch {
|
|
1505
1591
|
}
|
|
@@ -1626,6 +1712,12 @@ var sessionEndCommand = new Command13("session-end").description("Hook: called w
|
|
|
1626
1712
|
const durationMs = now.getTime() - startedAt.getTime();
|
|
1627
1713
|
const transcriptPath = hookData["transcript_path"];
|
|
1628
1714
|
const metrics = transcriptPath ? await parseTranscript(transcriptPath) : null;
|
|
1715
|
+
if (metrics && (session.runningPromptTokens || session.runningCostUsd)) {
|
|
1716
|
+
metrics.promptTokens = Math.max(0, metrics.promptTokens - (session.runningPromptTokens ?? 0));
|
|
1717
|
+
metrics.completionTokens = Math.max(0, metrics.completionTokens - (session.runningCompletionTokens ?? 0));
|
|
1718
|
+
metrics.cacheReadTokens = Math.max(0, metrics.cacheReadTokens - (session.runningCacheReadTokens ?? 0));
|
|
1719
|
+
metrics.totalCostUsd = Math.max(0, metrics.totalCostUsd - (session.runningCostUsd ?? 0));
|
|
1720
|
+
}
|
|
1629
1721
|
let gitCommitAfter;
|
|
1630
1722
|
try {
|
|
1631
1723
|
gitCommitAfter = execSync("git rev-parse HEAD", {
|