@lastbrain/module-ai 2.0.26 → 2.0.30

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 (365) hide show
  1. package/README.md +52 -1
  2. package/dist/ai.build.config.d.ts.map +1 -1
  3. package/dist/ai.build.config.js +508 -9
  4. package/dist/api/admin/ai-provider-models/[id].d.ts +18 -0
  5. package/dist/api/admin/ai-provider-models/[id].d.ts.map +1 -0
  6. package/dist/api/admin/ai-provider-models/[id].js +58 -0
  7. package/dist/api/admin/ai-provider-models.d.ts +20 -0
  8. package/dist/api/admin/ai-provider-models.d.ts.map +1 -0
  9. package/dist/api/admin/ai-provider-models.js +26 -0
  10. package/dist/api/admin/ai-providers/[key].d.ts +18 -0
  11. package/dist/api/admin/ai-providers/[key].d.ts.map +1 -0
  12. package/dist/api/admin/ai-providers/[key].js +55 -0
  13. package/dist/api/admin/ai-providers.d.ts +20 -0
  14. package/dist/api/admin/ai-providers.d.ts.map +1 -0
  15. package/dist/api/admin/ai-providers.js +26 -0
  16. package/dist/api/admin/billing-analytics.d.ts +43 -0
  17. package/dist/api/admin/billing-analytics.d.ts.map +1 -0
  18. package/dist/api/admin/billing-analytics.js +144 -0
  19. package/dist/api/admin/global-ai-settings.d.ts +14 -0
  20. package/dist/api/admin/global-ai-settings.d.ts.map +1 -0
  21. package/dist/api/admin/global-ai-settings.js +63 -0
  22. package/dist/api/admin/token-packs/[id].d.ts.map +1 -1
  23. package/dist/api/admin/token-packs/[id].js +3 -2
  24. package/dist/api/admin/token-packs.d.ts.map +1 -1
  25. package/dist/api/admin/token-packs.js +3 -2
  26. package/dist/api/admin/user-monthly-details.d.ts +49 -0
  27. package/dist/api/admin/user-monthly-details.d.ts.map +1 -0
  28. package/dist/api/admin/user-monthly-details.js +140 -0
  29. package/dist/api/admin/user-quota.d.ts +21 -0
  30. package/dist/api/admin/user-quota.d.ts.map +1 -0
  31. package/dist/api/admin/user-quota.js +59 -0
  32. package/dist/api/admin/user-token/[id].d.ts.map +1 -1
  33. package/dist/api/admin/user-token/[id].js +2 -1
  34. package/dist/api/admin/user-token.d.ts +5 -2
  35. package/dist/api/admin/user-token.d.ts.map +1 -1
  36. package/dist/api/admin/user-token.js +91 -17
  37. package/dist/api/admin/user-usage-by-model.d.ts +22 -0
  38. package/dist/api/admin/user-usage-by-model.d.ts.map +1 -0
  39. package/dist/api/admin/user-usage-by-model.js +78 -0
  40. package/dist/api/admin/user-wallet-analytics.d.ts +15 -0
  41. package/dist/api/admin/user-wallet-analytics.d.ts.map +1 -0
  42. package/dist/api/admin/user-wallet-analytics.js +67 -0
  43. package/dist/api/admin/wallet-repair/route.d.ts +30 -0
  44. package/dist/api/admin/wallet-repair/route.d.ts.map +1 -0
  45. package/dist/api/admin/wallet-repair/route.js +63 -0
  46. package/dist/api/auth/ai-model-settings.d.ts +21 -0
  47. package/dist/api/auth/ai-model-settings.d.ts.map +1 -0
  48. package/dist/api/auth/ai-model-settings.js +86 -0
  49. package/dist/api/auth/ai-settings.d.ts +17 -0
  50. package/dist/api/auth/ai-settings.d.ts.map +1 -0
  51. package/dist/api/auth/ai-settings.js +87 -0
  52. package/dist/api/auth/api-keys/[id].d.ts +17 -0
  53. package/dist/api/auth/api-keys/[id].d.ts.map +1 -0
  54. package/dist/api/auth/api-keys/[id].js +66 -0
  55. package/dist/api/auth/api-keys.d.ts +19 -0
  56. package/dist/api/auth/api-keys.d.ts.map +1 -0
  57. package/dist/api/auth/api-keys.js +94 -0
  58. package/dist/api/auth/create-checkout.d.ts +1 -1
  59. package/dist/api/auth/create-checkout.d.ts.map +1 -1
  60. package/dist/api/auth/create-checkout.js +8 -6
  61. package/dist/api/auth/generate-image.d.ts +2 -2
  62. package/dist/api/auth/generate-image.d.ts.map +1 -1
  63. package/dist/api/auth/generate-image.js +404 -104
  64. package/dist/api/auth/generate-text.d.ts +3 -2
  65. package/dist/api/auth/generate-text.d.ts.map +1 -1
  66. package/dist/api/auth/generate-text.js +130 -58
  67. package/dist/api/auth/process-ocr.d.ts +9 -0
  68. package/dist/api/auth/process-ocr.d.ts.map +1 -0
  69. package/dist/api/auth/process-ocr.js +43 -0
  70. package/dist/api/auth/prompts/stats.d.ts +14 -0
  71. package/dist/api/auth/prompts/stats.d.ts.map +1 -0
  72. package/dist/api/auth/prompts/stats.js +46 -0
  73. package/dist/api/auth/prompts.d.ts +26 -0
  74. package/dist/api/auth/prompts.d.ts.map +1 -0
  75. package/dist/api/auth/prompts.js +175 -0
  76. package/dist/api/auth/token-balance.d.ts +26 -0
  77. package/dist/api/auth/token-balance.d.ts.map +1 -0
  78. package/dist/api/auth/token-balance.js +47 -0
  79. package/dist/api/auth/token-checkout.d.ts.map +1 -1
  80. package/dist/api/auth/token-checkout.js +22 -4
  81. package/dist/api/auth/token-packs.d.ts.map +1 -1
  82. package/dist/api/auth/token-packs.js +2 -1
  83. package/dist/api/auth/usage-by-model.d.ts +25 -0
  84. package/dist/api/auth/usage-by-model.d.ts.map +1 -0
  85. package/dist/api/auth/usage-by-model.js +95 -0
  86. package/dist/api/auth/usage.d.ts +26 -0
  87. package/dist/api/auth/usage.d.ts.map +1 -0
  88. package/dist/api/auth/usage.js +127 -0
  89. package/dist/api/auth/user-tokens.d.ts.map +1 -1
  90. package/dist/api/auth/user-tokens.js +36 -2
  91. package/dist/api/auth/wallet/route.d.ts +17 -0
  92. package/dist/api/auth/wallet/route.d.ts.map +1 -0
  93. package/dist/api/auth/wallet/route.js +68 -0
  94. package/dist/api/auth/wallet.d.ts +16 -0
  95. package/dist/api/auth/wallet.d.ts.map +1 -0
  96. package/dist/api/auth/wallet.js +71 -0
  97. package/dist/api/public/gateway-models.d.ts +25 -0
  98. package/dist/api/public/gateway-models.d.ts.map +1 -0
  99. package/dist/api/public/gateway-models.js +49 -0
  100. package/dist/api/public/pricing-summary.d.ts +46 -0
  101. package/dist/api/public/pricing-summary.d.ts.map +1 -0
  102. package/dist/api/public/pricing-summary.js +70 -0
  103. package/dist/api/public/prompts/[id]/stats.d.ts +15 -0
  104. package/dist/api/public/prompts/[id]/stats.d.ts.map +1 -0
  105. package/dist/api/public/prompts/[id]/stats.js +37 -0
  106. package/dist/api/public/prompts/[id]/view.d.ts +15 -0
  107. package/dist/api/public/prompts/[id]/view.d.ts.map +1 -0
  108. package/dist/api/public/prompts/[id]/view.js +41 -0
  109. package/dist/api/public/prompts/slug/[slug].d.ts +15 -0
  110. package/dist/api/public/prompts/slug/[slug].d.ts.map +1 -0
  111. package/dist/api/public/prompts/slug/[slug].js +40 -0
  112. package/dist/api/public/prompts/user/[username].d.ts +17 -0
  113. package/dist/api/public/prompts/user/[username].d.ts.map +1 -0
  114. package/dist/api/public/prompts/user/[username].js +51 -0
  115. package/dist/api/public/prompts.d.ts +15 -0
  116. package/dist/api/public/prompts.d.ts.map +1 -0
  117. package/dist/api/public/prompts.js +45 -0
  118. package/dist/api/public/token-packs.d.ts +11 -0
  119. package/dist/api/public/token-packs.d.ts.map +1 -0
  120. package/dist/api/public/token-packs.js +25 -0
  121. package/dist/api/public/token-pricing.d.ts +44 -0
  122. package/dist/api/public/token-pricing.d.ts.map +1 -0
  123. package/dist/api/public/token-pricing.js +168 -0
  124. package/dist/api/public/v1/_lib/artifacts.d.ts +52 -0
  125. package/dist/api/public/v1/_lib/artifacts.d.ts.map +1 -0
  126. package/dist/api/public/v1/_lib/artifacts.js +217 -0
  127. package/dist/api/public/v1/_lib/auth.d.ts +43 -0
  128. package/dist/api/public/v1/_lib/auth.d.ts.map +1 -0
  129. package/dist/api/public/v1/_lib/auth.js +108 -0
  130. package/dist/api/public/v1/_lib/errors.d.ts +17 -0
  131. package/dist/api/public/v1/_lib/errors.d.ts.map +1 -0
  132. package/dist/api/public/v1/_lib/errors.js +16 -0
  133. package/dist/api/public/v1/_lib/log.d.ts +29 -0
  134. package/dist/api/public/v1/_lib/log.d.ts.map +1 -0
  135. package/dist/api/public/v1/_lib/log.js +68 -0
  136. package/dist/api/public/v1/_lib/quota.d.ts +24 -0
  137. package/dist/api/public/v1/_lib/quota.d.ts.map +1 -0
  138. package/dist/api/public/v1/_lib/quota.js +118 -0
  139. package/dist/api/public/v1/_lib/router.d.ts +54 -0
  140. package/dist/api/public/v1/_lib/router.d.ts.map +1 -0
  141. package/dist/api/public/v1/_lib/router.js +119 -0
  142. package/dist/api/public/v1/connect.d.ts +20 -0
  143. package/dist/api/public/v1/connect.d.ts.map +1 -0
  144. package/dist/api/public/v1/connect.js +119 -0
  145. package/dist/api/public/v1/doc.d.ts +239 -0
  146. package/dist/api/public/v1/doc.d.ts.map +1 -0
  147. package/dist/api/public/v1/doc.js +253 -0
  148. package/dist/api/public/v1/history/[id].d.ts +92 -0
  149. package/dist/api/public/v1/history/[id].d.ts.map +1 -0
  150. package/dist/api/public/v1/history/[id].js +176 -0
  151. package/dist/api/public/v1/history.d.ts +30 -0
  152. package/dist/api/public/v1/history.d.ts.map +1 -0
  153. package/dist/api/public/v1/history.js +142 -0
  154. package/dist/api/public/v1/image-ai.d.ts +24 -0
  155. package/dist/api/public/v1/image-ai.d.ts.map +1 -0
  156. package/dist/api/public/v1/image-ai.js +233 -0
  157. package/dist/api/public/v1/prompts.d.ts +19 -0
  158. package/dist/api/public/v1/prompts.d.ts.map +1 -0
  159. package/dist/api/public/v1/prompts.js +107 -0
  160. package/dist/api/public/v1/provider.d.ts +16 -0
  161. package/dist/api/public/v1/provider.d.ts.map +1 -0
  162. package/dist/api/public/v1/provider.js +130 -0
  163. package/dist/api/public/v1/purchase.d.ts +11 -0
  164. package/dist/api/public/v1/purchase.d.ts.map +1 -0
  165. package/dist/api/public/v1/purchase.js +18 -0
  166. package/dist/api/public/v1/status.d.ts +35 -0
  167. package/dist/api/public/v1/status.d.ts.map +1 -0
  168. package/dist/api/public/v1/status.js +163 -0
  169. package/dist/api/public/v1/text-ai.d.ts +26 -0
  170. package/dist/api/public/v1/text-ai.d.ts.map +1 -0
  171. package/dist/api/public/v1/text-ai.js +239 -0
  172. package/dist/api/public/webhook.d.ts.map +1 -1
  173. package/dist/api/public/webhook.js +50 -39
  174. package/dist/api/track-usage.d.ts +12 -0
  175. package/dist/api/track-usage.d.ts.map +1 -0
  176. package/dist/api/track-usage.js +37 -0
  177. package/dist/components/Doc.d.ts.map +1 -1
  178. package/dist/components/Doc.js +1 -1
  179. package/dist/components/DocUsageCustom.js +6 -6
  180. package/dist/components/admin/UserTokenTab.d.ts.map +1 -1
  181. package/dist/components/admin/UserTokenTab.js +170 -23
  182. package/dist/components/auth/AuthDashboardAi.d.ts +2 -0
  183. package/dist/components/auth/AuthDashboardAi.d.ts.map +1 -0
  184. package/dist/components/auth/AuthDashboardAi.js +53 -0
  185. package/dist/docs/REFACTORING_BILLING_GUIDE.d.ts +277 -0
  186. package/dist/docs/REFACTORING_BILLING_GUIDE.d.ts.map +1 -0
  187. package/dist/docs/REFACTORING_BILLING_GUIDE.js +276 -0
  188. package/dist/index.d.ts +15 -1
  189. package/dist/index.d.ts.map +1 -1
  190. package/dist/index.js +18 -1
  191. package/dist/scripts/migrate-tokens-to-wallet.d.ts +13 -0
  192. package/dist/scripts/migrate-tokens-to-wallet.d.ts.map +1 -0
  193. package/dist/scripts/migrate-tokens-to-wallet.js +165 -0
  194. package/dist/server/__tests__/billing.test.d.ts +5 -0
  195. package/dist/server/__tests__/billing.test.d.ts.map +1 -0
  196. package/dist/server/__tests__/billing.test.js +223 -0
  197. package/dist/server/ai-client.d.ts +59 -0
  198. package/dist/server/ai-client.d.ts.map +1 -0
  199. package/dist/server/ai-client.js +111 -0
  200. package/dist/server/ai-generation-service.d.ts +66 -0
  201. package/dist/server/ai-generation-service.d.ts.map +1 -0
  202. package/dist/server/ai-generation-service.js +274 -0
  203. package/dist/server/billing.d.ts +200 -0
  204. package/dist/server/billing.d.ts.map +1 -0
  205. package/dist/server/billing.js +488 -0
  206. package/dist/server/gateway-service.d.ts +13 -0
  207. package/dist/server/gateway-service.d.ts.map +1 -0
  208. package/dist/server/gateway-service.js +161 -0
  209. package/dist/server/global-settings.d.ts +16 -0
  210. package/dist/server/global-settings.d.ts.map +1 -0
  211. package/dist/server/global-settings.js +42 -0
  212. package/dist/server/model-filter.d.ts +25 -0
  213. package/dist/server/model-filter.d.ts.map +1 -0
  214. package/dist/server/model-filter.js +240 -0
  215. package/dist/server/ocr.d.ts +39 -0
  216. package/dist/server/ocr.d.ts.map +1 -0
  217. package/dist/server/ocr.js +280 -0
  218. package/dist/server/openai-client.d.ts +19 -0
  219. package/dist/server/openai-client.d.ts.map +1 -0
  220. package/dist/server/openai-client.js +26 -0
  221. package/dist/server/pricing-config.d.ts +18 -0
  222. package/dist/server/pricing-config.d.ts.map +1 -0
  223. package/dist/server/pricing-config.js +94 -0
  224. package/dist/server/pricing-validator.d.ts +41 -0
  225. package/dist/server/pricing-validator.d.ts.map +1 -0
  226. package/dist/server/pricing-validator.js +113 -0
  227. package/dist/server/pricing.d.ts +121 -0
  228. package/dist/server/pricing.d.ts.map +1 -0
  229. package/dist/server/pricing.js +225 -0
  230. package/dist/server/quota.d.ts +66 -0
  231. package/dist/server/quota.d.ts.map +1 -0
  232. package/dist/server/quota.js +538 -0
  233. package/dist/server/wallet-repair.d.ts +32 -0
  234. package/dist/server/wallet-repair.d.ts.map +1 -0
  235. package/dist/server/wallet-repair.js +189 -0
  236. package/dist/server.d.ts +13 -1
  237. package/dist/server.d.ts.map +1 -1
  238. package/dist/server.js +87 -16
  239. package/dist/sitemap/handlers/prompts.d.ts +6 -0
  240. package/dist/sitemap/handlers/prompts.d.ts.map +1 -0
  241. package/dist/sitemap/handlers/prompts.js +72 -0
  242. package/dist/sitemap/handlers/users.d.ts +6 -0
  243. package/dist/sitemap/handlers/users.d.ts.map +1 -0
  244. package/dist/sitemap/handlers/users.js +80 -0
  245. package/dist/sitemap/manifest.d.ts +8 -0
  246. package/dist/sitemap/manifest.d.ts.map +1 -0
  247. package/dist/sitemap/manifest.js +27 -0
  248. package/dist/types/gateway.d.ts +40 -0
  249. package/dist/types/gateway.d.ts.map +1 -0
  250. package/dist/types/gateway.js +4 -0
  251. package/dist/types/quota.d.ts +74 -0
  252. package/dist/types/quota.d.ts.map +1 -0
  253. package/dist/types/quota.js +11 -0
  254. package/dist/utils/date.d.ts +7 -0
  255. package/dist/utils/date.d.ts.map +1 -0
  256. package/dist/utils/date.js +17 -0
  257. package/dist/web/admin/AdminTokenPacksPage.js +1 -1
  258. package/dist/web/admin/BillingAnalyticsPage.d.ts +2 -0
  259. package/dist/web/admin/BillingAnalyticsPage.d.ts.map +1 -0
  260. package/dist/web/admin/BillingAnalyticsPage.js +141 -0
  261. package/dist/web/admin/GlobalAISettingsPage.d.ts +2 -0
  262. package/dist/web/admin/GlobalAISettingsPage.d.ts.map +1 -0
  263. package/dist/web/admin/GlobalAISettingsPage.js +93 -0
  264. package/dist/web/admin/UserTokenPage.d.ts.map +1 -1
  265. package/dist/web/admin/UserTokenPage.js +20 -7
  266. package/dist/web/auth/AISettingsPage.d.ts +2 -0
  267. package/dist/web/auth/AISettingsPage.d.ts.map +1 -0
  268. package/dist/web/auth/AISettingsPage.js +258 -0
  269. package/dist/web/auth/APIKeysPage.d.ts +2 -0
  270. package/dist/web/auth/APIKeysPage.d.ts.map +1 -0
  271. package/dist/web/auth/APIKeysPage.js +154 -0
  272. package/dist/web/auth/HistoryPage.d.ts +2 -0
  273. package/dist/web/auth/HistoryPage.d.ts.map +1 -0
  274. package/dist/web/auth/HistoryPage.js +279 -0
  275. package/dist/web/auth/PromptsPage.d.ts +5 -0
  276. package/dist/web/auth/PromptsPage.d.ts.map +1 -0
  277. package/dist/web/auth/PromptsPage.js +137 -0
  278. package/dist/web/auth/TokenPage.d.ts.map +1 -1
  279. package/dist/web/auth/TokenPage.js +88 -31
  280. package/dist/web/auth/UsageAndTokensPage.d.ts +2 -0
  281. package/dist/web/auth/UsageAndTokensPage.d.ts.map +1 -0
  282. package/dist/web/auth/UsageAndTokensPage.js +157 -0
  283. package/dist/web/auth/UsagePage.d.ts +2 -0
  284. package/dist/web/auth/UsagePage.d.ts.map +1 -0
  285. package/dist/web/auth/UsagePage.js +62 -0
  286. package/dist/web/auth/components/ApiKeyFilterSelect.d.ts +13 -0
  287. package/dist/web/auth/components/ApiKeyFilterSelect.d.ts.map +1 -0
  288. package/dist/web/auth/components/ApiKeyFilterSelect.js +16 -0
  289. package/dist/web/auth/components/ModelUsageTable.d.ts +19 -0
  290. package/dist/web/auth/components/ModelUsageTable.d.ts.map +1 -0
  291. package/dist/web/auth/components/ModelUsageTable.js +37 -0
  292. package/dist/web/auth/components/PurchaseButton.d.ts +7 -0
  293. package/dist/web/auth/components/PurchaseButton.d.ts.map +1 -0
  294. package/dist/web/auth/components/PurchaseButton.js +13 -0
  295. package/dist/web/auth/components/TokenHistoryCard.d.ts +20 -0
  296. package/dist/web/auth/components/TokenHistoryCard.d.ts.map +1 -0
  297. package/dist/web/auth/components/TokenHistoryCard.js +76 -0
  298. package/dist/web/auth/components/TokenKpiGrid.d.ts +24 -0
  299. package/dist/web/auth/components/TokenKpiGrid.d.ts.map +1 -0
  300. package/dist/web/auth/components/TokenKpiGrid.js +38 -0
  301. package/dist/web/auth/components/UsageByDayChart.d.ts +11 -0
  302. package/dist/web/auth/components/UsageByDayChart.d.ts.map +1 -0
  303. package/dist/web/auth/components/UsageByDayChart.js +32 -0
  304. package/dist/web/auth/components/UsageByModelBarChart.d.ts +12 -0
  305. package/dist/web/auth/components/UsageByModelBarChart.d.ts.map +1 -0
  306. package/dist/web/auth/components/UsageByModelBarChart.js +32 -0
  307. package/dist/web/auth/components/WalletStatusCard.d.ts +9 -0
  308. package/dist/web/auth/components/WalletStatusCard.d.ts.map +1 -0
  309. package/dist/web/auth/components/WalletStatusCard.js +50 -0
  310. package/dist/web/components/ImageGenerative.d.ts +3 -1
  311. package/dist/web/components/ImageGenerative.d.ts.map +1 -1
  312. package/dist/web/components/ImageGenerative.js +139 -52
  313. package/dist/web/components/TextareaGenerative.d.ts +3 -1
  314. package/dist/web/components/TextareaGenerative.d.ts.map +1 -1
  315. package/dist/web/components/TextareaGenerative.js +10 -5
  316. package/dist/web/public/PromptDetailPage.d.ts +25 -0
  317. package/dist/web/public/PromptDetailPage.d.ts.map +1 -0
  318. package/dist/web/public/PromptDetailPage.js +71 -0
  319. package/dist/web/public/PromptDetailPageServer.d.ts +15 -0
  320. package/dist/web/public/PromptDetailPageServer.d.ts.map +1 -0
  321. package/dist/web/public/PromptDetailPageServer.js +68 -0
  322. package/dist/web/public/PublicPromptsPage.d.ts +5 -0
  323. package/dist/web/public/PublicPromptsPage.d.ts.map +1 -0
  324. package/dist/web/public/PublicPromptsPage.js +110 -0
  325. package/dist/web/public/PurchaseTokensPage.d.ts +2 -0
  326. package/dist/web/public/PurchaseTokensPage.d.ts.map +1 -0
  327. package/dist/web/public/PurchaseTokensPage.js +98 -0
  328. package/dist/web/public/UserAvatar.d.ts +13 -0
  329. package/dist/web/public/UserAvatar.d.ts.map +1 -0
  330. package/dist/web/public/UserAvatar.js +13 -0
  331. package/dist/web/public/UserDetailPageServer.d.ts +15 -0
  332. package/dist/web/public/UserDetailPageServer.d.ts.map +1 -0
  333. package/dist/web/public/UserDetailPageServer.js +31 -0
  334. package/dist/web/public/UserPromptsPage.d.ts +9 -0
  335. package/dist/web/public/UserPromptsPage.d.ts.map +1 -0
  336. package/dist/web/public/UserPromptsPage.js +112 -0
  337. package/dist/web/public/UserPromptsPageServer.d.ts +15 -0
  338. package/dist/web/public/UserPromptsPageServer.d.ts.map +1 -0
  339. package/dist/web/public/UserPromptsPageServer.js +31 -0
  340. package/package.json +18 -9
  341. package/supabase/migrations/20251125000000_ai_tokens.sql +7 -0
  342. package/supabase/migrations/20260123100002_user_token_quota_monthly copy.sql +173 -0
  343. package/supabase/migrations/20260128100003_update_and_add_table.sql +368 -0
  344. package/supabase/migrations/20260128120000_seed_providers_models.sql +78 -0
  345. package/supabase/migrations/20260128131405_add_api_key_id_to_ledgers.sql +41 -0
  346. package/supabase/migrations/20260128140000_ai_artifacts_storage.sql +99 -0
  347. package/supabase/migrations/20260128140002_ai_user_settings.sql +57 -0
  348. package/supabase/migrations/20260128150000_drop_ai_user_settings.sql +21 -0
  349. package/supabase/migrations/20260128160000_wallet_billing_system.sql +192 -0
  350. package/supabase/migrations/20260128160001_wallet_rpc_functions.sql +165 -0
  351. package/supabase/migrations/20260128170000_add_pack_coef_to_token_packs.sql +30 -0
  352. package/supabase/migrations/20260129120000_wallet_view_rpc.sql +41 -0
  353. package/supabase/migrations/20260129220003_update_pack_margins.sql +31 -0
  354. package/supabase/migrations/20260129330004_ai_user_prompts.sql +151 -0
  355. package/supabase/migrations/20260129330005_ai_prompts_ip_tracking.sql +92 -0
  356. package/supabase/migrations/20260129330006_ai_prompts_slug.sql +64 -0
  357. package/supabase/migrations/20260129330007_ai_prompts_view_slug.sql +26 -0
  358. package/supabase/migrations/20260129440000_ai_prompts_view_username.sql +33 -0
  359. package/supabase/migrations/20260129450000_ai_prompts_add_lang.sql +40 -0
  360. package/supabase/migrations/20260131000000_extract_model_prompt_in_ledger.sql +92 -0
  361. package/supabase/migrations/20260131140000_fix_duplicate_purchases.sql +64 -0
  362. package/supabase/migrations/20260201120000_module-ai_default_models.sql +63 -0
  363. package/supabase/migrations/20260201130000_module-ai_remove_provider_tables.sql +17 -0
  364. package/supabase/migrations-down/20251217120000_user_token_quota_monthly.sql +34 -0
  365. package/supabase/migrations-down/20260128131405_add_api_key_id_to_ledgers.sql +25 -0
@@ -1,6 +1,7 @@
1
1
  import { NextResponse } from "next/server";
2
2
  import { getSupabaseServerClient, getApiBaseUrl } from "@lastbrain/core/server";
3
3
  import { createOneTimeCheckout } from "@lastbrain-labs/module-core-payment-pro/server";
4
+ import { logger } from "@lastbrain/core";
4
5
  /**
5
6
  * POST /api/ai/auth/token-checkout
6
7
  * Create a Stripe checkout session for token purchase
@@ -18,7 +19,11 @@ export async function POST(request) {
18
19
  if (!pack_id) {
19
20
  return NextResponse.json({ error: "Pack ID requis" }, { status: 400 });
20
21
  }
21
- // Get token pack details
22
+ // Extract locale from referer header
23
+ const referer = request.headers.get("referer") || "";
24
+ const localeMatch = referer.match(/\/([a-z]{2})(?:\/|$)/);
25
+ const locale = localeMatch ? localeMatch[1] : "fr";
26
+ // Get token pack details including pack_coef
22
27
  const { data: pack, error: packError } = await supabase
23
28
  .from("token_packs")
24
29
  .select("*")
@@ -28,6 +33,11 @@ export async function POST(request) {
28
33
  if (packError || !pack) {
29
34
  return NextResponse.json({ error: "Pack non trouvé" }, { status: 404 });
30
35
  }
36
+ // Use pack_coef from DB (fallback to 1.35 if not set)
37
+ const packCoef = pack.pack_coef || 1.35;
38
+ const packTokens = pack.tokens;
39
+ const packPriceUsd = pack.price_cents / 100;
40
+ logger.info(`[Token Checkout] Pack ${pack.name}: ${packTokens} tokens @ $${packPriceUsd} (coef: ${packCoef})`);
31
41
  // Build absolute URLs with a fully-qualified base (works on Vercel, custom domains, local)
32
42
  const baseUrl = getApiBaseUrl();
33
43
  const successUrl = `${baseUrl.replace(/\/$/, "")}${"/cart/success"}`;
@@ -41,9 +51,17 @@ export async function POST(request) {
41
51
  user_id: user.id,
42
52
  resourceType: "token_packs",
43
53
  resourceId: pack.id,
44
- successPath: "/cart/success",
45
- cancelPath: "/cart/cancel",
54
+ successPath: `/${locale}/auth/ai/tokens?success=true`,
55
+ cancelPath: `/${locale}/auth/ai/tokens?cancelled=true`,
46
56
  description: `${pack.tokens} tokens IA`,
57
+ email: user.email, // Pass email to link to existing Stripe customer
58
+ // Wallet-specific metadata for billing (passed via base type)
59
+ token_amount: packTokens,
60
+ token_pack_id: pack.id,
61
+ pack_tokens: packTokens.toString(),
62
+ pack_price_usd: packPriceUsd.toString(),
63
+ pack_coef: packCoef.toString(),
64
+ pack_name: pack.name,
47
65
  });
48
66
  return NextResponse.json({
49
67
  checkout_url: checkoutResult.url,
@@ -51,7 +69,7 @@ export async function POST(request) {
51
69
  }, { status: 200 });
52
70
  }
53
71
  catch (error) {
54
- console.error("[Token Checkout] Error:", error);
72
+ logger.error("[Token Checkout] Error:", error);
55
73
  return NextResponse.json({ error: error.message || "Erreur lors du checkout" }, { status: 500 });
56
74
  }
57
75
  }
@@ -1 +1 @@
1
- {"version":3,"file":"token-packs.d.ts","sourceRoot":"","sources":["../../../src/api/auth/token-packs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,YAAY,EAAE,MAAM,aAAa,CAAC;AAGxD;;;GAGG;AACH,wBAAsB,GAAG;;;;IA8BxB"}
1
+ {"version":3,"file":"token-packs.d.ts","sourceRoot":"","sources":["../../../src/api/auth/token-packs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,YAAY,EAAE,MAAM,aAAa,CAAC;AAIxD;;;GAGG;AACH,wBAAsB,GAAG;;;;IA8BxB"}
@@ -1,5 +1,6 @@
1
1
  import { NextResponse } from "next/server";
2
2
  import { getSupabaseServerClient } from "@lastbrain/core/server";
3
+ import { logger } from "@lastbrain/core";
3
4
  /**
4
5
  * GET /api/ai/auth/token-packs
5
6
  * Get active token packs available for purchase
@@ -23,7 +24,7 @@ export async function GET() {
23
24
  return NextResponse.json({ data }, { status: 200 });
24
25
  }
25
26
  catch (error) {
26
- console.error("[Token Packs] GET error:", error);
27
+ logger.error("[Token Packs] GET error:", error);
27
28
  return NextResponse.json({ error: error.message || "Erreur lors de la récupération des packs" }, { status: 500 });
28
29
  }
29
30
  }
@@ -0,0 +1,25 @@
1
+ import { NextRequest, NextResponse } from "next/server";
2
+ /**
3
+ * GET /api/ai/auth/usage-by-model
4
+ * Returns usage statistics grouped by model with costs in USD
5
+ * Supports filtering by month and API key
6
+ */
7
+ export declare function GET(request: NextRequest): Promise<NextResponse<{
8
+ data: {
9
+ avg_cost_per_call: number;
10
+ model: string;
11
+ provider: string;
12
+ endpoint: string;
13
+ total_cost_usd: number;
14
+ total_sell_usd: number;
15
+ call_count: number;
16
+ }[];
17
+ total_entries: number;
18
+ filters: {
19
+ month: string;
20
+ api_key_id: string;
21
+ };
22
+ }> | NextResponse<{
23
+ error: any;
24
+ }>>;
25
+ //# sourceMappingURL=usage-by-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage-by-model.d.ts","sourceRoot":"","sources":["../../../src/api/auth/usage-by-model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIxD;;;;GAIG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;;eAkE/B,MAAM;kBACH,MAAM;kBACN,MAAM;wBACA,MAAM;wBACN,MAAM;oBACV,MAAM;;;;;;;;;IAmDzB"}
@@ -0,0 +1,95 @@
1
+ import { NextResponse } from "next/server";
2
+ import { getSupabaseServerClient } from "@lastbrain/core/server";
3
+ import { logger } from "@lastbrain/core";
4
+ /**
5
+ * GET /api/ai/auth/usage-by-model
6
+ * Returns usage statistics grouped by model with costs in USD
7
+ * Supports filtering by month and API key
8
+ */
9
+ export async function GET(request) {
10
+ try {
11
+ const supabase = await getSupabaseServerClient();
12
+ const { data: { user }, } = await supabase.auth.getUser();
13
+ if (!user) {
14
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
15
+ }
16
+ // Get query params
17
+ const searchParams = request.nextUrl.searchParams;
18
+ const month = searchParams.get("month"); // Format: YYYY-MM
19
+ const apiKeyId = searchParams.get("api_key_id");
20
+ // Build query
21
+ let query = supabase
22
+ .from("user_token_ledger")
23
+ .select("model, provider_cost_usd, sell_usd, meta")
24
+ .eq("owner_id", user.id)
25
+ .eq("type", "use")
26
+ .order("ts", { ascending: false });
27
+ // Filter by month if provided
28
+ if (month && month !== "all") {
29
+ const startDate = `${month}-01`;
30
+ const [year, monthNum] = month.split("-");
31
+ const nextMonth = new Date(parseInt(year), parseInt(monthNum), 1);
32
+ const endDate = nextMonth.toISOString().split("T")[0];
33
+ query = query.gte("ts", startDate).lt("ts", endDate);
34
+ }
35
+ const { data: ledgerEntries, error } = await query;
36
+ if (error) {
37
+ logger.error("[usage-by-model] Error fetching ledger:", error);
38
+ return NextResponse.json({ error: "Failed to fetch usage data" }, { status: 500 });
39
+ }
40
+ // Filter by API key if provided
41
+ // Note: Web interface calls don't have api_key_id in meta, only API calls do
42
+ let filteredEntries = ledgerEntries || [];
43
+ if (apiKeyId && apiKeyId !== "all") {
44
+ if (apiKeyId === "web") {
45
+ // Show only web interface calls (no api_key_id)
46
+ filteredEntries = filteredEntries.filter((entry) => !entry.meta?.api_key_id);
47
+ }
48
+ else {
49
+ // Show only calls from specific API key
50
+ filteredEntries = filteredEntries.filter((entry) => entry.meta?.api_key_id === apiKeyId);
51
+ }
52
+ }
53
+ // Group by model + provider + endpoint
54
+ const groupedData = new Map();
55
+ for (const entry of filteredEntries) {
56
+ const model = entry.model || "unknown";
57
+ const provider = entry.meta?.provider || "unknown";
58
+ const endpoint = entry.meta?.endpoint || "unknown";
59
+ const key = `${model}|${provider}|${endpoint}`;
60
+ if (!groupedData.has(key)) {
61
+ groupedData.set(key, {
62
+ model,
63
+ provider,
64
+ endpoint,
65
+ total_cost_usd: 0,
66
+ total_sell_usd: 0,
67
+ call_count: 0,
68
+ });
69
+ }
70
+ const group = groupedData.get(key);
71
+ group.total_cost_usd += entry.provider_cost_usd || 0;
72
+ group.total_sell_usd += entry.sell_usd || 0;
73
+ group.call_count += 1;
74
+ }
75
+ // Convert to array and calculate averages
76
+ const result = Array.from(groupedData.values())
77
+ .map((item) => ({
78
+ ...item,
79
+ avg_cost_per_call: item.call_count > 0 ? item.total_sell_usd / item.call_count : 0,
80
+ }))
81
+ .sort((a, b) => b.total_sell_usd - a.total_sell_usd); // Sort by cost DESC
82
+ return NextResponse.json({
83
+ data: result,
84
+ total_entries: filteredEntries.length,
85
+ filters: {
86
+ month: month || "all",
87
+ api_key_id: apiKeyId || "all",
88
+ },
89
+ });
90
+ }
91
+ catch (error) {
92
+ logger.error("[usage-by-model] Unexpected error:", error);
93
+ return NextResponse.json({ error: error.message || "Internal server error" }, { status: 500 });
94
+ }
95
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Auth API for usage analytics
3
+ * GET /api/ai/auth/usage - Get user's API usage logs and statistics
4
+ */
5
+ import { NextRequest, NextResponse } from "next/server";
6
+ export declare function GET(request: NextRequest): Promise<NextResponse<{
7
+ data: {
8
+ logs: never[];
9
+ stats: {
10
+ total_calls: number;
11
+ total_tokens: number;
12
+ success_rate: number;
13
+ by_endpoint: Record<string, number>;
14
+ by_provider: Record<string, number>;
15
+ };
16
+ usage_by_model: {
17
+ model: string;
18
+ tokens: number;
19
+ calls: number;
20
+ }[];
21
+ usage_by_day: Record<string, string | number>[];
22
+ };
23
+ }> | NextResponse<{
24
+ error: any;
25
+ }>>;
26
+ //# sourceMappingURL=usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../../src/api/auth/usage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIxD,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;;;;;;;;;;;;;;;;;;IA+J7C"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Auth API for usage analytics
3
+ * GET /api/ai/auth/usage - Get user's API usage logs and statistics
4
+ */
5
+ import { NextResponse } from "next/server";
6
+ import { getSupabaseServerClient } from "@lastbrain/core/server";
7
+ import { logger } from "@lastbrain/core";
8
+ export async function GET(request) {
9
+ try {
10
+ const supabase = await getSupabaseServerClient();
11
+ const { data: { user }, } = await supabase.auth.getUser();
12
+ if (!user) {
13
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
14
+ }
15
+ // Get optional API key filter from query params
16
+ const searchParams = request.nextUrl.searchParams;
17
+ const apiKeyId = searchParams.get("api_key_id");
18
+ const month = searchParams.get("month"); // Format: YYYY-MM
19
+ logger.debug("[Usage API] Fetching usage for user:", user.id, "with apiKeyId:", apiKeyId, "month:", month);
20
+ // Build query for user_token_ledger (new billing system)
21
+ let ledgerQuery = supabase
22
+ .from("user_token_ledger")
23
+ .select("model, sell_usd, provider_cost_usd, ts, meta")
24
+ .eq("owner_id", user.id)
25
+ .eq("type", "use")
26
+ .order("ts", { ascending: false })
27
+ .limit(100);
28
+ // Filter by month if provided
29
+ if (month && month !== "all") {
30
+ const startDate = `${month}-01`;
31
+ const [year, monthNum] = month.split("-");
32
+ const nextMonth = new Date(parseInt(year), parseInt(monthNum), 1);
33
+ const endDate = nextMonth.toISOString().split("T")[0];
34
+ ledgerQuery = ledgerQuery.gte("ts", startDate).lt("ts", endDate);
35
+ }
36
+ // Filter by API key if provided
37
+ // Note: "web" means no api_key_id (web interface calls)
38
+ let ledgerEntries = [];
39
+ const { data: allLedgerEntries, error: ledgerError } = await ledgerQuery;
40
+ if (ledgerError) {
41
+ logger.error("[usage] Error fetching ledger", ledgerError);
42
+ return NextResponse.json({ error: ledgerError.message }, { status: 500 });
43
+ }
44
+ // Filter by API key in meta
45
+ if (apiKeyId && apiKeyId !== "all") {
46
+ if (apiKeyId === "web") {
47
+ ledgerEntries = (allLedgerEntries || []).filter((entry) => !entry.meta?.api_key_id);
48
+ }
49
+ else {
50
+ ledgerEntries = (allLedgerEntries || []).filter((entry) => entry.meta?.api_key_id === apiKeyId);
51
+ }
52
+ }
53
+ else {
54
+ ledgerEntries = allLedgerEntries || [];
55
+ }
56
+ logger.info("[Usage API] Ledger entries fetched:", ledgerEntries.length, "entries");
57
+ // Calculate statistics
58
+ const totalCalls = ledgerEntries.length;
59
+ const totalUsd = ledgerEntries.reduce((sum, entry) => sum + (entry.sell_usd || 0), 0);
60
+ const byEndpoint = {};
61
+ const byProvider = {};
62
+ ledgerEntries.forEach((entry) => {
63
+ const endpoint = entry.meta?.endpoint || "unknown";
64
+ const provider = entry.meta?.provider || "unknown";
65
+ byEndpoint[endpoint] = (byEndpoint[endpoint] || 0) + 1;
66
+ byProvider[provider] = (byProvider[provider] || 0) + 1;
67
+ });
68
+ // Group by model for chart (use sell_usd directly)
69
+ const modelUsage = new Map();
70
+ ledgerEntries.forEach((entry) => {
71
+ if (entry.model && entry.sell_usd) {
72
+ const current = modelUsage.get(entry.model) || { tokens: 0, calls: 0 };
73
+ modelUsage.set(entry.model, {
74
+ tokens: current.tokens + entry.sell_usd, // Store USD value in tokens field for compatibility
75
+ calls: current.calls + 1,
76
+ });
77
+ }
78
+ });
79
+ const usageByModel = Array.from(modelUsage.entries()).map(([model, data]) => ({
80
+ model,
81
+ tokens: data.tokens, // Actually USD value
82
+ calls: data.calls,
83
+ }));
84
+ // Group by day and model for daily chart
85
+ const dailyUsageMap = new Map();
86
+ ledgerEntries.forEach((entry) => {
87
+ if (entry.model && entry.sell_usd && entry.ts) {
88
+ const date = new Date(entry.ts).toISOString().split("T")[0]; // YYYY-MM-DD
89
+ if (!dailyUsageMap.has(date)) {
90
+ dailyUsageMap.set(date, new Map());
91
+ }
92
+ const dayMap = dailyUsageMap.get(date);
93
+ const currentUsd = dayMap.get(entry.model) || 0;
94
+ dayMap.set(entry.model, currentUsd + entry.sell_usd); // Store USD directly
95
+ }
96
+ });
97
+ // Convert to array format for chart
98
+ const usageByDay = Array.from(dailyUsageMap.entries())
99
+ .map(([date, modelMap]) => {
100
+ const dayData = { date };
101
+ modelMap.forEach((usdValue, model) => {
102
+ dayData[model] = usdValue;
103
+ });
104
+ return dayData;
105
+ })
106
+ .sort((a, b) => a.date.localeCompare(b.date));
107
+ const stats = {
108
+ total_calls: totalCalls,
109
+ total_tokens: totalUsd, // Actually USD value for backward compatibility
110
+ success_rate: 100, // All ledger entries are successful
111
+ by_endpoint: byEndpoint,
112
+ by_provider: byProvider,
113
+ };
114
+ return NextResponse.json({
115
+ data: {
116
+ logs: [], // Empty for backward compatibility
117
+ stats,
118
+ usage_by_model: usageByModel,
119
+ usage_by_day: usageByDay,
120
+ },
121
+ });
122
+ }
123
+ catch (error) {
124
+ logger.error("[usage] Unexpected error", error);
125
+ return NextResponse.json({ error: error.message }, { status: 500 });
126
+ }
127
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"user-tokens.d.ts","sourceRoot":"","sources":["../../../src/api/auth/user-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAKxD,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;;;;;;;;;;;;;IA0C7C"}
1
+ {"version":3,"file":"user-tokens.d.ts","sourceRoot":"","sources":["../../../src/api/auth/user-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAMxD,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;;;;;;;;;;;;;IAmF7C"}
@@ -1,6 +1,7 @@
1
1
  import { NextResponse } from "next/server";
2
2
  import { getSupabaseServerClient } from "@lastbrain/core/server";
3
3
  import { getTokenBalance, getTokenHistory, getTokenStats } from "../../server";
4
+ import { logger } from "@lastbrain/core";
4
5
  // GET /api/ai/user/tokens - Récupérer le solde et l'historique de l'utilisateur courant
5
6
  export async function GET(request) {
6
7
  try {
@@ -18,7 +19,40 @@ export async function GET(request) {
18
19
  // Récupérer l'historique complet (12 derniers mois)
19
20
  const searchParams = request.nextUrl.searchParams;
20
21
  const limit = parseInt(searchParams.get("limit") || "500");
21
- const history = await getTokenHistory(userId, limit, 0);
22
+ const apiKeyId = searchParams.get("api_key_id");
23
+ let history = await getTokenHistory(userId, limit, 0);
24
+ // Filtrer par api_key_id si fourni
25
+ // Si une clé spécifique est sélectionnée, récupérer les logs depuis ai_call_log
26
+ if (apiKeyId && apiKeyId !== "all") {
27
+ logger.debug(`[user-tokens] Fetching logs for api_key_id: ${apiKeyId}`);
28
+ // Récupérer les logs d'utilisation depuis ai_call_log
29
+ const { data: logs, error: logsError } = await supabase
30
+ .from("ai_call_log")
31
+ .select("*")
32
+ .eq("owner_id", userId)
33
+ .eq("api_key_id", apiKeyId)
34
+ .order("created_at", { ascending: false })
35
+ .limit(limit);
36
+ if (logsError) {
37
+ logger.error("[user-tokens] Error fetching logs:", logsError);
38
+ }
39
+ // Convertir les logs en format transaction
40
+ history = (logs || []).map((log) => ({
41
+ id: log.id,
42
+ owner_id: userId,
43
+ amount: -(log.tokens_total || 0), // Négatif car c'est une consommation
44
+ type: "use",
45
+ source: log.quota_used ? "quota" : "purchased",
46
+ description: log.endpoint || log.model,
47
+ model: log.model,
48
+ prompt: log.request_body?.prompt || log.request_body?.messages?.[0]?.content,
49
+ created_at: log.created_at,
50
+ ts: log.created_at,
51
+ running_balance: 0, // Non calculé pour les transactions filtrées
52
+ api_key_id: log.api_key_id,
53
+ }));
54
+ logger.debug(`[user-tokens] Converted ${history.length} logs to transactions`);
55
+ }
22
56
  return NextResponse.json({
23
57
  userId,
24
58
  balance,
@@ -28,7 +62,7 @@ export async function GET(request) {
28
62
  });
29
63
  }
30
64
  catch (error) {
31
- console.error("[GET /api/ai/user/tokens] Error:", error);
65
+ logger.error("[GET /api/ai/user/tokens] Error:", error);
32
66
  return NextResponse.json({ error: error.message || "Erreur serveur" }, { status: 500 });
33
67
  }
34
68
  }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * GET /api/ai/auth/wallet
3
+ * Returns user's wallet state (balance + USD values)
4
+ */
5
+ import { NextRequest, NextResponse } from "next/server";
6
+ export declare function GET(request: NextRequest): Promise<NextResponse<{
7
+ tokenBalance: number;
8
+ walletProviderBudgetUsd: number;
9
+ walletSellValueUsd: number;
10
+ percentRemaining: number;
11
+ status: "warning" | "ok" | "critical";
12
+ usdProviderPerToken: number;
13
+ usdSellPerToken: number;
14
+ }> | NextResponse<{
15
+ error: any;
16
+ }>>;
17
+ //# sourceMappingURL=route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/api/auth/wallet/route.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAKxD,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;;;;;;;;;IA4E7C"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * GET /api/ai/auth/wallet
3
+ * Returns user's wallet state (balance + USD values)
4
+ */
5
+ import { NextResponse } from "next/server";
6
+ import { logger } from "@lastbrain/core";
7
+ import { getSupabaseServerClient } from "@lastbrain/core/server";
8
+ import { getWalletState } from "../../../server/billing";
9
+ export async function GET(request) {
10
+ try {
11
+ const supabase = await getSupabaseServerClient();
12
+ const { data: { user }, error: authError, } = await supabase.auth.getUser();
13
+ if (authError || !user) {
14
+ return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
15
+ }
16
+ // Get wallet state
17
+ const wallet = await getWalletState(user.id);
18
+ // Calculate total purchased (from ledger - type 'purchase')
19
+ const { data: purchases, error: purchaseError } = await supabase
20
+ .from("user_token_ledger")
21
+ .select("sell_value_added_usd, pack_price_usd")
22
+ .eq("owner_id", user.id)
23
+ .eq("type", "purchase");
24
+ logger.info("[Wallet API] Purchase query:", {
25
+ userId: user.id,
26
+ purchases,
27
+ error: purchaseError,
28
+ });
29
+ // Sum all purchases (use sell_value_added_usd or pack_price_usd as fallback)
30
+ const totalPurchased = (purchases || []).reduce((sum, p) => {
31
+ const amount = parseFloat(p.sell_value_added_usd || "0") ||
32
+ parseFloat(p.pack_price_usd || "0");
33
+ return sum + amount;
34
+ }, 0);
35
+ logger.info("[Wallet API] Total purchased:", totalPurchased);
36
+ logger.info("[Wallet API] Current balance:", wallet.walletSellValueUsd);
37
+ // Calculate percent remaining
38
+ const percentRemaining = totalPurchased > 0
39
+ ? (wallet.walletSellValueUsd / totalPurchased) * 100
40
+ : 100;
41
+ // Determine status
42
+ let status = "ok";
43
+ if (percentRemaining < 10) {
44
+ status = "critical";
45
+ }
46
+ else if (percentRemaining < 25) {
47
+ status = "warning";
48
+ }
49
+ return NextResponse.json({
50
+ tokenBalance: wallet.tokenBalance,
51
+ walletProviderBudgetUsd: wallet.walletProviderBudgetUsd,
52
+ walletSellValueUsd: wallet.walletSellValueUsd,
53
+ percentRemaining,
54
+ status,
55
+ // Computed rates
56
+ usdProviderPerToken: wallet.tokenBalance > 0
57
+ ? wallet.walletProviderBudgetUsd / wallet.tokenBalance
58
+ : 0,
59
+ usdSellPerToken: wallet.tokenBalance > 0
60
+ ? wallet.walletSellValueUsd / wallet.tokenBalance
61
+ : 0,
62
+ });
63
+ }
64
+ catch (error) {
65
+ logger.error("[auth/wallet] Error:", error);
66
+ return NextResponse.json({ error: error.message || "Internal server error" }, { status: 500 });
67
+ }
68
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * GET /api/ai/auth/wallet
3
+ * Get user's wallet state for UI display
4
+ */
5
+ import { NextResponse } from "next/server";
6
+ export declare function GET(): Promise<NextResponse<{
7
+ walletSellValueUsd: number;
8
+ totalAdded: number;
9
+ totalUsed: number;
10
+ percentage: number;
11
+ tokenBalance: number;
12
+ status: string;
13
+ }> | NextResponse<{
14
+ error: any;
15
+ }>>;
16
+ //# sourceMappingURL=wallet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../../../src/api/auth/wallet.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,wBAAsB,GAAG;;;;;;;;;IAiFxB"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * GET /api/ai/auth/wallet
3
+ * Get user's wallet state for UI display
4
+ */
5
+ import { NextResponse } from "next/server";
6
+ import { getSupabaseServerClient } from "@lastbrain/core/server";
7
+ import { getWalletState } from "../../server/billing";
8
+ import { logger } from "@lastbrain/core";
9
+ export async function GET() {
10
+ try {
11
+ const supabase = await getSupabaseServerClient();
12
+ const { data: { user }, } = await supabase.auth.getUser();
13
+ if (!user) {
14
+ return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
15
+ }
16
+ const wallet = await getWalletState(user.id);
17
+ // Get all credit additions (purchases + manual adds) to calculate total initial balance
18
+ const { data: additions, error: additionsError } = await supabase
19
+ .from("user_token_ledger")
20
+ .select("sell_value_added_usd, pack_price_usd, type, created_at")
21
+ .eq("owner_id", user.id)
22
+ .in("type", ["purchase", "gift"]); // Include both purchases and gifts from admin
23
+ logger.info("[Wallet API] Credit additions query:", {
24
+ userId: user.id,
25
+ additions,
26
+ error: additionsError,
27
+ });
28
+ // Calculate total credits added (sum of sell_value_added_usd OR pack_price_usd as fallback)
29
+ const totalAdded = (additions || []).reduce((sum, p) => {
30
+ const amount = parseFloat(p.sell_value_added_usd || "0") ||
31
+ parseFloat(p.pack_price_usd || "0");
32
+ return sum + amount;
33
+ }, 0);
34
+ logger.info("[Wallet API] Total credits added:", totalAdded);
35
+ logger.info("[Wallet API] Current balance:", wallet.walletSellValueUsd);
36
+ // Calculate percent remaining: current / initial * 100
37
+ const percentRemaining = totalAdded > 0 ? (wallet.walletSellValueUsd / totalAdded) * 100 : 100; // If no credits added, show 100%
38
+ logger.info("[Wallet API] Percent calculation:", {
39
+ totalAdded,
40
+ currentBalance: wallet.walletSellValueUsd,
41
+ percentRemaining,
42
+ formula: `${wallet.walletSellValueUsd} / ${totalAdded} * 100 = ${percentRemaining}`,
43
+ });
44
+ // Get total spent from ledger (for UI display)
45
+ const { data: usageEntries } = await supabase
46
+ .from("user_token_ledger")
47
+ .select("cost_usd")
48
+ .eq("owner_id", user.id)
49
+ .eq("type", "use");
50
+ const totalUsed = (usageEntries || []).reduce((sum, entry) => {
51
+ return sum + (parseFloat(entry.cost_usd || "0") || 0);
52
+ }, 0);
53
+ return NextResponse.json({
54
+ walletSellValueUsd: wallet.walletSellValueUsd,
55
+ totalAdded,
56
+ totalUsed,
57
+ percentage: percentRemaining,
58
+ tokenBalance: wallet.tokenBalance, // For backward compat
59
+ status: percentRemaining > 50
60
+ ? "ok"
61
+ : percentRemaining > 25
62
+ ? "warning"
63
+ : "critical",
64
+ // walletProviderBudgetUsd is NOT included - internal use only
65
+ });
66
+ }
67
+ catch (error) {
68
+ logger.error("[Wallet API] Error:", error);
69
+ return NextResponse.json({ error: error.message || "Failed to fetch wallet" }, { status: 500 });
70
+ }
71
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * GET /api/ai/public/gateway-models
3
+ * Public route to list available AI models from Vercel AI Gateway
4
+ * No authentication required
5
+ */
6
+ import { NextRequest, NextResponse } from "next/server";
7
+ export declare function GET(request: NextRequest): Promise<NextResponse<{
8
+ providers: {
9
+ models: {
10
+ id: string;
11
+ name: string;
12
+ type: "audio" | "video" | "image" | "text" | "embedding" | "language";
13
+ provider: string;
14
+ max_tokens: number | undefined;
15
+ tags: string[] | undefined;
16
+ }[];
17
+ name: string;
18
+ display_name: string;
19
+ }[];
20
+ stale: boolean | undefined;
21
+ cached_at: string | undefined;
22
+ }> | NextResponse<{
23
+ error: any;
24
+ }>>;
25
+ //# sourceMappingURL=gateway-models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-models.d.ts","sourceRoot":"","sources":["../../../src/api/public/gateway-models.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIxD,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;;;;;;;;;;;;;;;;IA+C7C"}