@hasna/economy 0.3.28 → 0.5.0

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.
Files changed (216) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/CONTRIBUTING.md +1 -1
  3. package/README.md +18 -22
  4. package/SECURITY.md +1 -1
  5. package/dist/chunks/agent-registry-store-tpnhx3wj.js +39 -0
  6. package/dist/chunks/billing-bkpxy4kv.js +13 -0
  7. package/dist/chunks/config-j9mv3ehk.js +15 -0
  8. package/dist/chunks/index-2hwzmfgv.js +3407 -0
  9. package/dist/chunks/index-axh32d30.js +1313 -0
  10. package/dist/chunks/index-emvs5ph2.js +2085 -0
  11. package/dist/chunks/index-ez9thsr7.js +3440 -0
  12. package/dist/chunks/index-hesxq90g.js +62 -0
  13. package/dist/chunks/index-k540hfww.js +258 -0
  14. package/dist/chunks/index-kgy9b6bf.js +451 -0
  15. package/dist/chunks/index-kn5572kd.js +124 -0
  16. package/dist/chunks/index-p35cyhc4.js +4 -0
  17. package/dist/chunks/index-w3bvv0ns.js +26 -0
  18. package/dist/chunks/index-zpvea08j.js +3372 -0
  19. package/dist/chunks/menubar-6xtkt17h.js +296 -0
  20. package/dist/chunks/open-projects-6z4pq6mx.js +39 -0
  21. package/dist/chunks/pricing-f80p81gr.js +29 -0
  22. package/dist/chunks/pricing-vf2pycmh.js +30 -0
  23. package/dist/chunks/pricing-y21mcjsa.js +30 -0
  24. package/dist/chunks/serve-0k69e4h9.js +4655 -0
  25. package/dist/chunks/sqlite-store-501f32ts.js +258 -0
  26. package/dist/chunks/sqlite-store-fq4natnf.js +256 -0
  27. package/dist/chunks/sqlite-store-st99garx.js +258 -0
  28. package/dist/chunks/third-party-sqlite-5e85fxa2.js +11 -0
  29. package/dist/chunks/tui-7f8f951w.js +22 -0
  30. package/dist/chunks/watch-mm1j39vy.js +196 -0
  31. package/dist/chunks/webhooks-k4fh2t9c.js +109 -0
  32. package/dist/cli/commands/brief.d.ts.map +1 -1
  33. package/dist/cli/commands/extras.d.ts.map +1 -1
  34. package/dist/cli/commands/journal.d.ts +3 -0
  35. package/dist/cli/commands/journal.d.ts.map +1 -0
  36. package/dist/cli/commands/menubar.d.ts +97 -4
  37. package/dist/cli/commands/menubar.d.ts.map +1 -1
  38. package/dist/cli/commands/tui.d.ts +1 -1
  39. package/dist/cli/commands/tui.d.ts.map +1 -1
  40. package/dist/cli/commands/watch.d.ts.map +1 -1
  41. package/dist/cli/index.js +1524 -9998
  42. package/dist/db/cloud.d.ts +18 -12
  43. package/dist/db/cloud.d.ts.map +1 -1
  44. package/dist/db/database.d.ts +33 -12
  45. package/dist/db/database.d.ts.map +1 -1
  46. package/dist/db/ingest-concurrency-worker.d.ts +2 -0
  47. package/dist/db/ingest-concurrency-worker.d.ts.map +1 -0
  48. package/dist/db/ingest-errors.d.ts +9 -0
  49. package/dist/db/ingest-errors.d.ts.map +1 -0
  50. package/dist/db/ingest-schema.d.ts +3 -0
  51. package/dist/db/ingest-schema.d.ts.map +1 -0
  52. package/dist/db/ingest-specs.d.ts +8 -0
  53. package/dist/db/ingest-specs.d.ts.map +1 -0
  54. package/dist/db/ingest-test-contract.d.ts +3 -0
  55. package/dist/db/ingest-test-contract.d.ts.map +1 -0
  56. package/dist/db/ingest-validation.d.ts +12 -0
  57. package/dist/db/ingest-validation.d.ts.map +1 -0
  58. package/dist/db/ingest.d.ts +27 -0
  59. package/dist/db/ingest.d.ts.map +1 -0
  60. package/dist/db/legacy-schema.d.ts +7 -0
  61. package/dist/db/legacy-schema.d.ts.map +1 -0
  62. package/dist/db/observation-contract.d.ts +3 -0
  63. package/dist/db/observation-contract.d.ts.map +1 -0
  64. package/dist/db/observation-provenance.d.ts +23 -0
  65. package/dist/db/observation-provenance.d.ts.map +1 -0
  66. package/dist/db/observation-schema.d.ts +24 -0
  67. package/dist/db/observation-schema.d.ts.map +1 -0
  68. package/dist/db/pg-connection.d.ts +10 -0
  69. package/dist/db/pg-connection.d.ts.map +1 -0
  70. package/dist/db/pg-migrate.d.ts +4 -9
  71. package/dist/db/pg-migrate.d.ts.map +1 -1
  72. package/dist/db/pg-migrations.d.ts.map +1 -1
  73. package/dist/db/pg-protocol.d.ts +28 -0
  74. package/dist/db/pg-protocol.d.ts.map +1 -0
  75. package/dist/db/sqlite-store.d.ts +4 -0
  76. package/dist/db/sqlite-store.d.ts.map +1 -0
  77. package/dist/db/sync-pg.d.ts +17 -21
  78. package/dist/db/sync-pg.d.ts.map +1 -1
  79. package/dist/db/third-party-sqlite.d.ts +10 -0
  80. package/dist/db/third-party-sqlite.d.ts.map +1 -0
  81. package/dist/index.d.ts +3 -0
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +1281 -2405
  84. package/dist/ingest/claude-quota.d.ts.map +1 -1
  85. package/dist/ingest/claude.d.ts.map +1 -1
  86. package/dist/ingest/codex-quota.d.ts.map +1 -1
  87. package/dist/ingest/codex.d.ts +25 -0
  88. package/dist/ingest/codex.d.ts.map +1 -1
  89. package/dist/ingest/collection-outcome.d.ts +17 -0
  90. package/dist/ingest/collection-outcome.d.ts.map +1 -0
  91. package/dist/ingest/cursor.d.ts.map +1 -1
  92. package/dist/ingest/gemini.d.ts.map +1 -1
  93. package/dist/ingest/hermes.d.ts +1 -1
  94. package/dist/ingest/hermes.d.ts.map +1 -1
  95. package/dist/ingest/loops.d.ts +9 -0
  96. package/dist/ingest/loops.d.ts.map +1 -1
  97. package/dist/ingest/opencode.d.ts +1 -1
  98. package/dist/ingest/opencode.d.ts.map +1 -1
  99. package/dist/ingest/pi.d.ts +1 -1
  100. package/dist/ingest/pi.d.ts.map +1 -1
  101. package/dist/ingest/quota-observation.d.ts +16 -0
  102. package/dist/ingest/quota-observation.d.ts.map +1 -0
  103. package/dist/ingest/source-time.d.ts +4 -0
  104. package/dist/ingest/source-time.d.ts.map +1 -0
  105. package/dist/lib/accounts-store.d.ts +109 -0
  106. package/dist/lib/accounts-store.d.ts.map +1 -0
  107. package/dist/lib/accounts.d.ts +2 -1
  108. package/dist/lib/accounts.d.ts.map +1 -1
  109. package/dist/lib/analytics.d.ts.map +1 -1
  110. package/dist/lib/api-display-url.d.ts +19 -0
  111. package/dist/lib/api-display-url.d.ts.map +1 -0
  112. package/dist/lib/autosync-gate.d.ts +22 -0
  113. package/dist/lib/autosync-gate.d.ts.map +1 -0
  114. package/dist/lib/billing-diff.d.ts +18 -40
  115. package/dist/lib/billing-diff.d.ts.map +1 -1
  116. package/dist/lib/brief.d.ts +2 -0
  117. package/dist/lib/brief.d.ts.map +1 -1
  118. package/dist/lib/budget-decimal.d.ts +14 -0
  119. package/dist/lib/budget-decimal.d.ts.map +1 -0
  120. package/dist/lib/cloud-ingest.d.ts +30 -1
  121. package/dist/lib/cloud-ingest.d.ts.map +1 -1
  122. package/dist/lib/cloud-storage.d.ts +166 -10
  123. package/dist/lib/cloud-storage.d.ts.map +1 -1
  124. package/dist/lib/gatherer.d.ts.map +1 -1
  125. package/dist/lib/ingest-batches.d.ts +21 -0
  126. package/dist/lib/ingest-batches.d.ts.map +1 -0
  127. package/dist/lib/ingest-journal-client.d.ts +37 -0
  128. package/dist/lib/ingest-journal-client.d.ts.map +1 -0
  129. package/dist/lib/ingest-journal-lock.d.ts +5 -0
  130. package/dist/lib/ingest-journal-lock.d.ts.map +1 -0
  131. package/dist/lib/ingest-journal-maintenance.d.ts +92 -0
  132. package/dist/lib/ingest-journal-maintenance.d.ts.map +1 -0
  133. package/dist/lib/ingest-journal-operation.d.ts +55 -0
  134. package/dist/lib/ingest-journal-operation.d.ts.map +1 -0
  135. package/dist/lib/ingest-journal.d.ts +73 -0
  136. package/dist/lib/ingest-journal.d.ts.map +1 -0
  137. package/dist/lib/money-display.d.ts +13 -0
  138. package/dist/lib/money-display.d.ts.map +1 -0
  139. package/dist/lib/periods.d.ts +12 -0
  140. package/dist/lib/periods.d.ts.map +1 -1
  141. package/dist/lib/pricing.d.ts +14 -0
  142. package/dist/lib/pricing.d.ts.map +1 -1
  143. package/dist/lib/savings.d.ts +64 -7
  144. package/dist/lib/savings.d.ts.map +1 -1
  145. package/dist/lib/serve-auth.d.ts.map +1 -1
  146. package/dist/lib/store/index.d.ts +29 -22
  147. package/dist/lib/store/index.d.ts.map +1 -1
  148. package/dist/lib/summary-contract.d.ts +32 -0
  149. package/dist/lib/summary-contract.d.ts.map +1 -0
  150. package/dist/lib/summary-test-contract.d.ts +3 -0
  151. package/dist/lib/summary-test-contract.d.ts.map +1 -0
  152. package/dist/lib/sync-all.d.ts +4 -0
  153. package/dist/lib/sync-all.d.ts.map +1 -1
  154. package/dist/lib/sync-maintenance.d.ts.map +1 -1
  155. package/dist/lib/sync-report.d.ts +4 -0
  156. package/dist/lib/sync-report.d.ts.map +1 -0
  157. package/dist/lib/test-keychain-fixture.d.ts +9 -0
  158. package/dist/lib/test-keychain-fixture.d.ts.map +1 -0
  159. package/dist/mcp/agent-registry-store.d.ts +30 -0
  160. package/dist/mcp/agent-registry-store.d.ts.map +1 -0
  161. package/dist/mcp/agent-registry.d.ts +78 -0
  162. package/dist/mcp/agent-registry.d.ts.map +1 -0
  163. package/dist/mcp/harness.d.ts +26 -0
  164. package/dist/mcp/harness.d.ts.map +1 -0
  165. package/dist/mcp/index.js +3219 -3357
  166. package/dist/mcp/ingest-journal-tool.d.ts +2 -0
  167. package/dist/mcp/ingest-journal-tool.d.ts.map +1 -0
  168. package/dist/mcp/server.d.ts.map +1 -1
  169. package/dist/openapi.d.ts.map +1 -1
  170. package/dist/otel/index.js +2197 -121
  171. package/dist/server/human-auth.d.ts +20 -0
  172. package/dist/server/human-auth.d.ts.map +1 -0
  173. package/dist/server/index.js +10477 -6378
  174. package/dist/server/legacy-inventory.d.ts +52 -0
  175. package/dist/server/legacy-inventory.d.ts.map +1 -0
  176. package/dist/server/legacy-operations.d.ts +64 -0
  177. package/dist/server/legacy-operations.d.ts.map +1 -0
  178. package/dist/server/legacy-plan.d.ts +55 -0
  179. package/dist/server/legacy-plan.d.ts.map +1 -0
  180. package/dist/server/legacy-preservation.d.ts +58 -0
  181. package/dist/server/legacy-preservation.d.ts.map +1 -0
  182. package/dist/server/pg-sync-worker.js +195 -21
  183. package/dist/server/serve.d.ts +20 -18
  184. package/dist/server/serve.d.ts.map +1 -1
  185. package/dist/server/service-admission.d.ts +10 -0
  186. package/dist/server/service-admission.d.ts.map +1 -0
  187. package/dist/server/service-dispatcher.d.ts +45 -0
  188. package/dist/server/service-dispatcher.d.ts.map +1 -0
  189. package/dist/server/service-operations.d.ts +5 -0
  190. package/dist/server/service-operations.d.ts.map +1 -0
  191. package/dist/server/service-protocol.d.ts +50 -0
  192. package/dist/server/service-protocol.d.ts.map +1 -0
  193. package/dist/server/service-worker.d.ts +2 -0
  194. package/dist/server/service-worker.d.ts.map +1 -0
  195. package/dist/server/service-worker.js +8029 -0
  196. package/dist/types/index.d.ts +66 -0
  197. package/dist/types/index.d.ts.map +1 -1
  198. package/docs/README.md +1 -1
  199. package/docs/cli.md +2 -3
  200. package/docs/configuration.md +25 -12
  201. package/docs/cost-reporting.md +49 -0
  202. package/docs/historical-data-reconciliation.md +203 -0
  203. package/docs/ingest-journal.md +108 -0
  204. package/docs/ingestion.md +61 -5
  205. package/docs/mcp.md +5 -3
  206. package/docs/native-budget-save.md +84 -0
  207. package/docs/native-human-auth.md +102 -0
  208. package/docs/otel.md +8 -2
  209. package/docs/rest-api.md +4 -4
  210. package/package.json +17 -20
  211. package/postinstall.js +52 -1
  212. package/dashboard/README.md +0 -26
  213. package/dist/cli/brains.d.ts +0 -3
  214. package/dist/cli/brains.d.ts.map +0 -1
  215. package/dist/lib/test-hermetic-accounts.d.ts +0 -6
  216. package/dist/lib/test-hermetic-accounts.d.ts.map +0 -1
@@ -0,0 +1,258 @@
1
+ // @bun
2
+ import {
3
+ adoptResolverDataRoot,
4
+ bulkIngest,
5
+ cacheDir,
6
+ clearBillingRange,
7
+ countBillingRecords,
8
+ dataDir,
9
+ dedupeRequests,
10
+ deleteBudget,
11
+ deleteGoal,
12
+ deleteModelPricing,
13
+ deleteProject,
14
+ deleteSubscription,
15
+ getBudgetStatuses,
16
+ getCostCenter,
17
+ getDataDir,
18
+ getDbPath,
19
+ getExactDataRoot,
20
+ getGoalStatuses,
21
+ getHomeDir,
22
+ getIngestState,
23
+ getLegacyDataRoot,
24
+ getMachineId,
25
+ getModelPricing,
26
+ getProject,
27
+ getResolverDataRoot,
28
+ getSessionDetail,
29
+ initSchema,
30
+ insertFeedback,
31
+ listBudgets,
32
+ listGoals,
33
+ listMachineRegistry,
34
+ listMachines,
35
+ listModelPricing,
36
+ listProjects,
37
+ listSubscriptions,
38
+ loadIngestState,
39
+ queryAccountBreakdown,
40
+ queryAccountBreakdownSince,
41
+ queryAgentBreakdown,
42
+ queryAgentBreakdownSince,
43
+ queryBillingSummary,
44
+ queryCostCenterBreakdown,
45
+ queryDailyBreakdown,
46
+ queryHourlyBreakdown,
47
+ queryModelBreakdown,
48
+ queryModelBreakdownSince,
49
+ queryProjectBreakdown,
50
+ queryProjectBreakdownSince,
51
+ queryRequestsSince,
52
+ queryScanReceipts,
53
+ querySessions,
54
+ querySummary,
55
+ queryTopSessions,
56
+ queryUsageSnapshots,
57
+ queryZeroCostTokenizedModels,
58
+ rollupSession,
59
+ seedModelPricing,
60
+ setIngestState,
61
+ upsertBillingDaily,
62
+ upsertBudget,
63
+ upsertCostCenter,
64
+ upsertGoal,
65
+ upsertModelPricing,
66
+ upsertProject,
67
+ upsertRequest,
68
+ upsertScanReceipt,
69
+ upsertSession,
70
+ upsertSubscription,
71
+ upsertUsageSnapshot
72
+ } from "./index-ez9thsr7.js";
73
+ import {
74
+ __require
75
+ } from "./index-p35cyhc4.js";
76
+
77
+ // src/db/sqlite-adapter.ts
78
+ import { Database } from "bun:sqlite";
79
+
80
+ class SqliteAdapter {
81
+ db;
82
+ constructor(path) {
83
+ this.db = new Database(path, { create: true });
84
+ this.db.exec("PRAGMA journal_mode=WAL");
85
+ this.db.exec("PRAGMA foreign_keys=ON");
86
+ }
87
+ run(sql, ...params) {
88
+ const result = this.db.prepare(sql).run(...params);
89
+ return { changes: result.changes, lastInsertRowid: result.lastInsertRowid };
90
+ }
91
+ get(sql, ...params) {
92
+ return this.db.prepare(sql).get(...params);
93
+ }
94
+ all(sql, ...params) {
95
+ return this.db.prepare(sql).all(...params);
96
+ }
97
+ exec(sql) {
98
+ this.db.exec(sql);
99
+ }
100
+ query(sql) {
101
+ return this.db.query(sql);
102
+ }
103
+ prepare(sql) {
104
+ const stmt = this.db.prepare(sql);
105
+ return {
106
+ run(...params) {
107
+ const r = stmt.run(...params);
108
+ return { changes: r.changes, lastInsertRowid: r.lastInsertRowid };
109
+ },
110
+ get(...params) {
111
+ return stmt.get(...params);
112
+ },
113
+ all(...params) {
114
+ return stmt.all(...params);
115
+ },
116
+ finalize() {
117
+ stmt.finalize();
118
+ }
119
+ };
120
+ }
121
+ close() {
122
+ this.db.close();
123
+ }
124
+ transaction(fn) {
125
+ return this.db.transaction(fn)();
126
+ }
127
+ get raw() {
128
+ return this.db;
129
+ }
130
+ }
131
+
132
+ // src/db/sqlite-store.ts
133
+ import { existsSync, mkdirSync } from "fs";
134
+ function isSqliteBusyError(error) {
135
+ const candidate = error;
136
+ const code = typeof candidate.code === "string" ? candidate.code : "";
137
+ const message = typeof candidate.message === "string" ? candidate.message : String(error);
138
+ return code === "SQLITE_BUSY" || code === "SQLITE_BUSY_RECOVERY" || /database is locked|SQLITE_BUSY/i.test(message);
139
+ }
140
+ function retryDelayMs(attempt) {
141
+ return Math.min(1000, 50 * 2 ** attempt);
142
+ }
143
+ function withSqliteBusyRetry(operation, context) {
144
+ const maxAttempts = 8;
145
+ let lastError;
146
+ for (let attempt = 0;attempt < maxAttempts; attempt++) {
147
+ try {
148
+ return operation();
149
+ } catch (error) {
150
+ if (!isSqliteBusyError(error))
151
+ throw error;
152
+ lastError = error;
153
+ if (attempt === maxAttempts - 1)
154
+ break;
155
+ Bun.sleepSync(retryDelayMs(attempt));
156
+ }
157
+ }
158
+ throw new Error(`SQLite database is locked after ${maxAttempts} attempts while ${context}. Another economy sync/merge may be recovering the database; retry shortly.`, { cause: lastError });
159
+ }
160
+ function openDatabase(dbPath, skipSeed = false) {
161
+ const path = dbPath ?? getDbPath();
162
+ if (path !== ":memory:") {
163
+ const dir = path.substring(0, path.lastIndexOf("/"));
164
+ if (dir && !existsSync(dir))
165
+ mkdirSync(dir, { recursive: true });
166
+ }
167
+ const db = withSqliteBusyRetry(() => {
168
+ const opened = new SqliteAdapter(path);
169
+ try {
170
+ opened.exec("PRAGMA busy_timeout = 10000");
171
+ opened.exec("PRAGMA journal_mode = WAL");
172
+ opened.exec("PRAGMA foreign_keys = ON");
173
+ initSchema(opened);
174
+ return opened;
175
+ } catch (error) {
176
+ try {
177
+ opened.close();
178
+ } catch {}
179
+ throw error;
180
+ }
181
+ }, `opening ${path}`);
182
+ if (!skipSeed) {
183
+ import("./pricing-y21mcjsa.js").then(({ ensurePricingSeeded }) => ensurePricingSeeded(db)).catch(() => {});
184
+ }
185
+ return db;
186
+ }
187
+ export {
188
+ upsertUsageSnapshot,
189
+ upsertSubscription,
190
+ upsertSession,
191
+ upsertScanReceipt,
192
+ upsertRequest,
193
+ upsertProject,
194
+ upsertModelPricing,
195
+ upsertGoal,
196
+ upsertCostCenter,
197
+ upsertBudget,
198
+ upsertBillingDaily,
199
+ setIngestState,
200
+ seedModelPricing,
201
+ rollupSession,
202
+ queryZeroCostTokenizedModels,
203
+ queryUsageSnapshots,
204
+ queryTopSessions,
205
+ querySummary,
206
+ querySessions,
207
+ queryScanReceipts,
208
+ queryRequestsSince,
209
+ queryProjectBreakdownSince,
210
+ queryProjectBreakdown,
211
+ queryModelBreakdownSince,
212
+ queryModelBreakdown,
213
+ queryHourlyBreakdown,
214
+ queryDailyBreakdown,
215
+ queryCostCenterBreakdown,
216
+ queryBillingSummary,
217
+ queryAgentBreakdownSince,
218
+ queryAgentBreakdown,
219
+ queryAccountBreakdownSince,
220
+ queryAccountBreakdown,
221
+ openDatabase,
222
+ loadIngestState,
223
+ listSubscriptions,
224
+ listProjects,
225
+ listModelPricing,
226
+ listMachines,
227
+ listMachineRegistry,
228
+ listGoals,
229
+ listBudgets,
230
+ insertFeedback,
231
+ initSchema,
232
+ getSessionDetail,
233
+ getResolverDataRoot,
234
+ getProject,
235
+ getModelPricing,
236
+ getMachineId,
237
+ getLegacyDataRoot,
238
+ getIngestState,
239
+ getHomeDir,
240
+ getGoalStatuses,
241
+ getExactDataRoot,
242
+ getDbPath,
243
+ getDataDir,
244
+ getCostCenter,
245
+ getBudgetStatuses,
246
+ deleteSubscription,
247
+ deleteProject,
248
+ deleteModelPricing,
249
+ deleteGoal,
250
+ deleteBudget,
251
+ dedupeRequests,
252
+ dataDir,
253
+ countBillingRecords,
254
+ clearBillingRange,
255
+ cacheDir,
256
+ bulkIngest,
257
+ adoptResolverDataRoot
258
+ };
@@ -0,0 +1,256 @@
1
+ // @bun
2
+ import {
3
+ __require,
4
+ adoptResolverDataRoot,
5
+ bulkIngest,
6
+ cacheDir,
7
+ clearBillingRange,
8
+ countBillingRecords,
9
+ dataDir,
10
+ dedupeRequests,
11
+ deleteBudget,
12
+ deleteGoal,
13
+ deleteModelPricing,
14
+ deleteProject,
15
+ deleteSubscription,
16
+ getBudgetStatuses,
17
+ getCostCenter,
18
+ getDataDir,
19
+ getDbPath,
20
+ getExactDataRoot,
21
+ getGoalStatuses,
22
+ getHomeDir,
23
+ getIngestState,
24
+ getLegacyDataRoot,
25
+ getMachineId,
26
+ getModelPricing,
27
+ getProject,
28
+ getResolverDataRoot,
29
+ getSessionDetail,
30
+ initSchema,
31
+ insertFeedback,
32
+ listBudgets,
33
+ listGoals,
34
+ listMachineRegistry,
35
+ listMachines,
36
+ listModelPricing,
37
+ listProjects,
38
+ listSubscriptions,
39
+ loadIngestState,
40
+ queryAccountBreakdown,
41
+ queryAccountBreakdownSince,
42
+ queryAgentBreakdown,
43
+ queryAgentBreakdownSince,
44
+ queryBillingSummary,
45
+ queryCostCenterBreakdown,
46
+ queryDailyBreakdown,
47
+ queryHourlyBreakdown,
48
+ queryModelBreakdown,
49
+ queryModelBreakdownSince,
50
+ queryProjectBreakdown,
51
+ queryProjectBreakdownSince,
52
+ queryRequestsSince,
53
+ queryScanReceipts,
54
+ querySessions,
55
+ querySummary,
56
+ queryTopSessions,
57
+ queryUsageSnapshots,
58
+ queryZeroCostTokenizedModels,
59
+ rollupSession,
60
+ seedModelPricing,
61
+ setIngestState,
62
+ upsertBillingDaily,
63
+ upsertBudget,
64
+ upsertCostCenter,
65
+ upsertGoal,
66
+ upsertModelPricing,
67
+ upsertProject,
68
+ upsertRequest,
69
+ upsertScanReceipt,
70
+ upsertSession,
71
+ upsertSubscription,
72
+ upsertUsageSnapshot
73
+ } from "./index-zpvea08j.js";
74
+
75
+ // src/db/sqlite-adapter.ts
76
+ import { Database } from "bun:sqlite";
77
+
78
+ class SqliteAdapter {
79
+ db;
80
+ constructor(path) {
81
+ this.db = new Database(path, { create: true });
82
+ this.db.exec("PRAGMA journal_mode=WAL");
83
+ this.db.exec("PRAGMA foreign_keys=ON");
84
+ }
85
+ run(sql, ...params) {
86
+ const result = this.db.prepare(sql).run(...params);
87
+ return { changes: result.changes, lastInsertRowid: result.lastInsertRowid };
88
+ }
89
+ get(sql, ...params) {
90
+ return this.db.prepare(sql).get(...params);
91
+ }
92
+ all(sql, ...params) {
93
+ return this.db.prepare(sql).all(...params);
94
+ }
95
+ exec(sql) {
96
+ this.db.exec(sql);
97
+ }
98
+ query(sql) {
99
+ return this.db.query(sql);
100
+ }
101
+ prepare(sql) {
102
+ const stmt = this.db.prepare(sql);
103
+ return {
104
+ run(...params) {
105
+ const r = stmt.run(...params);
106
+ return { changes: r.changes, lastInsertRowid: r.lastInsertRowid };
107
+ },
108
+ get(...params) {
109
+ return stmt.get(...params);
110
+ },
111
+ all(...params) {
112
+ return stmt.all(...params);
113
+ },
114
+ finalize() {
115
+ stmt.finalize();
116
+ }
117
+ };
118
+ }
119
+ close() {
120
+ this.db.close();
121
+ }
122
+ transaction(fn) {
123
+ return this.db.transaction(fn)();
124
+ }
125
+ get raw() {
126
+ return this.db;
127
+ }
128
+ }
129
+
130
+ // src/db/sqlite-store.ts
131
+ import { existsSync, mkdirSync } from "fs";
132
+ function isSqliteBusyError(error) {
133
+ const candidate = error;
134
+ const code = typeof candidate.code === "string" ? candidate.code : "";
135
+ const message = typeof candidate.message === "string" ? candidate.message : String(error);
136
+ return code === "SQLITE_BUSY" || code === "SQLITE_BUSY_RECOVERY" || /database is locked|SQLITE_BUSY/i.test(message);
137
+ }
138
+ function retryDelayMs(attempt) {
139
+ return Math.min(1000, 50 * 2 ** attempt);
140
+ }
141
+ function withSqliteBusyRetry(operation, context) {
142
+ const maxAttempts = 8;
143
+ let lastError;
144
+ for (let attempt = 0;attempt < maxAttempts; attempt++) {
145
+ try {
146
+ return operation();
147
+ } catch (error) {
148
+ if (!isSqliteBusyError(error))
149
+ throw error;
150
+ lastError = error;
151
+ if (attempt === maxAttempts - 1)
152
+ break;
153
+ Bun.sleepSync(retryDelayMs(attempt));
154
+ }
155
+ }
156
+ throw new Error(`SQLite database is locked after ${maxAttempts} attempts while ${context}. Another economy sync/merge may be recovering the database; retry shortly.`, { cause: lastError });
157
+ }
158
+ function openDatabase(dbPath, skipSeed = false) {
159
+ const path = dbPath ?? getDbPath();
160
+ if (path !== ":memory:") {
161
+ const dir = path.substring(0, path.lastIndexOf("/"));
162
+ if (dir && !existsSync(dir))
163
+ mkdirSync(dir, { recursive: true });
164
+ }
165
+ const db = withSqliteBusyRetry(() => {
166
+ const opened = new SqliteAdapter(path);
167
+ try {
168
+ opened.exec("PRAGMA busy_timeout = 10000");
169
+ opened.exec("PRAGMA journal_mode = WAL");
170
+ opened.exec("PRAGMA foreign_keys = ON");
171
+ initSchema(opened);
172
+ return opened;
173
+ } catch (error) {
174
+ try {
175
+ opened.close();
176
+ } catch {}
177
+ throw error;
178
+ }
179
+ }, `opening ${path}`);
180
+ if (!skipSeed) {
181
+ import("./pricing-f80p81gr.js").then(({ ensurePricingSeeded }) => ensurePricingSeeded(db)).catch(() => {});
182
+ }
183
+ return db;
184
+ }
185
+ export {
186
+ upsertUsageSnapshot,
187
+ upsertSubscription,
188
+ upsertSession,
189
+ upsertScanReceipt,
190
+ upsertRequest,
191
+ upsertProject,
192
+ upsertModelPricing,
193
+ upsertGoal,
194
+ upsertCostCenter,
195
+ upsertBudget,
196
+ upsertBillingDaily,
197
+ setIngestState,
198
+ seedModelPricing,
199
+ rollupSession,
200
+ queryZeroCostTokenizedModels,
201
+ queryUsageSnapshots,
202
+ queryTopSessions,
203
+ querySummary,
204
+ querySessions,
205
+ queryScanReceipts,
206
+ queryRequestsSince,
207
+ queryProjectBreakdownSince,
208
+ queryProjectBreakdown,
209
+ queryModelBreakdownSince,
210
+ queryModelBreakdown,
211
+ queryHourlyBreakdown,
212
+ queryDailyBreakdown,
213
+ queryCostCenterBreakdown,
214
+ queryBillingSummary,
215
+ queryAgentBreakdownSince,
216
+ queryAgentBreakdown,
217
+ queryAccountBreakdownSince,
218
+ queryAccountBreakdown,
219
+ openDatabase,
220
+ loadIngestState,
221
+ listSubscriptions,
222
+ listProjects,
223
+ listModelPricing,
224
+ listMachines,
225
+ listMachineRegistry,
226
+ listGoals,
227
+ listBudgets,
228
+ insertFeedback,
229
+ initSchema,
230
+ getSessionDetail,
231
+ getResolverDataRoot,
232
+ getProject,
233
+ getModelPricing,
234
+ getMachineId,
235
+ getLegacyDataRoot,
236
+ getIngestState,
237
+ getHomeDir,
238
+ getGoalStatuses,
239
+ getExactDataRoot,
240
+ getDbPath,
241
+ getDataDir,
242
+ getCostCenter,
243
+ getBudgetStatuses,
244
+ deleteSubscription,
245
+ deleteProject,
246
+ deleteModelPricing,
247
+ deleteGoal,
248
+ deleteBudget,
249
+ dedupeRequests,
250
+ dataDir,
251
+ countBillingRecords,
252
+ clearBillingRange,
253
+ cacheDir,
254
+ bulkIngest,
255
+ adoptResolverDataRoot
256
+ };