@hasna/economy 0.5.1 → 0.5.3
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/CHANGELOG.md +12 -0
- package/dist/chunks/{billing-bkpxy4kv.js → billing-22az60hy.js} +2 -2
- package/dist/chunks/{config-j9mv3ehk.js → config-hsp7ndhj.js} +2 -2
- package/dist/chunks/{index-d480p2wh.js → index-1vz1arz5.js} +14 -13
- package/dist/chunks/{index-hesxq90g.js → index-9wa1f2kv.js} +1 -1
- package/dist/chunks/{index-49f12css.js → index-bn04v378.js} +2 -2
- package/dist/chunks/{index-zpvea08j.js → index-c7h2rxx1.js} +38 -12
- package/dist/chunks/{index-k540hfww.js → index-dk5rq1rq.js} +1 -1
- package/dist/chunks/{index-ez9thsr7.js → index-f5jv6q5q.js} +38 -12
- package/dist/chunks/{index-r1jv3kpy.js → index-mhrkwvtk.js} +3 -3
- package/dist/chunks/{index-xsah93s2.js → index-s9mvven6.js} +2 -2
- package/dist/chunks/{index-2hwzmfgv.js → index-vajzfzgv.js} +38 -12
- package/dist/chunks/{open-projects-6z4pq6mx.js → open-projects-8qm46m3d.js} +1 -1
- package/dist/chunks/{pricing-vf2pycmh.js → pricing-462f8xkm.js} +1 -1
- package/dist/chunks/{pricing-f80p81gr.js → pricing-k9wsjwbz.js} +1 -1
- package/dist/chunks/{pricing-y21mcjsa.js → pricing-vxejj1qa.js} +1 -1
- package/dist/chunks/{serve-2knem98x.js → serve-8yqe7nhs.js} +44 -11
- package/dist/chunks/{sqlite-store-501f32ts.js → sqlite-store-13nhr1z0.js} +2 -2
- package/dist/chunks/{sqlite-store-st99garx.js → sqlite-store-gamn65xp.js} +2 -2
- package/dist/chunks/{sqlite-store-fq4natnf.js → sqlite-store-ht6frztj.js} +2 -2
- package/dist/chunks/{tui-khmnkat2.js → tui-fe94bvp9.js} +4 -4
- package/dist/chunks/{watch-4y064yys.js → watch-ct8dvrpr.js} +5 -5
- package/dist/chunks/{webhooks-k4fh2t9c.js → webhooks-nw4daw9y.js} +20 -9
- package/dist/cli/index.js +27 -27
- package/dist/db/database.d.ts +2 -2
- package/dist/db/database.d.ts.map +1 -1
- package/dist/db/legacy-large-schema.d.ts +6 -0
- package/dist/db/legacy-large-schema.d.ts.map +1 -0
- package/dist/db/pg-migrations.d.ts.map +1 -1
- package/dist/db/sync-pg.d.ts.map +1 -1
- package/dist/index.js +15 -14
- package/dist/lib/analytics.d.ts +1 -1
- package/dist/lib/analytics.d.ts.map +1 -1
- package/dist/lib/periods.d.ts +20 -1
- package/dist/lib/periods.d.ts.map +1 -1
- package/dist/lib/spikes.d.ts +3 -3
- package/dist/lib/spikes.d.ts.map +1 -1
- package/dist/mcp/index.js +18 -17
- package/dist/otel/index.js +1 -1
- package/dist/server/index.js +213 -74
- package/dist/server/legacy-limits.d.ts +51 -0
- package/dist/server/legacy-limits.d.ts.map +1 -0
- package/dist/server/legacy-operations.d.ts +2 -1
- package/dist/server/legacy-operations.d.ts.map +1 -1
- package/dist/server/legacy-plan.d.ts +2 -1
- package/dist/server/legacy-plan.d.ts.map +1 -1
- package/dist/server/legacy-preservation.d.ts +2 -1
- package/dist/server/legacy-preservation.d.ts.map +1 -1
- package/dist/server/service-operations.d.ts.map +1 -1
- package/dist/server/service-worker.js +78 -33
- package/docs/historical-data-reconciliation.md +38 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -45,6 +45,7 @@ import {
|
|
|
45
45
|
queryUsageSnapshots,
|
|
46
46
|
requireCurrentBillingSummary,
|
|
47
47
|
requireCurrentCostSummary,
|
|
48
|
+
resolveReportingInterval,
|
|
48
49
|
sessionOverlapWhere,
|
|
49
50
|
stableJson,
|
|
50
51
|
subscriptionId,
|
|
@@ -55,13 +56,13 @@ import {
|
|
|
55
56
|
upsertSubscription,
|
|
56
57
|
usageSnapshotFilterForPeriod,
|
|
57
58
|
validateIngest
|
|
58
|
-
} from "./chunks/index-
|
|
59
|
+
} from "./chunks/index-c7h2rxx1.js";
|
|
59
60
|
// src/lib/store/index.ts
|
|
60
61
|
import { randomUUID } from "crypto";
|
|
61
62
|
// package.json
|
|
62
63
|
var package_default = {
|
|
63
64
|
name: "@hasna/economy",
|
|
64
|
-
version: "0.5.
|
|
65
|
+
version: "0.5.3",
|
|
65
66
|
description: "AI coding cost tracker \u2014 CLI + MCP server + REST API for Claude Code, Codex, OpenCode, Cursor, Pi, and Hermes, with legacy Gemini CLI session and Gemini API billing ingestion",
|
|
66
67
|
repository: {
|
|
67
68
|
type: "git",
|
|
@@ -1070,7 +1071,8 @@ function buildBrief(db, opts = {}) {
|
|
|
1070
1071
|
}
|
|
1071
1072
|
|
|
1072
1073
|
// src/lib/analytics.ts
|
|
1073
|
-
function queryProjectDetail(db, nameOrPath) {
|
|
1074
|
+
function queryProjectDetail(db, nameOrPath, now = new Date) {
|
|
1075
|
+
const dailyBounds = resolveReportingInterval({ kind: "rolling", unit: "day", count: 14 }, now);
|
|
1074
1076
|
const like = `%${nameOrPath}%`;
|
|
1075
1077
|
const sessions = db.prepare(`SELECT id, project_name, project_path, total_cost_usd, total_tokens, started_at
|
|
1076
1078
|
FROM economy_effective_sessions
|
|
@@ -1084,8 +1086,8 @@ function queryProjectDetail(db, nameOrPath) {
|
|
|
1084
1086
|
const daily = db.prepare(`SELECT DATE(r.timestamp) as date, COALESCE(SUM(r.cost_usd), 0) as cost_usd
|
|
1085
1087
|
FROM economy_effective_requests r JOIN economy_effective_sessions s ON r.session_id = s.id
|
|
1086
1088
|
WHERE (s.project_name LIKE ? OR s.project_path LIKE ?)
|
|
1087
|
-
AND r.timestamp >=
|
|
1088
|
-
GROUP BY date ORDER BY date ASC`).all(like, like);
|
|
1089
|
+
AND r.timestamp >= ? AND r.timestamp < ?
|
|
1090
|
+
GROUP BY date ORDER BY date ASC`).all(like, like, dailyBounds.start, dailyBounds.end_exclusive);
|
|
1089
1091
|
const models = db.prepare(`SELECT r.model as model, COUNT(*) as requests, COALESCE(SUM(r.cost_usd), 0) as cost_usd
|
|
1090
1092
|
FROM economy_effective_requests r JOIN economy_effective_sessions s ON r.session_id = s.id
|
|
1091
1093
|
WHERE s.project_name LIKE ? OR s.project_path LIKE ?
|
|
@@ -1124,18 +1126,17 @@ function queryRangeStats(db, from, to) {
|
|
|
1124
1126
|
return { cost: r.cost, requests: r.requests, tokens: r.tokens, sessions: s.sessions };
|
|
1125
1127
|
}
|
|
1126
1128
|
function queryForecast(db, now = new Date) {
|
|
1127
|
-
const
|
|
1128
|
-
const
|
|
1129
|
-
const
|
|
1130
|
-
const
|
|
1129
|
+
const month = resolveReportingInterval({ kind: "calendar", period: "month" }, now);
|
|
1130
|
+
const recent = resolveReportingInterval({ kind: "rolling", unit: "day", count: 7 }, now);
|
|
1131
|
+
const daysInMonth = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 0)).getUTCDate();
|
|
1132
|
+
const dayOfMonth = now.getUTCDate();
|
|
1133
|
+
const monthSoFar = db.prepare(`SELECT COALESCE(SUM(cost_usd),0) as cost FROM economy_effective_requests WHERE timestamp >= ? AND timestamp < ?`).get(month.start, recent.end_exclusive);
|
|
1131
1134
|
const dailyAvg = dayOfMonth > 0 ? monthSoFar.cost / dayOfMonth : 0;
|
|
1132
1135
|
const projected = dailyAvg * daysInMonth;
|
|
1133
|
-
const
|
|
1134
|
-
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
|
|
1135
|
-
const last7 = db.prepare(`SELECT COALESCE(SUM(cost_usd),0) as cost FROM economy_effective_requests WHERE DATE(timestamp) >= ?`).get(sevenDaysAgo.toISOString().substring(0, 10));
|
|
1136
|
+
const last7 = db.prepare(`SELECT COALESCE(SUM(cost_usd),0) as cost FROM economy_effective_requests WHERE timestamp >= ? AND timestamp < ?`).get(recent.start, recent.end_exclusive);
|
|
1136
1137
|
const last7DailyAvg = last7.cost / 7;
|
|
1137
1138
|
const dailyCosts = db.prepare(`SELECT DATE(timestamp) as date, COALESCE(SUM(cost_usd),0) as cost_usd
|
|
1138
|
-
FROM economy_effective_requests WHERE
|
|
1139
|
+
FROM economy_effective_requests WHERE timestamp >= ? AND timestamp < ? GROUP BY date ORDER BY cost_usd ASC`).all(month.start, recent.end_exclusive);
|
|
1139
1140
|
return {
|
|
1140
1141
|
day_of_month: dayOfMonth,
|
|
1141
1142
|
days_in_month: daysInMonth,
|
|
@@ -1337,7 +1338,7 @@ class LocalStore {
|
|
|
1337
1338
|
_db;
|
|
1338
1339
|
async db() {
|
|
1339
1340
|
if (!this._db) {
|
|
1340
|
-
const { openDatabase } = await import("./chunks/sqlite-store-
|
|
1341
|
+
const { openDatabase } = await import("./chunks/sqlite-store-ht6frztj.js");
|
|
1341
1342
|
this._db = openDatabase();
|
|
1342
1343
|
ensurePricingSeeded(this._db);
|
|
1343
1344
|
}
|
package/dist/lib/analytics.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export interface ProjectDetail {
|
|
|
23
23
|
top_sessions: ProjectDetailSession[];
|
|
24
24
|
}
|
|
25
25
|
/** Detailed breakdown for a single project matched by name or path substring. */
|
|
26
|
-
export declare function queryProjectDetail(db: Database, nameOrPath: string): ProjectDetail | null;
|
|
26
|
+
export declare function queryProjectDetail(db: Database, nameOrPath: string, now?: Date): ProjectDetail | null;
|
|
27
27
|
export type ExportType = 'sessions' | 'requests';
|
|
28
28
|
/** Raw rows for a CSV export. CSV formatting stays in the caller. */
|
|
29
29
|
export declare function queryExportRows(db: Database, type: ExportType, period: string): Array<Record<string, unknown>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/lib/analytics.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAIxE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAChD,MAAM,EAAE,kBAAkB,EAAE,CAAA;IAC5B,YAAY,EAAE,oBAAoB,EAAE,CAAA;CACrC;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/lib/analytics.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAIxE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAChD,MAAM,EAAE,kBAAkB,EAAE,CAAA;IAC5B,YAAY,EAAE,oBAAoB,EAAE,CAAA;CACrC;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,aAAa,GAAG,IAAI,CAoD3G;AAID,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,UAAU,CAAA;AAShD,qEAAqE;AACrE,wBAAgB,eAAe,CAC7B,EAAE,EAAE,QAAQ,EACZ,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,GACb,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAOhC;AAID,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU,CAUlF;AAID,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,gBAAgB,EAAE,MAAM,CAAA;IACxB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,mBAAmB,EAAE,MAAM,CAAA;IAC3B,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACvD,kBAAkB,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;CAC9D;AAED,0DAA0D;AAC1D,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAE,IAAiB,GAAG,YAAY,CAiChF;AAID,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,QAAQ,GAAG,eAAe,EAAE,CAWpE"}
|
package/dist/lib/periods.d.ts
CHANGED
|
@@ -4,7 +4,26 @@ export interface CalendarPeriodBounds {
|
|
|
4
4
|
start_date: string | null;
|
|
5
5
|
end_date_exclusive: string | null;
|
|
6
6
|
}
|
|
7
|
-
|
|
7
|
+
export type ReportingInterval = {
|
|
8
|
+
kind: 'calendar';
|
|
9
|
+
period: Period;
|
|
10
|
+
} | {
|
|
11
|
+
kind: 'rolling';
|
|
12
|
+
unit: 'day' | 'hour';
|
|
13
|
+
count: number;
|
|
14
|
+
};
|
|
15
|
+
export interface ReportingBounds {
|
|
16
|
+
time_zone: 'UTC';
|
|
17
|
+
start: string | null;
|
|
18
|
+
end_exclusive: string | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* All ranges are half-open and use one supplied clock. Calendar weeks start on
|
|
22
|
+
* Sunday. N rolling days means N UTC dates including today (which is partial),
|
|
23
|
+
* while N rolling hours means the elapsed N hours ending at the supplied clock.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveReportingInterval(interval: ReportingInterval, now?: Date): ReportingBounds;
|
|
26
|
+
/** Retain the calendar report's existing public field names. */
|
|
8
27
|
export declare function calendarPeriodBounds(period: Period, now?: Date): CalendarPeriodBounds;
|
|
9
28
|
/** Column names are code-owned identifiers; only generated ISO dates enter SQL. */
|
|
10
29
|
export declare function calendarPeriodWhere(period: Period, column: string, now?: Date): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"periods.d.ts","sourceRoot":"","sources":["../../src/lib/periods.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAM/C,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,KAAK,CAAA;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAA;CAClC;AAED,
|
|
1
|
+
{"version":3,"file":"periods.d.ts","sourceRoot":"","sources":["../../src/lib/periods.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAM/C,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,KAAK,CAAA;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAA;CAClC;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,KAAK,GAAG,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5D,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,KAAK,CAAA;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,OAAa,GAAG,eAAe,CA+CvG;AAED,gEAAgE;AAChE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,oBAAoB,CAG3F;AAED,mFAAmF;AACnF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,MAAM,CAO5F;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAK/G;AAED,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,MAAM,EAAC,MAAM,EAAC,KAAK,EAAC,MAAM,EAAC,GAAG,OAAW,GAAE,MAAM,CAIpF"}
|
package/dist/lib/spikes.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export interface SpikeInfo {
|
|
|
5
5
|
average_usd: number;
|
|
6
6
|
ratio: number;
|
|
7
7
|
}
|
|
8
|
-
/** Detect
|
|
8
|
+
/** Detect spikes against consecutive observed UTC days; a missing day is unknown. */
|
|
9
9
|
export declare function detectCostSpikes(dailyTotals: Array<{
|
|
10
10
|
date: string;
|
|
11
11
|
cost_usd: number;
|
|
@@ -13,6 +13,6 @@ export declare function detectCostSpikes(dailyTotals: Array<{
|
|
|
13
13
|
windowDays?: number;
|
|
14
14
|
multiplier?: number;
|
|
15
15
|
}): SpikeInfo[];
|
|
16
|
-
export declare function queryRecentSpikes(db: Database, days?: number): SpikeInfo[];
|
|
17
|
-
export declare function getTodaySpike(db: Database): SpikeInfo | null;
|
|
16
|
+
export declare function queryRecentSpikes(db: Database, days?: number, now?: Date): SpikeInfo[];
|
|
17
|
+
export declare function getTodaySpike(db: Database, now?: Date): SpikeInfo | null;
|
|
18
18
|
//# sourceMappingURL=spikes.d.ts.map
|
package/dist/lib/spikes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spikes.d.ts","sourceRoot":"","sources":["../../src/lib/spikes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"spikes.d.ts","sourceRoot":"","sources":["../../src/lib/spikes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAGxE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,qFAAqF;AACrF,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,EACtD,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAClD,SAAS,EAAE,CA8Bb;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,SAAK,EAAE,GAAG,OAAa,GAAG,SAAS,EAAE,CAWxF;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,OAAa,GAAG,SAAS,GAAG,IAAI,CAI9E"}
|
package/dist/mcp/index.js
CHANGED
|
@@ -56,6 +56,7 @@ import {
|
|
|
56
56
|
queryZeroCostTokenizedModels,
|
|
57
57
|
requireCurrentBillingSummary,
|
|
58
58
|
requireCurrentCostSummary,
|
|
59
|
+
resolveReportingInterval,
|
|
59
60
|
rollupSession,
|
|
60
61
|
scanReceiptId,
|
|
61
62
|
sessionOverlapWhere,
|
|
@@ -74,7 +75,7 @@ import {
|
|
|
74
75
|
upsertUsageSnapshot,
|
|
75
76
|
usageSnapshotFilterForPeriod,
|
|
76
77
|
validateIngest
|
|
77
|
-
} from "../chunks/index-
|
|
78
|
+
} from "../chunks/index-vajzfzgv.js";
|
|
78
79
|
import {
|
|
79
80
|
__require
|
|
80
81
|
} from "../chunks/index-p35cyhc4.js";
|
|
@@ -84,7 +85,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
84
85
|
// package.json
|
|
85
86
|
var package_default = {
|
|
86
87
|
name: "@hasna/economy",
|
|
87
|
-
version: "0.5.
|
|
88
|
+
version: "0.5.3",
|
|
88
89
|
description: "AI coding cost tracker \u2014 CLI + MCP server + REST API for Claude Code, Codex, OpenCode, Cursor, Pi, and Hermes, with legacy Gemini CLI session and Gemini API billing ingestion",
|
|
89
90
|
repository: {
|
|
90
91
|
type: "git",
|
|
@@ -3579,7 +3580,7 @@ function backfillMachineId(db) {
|
|
|
3579
3580
|
return { requests: Number(reqCount.changes), sessions: Number(sessCount.changes) };
|
|
3580
3581
|
}
|
|
3581
3582
|
async function recalculateZeroCostRequests(db) {
|
|
3582
|
-
const { assessCostFromDb: assessCostFromDb2 } = await import("../chunks/pricing-
|
|
3583
|
+
const { assessCostFromDb: assessCostFromDb2 } = await import("../chunks/pricing-vxejj1qa.js");
|
|
3583
3584
|
const zeroRows = db.prepare(`SELECT id, model, input_tokens, output_tokens, cache_read_tokens, cache_create_tokens, cache_create_5m_tokens, cache_create_1h_tokens
|
|
3584
3585
|
FROM requests
|
|
3585
3586
|
WHERE cost_usd = 0
|
|
@@ -3788,7 +3789,7 @@ async function postIngest(cloud, body) {
|
|
|
3788
3789
|
}
|
|
3789
3790
|
async function syncAllToCloud(cloud, opts = {}) {
|
|
3790
3791
|
await runIngestJournalOperation(cloud, { action: "reconcile" });
|
|
3791
|
-
const { openDatabase } = await import("../chunks/sqlite-store-
|
|
3792
|
+
const { openDatabase } = await import("../chunks/sqlite-store-gamn65xp.js");
|
|
3792
3793
|
const scratch = openDatabase(":memory:", true);
|
|
3793
3794
|
ensurePricingSeeded(scratch);
|
|
3794
3795
|
const cachePath = opts.cachePath ?? getIngestCachePath();
|
|
@@ -4714,7 +4715,8 @@ function buildBrief(db, opts = {}) {
|
|
|
4714
4715
|
}
|
|
4715
4716
|
|
|
4716
4717
|
// src/lib/analytics.ts
|
|
4717
|
-
function queryProjectDetail(db, nameOrPath) {
|
|
4718
|
+
function queryProjectDetail(db, nameOrPath, now2 = new Date) {
|
|
4719
|
+
const dailyBounds = resolveReportingInterval({ kind: "rolling", unit: "day", count: 14 }, now2);
|
|
4718
4720
|
const like = `%${nameOrPath}%`;
|
|
4719
4721
|
const sessions = db.prepare(`SELECT id, project_name, project_path, total_cost_usd, total_tokens, started_at
|
|
4720
4722
|
FROM economy_effective_sessions
|
|
@@ -4728,8 +4730,8 @@ function queryProjectDetail(db, nameOrPath) {
|
|
|
4728
4730
|
const daily = db.prepare(`SELECT DATE(r.timestamp) as date, COALESCE(SUM(r.cost_usd), 0) as cost_usd
|
|
4729
4731
|
FROM economy_effective_requests r JOIN economy_effective_sessions s ON r.session_id = s.id
|
|
4730
4732
|
WHERE (s.project_name LIKE ? OR s.project_path LIKE ?)
|
|
4731
|
-
AND r.timestamp >=
|
|
4732
|
-
GROUP BY date ORDER BY date ASC`).all(like, like);
|
|
4733
|
+
AND r.timestamp >= ? AND r.timestamp < ?
|
|
4734
|
+
GROUP BY date ORDER BY date ASC`).all(like, like, dailyBounds.start, dailyBounds.end_exclusive);
|
|
4733
4735
|
const models = db.prepare(`SELECT r.model as model, COUNT(*) as requests, COALESCE(SUM(r.cost_usd), 0) as cost_usd
|
|
4734
4736
|
FROM economy_effective_requests r JOIN economy_effective_sessions s ON r.session_id = s.id
|
|
4735
4737
|
WHERE s.project_name LIKE ? OR s.project_path LIKE ?
|
|
@@ -4768,18 +4770,17 @@ function queryRangeStats(db, from, to) {
|
|
|
4768
4770
|
return { cost: r.cost, requests: r.requests, tokens: r.tokens, sessions: s.sessions };
|
|
4769
4771
|
}
|
|
4770
4772
|
function queryForecast(db, now2 = new Date) {
|
|
4771
|
-
const
|
|
4772
|
-
const
|
|
4773
|
-
const
|
|
4774
|
-
const
|
|
4773
|
+
const month = resolveReportingInterval({ kind: "calendar", period: "month" }, now2);
|
|
4774
|
+
const recent = resolveReportingInterval({ kind: "rolling", unit: "day", count: 7 }, now2);
|
|
4775
|
+
const daysInMonth = new Date(Date.UTC(now2.getUTCFullYear(), now2.getUTCMonth() + 1, 0)).getUTCDate();
|
|
4776
|
+
const dayOfMonth = now2.getUTCDate();
|
|
4777
|
+
const monthSoFar = db.prepare(`SELECT COALESCE(SUM(cost_usd),0) as cost FROM economy_effective_requests WHERE timestamp >= ? AND timestamp < ?`).get(month.start, recent.end_exclusive);
|
|
4775
4778
|
const dailyAvg = dayOfMonth > 0 ? monthSoFar.cost / dayOfMonth : 0;
|
|
4776
4779
|
const projected = dailyAvg * daysInMonth;
|
|
4777
|
-
const
|
|
4778
|
-
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
|
|
4779
|
-
const last7 = db.prepare(`SELECT COALESCE(SUM(cost_usd),0) as cost FROM economy_effective_requests WHERE DATE(timestamp) >= ?`).get(sevenDaysAgo.toISOString().substring(0, 10));
|
|
4780
|
+
const last7 = db.prepare(`SELECT COALESCE(SUM(cost_usd),0) as cost FROM economy_effective_requests WHERE timestamp >= ? AND timestamp < ?`).get(recent.start, recent.end_exclusive);
|
|
4780
4781
|
const last7DailyAvg = last7.cost / 7;
|
|
4781
4782
|
const dailyCosts = db.prepare(`SELECT DATE(timestamp) as date, COALESCE(SUM(cost_usd),0) as cost_usd
|
|
4782
|
-
FROM economy_effective_requests WHERE
|
|
4783
|
+
FROM economy_effective_requests WHERE timestamp >= ? AND timestamp < ? GROUP BY date ORDER BY cost_usd ASC`).all(month.start, recent.end_exclusive);
|
|
4783
4784
|
return {
|
|
4784
4785
|
day_of_month: dayOfMonth,
|
|
4785
4786
|
days_in_month: daysInMonth,
|
|
@@ -4830,7 +4831,7 @@ class LocalStore2 {
|
|
|
4830
4831
|
_db;
|
|
4831
4832
|
async db() {
|
|
4832
4833
|
if (!this._db) {
|
|
4833
|
-
const { openDatabase } = await import("../chunks/sqlite-store-
|
|
4834
|
+
const { openDatabase } = await import("../chunks/sqlite-store-gamn65xp.js");
|
|
4834
4835
|
this._db = openDatabase();
|
|
4835
4836
|
ensurePricingSeeded(this._db);
|
|
4836
4837
|
}
|
|
@@ -5193,7 +5194,7 @@ function buildServer() {
|
|
|
5193
5194
|
let _db;
|
|
5194
5195
|
const localDb = async () => {
|
|
5195
5196
|
if (!_db) {
|
|
5196
|
-
const { openDatabase } = await import("../chunks/sqlite-store-
|
|
5197
|
+
const { openDatabase } = await import("../chunks/sqlite-store-gamn65xp.js");
|
|
5197
5198
|
_db = openDatabase();
|
|
5198
5199
|
ensurePricingSeeded(_db);
|
|
5199
5200
|
}
|
package/dist/otel/index.js
CHANGED
|
@@ -3458,7 +3458,7 @@ async function pushIngestRows(cloud, scratch) {
|
|
|
3458
3458
|
// package.json
|
|
3459
3459
|
var package_default = {
|
|
3460
3460
|
name: "@hasna/economy",
|
|
3461
|
-
version: "0.5.
|
|
3461
|
+
version: "0.5.3",
|
|
3462
3462
|
description: "AI coding cost tracker \u2014 CLI + MCP server + REST API for Claude Code, Codex, OpenCode, Cursor, Pi, and Hermes, with legacy Gemini CLI session and Gemini API billing ingestion",
|
|
3463
3463
|
repository: {
|
|
3464
3464
|
type: "git",
|