storyforge 0.4.20 → 0.4.21
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.
|
@@ -75,6 +75,47 @@ function listJsonlFiles(rootDir) {
|
|
|
75
75
|
}
|
|
76
76
|
return out;
|
|
77
77
|
}
|
|
78
|
+
function parseClaudeFileDirect(file, seen) {
|
|
79
|
+
let content;
|
|
80
|
+
try {
|
|
81
|
+
content = fs.readFileSync(file, "utf-8");
|
|
82
|
+
} catch {
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
const out = [];
|
|
86
|
+
for (const raw of content.split(/\r?\n/)) {
|
|
87
|
+
if (!raw.trim()) continue;
|
|
88
|
+
let obj;
|
|
89
|
+
try {
|
|
90
|
+
obj = JSON.parse(raw);
|
|
91
|
+
} catch {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const usage = obj?.message?.usage;
|
|
95
|
+
if (!usage) continue;
|
|
96
|
+
const messageId = obj?.message?.id;
|
|
97
|
+
if (messageId) {
|
|
98
|
+
if (seen.has(messageId)) continue;
|
|
99
|
+
seen.add(messageId);
|
|
100
|
+
}
|
|
101
|
+
const model = String(obj?.message?.model ?? "").toLowerCase();
|
|
102
|
+
if (!model) continue;
|
|
103
|
+
const tsRaw = obj?.timestamp ?? obj?.ts;
|
|
104
|
+
const ts = tsRaw ? new Date(tsRaw).getTime() : Date.now();
|
|
105
|
+
if (!Number.isFinite(ts)) continue;
|
|
106
|
+
out.push({
|
|
107
|
+
ts,
|
|
108
|
+
model,
|
|
109
|
+
usage: {
|
|
110
|
+
input: usage.input_tokens ?? 0,
|
|
111
|
+
cacheRead: usage.cache_read_input_tokens ?? 0,
|
|
112
|
+
cacheCreate: usage.cache_creation_input_tokens ?? 0,
|
|
113
|
+
output: usage.output_tokens ?? 0
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return out;
|
|
118
|
+
}
|
|
78
119
|
function parseCodexFile(file) {
|
|
79
120
|
let content;
|
|
80
121
|
try {
|
|
@@ -115,11 +156,17 @@ function parseCodexFile(file) {
|
|
|
115
156
|
return out;
|
|
116
157
|
}
|
|
117
158
|
async function gatherCliUsage() {
|
|
159
|
+
const CCUSAGE_TIMEOUT_MS = 8e3;
|
|
118
160
|
const claudeEntries = [];
|
|
119
161
|
let claudeFileCount = 0;
|
|
120
162
|
let claudeError;
|
|
121
163
|
try {
|
|
122
|
-
const blocks = await
|
|
164
|
+
const blocks = await Promise.race([
|
|
165
|
+
loadSessionBlockData(),
|
|
166
|
+
new Promise(
|
|
167
|
+
(_, reject) => setTimeout(() => reject(new Error(`ccusage timed out after ${CCUSAGE_TIMEOUT_MS}ms (LiteLLM pricing fetch likely blocked)`)), CCUSAGE_TIMEOUT_MS)
|
|
168
|
+
)
|
|
169
|
+
]);
|
|
123
170
|
for (const block of blocks) {
|
|
124
171
|
const entries = block.entries ?? [];
|
|
125
172
|
for (const e of entries) {
|
|
@@ -142,8 +189,15 @@ async function gatherCliUsage() {
|
|
|
142
189
|
}
|
|
143
190
|
claudeFileCount = listJsonlFiles(path.join(os.homedir(), ".claude", "projects")).length;
|
|
144
191
|
} catch (err) {
|
|
145
|
-
claudeError = err.message ??
|
|
146
|
-
console.error("[cli-usage] ccusage loader failed:", claudeError);
|
|
192
|
+
claudeError = `ccusage unavailable, using fallback parser (${err.message?.slice(0, 80) ?? "unknown"})`;
|
|
193
|
+
console.error("[cli-usage] ccusage loader failed, falling back:", claudeError);
|
|
194
|
+
const claudeDir = path.join(os.homedir(), ".claude", "projects");
|
|
195
|
+
const claudeFiles = listJsonlFiles(claudeDir);
|
|
196
|
+
claudeFileCount = claudeFiles.length;
|
|
197
|
+
const seen = /* @__PURE__ */ new Set();
|
|
198
|
+
for (const f of claudeFiles) {
|
|
199
|
+
claudeEntries.push(...parseClaudeFileDirect(f, seen));
|
|
200
|
+
}
|
|
147
201
|
}
|
|
148
202
|
const codexDir = path.join(os.homedir(), ".codex", "sessions");
|
|
149
203
|
const codexFiles = listJsonlFiles(codexDir);
|
package/dist/index.js
CHANGED
|
@@ -841,7 +841,7 @@ async function devCommand(options) {
|
|
|
841
841
|
}
|
|
842
842
|
void (async () => {
|
|
843
843
|
try {
|
|
844
|
-
const { gatherCliUsage, CLI_USAGE_PARSER_VERSION } = await import("./cli-usage-
|
|
844
|
+
const { gatherCliUsage, CLI_USAGE_PARSER_VERSION } = await import("./cli-usage-P3LK7WEE.js");
|
|
845
845
|
const report = await gatherCliUsage();
|
|
846
846
|
const g = global;
|
|
847
847
|
g.__forgeCliUsageCache = { at: Date.now(), ver: CLI_USAGE_PARSER_VERSION, data: report };
|
|
@@ -877,7 +877,7 @@ async function devCommand(options) {
|
|
|
877
877
|
const pathname = url.pathname;
|
|
878
878
|
if (pathname === "/api/cli-usage") {
|
|
879
879
|
try {
|
|
880
|
-
const { gatherCliUsage, CLI_USAGE_PARSER_VERSION } = await import("./cli-usage-
|
|
880
|
+
const { gatherCliUsage, CLI_USAGE_PARSER_VERSION } = await import("./cli-usage-P3LK7WEE.js");
|
|
881
881
|
const g = global;
|
|
882
882
|
const now = Date.now();
|
|
883
883
|
if (g.__forgeCliUsageCache && g.__forgeCliUsageCache.ver === CLI_USAGE_PARSER_VERSION && now - g.__forgeCliUsageCache.at < 3e4) {
|