@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,223 @@
1
+ /**
2
+ * Tests unitaires pour le système de billing centralisé
3
+ */
4
+ import { describe, it, expect } from "vitest";
5
+ import { computeAndDebitAIUsage } from "../billing";
6
+ describe("computeAndDebitAIUsage - Système de billing centralisé", () => {
7
+ // Wallet mock standard (pack 5$ avec coef 2.5)
8
+ const mockWallet = {
9
+ tokenBalance: 100000,
10
+ walletProviderBudgetUsd: 2.0, // 5$ / 2.5
11
+ walletSellValueUsd: 5.0,
12
+ };
13
+ describe("Application des minimums par action", () => {
14
+ it("recette applique minimum 0.20$", () => {
15
+ const result = computeAndDebitAIUsage({
16
+ userId: "test-user-123",
17
+ actionType: "generate-recipe-text",
18
+ providerCostUsd: 0.001, // Très bas
19
+ wallet: mockWallet,
20
+ metadata: { model: "gpt-4o-mini", provider: "openai" },
21
+ });
22
+ expect(result.success).toBe(true);
23
+ expect(result.sellCostUsd).toBeGreaterThanOrEqual(0.2);
24
+ expect(result.sellCostUsd).toBe(0.2); // Exactement le minimum
25
+ });
26
+ it("image applique minimum 0.05$", () => {
27
+ const result = computeAndDebitAIUsage({
28
+ userId: "test-user-456",
29
+ actionType: "generate-image",
30
+ providerCostUsd: 0.001,
31
+ wallet: mockWallet,
32
+ metadata: { model: "dall-e-3", provider: "openai" },
33
+ });
34
+ expect(result.success).toBe(true);
35
+ expect(result.sellCostUsd).toBeGreaterThanOrEqual(0.05);
36
+ });
37
+ it("generate-text générique n'applique pas de minimum", () => {
38
+ const result = computeAndDebitAIUsage({
39
+ userId: "test-user-789",
40
+ actionType: "generate-text",
41
+ providerCostUsd: 0.001,
42
+ wallet: mockWallet,
43
+ metadata: { model: "gpt-4o-mini", provider: "openai" },
44
+ });
45
+ expect(result.success).toBe(true);
46
+ // Avec marge 60%, sell = 0.001 / 0.4 = 0.0025, arrondi ceil = 0.0025
47
+ expect(result.sellCostUsd).toBeLessThan(0.01);
48
+ });
49
+ it("autocomplete n'applique pas de minimum", () => {
50
+ const result = computeAndDebitAIUsage({
51
+ userId: "test-user-abc",
52
+ actionType: "autocomplete",
53
+ providerCostUsd: 0.0001,
54
+ wallet: mockWallet,
55
+ metadata: { model: "gpt-4o-mini", provider: "openai" },
56
+ });
57
+ expect(result.success).toBe(true);
58
+ expect(result.sellCostUsd).toBeLessThan(0.001);
59
+ });
60
+ });
61
+ describe("Calcul de la marge (60%)", () => {
62
+ it("marge correcte pour coût sans minimum", () => {
63
+ const result = computeAndDebitAIUsage({
64
+ userId: "test-user",
65
+ actionType: "generate-text",
66
+ providerCostUsd: 0.1,
67
+ wallet: mockWallet,
68
+ metadata: { model: "gpt-4o-mini" },
69
+ });
70
+ expect(result.success).toBe(true);
71
+ // sell = 0.1 / 0.4 = 0.25
72
+ expect(result.sellCostUsd).toBeCloseTo(0.25, 2);
73
+ expect(result.marginUsd).toBeCloseTo(0.15, 2);
74
+ expect(result.marginPercent).toBeCloseTo(60, 0);
75
+ });
76
+ it("marge élevée quand minimum appliqué", () => {
77
+ const result = computeAndDebitAIUsage({
78
+ userId: "test-user",
79
+ actionType: "generate-recipe-text",
80
+ providerCostUsd: 0.001, // Très bas
81
+ wallet: mockWallet,
82
+ metadata: { model: "gpt-4o-mini" },
83
+ });
84
+ expect(result.success).toBe(true);
85
+ expect(result.sellCostUsd).toBe(0.2); // Minimum
86
+ expect(result.marginUsd).toBeCloseTo(0.199, 3);
87
+ // Marge très élevée: (0.199 / 0.2) * 100 ≈ 99.5%
88
+ expect(result.marginPercent).toBeGreaterThan(99);
89
+ });
90
+ });
91
+ describe("Vérifications budget provider", () => {
92
+ it("refuse si budget provider insuffisant", () => {
93
+ const result = computeAndDebitAIUsage({
94
+ userId: "test-user",
95
+ actionType: "generate-recipe-text",
96
+ providerCostUsd: 3.0, // Plus que 2.0 disponible
97
+ wallet: mockWallet,
98
+ metadata: { model: "gpt-4" },
99
+ });
100
+ expect(result.success).toBe(false);
101
+ expect(result.error).toBe("insufficient_credits");
102
+ });
103
+ it("refuse si sell value insuffisante", () => {
104
+ const result = computeAndDebitAIUsage({
105
+ userId: "test-user",
106
+ actionType: "generate-recipe-text",
107
+ providerCostUsd: 0.5, // OK pour provider
108
+ wallet: {
109
+ ...mockWallet,
110
+ walletSellValueUsd: 0.1, // Insuffisant pour 0.2$ minimum
111
+ },
112
+ metadata: { model: "gpt-4o-mini" },
113
+ });
114
+ expect(result.success).toBe(false);
115
+ expect(result.error).toBe("insufficient_credits");
116
+ });
117
+ it("accepte si budgets suffisants", () => {
118
+ const result = computeAndDebitAIUsage({
119
+ userId: "test-user",
120
+ actionType: "generate-recipe-text",
121
+ providerCostUsd: 0.05,
122
+ wallet: mockWallet,
123
+ metadata: { model: "gpt-4o-mini" },
124
+ });
125
+ expect(result.success).toBe(true);
126
+ expect(result.newWallet).toBeDefined();
127
+ expect(result.newWallet.walletProviderBudgetUsd).toBeCloseTo(1.95, 2);
128
+ expect(result.newWallet.walletSellValueUsd).toBeCloseTo(4.8, 2);
129
+ });
130
+ });
131
+ describe("Calcul percent remaining", () => {
132
+ it("calcule correctement le pourcentage restant", () => {
133
+ const result = computeAndDebitAIUsage({
134
+ userId: "test-user",
135
+ actionType: "generate-recipe-text",
136
+ providerCostUsd: 0.1,
137
+ wallet: mockWallet,
138
+ metadata: { model: "gpt-4o-mini" },
139
+ });
140
+ expect(result.success).toBe(true);
141
+ // Débite 0.20$ (minimum) sur 5$ = reste 4.8$
142
+ // 4.8 / 5 = 96%
143
+ expect(result.newWallet.percentRemaining).toBeCloseTo(96, 0);
144
+ });
145
+ it("pourcentage proche de 0 quand presque épuisé", () => {
146
+ const lowWallet = {
147
+ tokenBalance: 1000,
148
+ walletProviderBudgetUsd: 0.1,
149
+ walletSellValueUsd: 0.25,
150
+ };
151
+ const result = computeAndDebitAIUsage({
152
+ userId: "test-user",
153
+ actionType: "generate-recipe-text",
154
+ providerCostUsd: 0.05,
155
+ wallet: lowWallet,
156
+ metadata: { model: "gpt-4o-mini" },
157
+ });
158
+ expect(result.success).toBe(true);
159
+ // 0.25 - 0.20 = 0.05 restant
160
+ // 0.05 / 0.25 = 20%
161
+ expect(result.newWallet.percentRemaining).toBeCloseTo(20, 0);
162
+ });
163
+ });
164
+ describe("Override minimum", () => {
165
+ it("permet de surcharger le minimum par action", () => {
166
+ const result = computeAndDebitAIUsage({
167
+ userId: "test-user",
168
+ actionType: "generate-recipe-text", // Min 0.20 par défaut
169
+ providerCostUsd: 0.001,
170
+ wallet: mockWallet,
171
+ metadata: { model: "gpt-4o-mini" },
172
+ minSellUsdOverride: 0.5, // Forcer 0.50$ minimum
173
+ });
174
+ expect(result.success).toBe(true);
175
+ expect(result.sellCostUsd).toBe(0.5);
176
+ });
177
+ it("override à 0 désactive le minimum", () => {
178
+ const result = computeAndDebitAIUsage({
179
+ userId: "test-user",
180
+ actionType: "generate-recipe-text", // Min 0.20 par défaut
181
+ providerCostUsd: 0.001,
182
+ wallet: mockWallet,
183
+ metadata: { model: "gpt-4o-mini" },
184
+ minSellUsdOverride: 0, // Désactiver minimum
185
+ });
186
+ expect(result.success).toBe(true);
187
+ // Marge 60% seulement: 0.001 / 0.4 = 0.0025
188
+ expect(result.sellCostUsd).toBeLessThan(0.01);
189
+ });
190
+ });
191
+ describe("Protection contre abus", () => {
192
+ it("empêche génération de 1000 recettes pour 5$", () => {
193
+ const wallet = { ...mockWallet };
194
+ let successCount = 0;
195
+ let totalCost = 0;
196
+ // Tenter de générer jusqu'à épuisement
197
+ for (let i = 0; i < 1000; i++) {
198
+ const result = computeAndDebitAIUsage({
199
+ userId: "test-user",
200
+ actionType: "generate-recipe-text",
201
+ providerCostUsd: 0.001, // Coût très bas
202
+ wallet,
203
+ metadata: { model: "gpt-4o-mini" },
204
+ });
205
+ if (result.success) {
206
+ successCount++;
207
+ totalCost += result.sellCostUsd;
208
+ // Mettre à jour wallet simulé
209
+ wallet.walletProviderBudgetUsd =
210
+ result.newWallet.walletProviderBudgetUsd;
211
+ wallet.walletSellValueUsd = result.newWallet.walletSellValueUsd;
212
+ }
213
+ else {
214
+ break;
215
+ }
216
+ }
217
+ // Avec minimum 0.20$ par recette, max = 5 / 0.20 = 25 recettes
218
+ expect(successCount).toBeLessThanOrEqual(25);
219
+ expect(successCount).toBeGreaterThanOrEqual(20); // Au moins 20
220
+ expect(totalCost).toBeLessThanOrEqual(5.01); // Légèrement plus pour arrondis
221
+ });
222
+ });
223
+ });
@@ -0,0 +1,59 @@
1
+ /**
2
+ * AI client using Vercel AI SDK with Gateway
3
+ * Gateway key (vck_...) enables direct model string usage
4
+ */
5
+ /**
6
+ * Text generation using Vercel AI Gateway
7
+ * Model format: "provider/model" (e.g., "openai/gpt-4o-mini", "anthropic/claude-sonnet-4.5")
8
+ */
9
+ export interface TextAIParams {
10
+ prompt: string;
11
+ model?: string;
12
+ system?: string;
13
+ maxTokens?: number;
14
+ temperature?: number;
15
+ }
16
+ export interface TextAIResult {
17
+ text: string;
18
+ usage?: {
19
+ promptTokens: number;
20
+ completionTokens: number;
21
+ totalTokens: number;
22
+ };
23
+ raw?: any;
24
+ }
25
+ export declare function textAI(params: TextAIParams): Promise<TextAIResult>;
26
+ /**
27
+ * Image generation using Vercel AI Gateway
28
+ * Model format: "provider/model" (e.g., "openai/dall-e-3")
29
+ */
30
+ export interface ImageAIParams {
31
+ prompt: string;
32
+ model?: string;
33
+ size?: string;
34
+ n?: number;
35
+ }
36
+ export interface ImageAIResult {
37
+ imageUrl: string;
38
+ tokensUsed?: number;
39
+ raw?: any;
40
+ }
41
+ export declare function imageAI(params: ImageAIParams): Promise<ImageAIResult>;
42
+ /**
43
+ * Embedding generation using Vercel AI Gateway
44
+ * Model format: "provider/model" (e.g., "openai/text-embedding-3-small")
45
+ */
46
+ export interface EmbedAIParams {
47
+ input: string | string[];
48
+ model?: string;
49
+ }
50
+ export interface EmbedAIResult {
51
+ embedding?: number[];
52
+ embeddings?: number[][];
53
+ usage?: {
54
+ tokens: number;
55
+ };
56
+ raw?: any;
57
+ }
58
+ export declare function embedAI(params: EmbedAIParams): Promise<EmbedAIResult>;
59
+ //# sourceMappingURL=ai-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-client.d.ts","sourceRoot":"","sources":["../../src/server/ai-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAyBH;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,GAAG,CAAC,EAAE,GAAG,CAAC;CACX;AAED,wBAAsB,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAkCxE;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,GAAG,CAAC;CACX;AAED,wBAAsB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CA6C3E;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,GAAG,CAAC,EAAE,GAAG,CAAC;CACX;AAED,wBAAsB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAwB3E"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * AI client using Vercel AI SDK with Gateway
3
+ * Gateway key (vck_...) enables direct model string usage
4
+ */
5
+ import { generateText, generateImage, embed } from "ai";
6
+ import { logger } from "@lastbrain/core";
7
+ // Gateway API key - no need to create providers
8
+ const gatewayKey = process.env.AI_GATEWAY_API_KEY;
9
+ if (!gatewayKey) {
10
+ logger.error("[AI Client] AI_GATEWAY_API_KEY not configured");
11
+ }
12
+ // Get default models from environment with fallbacks
13
+ function getDefaultTextModel() {
14
+ return process.env.AI_DEFAULT_TEXT_MODEL || "openai/gpt-4o-mini";
15
+ }
16
+ function getDefaultImageModel() {
17
+ return process.env.AI_DEFAULT_IMAGE_MODEL || "openai/dall-e-3";
18
+ }
19
+ function getDefaultEmbedModel() {
20
+ return process.env.AI_DEFAULT_EMBED_MODEL || "openai/text-embedding-3-small";
21
+ }
22
+ export async function textAI(params) {
23
+ const fullModel = params.model || getDefaultTextModel();
24
+ logger.info(`[textAI] Generating text with model: ${fullModel}`);
25
+ try {
26
+ // With Gateway, pass model string directly (e.g., "openai/gpt-4o-mini")
27
+ const result = await generateText({
28
+ model: fullModel,
29
+ prompt: params.prompt,
30
+ system: params.system,
31
+ temperature: params.temperature,
32
+ ...(params.maxTokens && { maxTokens: params.maxTokens }),
33
+ });
34
+ logger.info(`[textAI] Generation complete. Usage: ${JSON.stringify(result.usage)}`);
35
+ return {
36
+ text: result.text,
37
+ usage: result.usage
38
+ ? {
39
+ promptTokens: result.usage.inputTokens ?? 0,
40
+ completionTokens: result.usage.outputTokens ?? 0,
41
+ totalTokens: result.usage.totalTokens ?? 0,
42
+ }
43
+ : undefined,
44
+ raw: result,
45
+ };
46
+ }
47
+ catch (error) {
48
+ logger.error(`[textAI] Error with model ${fullModel}:`, error);
49
+ throw new Error(`Text generation failed: ${error.message}`);
50
+ }
51
+ }
52
+ export async function imageAI(params) {
53
+ const fullModel = params.model || getDefaultImageModel();
54
+ logger.info(`[imageAI] Generating image with model: ${fullModel}`);
55
+ try {
56
+ // Use generateImage API for image generation
57
+ const result = await generateImage({
58
+ model: fullModel,
59
+ prompt: params.prompt,
60
+ });
61
+ // Image is available in result.image
62
+ if (!result.image) {
63
+ logger.error("[imageAI] No image generated", { result });
64
+ throw new Error("No image generated by the model");
65
+ }
66
+ // Convert to base64 data URL
67
+ const imageUrl = `data:${result.image.mediaType};base64,${result.image.base64}`;
68
+ // Log pour déboguer l'usage réel
69
+ logger.info(`[imageAI] Generated image with model ${fullModel}`, {
70
+ usage: result.usage,
71
+ rawUsage: JSON.stringify(result.usage),
72
+ });
73
+ // Use token usage from result - vérifier plusieurs formats possibles
74
+ const tokensUsed = result.usage?.totalTokens ||
75
+ result.usage?.total ||
76
+ result.usage?.tokens ||
77
+ 6000;
78
+ logger.info(`[imageAI] Tokens used: ${tokensUsed}`);
79
+ return {
80
+ imageUrl,
81
+ tokensUsed,
82
+ raw: result,
83
+ };
84
+ }
85
+ catch (error) {
86
+ logger.error(`[imageAI] Error with model ${fullModel}:`, error);
87
+ throw new Error(`Image generation failed: ${error.message}`);
88
+ }
89
+ }
90
+ export async function embedAI(params) {
91
+ const fullModel = params.model || getDefaultEmbedModel();
92
+ logger.info(`[embedAI] Generating embedding with model: ${fullModel}`);
93
+ try {
94
+ // With Gateway, pass model string directly
95
+ const result = await embed({
96
+ model: fullModel,
97
+ value: typeof params.input === "string"
98
+ ? params.input
99
+ : params.input.join("\n"),
100
+ });
101
+ return {
102
+ embedding: result.embedding,
103
+ usage: result.usage ? { tokens: result.usage.tokens } : undefined,
104
+ raw: result,
105
+ };
106
+ }
107
+ catch (error) {
108
+ logger.error(`[embedAI] Error with model ${fullModel}:`, error);
109
+ throw new Error(`Embedding generation failed: ${error.message}`);
110
+ }
111
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Centralized AI Generation Service
3
+ *
4
+ * SINGLE SOURCE OF TRUTH for all AI generation with billing
5
+ * Used by both internal auth endpoints AND public API v1
6
+ *
7
+ * This service handles:
8
+ * 1. Pricing validation
9
+ * 2. Wallet pre-check (> 0)
10
+ * 3. AI API call
11
+ * 4. Real cost computation with minimums
12
+ * 5. Wallet debit
13
+ * 6. Ledger recording
14
+ */
15
+ import { type ActionType } from "./billing";
16
+ export interface TextGenerationParams {
17
+ prompt: string;
18
+ model?: string;
19
+ systemPrompt?: string;
20
+ maxTokens?: number;
21
+ temperature?: number;
22
+ actionType?: ActionType;
23
+ context?: string;
24
+ promptUser?: string;
25
+ metadata?: Record<string, any>;
26
+ }
27
+ export interface ImageGenerationParams {
28
+ prompt: string;
29
+ model?: string;
30
+ size?: "256x256" | "512x512" | "1024x1024" | "1792x1024" | "1024x1792";
31
+ quality?: "standard" | "hd";
32
+ actionType?: ActionType;
33
+ metadata?: Record<string, any>;
34
+ }
35
+ export interface GenerationResult {
36
+ success: boolean;
37
+ error?: string;
38
+ errorCode?: "NO_CREDITS" | "NO_PRICING" | "MODEL_NOT_ALLOWED" | "PROVIDER_ERROR";
39
+ text?: string;
40
+ inputTokens?: number;
41
+ outputTokens?: number;
42
+ imageUrl?: string;
43
+ revisedPrompt?: string;
44
+ model?: string;
45
+ provider?: string;
46
+ providerCostUsd?: number;
47
+ sellCostUsd?: number;
48
+ marginPercent?: number;
49
+ }
50
+ /**
51
+ * Generate text with automatic billing
52
+ *
53
+ * @param userId User ID
54
+ * @param params Generation parameters
55
+ * @returns Generation result with billing info
56
+ */
57
+ export declare function generateTextWithBilling(userId: string, params: TextGenerationParams): Promise<GenerationResult>;
58
+ /**
59
+ * Generate image with automatic billing
60
+ *
61
+ * @param userId User ID
62
+ * @param params Generation parameters
63
+ * @returns Generation result with billing info
64
+ */
65
+ export declare function generateImageWithBilling(userId: string, params: ImageGenerationParams): Promise<GenerationResult>;
66
+ //# sourceMappingURL=ai-generation-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-generation-service.d.ts","sourceRoot":"","sources":["../../src/server/ai-generation-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH,OAAO,EAKL,KAAK,UAAU,EAChB,MAAM,WAAW,CAAC;AAMnB,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;IACvE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EACN,YAAY,GACZ,YAAY,GACZ,mBAAmB,GACnB,gBAAgB,CAAC;IAGrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IAGvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CAqK3B;AAMD;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CAwJ3B"}