@hasna/economy 0.2.17 → 0.2.18
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/LICENSE +186 -13
- package/README.md +186 -13
- package/dashboard/dist/assets/index-5mUN0CPj.css +1 -0
- package/dashboard/dist/assets/index-L1FgNQ4t.js +93 -0
- package/dashboard/dist/index.html +14 -0
- package/dashboard/dist/logo.jpg +0 -0
- package/dashboard/dist/vite.svg +1 -0
- package/dist/cli/index.js +134 -783
- package/dist/db/database.d.ts +1 -23
- package/dist/db/database.d.ts.map +1 -1
- package/dist/db/pg-migrations.d.ts.map +1 -1
- package/dist/index.js +54 -206
- package/dist/ingest/claude.d.ts +1 -6
- package/dist/ingest/claude.d.ts.map +1 -1
- package/dist/ingest/codex.d.ts +1 -1
- package/dist/ingest/codex.d.ts.map +1 -1
- package/dist/ingest/gemini.d.ts +1 -1
- package/dist/ingest/gemini.d.ts.map +1 -1
- package/dist/lib/pricing.d.ts +1 -1
- package/dist/lib/pricing.d.ts.map +1 -1
- package/dist/lib/webhooks.d.ts +1 -1
- package/dist/lib/webhooks.d.ts.map +1 -1
- package/dist/mcp/index.js +384 -600
- package/dist/server/index.d.ts +0 -1
- package/dist/server/index.js +63 -357
- package/dist/server/serve.d.ts +1 -1
- package/dist/server/serve.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -4
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +7 -3
- package/dist/ingest/billing.d.ts +0 -18
- package/dist/ingest/billing.d.ts.map +0 -1
- package/dist/lib/package-metadata.d.ts +0 -8
- package/dist/lib/package-metadata.d.ts.map +0 -1
package/dist/db/database.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { SqliteAdapter as Database } from '@hasna/cloud';
|
|
2
2
|
import type { EconomyRequest, EconomySession, EconomyProject, Budget, BudgetStatus, CostSummary, ModelBreakdown, ProjectBreakdown, Period, SessionFilter } from '../types/index.js';
|
|
3
|
-
export declare function getMachineId(): string;
|
|
4
3
|
export declare function getDataDir(): string;
|
|
5
4
|
export declare function getDbPath(): string;
|
|
6
5
|
export declare function openDatabase(dbPath?: string, skipSeed?: boolean): Database;
|
|
@@ -9,7 +8,7 @@ export declare function upsertSession(db: Database, session: EconomySession): vo
|
|
|
9
8
|
export declare function rollupSession(db: Database, sessionId: string): void;
|
|
10
9
|
export declare function querySessions(db: Database, filter?: SessionFilter): EconomySession[];
|
|
11
10
|
export declare function queryTopSessions(db: Database, n?: number, agent?: string): EconomySession[];
|
|
12
|
-
export declare function querySummary(db: Database, period: Period
|
|
11
|
+
export declare function querySummary(db: Database, period: Period): CostSummary;
|
|
13
12
|
export declare function queryModelBreakdown(db: Database): ModelBreakdown[];
|
|
14
13
|
export declare function queryProjectBreakdown(db: Database): ProjectBreakdown[];
|
|
15
14
|
export declare function queryDailyBreakdown(db: Database, days?: number): Array<{
|
|
@@ -48,27 +47,6 @@ export declare function getGoalStatuses(db: Database): GoalStatus[];
|
|
|
48
47
|
export declare function getIngestState(db: Database, source: string, key: string): string | null;
|
|
49
48
|
export declare function setIngestState(db: Database, source: string, key: string, value: string): void;
|
|
50
49
|
export declare function queryRequestsSince(db: Database, since: string): EconomyRequest[];
|
|
51
|
-
export interface BillingDaily {
|
|
52
|
-
date: string;
|
|
53
|
-
provider: 'anthropic' | 'openai' | string;
|
|
54
|
-
description: string;
|
|
55
|
-
cost_usd: number;
|
|
56
|
-
updated_at: string;
|
|
57
|
-
}
|
|
58
|
-
export declare function upsertBillingDaily(db: Database, row: BillingDaily): void;
|
|
59
|
-
export declare function clearBillingRange(db: Database, provider: string, fromDate: string, toDate: string): void;
|
|
60
|
-
export declare function queryBillingSummary(db: Database, period: Period): {
|
|
61
|
-
total_usd: number;
|
|
62
|
-
by_provider: Record<string, number>;
|
|
63
|
-
};
|
|
64
|
-
export interface MachineInfo {
|
|
65
|
-
machine_id: string;
|
|
66
|
-
sessions: number;
|
|
67
|
-
requests: number;
|
|
68
|
-
total_cost_usd: number;
|
|
69
|
-
last_active: string;
|
|
70
|
-
}
|
|
71
|
-
export declare function listMachines(db: Database): MachineInfo[];
|
|
72
50
|
export interface DbModelPricing {
|
|
73
51
|
model: string;
|
|
74
52
|
input_per_1m: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pg-migrations.d.ts","sourceRoot":"","sources":["../../src/db/pg-migrations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"pg-migrations.d.ts","sourceRoot":"","sources":["../../src/db/pg-migrations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,aAAa,EAAE,MAAM,EAmGjC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -77,7 +77,6 @@ var DEFAULT_PRICING;
|
|
|
77
77
|
var init_pricing = __esm(() => {
|
|
78
78
|
init_database();
|
|
79
79
|
DEFAULT_PRICING = {
|
|
80
|
-
"claude-opus-4-7": { inputPer1M: 5, outputPer1M: 25, cacheReadPer1M: 0.5, cacheWritePer1M: 6.25 },
|
|
81
80
|
"claude-opus-4-6": { inputPer1M: 5, outputPer1M: 25, cacheReadPer1M: 0.5, cacheWritePer1M: 6.25 },
|
|
82
81
|
"claude-opus-4-5": { inputPer1M: 5, outputPer1M: 25, cacheReadPer1M: 0.5, cacheWritePer1M: 6.25 },
|
|
83
82
|
"claude-sonnet-4-6": { inputPer1M: 3, outputPer1M: 15, cacheReadPer1M: 0.3, cacheWritePer1M: 3.75 },
|
|
@@ -88,55 +87,28 @@ var init_pricing = __esm(() => {
|
|
|
88
87
|
"claude-3-opus": { inputPer1M: 15, outputPer1M: 75, cacheReadPer1M: 1.5, cacheWritePer1M: 18.75 },
|
|
89
88
|
"claude-3-sonnet": { inputPer1M: 3, outputPer1M: 15, cacheReadPer1M: 0.3, cacheWritePer1M: 3.75 },
|
|
90
89
|
"claude-3-haiku": { inputPer1M: 0.25, outputPer1M: 1.25, cacheReadPer1M: 0.03, cacheWritePer1M: 0.3 },
|
|
91
|
-
"gemini-3.1-pro": { inputPer1M: 1.25, outputPer1M: 10, cacheReadPer1M: 0.31, cacheWritePer1M: 0 },
|
|
92
|
-
"gemini-2.5-pro": { inputPer1M: 1.25, outputPer1M: 10, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
93
|
-
"gemini-2.5-flash": { inputPer1M: 0.15, outputPer1M: 0.6, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
94
90
|
"gemini-2.0-flash": { inputPer1M: 0.075, outputPer1M: 0.3, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
91
|
+
"gemini-2.5-pro": { inputPer1M: 1.25, outputPer1M: 10, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
95
92
|
"gemini-1.5-pro": { inputPer1M: 1.25, outputPer1M: 5, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
96
93
|
"gemini-1.5-flash": { inputPer1M: 0.075, outputPer1M: 0.3, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
97
|
-
"gpt-5.4": { inputPer1M: 2.5, outputPer1M: 15, cacheReadPer1M: 0.25, cacheWritePer1M: 0 },
|
|
98
|
-
"gpt-5.4-pro": { inputPer1M: 30, outputPer1M: 180, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
99
|
-
"gpt-5.4-mini": { inputPer1M: 0.75, outputPer1M: 4.5, cacheReadPer1M: 0.075, cacheWritePer1M: 0 },
|
|
100
94
|
"gpt-5.3-codex": { inputPer1M: 1.75, outputPer1M: 14, cacheReadPer1M: 0.44, cacheWritePer1M: 0 },
|
|
101
|
-
"gpt-5.3-chat": { inputPer1M: 2, outputPer1M: 8, cacheReadPer1M: 0.5, cacheWritePer1M: 0 },
|
|
102
95
|
"gpt-5.2-codex": { inputPer1M: 1.75, outputPer1M: 14, cacheReadPer1M: 0.44, cacheWritePer1M: 0 },
|
|
103
96
|
"gpt-5-codex": { inputPer1M: 1.75, outputPer1M: 14, cacheReadPer1M: 0.44, cacheWritePer1M: 0 },
|
|
104
|
-
"gpt-5-mini": { inputPer1M: 0.3, outputPer1M: 1.2, cacheReadPer1M: 0.075, cacheWritePer1M: 0 },
|
|
105
|
-
"gpt-5.2": { inputPer1M: 2, outputPer1M: 8, cacheReadPer1M: 0.5, cacheWritePer1M: 0 },
|
|
106
97
|
"gpt-4o": { inputPer1M: 2.5, outputPer1M: 10, cacheReadPer1M: 1.25, cacheWritePer1M: 0 },
|
|
107
98
|
"gpt-4o-mini": { inputPer1M: 0.15, outputPer1M: 0.6, cacheReadPer1M: 0.075, cacheWritePer1M: 0 },
|
|
108
99
|
o1: { inputPer1M: 15, outputPer1M: 60, cacheReadPer1M: 7.5, cacheWritePer1M: 0 },
|
|
109
100
|
"o1-mini": { inputPer1M: 3, outputPer1M: 12, cacheReadPer1M: 1.5, cacheWritePer1M: 0 },
|
|
110
101
|
o3: { inputPer1M: 10, outputPer1M: 40, cacheReadPer1M: 2.5, cacheWritePer1M: 0 },
|
|
111
102
|
"o3-mini": { inputPer1M: 1.1, outputPer1M: 4.4, cacheReadPer1M: 0.55, cacheWritePer1M: 0 },
|
|
112
|
-
"o4-mini": { inputPer1M: 1.1, outputPer1M: 4.4, cacheReadPer1M: 0.275, cacheWritePer1M: 0 }
|
|
113
|
-
"qwen3.6-plus": { inputPer1M: 0.8, outputPer1M: 2, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
114
|
-
"qwen3.6": { inputPer1M: 0.3, outputPer1M: 0.6, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
115
|
-
"minimax-m2.7": { inputPer1M: 0.7, outputPer1M: 0.7, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
116
|
-
"minimax-m2.7-highspeed": { inputPer1M: 0.7, outputPer1M: 0.7, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
117
|
-
"minimax-m1": { inputPer1M: 0.2, outputPer1M: 1.1, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
118
|
-
"grok-3": { inputPer1M: 3, outputPer1M: 15, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
119
|
-
"grok-3-mini": { inputPer1M: 0.3, outputPer1M: 0.5, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
120
|
-
"glm-5.1": { inputPer1M: 0.7, outputPer1M: 0.7, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
121
|
-
"glm-5": { inputPer1M: 0.7, outputPer1M: 0.7, cacheReadPer1M: 0, cacheWritePer1M: 0 },
|
|
122
|
-
"kimi-k2": { inputPer1M: 0.6, outputPer1M: 0.6, cacheReadPer1M: 0, cacheWritePer1M: 0 }
|
|
103
|
+
"o4-mini": { inputPer1M: 1.1, outputPer1M: 4.4, cacheReadPer1M: 0.275, cacheWritePer1M: 0 }
|
|
123
104
|
};
|
|
124
105
|
});
|
|
125
106
|
|
|
126
107
|
// src/db/database.ts
|
|
127
108
|
import { SqliteAdapter as Database } from "@hasna/cloud";
|
|
128
109
|
import { copyFileSync, existsSync, mkdirSync, readdirSync, statSync } from "fs";
|
|
129
|
-
import { hostname } from "os";
|
|
130
110
|
import { homedir } from "os";
|
|
131
111
|
import { join } from "path";
|
|
132
|
-
function getMachineId() {
|
|
133
|
-
if (process.env["ECONOMY_MACHINE_ID"])
|
|
134
|
-
return process.env["ECONOMY_MACHINE_ID"];
|
|
135
|
-
const h = hostname().toLowerCase();
|
|
136
|
-
if (h.startsWith("spark") || h.startsWith("apple"))
|
|
137
|
-
return h.split(".")[0];
|
|
138
|
-
return h.split(".")[0];
|
|
139
|
-
}
|
|
140
112
|
function getDataDir() {
|
|
141
113
|
const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir();
|
|
142
114
|
const newDir = join(home, ".hasna", "economy");
|
|
@@ -169,7 +141,6 @@ function openDatabase(dbPath, skipSeed = false) {
|
|
|
169
141
|
}
|
|
170
142
|
const db = new Database(path);
|
|
171
143
|
db.exec("PRAGMA journal_mode = WAL");
|
|
172
|
-
db.exec("PRAGMA busy_timeout = 5000");
|
|
173
144
|
db.exec("PRAGMA foreign_keys = ON");
|
|
174
145
|
initSchema(db);
|
|
175
146
|
if (!skipSeed) {
|
|
@@ -191,8 +162,7 @@ function initSchema(db) {
|
|
|
191
162
|
cost_usd REAL NOT NULL DEFAULT 0,
|
|
192
163
|
duration_ms INTEGER DEFAULT 0,
|
|
193
164
|
timestamp TEXT NOT NULL,
|
|
194
|
-
source_request_id TEXT
|
|
195
|
-
machine_id TEXT DEFAULT ''
|
|
165
|
+
source_request_id TEXT
|
|
196
166
|
);
|
|
197
167
|
|
|
198
168
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
@@ -204,8 +174,7 @@ function initSchema(db) {
|
|
|
204
174
|
ended_at TEXT,
|
|
205
175
|
total_cost_usd REAL DEFAULT 0,
|
|
206
176
|
total_tokens INTEGER DEFAULT 0,
|
|
207
|
-
request_count INTEGER DEFAULT 0
|
|
208
|
-
machine_id TEXT DEFAULT ''
|
|
177
|
+
request_count INTEGER DEFAULT 0
|
|
209
178
|
);
|
|
210
179
|
|
|
211
180
|
CREATE TABLE IF NOT EXISTS projects (
|
|
@@ -270,27 +239,6 @@ function initSchema(db) {
|
|
|
270
239
|
machine_id TEXT,
|
|
271
240
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
272
241
|
);
|
|
273
|
-
|
|
274
|
-
CREATE TABLE IF NOT EXISTS billing_daily (
|
|
275
|
-
date TEXT NOT NULL,
|
|
276
|
-
provider TEXT NOT NULL,
|
|
277
|
-
description TEXT DEFAULT '',
|
|
278
|
-
cost_usd REAL NOT NULL DEFAULT 0,
|
|
279
|
-
updated_at TEXT NOT NULL,
|
|
280
|
-
PRIMARY KEY (date, provider, description)
|
|
281
|
-
);
|
|
282
|
-
|
|
283
|
-
CREATE INDEX IF NOT EXISTS idx_billing_date ON billing_daily(date);
|
|
284
|
-
CREATE INDEX IF NOT EXISTS idx_billing_provider ON billing_daily(provider);
|
|
285
|
-
`);
|
|
286
|
-
const cols = db.prepare(`PRAGMA table_info(requests)`).all();
|
|
287
|
-
if (!cols.some((c) => c.name === "machine_id")) {
|
|
288
|
-
db.exec(`ALTER TABLE requests ADD COLUMN machine_id TEXT DEFAULT ''`);
|
|
289
|
-
db.exec(`ALTER TABLE sessions ADD COLUMN machine_id TEXT DEFAULT ''`);
|
|
290
|
-
}
|
|
291
|
-
db.exec(`
|
|
292
|
-
CREATE INDEX IF NOT EXISTS idx_requests_machine ON requests(machine_id);
|
|
293
|
-
CREATE INDEX IF NOT EXISTS idx_sessions_machine ON sessions(machine_id);
|
|
294
242
|
`);
|
|
295
243
|
}
|
|
296
244
|
function periodWhere(period) {
|
|
@@ -300,11 +248,11 @@ function periodWhere(period) {
|
|
|
300
248
|
case "yesterday":
|
|
301
249
|
return `DATE(timestamp) = DATE('now', '-1 day')`;
|
|
302
250
|
case "week":
|
|
303
|
-
return `timestamp >= DATE('now', '
|
|
251
|
+
return `timestamp >= DATE('now', '-7 days')`;
|
|
304
252
|
case "month":
|
|
305
|
-
return `timestamp >= DATE('now', '
|
|
253
|
+
return `timestamp >= DATE('now', '-30 days')`;
|
|
306
254
|
case "year":
|
|
307
|
-
return `timestamp >= DATE('now', '
|
|
255
|
+
return `timestamp >= DATE('now', '-365 days')`;
|
|
308
256
|
case "all":
|
|
309
257
|
return "1=1";
|
|
310
258
|
}
|
|
@@ -316,11 +264,11 @@ function sessionPeriodWhere(period) {
|
|
|
316
264
|
case "yesterday":
|
|
317
265
|
return `DATE(started_at) = DATE('now', '-1 day')`;
|
|
318
266
|
case "week":
|
|
319
|
-
return `started_at >= DATE('now', '
|
|
267
|
+
return `started_at >= DATE('now', '-7 days')`;
|
|
320
268
|
case "month":
|
|
321
|
-
return `started_at >= DATE('now', '
|
|
269
|
+
return `started_at >= DATE('now', '-30 days')`;
|
|
322
270
|
case "year":
|
|
323
|
-
return `started_at >= DATE('now', '
|
|
271
|
+
return `started_at >= DATE('now', '-365 days')`;
|
|
324
272
|
case "all":
|
|
325
273
|
return "1=1";
|
|
326
274
|
}
|
|
@@ -330,17 +278,17 @@ function upsertRequest(db, req) {
|
|
|
330
278
|
INSERT OR REPLACE INTO requests
|
|
331
279
|
(id, agent, session_id, model, input_tokens, output_tokens,
|
|
332
280
|
cache_read_tokens, cache_create_tokens, cost_usd, duration_ms,
|
|
333
|
-
timestamp, source_request_id
|
|
334
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
|
|
335
|
-
`).run(req.id, req.agent, req.session_id, req.model, req.input_tokens, req.output_tokens, req.cache_read_tokens, req.cache_create_tokens, req.cost_usd, req.duration_ms, req.timestamp, req.source_request_id
|
|
281
|
+
timestamp, source_request_id)
|
|
282
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
283
|
+
`).run(req.id, req.agent, req.session_id, req.model, req.input_tokens, req.output_tokens, req.cache_read_tokens, req.cache_create_tokens, req.cost_usd, req.duration_ms, req.timestamp, req.source_request_id);
|
|
336
284
|
}
|
|
337
285
|
function upsertSession(db, session) {
|
|
338
286
|
db.prepare(`
|
|
339
287
|
INSERT OR REPLACE INTO sessions
|
|
340
288
|
(id, agent, project_path, project_name, started_at, ended_at,
|
|
341
|
-
total_cost_usd, total_tokens, request_count
|
|
342
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?,
|
|
343
|
-
`).run(session.id, session.agent, session.project_path, session.project_name, session.started_at, session.ended_at ?? null, session.total_cost_usd, session.total_tokens, session.request_count
|
|
289
|
+
total_cost_usd, total_tokens, request_count)
|
|
290
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
291
|
+
`).run(session.id, session.agent, session.project_path, session.project_name, session.started_at, session.ended_at ?? null, session.total_cost_usd, session.total_tokens, session.request_count);
|
|
344
292
|
}
|
|
345
293
|
function rollupSession(db, sessionId) {
|
|
346
294
|
db.prepare(`
|
|
@@ -370,10 +318,6 @@ function querySessions(db, filter = {}) {
|
|
|
370
318
|
conditions.push("started_at >= ?");
|
|
371
319
|
params.push(filter.since);
|
|
372
320
|
}
|
|
373
|
-
if (filter.machine) {
|
|
374
|
-
conditions.push("machine_id = ?");
|
|
375
|
-
params.push(filter.machine);
|
|
376
|
-
}
|
|
377
321
|
if (filter.search) {
|
|
378
322
|
const q = `%${filter.search}%`;
|
|
379
323
|
conditions.push("(project_name LIKE ? OR agent LIKE ? OR id LIKE ?)");
|
|
@@ -392,25 +336,24 @@ function queryTopSessions(db, n = 10, agent) {
|
|
|
392
336
|
}
|
|
393
337
|
return db.prepare(`SELECT * FROM sessions ORDER BY total_cost_usd DESC LIMIT ?`).all(n);
|
|
394
338
|
}
|
|
395
|
-
function querySummary(db, period
|
|
339
|
+
function querySummary(db, period) {
|
|
396
340
|
const rWhere = periodWhere(period);
|
|
397
341
|
const sWhere = sessionPeriodWhere(period);
|
|
398
|
-
const machineClause = machine ? ` AND machine_id = '${machine.replace(/'/g, "''")}'` : "";
|
|
399
342
|
const r = db.prepare(`
|
|
400
343
|
SELECT COALESCE(SUM(cost_usd), 0) as total_usd,
|
|
401
344
|
COUNT(*) as requests,
|
|
402
345
|
COALESCE(SUM(input_tokens + output_tokens + cache_read_tokens + cache_create_tokens), 0) as tokens
|
|
403
|
-
FROM requests WHERE ${rWhere}
|
|
346
|
+
FROM requests WHERE ${rWhere}
|
|
404
347
|
`).get();
|
|
405
348
|
const codexTotals = db.prepare(`
|
|
406
349
|
SELECT COALESCE(SUM(total_cost_usd), 0) as cost_usd,
|
|
407
350
|
COALESCE(SUM(total_tokens), 0) as tokens,
|
|
408
351
|
COUNT(*) as sessions
|
|
409
352
|
FROM sessions
|
|
410
|
-
WHERE ${sWhere}
|
|
353
|
+
WHERE ${sWhere}
|
|
411
354
|
AND id NOT IN (SELECT DISTINCT session_id FROM requests)
|
|
412
355
|
`).get();
|
|
413
|
-
const sessionCount = db.prepare(`SELECT COUNT(*) as sessions FROM sessions WHERE ${sWhere}
|
|
356
|
+
const sessionCount = db.prepare(`SELECT COUNT(*) as sessions FROM sessions WHERE ${sWhere}`).get();
|
|
414
357
|
return {
|
|
415
358
|
total_usd: r.total_usd + codexTotals.cost_usd,
|
|
416
359
|
requests: r.requests,
|
|
@@ -430,66 +373,23 @@ function queryModelBreakdown(db) {
|
|
|
430
373
|
FROM requests GROUP BY model, agent ORDER BY cost_usd DESC
|
|
431
374
|
`).all();
|
|
432
375
|
}
|
|
433
|
-
function labelForPath(projectPath, projectName) {
|
|
434
|
-
if (projectName && projectName.trim() !== "")
|
|
435
|
-
return projectName;
|
|
436
|
-
if (!projectPath)
|
|
437
|
-
return "";
|
|
438
|
-
const segments = projectPath.split("/").filter(Boolean);
|
|
439
|
-
const projectPrefix = /^(open|skill|hook|service|connect|platform|agent|tool|iapp|project|scaffold|capp)-/;
|
|
440
|
-
for (const seg of segments) {
|
|
441
|
-
if (projectPrefix.test(seg))
|
|
442
|
-
return seg;
|
|
443
|
-
}
|
|
444
|
-
const generic = new Set(["web", "app", "apps", "packages", "src", "lib", "server", "client", "api", "frontend", "backend"]);
|
|
445
|
-
for (let i = segments.length - 1;i >= 0; i--) {
|
|
446
|
-
if (!generic.has(segments[i].toLowerCase()))
|
|
447
|
-
return segments[i];
|
|
448
|
-
}
|
|
449
|
-
return segments[segments.length - 1] ?? projectPath;
|
|
450
|
-
}
|
|
451
376
|
function queryProjectBreakdown(db) {
|
|
452
|
-
|
|
453
|
-
SELECT
|
|
454
|
-
|
|
455
|
-
|
|
377
|
+
return db.prepare(`
|
|
378
|
+
SELECT
|
|
379
|
+
s.project_path,
|
|
380
|
+
COALESCE(p.name, s.project_name) as project_name,
|
|
381
|
+
COUNT(DISTINCT s.id) as sessions,
|
|
382
|
+
COUNT(r.id) as requests,
|
|
383
|
+
COALESCE(SUM(r.cost_usd), COALESCE(SUM(s.total_cost_usd), 0)) as cost_usd,
|
|
384
|
+
COALESCE(SUM(r.input_tokens + r.output_tokens + r.cache_read_tokens + r.cache_create_tokens), 0) as total_tokens,
|
|
385
|
+
MAX(s.started_at) as last_active
|
|
386
|
+
FROM sessions s
|
|
387
|
+
LEFT JOIN projects p ON p.path = s.project_path OR p.name = s.project_name
|
|
388
|
+
LEFT JOIN requests r ON r.session_id = s.id
|
|
389
|
+
WHERE s.project_path != '' OR s.project_name != ''
|
|
390
|
+
GROUP BY s.project_path
|
|
391
|
+
ORDER BY cost_usd DESC
|
|
456
392
|
`).all();
|
|
457
|
-
const groups = new Map;
|
|
458
|
-
for (const s of sessions) {
|
|
459
|
-
const label = labelForPath(s.project_path, s.project_name);
|
|
460
|
-
if (!label)
|
|
461
|
-
continue;
|
|
462
|
-
const g = groups.get(label) ?? { sessionIds: [], samplePath: s.project_path, totalCost: 0, lastActive: "" };
|
|
463
|
-
g.sessionIds.push(s.id);
|
|
464
|
-
g.totalCost += s.total_cost_usd || 0;
|
|
465
|
-
if (!g.lastActive || s.started_at > g.lastActive)
|
|
466
|
-
g.lastActive = s.started_at;
|
|
467
|
-
if (!g.samplePath)
|
|
468
|
-
g.samplePath = s.project_path;
|
|
469
|
-
groups.set(label, g);
|
|
470
|
-
}
|
|
471
|
-
const result = [];
|
|
472
|
-
for (const [label, g] of groups.entries()) {
|
|
473
|
-
const placeholders = g.sessionIds.map(() => "?").join(",");
|
|
474
|
-
const reqStats = placeholders.length ? db.prepare(`
|
|
475
|
-
SELECT
|
|
476
|
-
COUNT(*) as requests,
|
|
477
|
-
COALESCE(SUM(cost_usd), 0) as cost_usd,
|
|
478
|
-
COALESCE(SUM(input_tokens + output_tokens + cache_read_tokens + cache_create_tokens), 0) as total_tokens
|
|
479
|
-
FROM requests WHERE session_id IN (${placeholders})
|
|
480
|
-
`).get(...g.sessionIds) : { requests: 0, cost_usd: 0, total_tokens: 0 };
|
|
481
|
-
result.push({
|
|
482
|
-
project_path: g.samplePath,
|
|
483
|
-
project_name: label,
|
|
484
|
-
sessions: g.sessionIds.length,
|
|
485
|
-
requests: reqStats.requests,
|
|
486
|
-
total_tokens: reqStats.total_tokens,
|
|
487
|
-
cost_usd: reqStats.cost_usd > 0 ? reqStats.cost_usd : g.totalCost,
|
|
488
|
-
last_active: g.lastActive
|
|
489
|
-
});
|
|
490
|
-
}
|
|
491
|
-
result.sort((a, b) => b.cost_usd - a.cost_usd);
|
|
492
|
-
return result;
|
|
493
393
|
}
|
|
494
394
|
function queryDailyBreakdown(db, days = 30) {
|
|
495
395
|
return db.prepare(`
|
|
@@ -607,40 +507,6 @@ function setIngestState(db, source, key, value) {
|
|
|
607
507
|
function queryRequestsSince(db, since) {
|
|
608
508
|
return db.prepare(`SELECT * FROM requests WHERE timestamp > ? ORDER BY timestamp ASC`).all(since);
|
|
609
509
|
}
|
|
610
|
-
function upsertBillingDaily(db, row) {
|
|
611
|
-
db.prepare(`
|
|
612
|
-
INSERT OR REPLACE INTO billing_daily (date, provider, description, cost_usd, updated_at)
|
|
613
|
-
VALUES (?, ?, ?, ?, ?)
|
|
614
|
-
`).run(row.date, row.provider, row.description, row.cost_usd, row.updated_at);
|
|
615
|
-
}
|
|
616
|
-
function clearBillingRange(db, provider, fromDate, toDate) {
|
|
617
|
-
db.prepare(`DELETE FROM billing_daily WHERE provider = ? AND date >= ? AND date <= ?`).run(provider, fromDate, toDate);
|
|
618
|
-
}
|
|
619
|
-
function queryBillingSummary(db, period) {
|
|
620
|
-
const where = period === "today" ? `date = DATE('now')` : period === "yesterday" ? `date = DATE('now', '-1 day')` : period === "week" ? `date >= DATE('now', 'weekday 0', '-7 days')` : period === "month" ? `date >= DATE('now', 'start of month')` : period === "year" ? `date >= DATE('now', 'start of year')` : "1=1";
|
|
621
|
-
const rows = db.prepare(`SELECT provider, SUM(cost_usd) as cost FROM billing_daily WHERE ${where} GROUP BY provider`).all();
|
|
622
|
-
const by_provider = {};
|
|
623
|
-
let total = 0;
|
|
624
|
-
for (const r of rows) {
|
|
625
|
-
by_provider[r.provider] = r.cost;
|
|
626
|
-
total += r.cost;
|
|
627
|
-
}
|
|
628
|
-
return { total_usd: total, by_provider };
|
|
629
|
-
}
|
|
630
|
-
function listMachines(db) {
|
|
631
|
-
return db.prepare(`
|
|
632
|
-
SELECT
|
|
633
|
-
s.machine_id,
|
|
634
|
-
COUNT(DISTINCT s.id) as sessions,
|
|
635
|
-
COALESCE((SELECT COUNT(*) FROM requests r WHERE r.machine_id = s.machine_id), 0) as requests,
|
|
636
|
-
COALESCE(SUM(s.total_cost_usd), 0) as total_cost_usd,
|
|
637
|
-
MAX(s.started_at) as last_active
|
|
638
|
-
FROM sessions s
|
|
639
|
-
WHERE s.machine_id != ''
|
|
640
|
-
GROUP BY s.machine_id
|
|
641
|
-
ORDER BY total_cost_usd DESC
|
|
642
|
-
`).all();
|
|
643
|
-
}
|
|
644
510
|
function upsertModelPricing(db, p) {
|
|
645
511
|
db.prepare(`
|
|
646
512
|
INSERT OR REPLACE INTO model_pricing
|
|
@@ -658,11 +524,11 @@ function deleteModelPricing(db, model) {
|
|
|
658
524
|
db.prepare(`DELETE FROM model_pricing WHERE model = ?`).run(model);
|
|
659
525
|
}
|
|
660
526
|
function seedModelPricing(db, defaults) {
|
|
661
|
-
const existing =
|
|
527
|
+
const existing = db.prepare(`SELECT COUNT(*) as count FROM model_pricing`).get();
|
|
528
|
+
if (existing.count > 0)
|
|
529
|
+
return;
|
|
662
530
|
const now = new Date().toISOString();
|
|
663
531
|
for (const [model, p] of Object.entries(defaults)) {
|
|
664
|
-
if (existing.has(model))
|
|
665
|
-
continue;
|
|
666
532
|
upsertModelPricing(db, {
|
|
667
533
|
model,
|
|
668
534
|
input_per_1m: p.inputPer1M,
|
|
@@ -903,8 +769,7 @@ import { join as join3, basename } from "path";
|
|
|
903
769
|
function autoDetectProject(cwd, projects) {
|
|
904
770
|
return projects.find((p) => cwd === p.path || cwd.startsWith(p.path + "/"));
|
|
905
771
|
}
|
|
906
|
-
var
|
|
907
|
-
var TAKUMI_PROJECTS_DIR = join3(homedir2(), ".takumi", "projects");
|
|
772
|
+
var PROJECTS_DIR = join3(homedir2(), ".claude", "projects");
|
|
908
773
|
function dirNameToPath(dirName) {
|
|
909
774
|
return dirName.replace(/^-/, "/").replace(/-/g, "/").replace(/\/\//g, "/-");
|
|
910
775
|
}
|
|
@@ -924,36 +789,29 @@ function collectJsonlFiles(projectDir) {
|
|
|
924
789
|
return files;
|
|
925
790
|
}
|
|
926
791
|
async function ingestClaude(db, verbose = false, _telemetryDir) {
|
|
927
|
-
|
|
928
|
-
}
|
|
929
|
-
async function ingestTakumi(db, verbose = false) {
|
|
930
|
-
return ingestJsonlProjects(db, TAKUMI_PROJECTS_DIR, "takumi", verbose);
|
|
931
|
-
}
|
|
932
|
-
async function ingestJsonlProjects(db, projectsDir, agentName, verbose = false) {
|
|
933
|
-
if (!existsSync3(projectsDir)) {
|
|
792
|
+
if (!existsSync3(PROJECTS_DIR)) {
|
|
934
793
|
if (verbose)
|
|
935
|
-
console.log(
|
|
794
|
+
console.log("Claude projects dir not found:", PROJECTS_DIR);
|
|
936
795
|
return { files: 0, requests: 0, sessions: 0 };
|
|
937
796
|
}
|
|
938
|
-
const machineId = getMachineId();
|
|
939
797
|
let totalFiles = 0;
|
|
940
798
|
let totalRequests = 0;
|
|
941
799
|
const touchedSessions = new Set;
|
|
942
800
|
const registeredProjects = db.prepare(`SELECT path, name FROM projects ORDER BY LENGTH(path) DESC`).all();
|
|
943
|
-
const projectDirs = readdirSync2(
|
|
801
|
+
const projectDirs = readdirSync2(PROJECTS_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
944
802
|
for (const projectDirEntry of projectDirs) {
|
|
945
|
-
const projectDirPath = join3(
|
|
803
|
+
const projectDirPath = join3(PROJECTS_DIR, projectDirEntry.name);
|
|
946
804
|
const projectPath = dirNameToPath(projectDirEntry.name);
|
|
947
805
|
const jsonlFiles = collectJsonlFiles(projectDirPath);
|
|
948
806
|
for (const filePath of jsonlFiles) {
|
|
949
|
-
const stateKey = filePath.replace(
|
|
807
|
+
const stateKey = filePath.replace(PROJECTS_DIR, "");
|
|
950
808
|
let fileMtime = "0";
|
|
951
809
|
try {
|
|
952
810
|
fileMtime = statSync2(filePath).mtimeMs.toString();
|
|
953
811
|
} catch {
|
|
954
812
|
continue;
|
|
955
813
|
}
|
|
956
|
-
const processed = getIngestState(db,
|
|
814
|
+
const processed = getIngestState(db, "claude", stateKey);
|
|
957
815
|
if (processed === fileMtime)
|
|
958
816
|
continue;
|
|
959
817
|
let lines;
|
|
@@ -994,10 +852,10 @@ async function ingestJsonlProjects(db, projectsDir, agentName, verbose = false)
|
|
|
994
852
|
if (inputTokens + outputTokens + cacheWriteTokens === 0)
|
|
995
853
|
continue;
|
|
996
854
|
const costUsd = computeCostFromDb(db, model, inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens);
|
|
997
|
-
const reqId =
|
|
855
|
+
const reqId = `claude-${sessionId}-${timestamp}`;
|
|
998
856
|
upsertRequest(db, {
|
|
999
857
|
id: reqId,
|
|
1000
|
-
agent:
|
|
858
|
+
agent: "claude",
|
|
1001
859
|
session_id: sessionId,
|
|
1002
860
|
model,
|
|
1003
861
|
input_tokens: inputTokens,
|
|
@@ -1007,8 +865,7 @@ async function ingestJsonlProjects(db, projectsDir, agentName, verbose = false)
|
|
|
1007
865
|
cost_usd: costUsd,
|
|
1008
866
|
duration_ms: 0,
|
|
1009
867
|
timestamp,
|
|
1010
|
-
source_request_id: reqId
|
|
1011
|
-
machine_id: machineId
|
|
868
|
+
source_request_id: reqId
|
|
1012
869
|
});
|
|
1013
870
|
if (!touchedSessions.has(sessionId)) {
|
|
1014
871
|
const existing = db.prepare(`SELECT id FROM sessions WHERE id = ?`).get(sessionId);
|
|
@@ -1017,15 +874,14 @@ async function ingestJsonlProjects(db, projectsDir, agentName, verbose = false)
|
|
|
1017
874
|
const detectedProject = autoDetectProject(effectiveCwd, registeredProjects);
|
|
1018
875
|
const session = {
|
|
1019
876
|
id: sessionId,
|
|
1020
|
-
agent:
|
|
877
|
+
agent: "claude",
|
|
1021
878
|
project_path: detectedProject ? detectedProject.path : effectiveCwd,
|
|
1022
879
|
project_name: detectedProject ? detectedProject.name : "",
|
|
1023
880
|
started_at: timestamp,
|
|
1024
881
|
ended_at: null,
|
|
1025
882
|
total_cost_usd: 0,
|
|
1026
883
|
total_tokens: 0,
|
|
1027
|
-
request_count: 0
|
|
1028
|
-
machine_id: machineId
|
|
884
|
+
request_count: 0
|
|
1029
885
|
};
|
|
1030
886
|
upsertSession(db, session);
|
|
1031
887
|
}
|
|
@@ -1033,7 +889,7 @@ async function ingestJsonlProjects(db, projectsDir, agentName, verbose = false)
|
|
|
1033
889
|
}
|
|
1034
890
|
totalRequests++;
|
|
1035
891
|
}
|
|
1036
|
-
setIngestState(db,
|
|
892
|
+
setIngestState(db, "claude", stateKey, fileMtime);
|
|
1037
893
|
totalFiles++;
|
|
1038
894
|
}
|
|
1039
895
|
}
|
|
@@ -1047,7 +903,7 @@ init_database();
|
|
|
1047
903
|
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
1048
904
|
import { homedir as homedir3 } from "os";
|
|
1049
905
|
import { join as join4, basename as basename2 } from "path";
|
|
1050
|
-
import { Database as
|
|
906
|
+
import { Database as Database2 } from "bun:sqlite";
|
|
1051
907
|
var CODEX_DB_PATH = join4(homedir3(), ".codex", "state_5.sqlite");
|
|
1052
908
|
var CODEX_CONFIG_PATH = join4(homedir3(), ".codex", "config.toml");
|
|
1053
909
|
function readCodexModel() {
|
|
@@ -1067,11 +923,10 @@ async function ingestCodex(db, verbose = false) {
|
|
|
1067
923
|
console.log("Codex DB not found:", CODEX_DB_PATH);
|
|
1068
924
|
return { sessions: 0 };
|
|
1069
925
|
}
|
|
1070
|
-
const machineId = getMachineId();
|
|
1071
926
|
let codexDb = null;
|
|
1072
927
|
let ingested = 0;
|
|
1073
928
|
try {
|
|
1074
|
-
codexDb = new
|
|
929
|
+
codexDb = new Database2(CODEX_DB_PATH, { readonly: true });
|
|
1075
930
|
const threads = codexDb.prepare(`SELECT id, cwd, created_at, updated_at, tokens_used, title FROM threads WHERE tokens_used > 0`).all();
|
|
1076
931
|
for (const thread of threads) {
|
|
1077
932
|
const stateKey = thread.id;
|
|
@@ -1092,8 +947,7 @@ async function ingestCodex(db, verbose = false) {
|
|
|
1092
947
|
ended_at: endedAt,
|
|
1093
948
|
total_cost_usd: costUsd,
|
|
1094
949
|
total_tokens: thread.tokens_used,
|
|
1095
|
-
request_count: 1
|
|
1096
|
-
machine_id: machineId
|
|
950
|
+
request_count: 1
|
|
1097
951
|
});
|
|
1098
952
|
setIngestState(db, "codex", stateKey, "done");
|
|
1099
953
|
ingested++;
|
|
@@ -1112,7 +966,6 @@ export {
|
|
|
1112
966
|
upsertModelPricing,
|
|
1113
967
|
upsertGoal,
|
|
1114
968
|
upsertBudget,
|
|
1115
|
-
upsertBillingDaily,
|
|
1116
969
|
setIngestState,
|
|
1117
970
|
setActiveModel,
|
|
1118
971
|
seedModelPricing,
|
|
@@ -1125,22 +978,18 @@ export {
|
|
|
1125
978
|
queryProjectBreakdown,
|
|
1126
979
|
queryModelBreakdown,
|
|
1127
980
|
queryDailyBreakdown,
|
|
1128
|
-
queryBillingSummary,
|
|
1129
981
|
openDatabase,
|
|
1130
982
|
normalizeModelName,
|
|
1131
983
|
listProjects,
|
|
1132
984
|
listModelPricing,
|
|
1133
|
-
listMachines,
|
|
1134
985
|
listGoals,
|
|
1135
986
|
listBudgets,
|
|
1136
|
-
ingestTakumi,
|
|
1137
987
|
ingestCodex,
|
|
1138
988
|
ingestClaude,
|
|
1139
989
|
getProject,
|
|
1140
990
|
getPricingFromDb,
|
|
1141
991
|
getPricing,
|
|
1142
992
|
getModelPricing,
|
|
1143
|
-
getMachineId,
|
|
1144
993
|
getIngestState,
|
|
1145
994
|
getGoalStatuses,
|
|
1146
995
|
getDbPath,
|
|
@@ -1155,7 +1004,6 @@ export {
|
|
|
1155
1004
|
deleteBudget,
|
|
1156
1005
|
computeCostFromDb,
|
|
1157
1006
|
computeCost,
|
|
1158
|
-
clearBillingRange,
|
|
1159
1007
|
clearActiveModel,
|
|
1160
1008
|
DEFAULT_PRICING,
|
|
1161
1009
|
DEFAULT_MODEL
|
package/dist/ingest/claude.d.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Database } from 'bun:sqlite';
|
|
2
2
|
export declare function ingestClaude(db: Database, verbose?: boolean, _telemetryDir?: string): Promise<{
|
|
3
3
|
files: number;
|
|
4
4
|
requests: number;
|
|
5
5
|
sessions: number;
|
|
6
6
|
}>;
|
|
7
|
-
export declare function ingestTakumi(db: Database, verbose?: boolean): Promise<{
|
|
8
|
-
files: number;
|
|
9
|
-
requests: number;
|
|
10
|
-
sessions: number;
|
|
11
|
-
}>;
|
|
12
7
|
//# sourceMappingURL=claude.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/ingest/claude.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/ingest/claude.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AA2DrC,wBAAsB,YAAY,CAChC,EAAE,EAAE,QAAQ,EACZ,OAAO,UAAQ,EACf,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA2HhE"}
|
package/dist/ingest/codex.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/ingest/codex.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/ingest/codex.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAkBrC,iBAAS,cAAc,IAAI,MAAM,CAShC;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,UAAQ,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAyD9F;AAED,OAAO,EAAE,cAAc,EAAE,CAAA"}
|
package/dist/ingest/gemini.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/ingest/gemini.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/ingest/gemini.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AA0BrC,wBAAsB,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA2EjG"}
|
package/dist/lib/pricing.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Database } from 'bun:sqlite';
|
|
2
2
|
import type { ModelPricing } from '../types/index.js';
|
|
3
3
|
export declare const DEFAULT_PRICING: Record<string, ModelPricing>;
|
|
4
4
|
export declare function normalizeModelName(raw: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../src/lib/pricing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../src/lib/pricing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAKrD,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CA6BxD,CAAA;AAGD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKtD;AAGD,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAEtD;AAGD,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAuBjF;AAGD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAO7D;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,eAAe,SAAI,EACnB,gBAAgB,SAAI,GACnB,MAAM,CASR;AAED,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,QAAQ,EACZ,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,eAAe,SAAI,EACnB,gBAAgB,SAAI,GACnB,MAAM,CASR"}
|
package/dist/lib/webhooks.d.ts
CHANGED