@blockrun/clawrouter 0.12.92 → 0.12.94
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/cli.js +76 -0
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -45644,6 +45644,48 @@ async function getStats(days = 7) {
|
|
|
45644
45644
|
// How many entries have valid baseline tracking
|
|
45645
45645
|
};
|
|
45646
45646
|
}
|
|
45647
|
+
async function formatRecentLogs(days = 1) {
|
|
45648
|
+
const logFiles = await getLogFiles();
|
|
45649
|
+
const filesToRead = logFiles.slice(0, days);
|
|
45650
|
+
const allEntries = [];
|
|
45651
|
+
for (const file of filesToRead) {
|
|
45652
|
+
const entries = await parseLogFile(join4(LOG_DIR2, file));
|
|
45653
|
+
allEntries.push(...entries);
|
|
45654
|
+
}
|
|
45655
|
+
allEntries.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
|
|
45656
|
+
const lines = [];
|
|
45657
|
+
lines.push("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
|
|
45658
|
+
lines.push(`\u2551 ClawRouter Request Log \u2014 last ${days === 1 ? "24h" : `${days} days`}`.padEnd(72) + "\u2551");
|
|
45659
|
+
lines.push("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2566\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2566\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2566\u2550\u2550\u2550\u2550\u2550\u2550\u2566\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563");
|
|
45660
|
+
lines.push("\u2551 Time \u2551 Model \u2551 Cost \u2551 ms \u2551 Status \u2551");
|
|
45661
|
+
lines.push("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256C\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256C\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256C\u2550\u2550\u2550\u2550\u2550\u2550\u256C\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563");
|
|
45662
|
+
if (allEntries.length === 0) {
|
|
45663
|
+
lines.push("\u2551 No requests found".padEnd(72) + "\u2551");
|
|
45664
|
+
}
|
|
45665
|
+
let totalCost = 0;
|
|
45666
|
+
for (const e7 of allEntries) {
|
|
45667
|
+
const time = e7.timestamp.slice(11, 19);
|
|
45668
|
+
const date = e7.timestamp.slice(5, 10);
|
|
45669
|
+
const displayTime = `${date} ${time}`;
|
|
45670
|
+
const model = e7.model.length > 24 ? e7.model.slice(0, 21) + "..." : e7.model;
|
|
45671
|
+
const cost = `$${e7.cost.toFixed(4)}`;
|
|
45672
|
+
const ms = e7.latencyMs > 9999 ? `${(e7.latencyMs / 1e3).toFixed(1)}s` : `${e7.latencyMs}ms`;
|
|
45673
|
+
const status = e7.status === "error" ? " ERROR " : " OK ";
|
|
45674
|
+
totalCost += e7.cost;
|
|
45675
|
+
lines.push(
|
|
45676
|
+
`\u2551 ${displayTime.padEnd(16)}\u2551 ${model.padEnd(24)}\u2551 ${cost.padStart(7)}\u2551 ${ms.padStart(4)}\u2551${status}\u2551`
|
|
45677
|
+
);
|
|
45678
|
+
}
|
|
45679
|
+
lines.push("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2569\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2569\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2569\u2550\u2550\u2550\u2550\u2550\u2550\u2569\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563");
|
|
45680
|
+
lines.push(
|
|
45681
|
+
`\u2551 ${allEntries.length} request${allEntries.length !== 1 ? "s" : ""} Total spent: $${totalCost.toFixed(4)}`.padEnd(72) + "\u2551"
|
|
45682
|
+
);
|
|
45683
|
+
lines.push(
|
|
45684
|
+
"\u2551 Logs: ~/.openclaw/blockrun/logs/ (JSONL \u2014 one entry per request)".padEnd(72) + "\u2551"
|
|
45685
|
+
);
|
|
45686
|
+
lines.push("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D");
|
|
45687
|
+
return lines.join("\n");
|
|
45688
|
+
}
|
|
45647
45689
|
async function clearStats() {
|
|
45648
45690
|
try {
|
|
45649
45691
|
const files = await readdir(LOG_DIR2);
|
|
@@ -52439,6 +52481,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
52439
52481
|
let accumulatedContent = "";
|
|
52440
52482
|
let responseInputTokens;
|
|
52441
52483
|
let responseOutputTokens;
|
|
52484
|
+
let requestHadError = false;
|
|
52442
52485
|
const isChatCompletion = req.url?.includes("/chat/completions");
|
|
52443
52486
|
const sessionId = getSessionId(req.headers);
|
|
52444
52487
|
let effectiveSessionId = sessionId;
|
|
@@ -53703,6 +53746,7 @@ data: [DONE]
|
|
|
53703
53746
|
const rawErrBody = lastError?.body || structuredMessage;
|
|
53704
53747
|
const errStatus = lastError?.status || 502;
|
|
53705
53748
|
const transformedErr = transformPaymentError(rawErrBody);
|
|
53749
|
+
requestHadError = true;
|
|
53706
53750
|
if (headersSentEarly) {
|
|
53707
53751
|
let errPayload;
|
|
53708
53752
|
try {
|
|
@@ -53746,6 +53790,21 @@ data: [DONE]
|
|
|
53746
53790
|
completedAt: Date.now()
|
|
53747
53791
|
});
|
|
53748
53792
|
}
|
|
53793
|
+
const errModel = routingDecision?.model ?? modelId;
|
|
53794
|
+
if (errModel) {
|
|
53795
|
+
const errPayment = paymentStore.getStore()?.amountUsd ?? 0;
|
|
53796
|
+
logUsage({
|
|
53797
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
53798
|
+
model: errModel,
|
|
53799
|
+
tier: routingDecision?.tier ?? "DIRECT",
|
|
53800
|
+
cost: errPayment,
|
|
53801
|
+
baselineCost: errPayment,
|
|
53802
|
+
savings: 0,
|
|
53803
|
+
latencyMs: Date.now() - startTime,
|
|
53804
|
+
status: "error"
|
|
53805
|
+
}).catch(() => {
|
|
53806
|
+
});
|
|
53807
|
+
}
|
|
53749
53808
|
return;
|
|
53750
53809
|
}
|
|
53751
53810
|
const responseChunks = [];
|
|
@@ -54080,6 +54139,7 @@ data: [DONE]
|
|
|
54080
54139
|
baselineCost: logBaseline,
|
|
54081
54140
|
savings: logSavings,
|
|
54082
54141
|
latencyMs: Date.now() - startTime,
|
|
54142
|
+
status: requestHadError ? "error" : "success",
|
|
54083
54143
|
...responseInputTokens !== void 0 && { inputTokens: responseInputTokens },
|
|
54084
54144
|
...responseOutputTokens !== void 0 && { outputTokens: responseOutputTokens }
|
|
54085
54145
|
};
|
|
@@ -54692,6 +54752,7 @@ Usage:
|
|
|
54692
54752
|
clawrouter doctor [opus] [question]
|
|
54693
54753
|
clawrouter partners [test]
|
|
54694
54754
|
clawrouter report [daily|weekly|monthly] [--json]
|
|
54755
|
+
clawrouter logs [--days <n>]
|
|
54695
54756
|
|
|
54696
54757
|
Options:
|
|
54697
54758
|
--version, -v Show version number
|
|
@@ -54701,6 +54762,8 @@ Options:
|
|
|
54701
54762
|
Commands:
|
|
54702
54763
|
doctor AI-powered diagnostics (default: Sonnet ~$0.003)
|
|
54703
54764
|
doctor opus Use Opus for deeper analysis (~$0.01)
|
|
54765
|
+
logs Per-request breakdown: model, cost, latency, status
|
|
54766
|
+
logs --days 7 Show last 7 days of requests (default: 1 day)
|
|
54704
54767
|
partners List available partner APIs with pricing
|
|
54705
54768
|
partners test Test partner API endpoints (expect 402 = alive)
|
|
54706
54769
|
wallet recover Restore wallet.key from mnemonic (if generated by ClawRouter)
|
|
@@ -54735,6 +54798,8 @@ function parseArgs(args) {
|
|
|
54735
54798
|
version: false,
|
|
54736
54799
|
help: false,
|
|
54737
54800
|
doctor: false,
|
|
54801
|
+
logs: false,
|
|
54802
|
+
logsDays: 1,
|
|
54738
54803
|
partners: false,
|
|
54739
54804
|
partnersTest: false,
|
|
54740
54805
|
report: false,
|
|
@@ -54752,6 +54817,12 @@ function parseArgs(args) {
|
|
|
54752
54817
|
result.help = true;
|
|
54753
54818
|
} else if (arg === "doctor" || arg === "--doctor") {
|
|
54754
54819
|
result.doctor = true;
|
|
54820
|
+
} else if (arg === "logs") {
|
|
54821
|
+
result.logs = true;
|
|
54822
|
+
if (args[i + 1] === "--days" && args[i + 2]) {
|
|
54823
|
+
result.logsDays = parseInt(args[i + 2], 10) || 1;
|
|
54824
|
+
i += 2;
|
|
54825
|
+
}
|
|
54755
54826
|
} else if (arg === "partners") {
|
|
54756
54827
|
result.partners = true;
|
|
54757
54828
|
if (args[i + 1] === "test") {
|
|
@@ -54812,6 +54883,11 @@ async function main() {
|
|
|
54812
54883
|
await runDoctor(userQuestion, model);
|
|
54813
54884
|
process.exit(0);
|
|
54814
54885
|
}
|
|
54886
|
+
if (args.logs) {
|
|
54887
|
+
const output = await formatRecentLogs(args.logsDays);
|
|
54888
|
+
console.log(output);
|
|
54889
|
+
process.exit(0);
|
|
54890
|
+
}
|
|
54815
54891
|
if (args.partners) {
|
|
54816
54892
|
if (PARTNER_SERVICES.length === 0) {
|
|
54817
54893
|
console.log("No partner APIs available.");
|