@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
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Wallet Repair Utilities
3
+ * For fixing wallets that were not initialized correctly (legacy credits, manual edits, etc.)
4
+ */
5
+ import { logger } from "@lastbrain/core";
6
+ import { getSupabaseServiceClient } from "@lastbrain/core/server";
7
+ /**
8
+ * Recalculate wallet budget from ledger history
9
+ * Useful for users who have tokens but wallet = 0 USD
10
+ */
11
+ export async function repairUserWallet(userId, tokenBalance) {
12
+ const supabase = await getSupabaseServiceClient();
13
+ try {
14
+ // 1. Get current state
15
+ const { data: currentWallet, error: walletError } = await supabase
16
+ .from("user_token_wallet")
17
+ .select("wallet_provider_budget_usd, wallet_sell_value_usd")
18
+ .eq("user_id", userId)
19
+ .single();
20
+ if (walletError) {
21
+ throw new Error(`Wallet not found: ${walletError.message}`);
22
+ }
23
+ // Get token balance (either from parameter or query)
24
+ let currentTokenBalance = tokenBalance ?? 0;
25
+ if (tokenBalance === undefined) {
26
+ const { data: balance, error: balanceError } = await supabase.rpc("get_user_token_balance", { p_owner_id: userId });
27
+ if (balanceError || !balance || balance.length === 0) {
28
+ throw new Error("No token balance found");
29
+ }
30
+ currentTokenBalance = balance[0].balance || 0;
31
+ }
32
+ logger.info(`[repairWallet] User ${userId} - Current: ${currentTokenBalance} tokens, wallet: ${currentWallet.wallet_provider_budget_usd} provider USD, ${currentWallet.wallet_sell_value_usd} sell USD`);
33
+ // 2. Fetch all ledger entries
34
+ const { data: ledger, error: ledgerError } = await supabase
35
+ .from("user_token_ledger")
36
+ .select("type, amount, pack_price_usd, pack_coef, provider_cost_usd, sell_usd")
37
+ .eq("owner_id", userId)
38
+ .order("ts", { ascending: true });
39
+ if (ledgerError) {
40
+ throw new Error(`Ledger query failed: ${ledgerError.message}`);
41
+ }
42
+ if (!ledger || ledger.length === 0) {
43
+ logger.warn("[repairWallet] No ledger entries, nothing to repair");
44
+ return {
45
+ success: true,
46
+ before: {
47
+ balance: currentTokenBalance,
48
+ providerBudget: currentWallet.wallet_provider_budget_usd,
49
+ sellValue: currentWallet.wallet_sell_value_usd,
50
+ },
51
+ after: {
52
+ balance: currentTokenBalance,
53
+ providerBudget: currentWallet.wallet_provider_budget_usd,
54
+ sellValue: currentWallet.wallet_sell_value_usd,
55
+ },
56
+ };
57
+ }
58
+ // 3. Recalculate wallet from scratch
59
+ let totalProviderBudget = 0;
60
+ let totalSellValue = 0;
61
+ for (const entry of ledger) {
62
+ if (entry.type === "purchase") {
63
+ // Add purchase budget
64
+ let packPriceUsd = entry.pack_price_usd || 0;
65
+ const packCoef = entry.pack_coef || 1.35;
66
+ // FALLBACK: If pack_price_usd is missing (legacy/manual credits)
67
+ // Estimate based on typical pack pricing: ~$0.00005 per token
68
+ if (packPriceUsd === 0 && entry.amount > 0) {
69
+ const tokensAdded = entry.amount;
70
+ // Estimate pack price based on token tier pricing
71
+ if (tokensAdded >= 1_000_000) {
72
+ // Large pack: 1.20 coef → $0.00006/token
73
+ packPriceUsd = tokensAdded * 0.00006;
74
+ }
75
+ else if (tokensAdded >= 50_000) {
76
+ // Medium pack: 1.35 coef → $0.00005/token
77
+ packPriceUsd = tokensAdded * 0.00005;
78
+ }
79
+ else {
80
+ // Small pack: 1.50 coef → $0.000075/token
81
+ packPriceUsd = tokensAdded * 0.000075;
82
+ }
83
+ logger.info(`[repairWallet] Estimated pack price for ${tokensAdded} tokens: $${packPriceUsd.toFixed(2)} (legacy credit)`);
84
+ }
85
+ const providerBudget = packPriceUsd / packCoef;
86
+ const sellValue = packPriceUsd;
87
+ totalProviderBudget += providerBudget;
88
+ totalSellValue += sellValue;
89
+ }
90
+ else if (entry.type === "use") {
91
+ // Subtract consumption
92
+ const providerCost = entry.provider_cost_usd || 0;
93
+ const sellUsd = entry.sell_usd || 0;
94
+ totalProviderBudget -= providerCost;
95
+ totalSellValue -= sellUsd;
96
+ }
97
+ }
98
+ // Round to 6 decimals
99
+ totalProviderBudget =
100
+ Math.round(totalProviderBudget * 1_000_000) / 1_000_000;
101
+ totalSellValue = Math.round(totalSellValue * 1_000_000) / 1_000_000;
102
+ // Safety: negative values should be 0
103
+ if (totalProviderBudget < 0)
104
+ totalProviderBudget = 0;
105
+ if (totalSellValue < 0)
106
+ totalSellValue = 0;
107
+ logger.info(`[repairWallet] Recalculated: provider budget = ${totalProviderBudget}, sell value = ${totalSellValue}`);
108
+ // 4. Update wallet
109
+ const { error: updateError } = await supabase
110
+ .from("user_token_wallet")
111
+ .update({
112
+ wallet_provider_budget_usd: totalProviderBudget,
113
+ wallet_sell_value_usd: totalSellValue,
114
+ })
115
+ .eq("user_id", userId);
116
+ if (updateError) {
117
+ throw new Error(`Wallet update failed: ${updateError.message}`);
118
+ }
119
+ logger.info(`[repairWallet] ✅ Wallet repaired for user ${userId}: ${totalProviderBudget} provider USD, ${totalSellValue} sell USD`);
120
+ return {
121
+ success: true,
122
+ before: {
123
+ balance: currentTokenBalance,
124
+ providerBudget: currentWallet.wallet_provider_budget_usd,
125
+ sellValue: currentWallet.wallet_sell_value_usd,
126
+ },
127
+ after: {
128
+ balance: currentTokenBalance,
129
+ providerBudget: totalProviderBudget,
130
+ sellValue: totalSellValue,
131
+ },
132
+ };
133
+ }
134
+ catch (error) {
135
+ logger.error("[repairWallet] Error:", error);
136
+ return {
137
+ success: false,
138
+ error: error.message || "Wallet repair failed",
139
+ };
140
+ }
141
+ }
142
+ /**
143
+ * Repair all wallets in the system
144
+ */
145
+ export async function repairAllWallets() {
146
+ const supabase = await getSupabaseServiceClient();
147
+ try {
148
+ // Get all wallets with tokens but 0 budget
149
+ // Query the view directly instead of using RPC
150
+ const { data: wallets, error } = await supabase
151
+ .from("user_token_balance_with_wallet")
152
+ .select("*");
153
+ if (error) {
154
+ throw new Error(`Query failed: ${error.message}`);
155
+ }
156
+ const walletsToRepair = (wallets || []).filter((w) => w.token_balance > 0 &&
157
+ (w.wallet_provider_budget_usd === 0 || w.wallet_sell_value_usd === 0));
158
+ logger.info(`[repairAllWallets] Found ${walletsToRepair.length} wallets to repair`);
159
+ let repaired = 0;
160
+ let failed = 0;
161
+ const errors = [];
162
+ for (const wallet of walletsToRepair) {
163
+ const result = await repairUserWallet(wallet.user_id, wallet.token_balance);
164
+ if (result.success) {
165
+ repaired++;
166
+ }
167
+ else {
168
+ failed++;
169
+ errors.push(`${wallet.user_id}: ${result.error}`);
170
+ }
171
+ }
172
+ logger.info(`[repairAllWallets] ✅ Repaired ${repaired} wallets, ${failed} failed`);
173
+ return {
174
+ success: true,
175
+ repaired,
176
+ failed,
177
+ errors,
178
+ };
179
+ }
180
+ catch (error) {
181
+ logger.error("[repairAllWallets] Error:", error);
182
+ return {
183
+ success: false,
184
+ repaired: 0,
185
+ failed: 0,
186
+ errors: [error.message],
187
+ };
188
+ }
189
+ }
package/dist/server.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ export { generateMetadata as generatePromptDetailMetadata } from "./web/public/PromptDetailPageServer";
2
+ export { textAI, imageAI, embedAI } from "./server/ai-client";
1
3
  /**
2
4
  * Interface pour le résultat d'opération sur les tokens
3
5
  */
@@ -15,6 +17,7 @@ export interface TokenLedgerEntry {
15
17
  ts: string;
16
18
  type: "purchase" | "gift" | "use" | "adjust";
17
19
  amount: number;
20
+ source?: "purchased" | "quota";
18
21
  model?: string;
19
22
  prompt?: string;
20
23
  meta?: Record<string, any>;
@@ -38,7 +41,7 @@ export declare function getTokenBalance(userId: string): Promise<number>;
38
41
  */
39
42
  export declare function checkTokenBalance(userId: string, amount: number): Promise<boolean>;
40
43
  /**
41
- * Récupère l'historique des tokens d'un utilisateur
44
+ * Récupère l'historique des tokens d'un utilisateur (acheté + quota)
42
45
  */
43
46
  export declare function getTokenHistory(userId: string, limit?: number, offset?: number): Promise<TokenLedgerEntry[]>;
44
47
  /**
@@ -58,4 +61,13 @@ export declare function getAllUsersTokenBalance(limit?: number, offset?: number)
58
61
  owner_id: any;
59
62
  balance: any;
60
63
  }[]>;
64
+ export { getUserQuotaStatus, debitTokensWithPriority, updateUserQuota, updateCustomQuota, getQuotaUsageHistory, handleSubscriptionQuotaUpdate, refundTokens, } from "./server/quota";
65
+ export { computeAndDebitAIUsage, computeProviderCostUsd, getWalletState, type ActionType, type ComputeAndDebitParams, type ComputeAndDebitResult, type ProviderPricing, type Usage, type WalletState, } from "./server/billing";
66
+ export { validateTextPricing, validateImagePricing, validateEstimatedCost, type PricingValidationResult, } from "./server/pricing-validator";
67
+ export { generateTextWithBilling, generateImageWithBilling, type TextGenerationParams, type ImageGenerationParams, type GenerationResult, } from "./server/ai-generation-service";
68
+ export { processOCRWithTokens } from "./server/ocr";
69
+ export type { ProcessOCRParams, ProcessOCRResponse, OCRResult, } from "./server/ocr";
70
+ export { default as PromptDetailPageServer, generateMetadata, } from "./web/public/PromptDetailPageServer";
71
+ export { default as UserPromptsPageServer, generateMetadata as generateUserPromptsMetadata, } from "./web/public/UserPromptsPageServer";
72
+ export { default as UserDetailPageServer, generateMetadata as generateUserDetailMetadata, } from "./web/public/UserDetailPageServer";
61
73
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,UAAU,GAAG,MAAM,GAAG,QAAiB,EAC7C,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EAC9B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,oBAAoB,CAAC,CA+B/B;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EACf,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAoD/B;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBrE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC,CAGlB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAW,EAClB,MAAM,GAAE,MAAU,GACjB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAiB7B;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM;;;;;;GA4CjD;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,GAAE,MAAW,EAClB,MAAM,GAAE,MAAU;;;KAiBnB"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/dist/server.js CHANGED
@@ -1,14 +1,19 @@
1
1
  // Server-only exports (Route Handlers, Server Actions, etc.)
2
+ import { logger } from "@lastbrain/core";
2
3
  import { getSupabaseServerClient } from "@lastbrain/core/server";
4
+ // Server Components
5
+ export { generateMetadata as generatePromptDetailMetadata } from "./web/public/PromptDetailPageServer";
6
+ // AI SDK client utilities
7
+ export { textAI, imageAI, embedAI } from "./server/ai-client";
3
8
  /**
4
9
  * Ajoute des tokens au compte d'un utilisateur
5
10
  */
6
11
  export async function addTokens(userId, amount, type = "gift", meta = {}, createdBy) {
7
- if (amount <= 0) {
12
+ if (amount === 0) {
8
13
  return {
9
14
  success: false,
10
15
  balance: 0,
11
- error: "Le montant doit être positif",
16
+ error: "Le montant ne peut pas être zéro",
12
17
  };
13
18
  }
14
19
  const supabase = await getSupabaseServerClient();
@@ -26,7 +31,7 @@ export async function addTokens(userId, amount, type = "gift", meta = {}, create
26
31
  return { success: true, balance };
27
32
  }
28
33
  catch (error) {
29
- console.error("[addTokens] Error:", error);
34
+ logger.error("[addTokens] Error:", error);
30
35
  return {
31
36
  success: false,
32
37
  balance: 0,
@@ -78,7 +83,7 @@ export async function deductTokens(userId, amount, model, prompt, meta = {}) {
78
83
  return { success: true, balance };
79
84
  }
80
85
  catch (error) {
81
- console.error("[deductTokens] Error:", error);
86
+ logger.error("[deductTokens] Error:", error);
82
87
  return {
83
88
  success: false,
84
89
  balance: 0,
@@ -105,7 +110,7 @@ export async function getTokenBalance(userId) {
105
110
  return data?.balance || 0;
106
111
  }
107
112
  catch (error) {
108
- console.error("[getTokenBalance] Error:", error);
113
+ logger.error("[getTokenBalance] Error:", error);
109
114
  return 0;
110
115
  }
111
116
  }
@@ -117,23 +122,75 @@ export async function checkTokenBalance(userId, amount) {
117
122
  return balance >= amount;
118
123
  }
119
124
  /**
120
- * Récupère l'historique des tokens d'un utilisateur
125
+ * Récupère l'historique des tokens d'un utilisateur (acheté + quota)
121
126
  */
122
127
  export async function getTokenHistory(userId, limit = 50, offset = 0) {
123
128
  const supabase = await getSupabaseServerClient();
124
129
  try {
125
- const { data, error } = await supabase
130
+ // Récupérer les transactions achetées
131
+ const { data: purchasedData, error: purchasedError } = await supabase
126
132
  .from("user_token_ledger")
127
- .select("amount,created_at,created_by,id,model,owner_id,prompt,ts,type")
133
+ .select("amount,created_at,created_by,id,model,owner_id,prompt,ts,type,meta")
128
134
  .eq("owner_id", userId)
129
- .order("ts", { ascending: false })
130
- .range(offset, offset + limit - 1);
131
- if (error)
132
- throw error;
133
- return data || [];
135
+ .order("ts", { ascending: false });
136
+ if (purchasedError)
137
+ throw purchasedError;
138
+ // Récupérer les transactions de quota
139
+ const { data: quotaData, error: quotaError } = await supabase
140
+ .from("user_token_quota_ledger")
141
+ .select("id,owner_id,tokens_used,created_at,prompt,model,meta")
142
+ .eq("owner_id", userId)
143
+ .order("created_at", { ascending: false });
144
+ if (quotaError)
145
+ throw quotaError;
146
+ // Fusionner et trier
147
+ const combined = [];
148
+ // Ajouter les transactions achetées avec le champ source
149
+ if (purchasedData) {
150
+ purchasedData.forEach((t) => {
151
+ combined.push({
152
+ id: t.id,
153
+ amount: t.amount,
154
+ type: t.type,
155
+ source: "purchased",
156
+ created_at: t.created_at,
157
+ created_by: t.created_by,
158
+ model: t.model,
159
+ owner_id: t.owner_id,
160
+ prompt: t.prompt,
161
+ ts: t.ts,
162
+ meta: t.meta, // Inclure les métadonnées (sell_usd, provider_cost_usd, margin_usd)
163
+ });
164
+ });
165
+ }
166
+ // Ajouter les transactions quota avec le champ source
167
+ if (quotaData) {
168
+ quotaData.forEach((t) => {
169
+ combined.push({
170
+ id: t.id,
171
+ amount: -t.tokens_used, // Convertir en négatif pour montrer la soustraction
172
+ type: "use",
173
+ source: "quota",
174
+ created_at: t.created_at,
175
+ owner_id: userId,
176
+ model: t.model,
177
+ prompt: t.prompt,
178
+ ts: t.created_at,
179
+ meta: t.meta, // Inclure les métadonnées si disponibles
180
+ });
181
+ });
182
+ }
183
+ // Trier par date décroissante
184
+ combined.sort((a, b) => {
185
+ const dateA = new Date(a.created_at).getTime();
186
+ const dateB = new Date(b.created_at).getTime();
187
+ return dateB - dateA;
188
+ });
189
+ // Appliquer pagination sur le tableau fusionné
190
+ return combined.slice(offset, offset + limit);
134
191
  }
135
192
  catch (error) {
136
- console.error("[getTokenHistory] Error:", error);
193
+ logger.error("[getTokenHistory] Error:", error);
137
194
  return [];
138
195
  }
139
196
  }
@@ -174,7 +231,7 @@ export async function getTokenStats(userId) {
174
231
  return stats;
175
232
  }
176
233
  catch (error) {
177
- console.error("[getTokenStats] Error:", error);
234
+ logger.error("[getTokenStats] Error:", error);
178
235
  return {
179
236
  balance: 0,
180
237
  totalPurchased: 0,
@@ -200,7 +257,21 @@ export async function getAllUsersTokenBalance(limit = 50, offset = 0) {
200
257
  return data || [];
201
258
  }
202
259
  catch (error) {
203
- console.error("[getAllUsersTokenBalance] Error:", error);
260
+ logger.error("[getAllUsersTokenBalance] Error:", error);
204
261
  return [];
205
262
  }
206
263
  }
264
+ // Export quota management functions for use by other modules (e.g., billing-pro)
265
+ export { getUserQuotaStatus, debitTokensWithPriority, updateUserQuota, updateCustomQuota, getQuotaUsageHistory, handleSubscriptionQuotaUpdate, refundTokens, } from "./server/quota";
266
+ // Export centralized billing functions (NEW SYSTEM)
267
+ export { computeAndDebitAIUsage, computeProviderCostUsd, getWalletState, } from "./server/billing";
268
+ // Export pricing validation (SECURITY)
269
+ export { validateTextPricing, validateImagePricing, validateEstimatedCost, } from "./server/pricing-validator";
270
+ // Export centralized AI generation service (SINGLE SOURCE OF TRUTH)
271
+ export { generateTextWithBilling, generateImageWithBilling, } from "./server/ai-generation-service";
272
+ // Export OCR processing with token management
273
+ export { processOCRWithTokens } from "./server/ocr";
274
+ // Export Server Components for public pages
275
+ export { default as PromptDetailPageServer, generateMetadata, } from "./web/public/PromptDetailPageServer";
276
+ export { default as UserPromptsPageServer, generateMetadata as generateUserPromptsMetadata, } from "./web/public/UserPromptsPageServer";
277
+ export { default as UserDetailPageServer, generateMetadata as generateUserDetailMetadata, } from "./web/public/UserDetailPageServer";
@@ -0,0 +1,6 @@
1
+ export declare function GET(_request: Request, context: {
2
+ params: Promise<{
3
+ lang: string;
4
+ }>;
5
+ }): Promise<Response>;
6
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/sitemap/handlers/prompts.ts"],"names":[],"mappings":"AAYA,wBAAsB,GAAG,CACvB,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAC7C,OAAO,CAAC,QAAQ,CAAC,CAyEnB"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Handler pour les prompts publics
3
+ */
4
+ import { getSupabaseServiceClient } from "@lastbrain/core/server";
5
+ import { LOCALE_MAP } from "@lastbrain/core";
6
+ export async function GET(_request, context) {
7
+ const params = await context.params;
8
+ const { lang } = params;
9
+ if (!LOCALE_MAP[lang]) {
10
+ return new Response("Invalid language", { status: 404 });
11
+ }
12
+ const baseUrl = process.env.NEXT_PUBLIC_SITE_URL ||
13
+ (process.env.VERCEL_URL
14
+ ? `https://${process.env.VERCEL_URL}`
15
+ : "https://example.com");
16
+ try {
17
+ const supabase = getSupabaseServiceClient();
18
+ const { data: prompts, error } = await supabase
19
+ .from("public_prompts_with_stats")
20
+ .select("slug, created_at, views")
21
+ .order("views", { ascending: false })
22
+ .eq("lang", lang)
23
+ .limit(1000);
24
+ if (error) {
25
+ return new Response(JSON.stringify({ error: error.message }), {
26
+ status: 500,
27
+ headers: { "Content-Type": "application/json" },
28
+ });
29
+ }
30
+ const items = (prompts || []);
31
+ const urls = items.map((prompt) => {
32
+ // Priority basée sur les vues
33
+ let priority = 0.5;
34
+ if (prompt.views > 100)
35
+ priority = 0.9;
36
+ else if (prompt.views > 50)
37
+ priority = 0.8;
38
+ else if (prompt.views > 10)
39
+ priority = 0.7;
40
+ else if (prompt.views > 0)
41
+ priority = 0.6;
42
+ return {
43
+ url: `${baseUrl}/${lang}/prompts/${prompt.slug}`,
44
+ lastmod: prompt.created_at || new Date().toISOString(),
45
+ changefreq: "weekly",
46
+ priority,
47
+ };
48
+ });
49
+ const urlEntries = urls
50
+ .map((e) => ` <url>
51
+ <loc>${e.url}</loc>
52
+ <lastmod>${e.lastmod}</lastmod>
53
+ <changefreq>${e.changefreq}</changefreq>
54
+ <priority>${e.priority}</priority>
55
+ </url>`)
56
+ .join("\n");
57
+ const xml = `<?xml version="1.0" encoding="UTF-8"?>
58
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
59
+ ${urlEntries}
60
+ </urlset>`;
61
+ return new Response(xml, {
62
+ headers: {
63
+ "Content-Type": "application/xml",
64
+ "Cache-Control": "public, max-age=3600",
65
+ },
66
+ });
67
+ }
68
+ catch (err) {
69
+ console.error("Sitemap prompts error:", err);
70
+ return new Response("Internal error", { status: 500 });
71
+ }
72
+ }
@@ -0,0 +1,6 @@
1
+ export declare function GET(_request: Request, context: {
2
+ params: Promise<{
3
+ lang: string;
4
+ }>;
5
+ }): Promise<Response>;
6
+ //# sourceMappingURL=users.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../../src/sitemap/handlers/users.ts"],"names":[],"mappings":"AAWA,wBAAsB,GAAG,CACvB,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAC7C,OAAO,CAAC,QAAQ,CAAC,CA0FnB"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Handler pour les profils utilisateurs avec prompts publics
3
+ */
4
+ import { getSupabaseServiceClient } from "@lastbrain/core/server";
5
+ import { LOCALE_MAP } from "@lastbrain/core";
6
+ export async function GET(_request, context) {
7
+ const params = await context.params;
8
+ const { lang } = params;
9
+ if (!LOCALE_MAP[lang]) {
10
+ return new Response("Invalid language", { status: 404 });
11
+ }
12
+ const baseUrl = process.env.NEXT_PUBLIC_SITE_URL ||
13
+ (process.env.VERCEL_URL
14
+ ? `https://${process.env.VERCEL_URL}`
15
+ : "https://example.com");
16
+ try {
17
+ const supabase = getSupabaseServiceClient();
18
+ // Récupérer les utilisateurs ayant au moins un prompt public via la vue
19
+ const { data, error } = await supabase
20
+ .from("public_prompts_with_stats")
21
+ .select("username")
22
+ .not("username", "is", null);
23
+ if (error) {
24
+ return new Response(JSON.stringify({ error: error.message }), {
25
+ status: 500,
26
+ headers: { "Content-Type": "application/json" },
27
+ });
28
+ }
29
+ // Compter les prompts par utilisateur
30
+ const userPromptCounts = new Map();
31
+ (data || []).forEach((item) => {
32
+ const username = item.username;
33
+ if (username) {
34
+ userPromptCounts.set(username, (userPromptCounts.get(username) || 0) + 1);
35
+ }
36
+ });
37
+ const users = Array.from(userPromptCounts.entries()).map(([username, count]) => ({
38
+ username,
39
+ prompt_count: count,
40
+ }));
41
+ const urls = users.map((user) => {
42
+ // Priority basée sur le nombre de prompts
43
+ let priority = 0.5;
44
+ if (user.prompt_count > 20)
45
+ priority = 0.8;
46
+ else if (user.prompt_count > 10)
47
+ priority = 0.7;
48
+ else if (user.prompt_count > 5)
49
+ priority = 0.6;
50
+ return {
51
+ url: `${baseUrl}/${lang}/user/${user.username}`,
52
+ lastmod: new Date().toISOString(),
53
+ changefreq: "weekly",
54
+ priority,
55
+ };
56
+ });
57
+ const urlEntries = urls
58
+ .map((e) => ` <url>
59
+ <loc>${e.url}</loc>
60
+ <lastmod>${e.lastmod}</lastmod>
61
+ <changefreq>${e.changefreq}</changefreq>
62
+ <priority>${e.priority}</priority>
63
+ </url>`)
64
+ .join("\n");
65
+ const xml = `<?xml version="1.0" encoding="UTF-8"?>
66
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
67
+ ${urlEntries}
68
+ </urlset>`;
69
+ return new Response(xml, {
70
+ headers: {
71
+ "Content-Type": "application/xml",
72
+ "Cache-Control": "public, max-age=3600",
73
+ },
74
+ });
75
+ }
76
+ catch (err) {
77
+ console.error("Sitemap users error:", err);
78
+ return new Response("Internal error", { status: 500 });
79
+ }
80
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Manifest des sitemaps du module AI
3
+ * Déclare tous les sitemaps enfants à générer
4
+ */
5
+ import type { SitemapManifest, SitemapChild, SitemapChildKind } from "@lastbrain/core";
6
+ export type { SitemapManifest, SitemapChild, SitemapChildKind };
7
+ export declare const sitemapManifest: SitemapManifest;
8
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/sitemap/manifest.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACZ,gBAAgB,EACjB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAChE,eAAO,MAAM,eAAe,EAAE,eA0BpB,CAAC"}
@@ -0,0 +1,27 @@
1
+ export const sitemapManifest = {
2
+ module: "ai",
3
+ enabled: true,
4
+ includePublicPagesFromBuildConfig: true,
5
+ children: [
6
+ // Pages statiques (générées auto depuis build.config)
7
+ {
8
+ id: "static",
9
+ path: ":lang/static.xml",
10
+ kind: "static",
11
+ },
12
+ // Prompts publics par langue
13
+ {
14
+ id: "prompts",
15
+ path: ":lang/prompts.xml",
16
+ kind: "reexport",
17
+ handler: "@lastbrain/module-ai/sitemap/handlers/prompts",
18
+ },
19
+ // Profils utilisateurs avec prompts publics
20
+ {
21
+ id: "users",
22
+ path: ":lang/users.xml",
23
+ kind: "reexport",
24
+ handler: "@lastbrain/module-ai/sitemap/handlers/users",
25
+ },
26
+ ],
27
+ };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Types for Vercel AI Gateway /v1/models API
3
+ */
4
+ export interface GatewayPricing {
5
+ input: number;
6
+ output: number;
7
+ image?: number;
8
+ request?: number;
9
+ web_search?: number;
10
+ }
11
+ export interface GatewayModel {
12
+ id: string;
13
+ name: string;
14
+ description?: string;
15
+ type: "text" | "image" | "embedding" | "audio" | "video" | "language";
16
+ provider: string;
17
+ context_window?: number;
18
+ max_tokens?: number;
19
+ pricing?: GatewayPricing;
20
+ tags?: string[];
21
+ supports_tools?: boolean;
22
+ supports_vision?: boolean;
23
+ }
24
+ export interface GatewayProvider {
25
+ name: string;
26
+ display_name: string;
27
+ models: GatewayModel[];
28
+ }
29
+ export interface GatewayModelsResponse {
30
+ providers: GatewayProvider[];
31
+ stale?: boolean;
32
+ cached_at?: string;
33
+ }
34
+ export interface UserModelSettings {
35
+ owner_id: string;
36
+ enabled_models: string[];
37
+ enabled_providers?: string[];
38
+ updated_at?: string;
39
+ }
40
+ //# sourceMappingURL=gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/types/gateway.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,WAAW,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,YAAY,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}