MCPcopy Create free account
hub / github.com/Fibi66/FeiControl / buildCostReport

Function buildCostReport

src/lib/usage-scanner.ts:127–265  ·  view source on GitHub ↗
(filterDays?: number)

Source from the content-addressed store, hash-verified

125 * Build full cost report from JSONL data
126 */
127export async function buildCostReport(filterDays?: number) {
128 const allEntries = await scanAllUsage();
129
130 const now = new Date();
131 const todayStr = now.toISOString().split("T")[0];
132 const yesterday = new Date(now);
133 yesterday.setDate(yesterday.getDate() - 1);
134 const yesterdayStr = yesterday.toISOString().split("T")[0];
135 const thisMonthPrefix = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
136 const lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1);
137 const lastMonthPrefix = `${lastMonth.getFullYear()}-${String(lastMonth.getMonth() + 1).padStart(2, "0")}`;
138
139 // Filter by timeframe if specified
140 let cutoffDate = "";
141 if (filterDays) {
142 const cutoff = new Date(now);
143 cutoff.setDate(cutoff.getDate() - filterDays);
144 cutoffDate = cutoff.toISOString().split("T")[0];
145 }
146
147 const filtered = cutoffDate
148 ? allEntries.filter((e) => e.date >= cutoffDate)
149 : allEntries;
150
151 // Calculate costs for each entry
152 function entryCost(e: UsageEntry): number {
153 return calculateCost(e.model, e.inputTokens, e.outputTokens, e.cacheReadTokens, e.cacheWriteTokens);
154 }
155
156 // Summary costs
157 const todayEntries = allEntries.filter((e) => e.date === todayStr);
158 const yesterdayEntries = allEntries.filter((e) => e.date === yesterdayStr);
159 const thisMonthEntries = allEntries.filter((e) => e.date.startsWith(thisMonthPrefix));
160 const lastMonthEntries = allEntries.filter((e) => e.date.startsWith(lastMonthPrefix));
161
162 const todayCost = todayEntries.reduce((s, e) => s + entryCost(e), 0);
163 const yesterdayCost = yesterdayEntries.reduce((s, e) => s + entryCost(e), 0);
164 const thisMonthCost = thisMonthEntries.reduce((s, e) => s + entryCost(e), 0);
165 const lastMonthCost = lastMonthEntries.reduce((s, e) => s + entryCost(e), 0);
166
167 const daysInMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();
168 const daysElapsed = now.getDate();
169 const projected = daysElapsed > 0 ? (thisMonthCost / daysElapsed) * daysInMonth : 0;
170
171 // By agent
172 const agentMap = new Map<string, { cost: number; tokens: number; in: number; out: number; cr: number; cw: number; msgs: number }>();
173 for (const e of filtered) {
174 const key = e.agentId;
175 const prev = agentMap.get(key) || { cost: 0, tokens: 0, in: 0, out: 0, cr: 0, cw: 0, msgs: 0 };
176 prev.cost += entryCost(e);
177 prev.tokens += e.totalTokens;
178 prev.in += e.inputTokens;
179 prev.out += e.outputTokens;
180 prev.cr += e.cacheReadTokens;
181 prev.cw += e.cacheWriteTokens;
182 prev.msgs += 1;
183 agentMap.set(key, prev);
184 }

Callers 1

GETFunction · 0.90

Calls 3

getModelNameFunction · 0.90
scanAllUsageFunction · 0.85
entryCostFunction · 0.85

Tested by

no test coverage detected