@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.
- package/README.md +52 -1
- package/dist/ai.build.config.d.ts.map +1 -1
- package/dist/ai.build.config.js +508 -9
- package/dist/api/admin/ai-provider-models/[id].d.ts +18 -0
- package/dist/api/admin/ai-provider-models/[id].d.ts.map +1 -0
- package/dist/api/admin/ai-provider-models/[id].js +58 -0
- package/dist/api/admin/ai-provider-models.d.ts +20 -0
- package/dist/api/admin/ai-provider-models.d.ts.map +1 -0
- package/dist/api/admin/ai-provider-models.js +26 -0
- package/dist/api/admin/ai-providers/[key].d.ts +18 -0
- package/dist/api/admin/ai-providers/[key].d.ts.map +1 -0
- package/dist/api/admin/ai-providers/[key].js +55 -0
- package/dist/api/admin/ai-providers.d.ts +20 -0
- package/dist/api/admin/ai-providers.d.ts.map +1 -0
- package/dist/api/admin/ai-providers.js +26 -0
- package/dist/api/admin/billing-analytics.d.ts +43 -0
- package/dist/api/admin/billing-analytics.d.ts.map +1 -0
- package/dist/api/admin/billing-analytics.js +144 -0
- package/dist/api/admin/global-ai-settings.d.ts +14 -0
- package/dist/api/admin/global-ai-settings.d.ts.map +1 -0
- package/dist/api/admin/global-ai-settings.js +63 -0
- package/dist/api/admin/token-packs/[id].d.ts.map +1 -1
- package/dist/api/admin/token-packs/[id].js +3 -2
- package/dist/api/admin/token-packs.d.ts.map +1 -1
- package/dist/api/admin/token-packs.js +3 -2
- package/dist/api/admin/user-monthly-details.d.ts +49 -0
- package/dist/api/admin/user-monthly-details.d.ts.map +1 -0
- package/dist/api/admin/user-monthly-details.js +140 -0
- package/dist/api/admin/user-quota.d.ts +21 -0
- package/dist/api/admin/user-quota.d.ts.map +1 -0
- package/dist/api/admin/user-quota.js +59 -0
- package/dist/api/admin/user-token/[id].d.ts.map +1 -1
- package/dist/api/admin/user-token/[id].js +2 -1
- package/dist/api/admin/user-token.d.ts +5 -2
- package/dist/api/admin/user-token.d.ts.map +1 -1
- package/dist/api/admin/user-token.js +91 -17
- package/dist/api/admin/user-usage-by-model.d.ts +22 -0
- package/dist/api/admin/user-usage-by-model.d.ts.map +1 -0
- package/dist/api/admin/user-usage-by-model.js +78 -0
- package/dist/api/admin/user-wallet-analytics.d.ts +15 -0
- package/dist/api/admin/user-wallet-analytics.d.ts.map +1 -0
- package/dist/api/admin/user-wallet-analytics.js +67 -0
- package/dist/api/admin/wallet-repair/route.d.ts +30 -0
- package/dist/api/admin/wallet-repair/route.d.ts.map +1 -0
- package/dist/api/admin/wallet-repair/route.js +63 -0
- package/dist/api/auth/ai-model-settings.d.ts +21 -0
- package/dist/api/auth/ai-model-settings.d.ts.map +1 -0
- package/dist/api/auth/ai-model-settings.js +86 -0
- package/dist/api/auth/ai-settings.d.ts +17 -0
- package/dist/api/auth/ai-settings.d.ts.map +1 -0
- package/dist/api/auth/ai-settings.js +87 -0
- package/dist/api/auth/api-keys/[id].d.ts +17 -0
- package/dist/api/auth/api-keys/[id].d.ts.map +1 -0
- package/dist/api/auth/api-keys/[id].js +66 -0
- package/dist/api/auth/api-keys.d.ts +19 -0
- package/dist/api/auth/api-keys.d.ts.map +1 -0
- package/dist/api/auth/api-keys.js +94 -0
- package/dist/api/auth/create-checkout.d.ts +1 -1
- package/dist/api/auth/create-checkout.d.ts.map +1 -1
- package/dist/api/auth/create-checkout.js +8 -6
- package/dist/api/auth/generate-image.d.ts +2 -2
- package/dist/api/auth/generate-image.d.ts.map +1 -1
- package/dist/api/auth/generate-image.js +404 -104
- package/dist/api/auth/generate-text.d.ts +3 -2
- package/dist/api/auth/generate-text.d.ts.map +1 -1
- package/dist/api/auth/generate-text.js +130 -58
- package/dist/api/auth/process-ocr.d.ts +9 -0
- package/dist/api/auth/process-ocr.d.ts.map +1 -0
- package/dist/api/auth/process-ocr.js +43 -0
- package/dist/api/auth/prompts/stats.d.ts +14 -0
- package/dist/api/auth/prompts/stats.d.ts.map +1 -0
- package/dist/api/auth/prompts/stats.js +46 -0
- package/dist/api/auth/prompts.d.ts +26 -0
- package/dist/api/auth/prompts.d.ts.map +1 -0
- package/dist/api/auth/prompts.js +175 -0
- package/dist/api/auth/token-balance.d.ts +26 -0
- package/dist/api/auth/token-balance.d.ts.map +1 -0
- package/dist/api/auth/token-balance.js +47 -0
- package/dist/api/auth/token-checkout.d.ts.map +1 -1
- package/dist/api/auth/token-checkout.js +22 -4
- package/dist/api/auth/token-packs.d.ts.map +1 -1
- package/dist/api/auth/token-packs.js +2 -1
- package/dist/api/auth/usage-by-model.d.ts +25 -0
- package/dist/api/auth/usage-by-model.d.ts.map +1 -0
- package/dist/api/auth/usage-by-model.js +95 -0
- package/dist/api/auth/usage.d.ts +26 -0
- package/dist/api/auth/usage.d.ts.map +1 -0
- package/dist/api/auth/usage.js +127 -0
- package/dist/api/auth/user-tokens.d.ts.map +1 -1
- package/dist/api/auth/user-tokens.js +36 -2
- package/dist/api/auth/wallet/route.d.ts +17 -0
- package/dist/api/auth/wallet/route.d.ts.map +1 -0
- package/dist/api/auth/wallet/route.js +68 -0
- package/dist/api/auth/wallet.d.ts +16 -0
- package/dist/api/auth/wallet.d.ts.map +1 -0
- package/dist/api/auth/wallet.js +71 -0
- package/dist/api/public/gateway-models.d.ts +25 -0
- package/dist/api/public/gateway-models.d.ts.map +1 -0
- package/dist/api/public/gateway-models.js +49 -0
- package/dist/api/public/pricing-summary.d.ts +46 -0
- package/dist/api/public/pricing-summary.d.ts.map +1 -0
- package/dist/api/public/pricing-summary.js +70 -0
- package/dist/api/public/prompts/[id]/stats.d.ts +15 -0
- package/dist/api/public/prompts/[id]/stats.d.ts.map +1 -0
- package/dist/api/public/prompts/[id]/stats.js +37 -0
- package/dist/api/public/prompts/[id]/view.d.ts +15 -0
- package/dist/api/public/prompts/[id]/view.d.ts.map +1 -0
- package/dist/api/public/prompts/[id]/view.js +41 -0
- package/dist/api/public/prompts/slug/[slug].d.ts +15 -0
- package/dist/api/public/prompts/slug/[slug].d.ts.map +1 -0
- package/dist/api/public/prompts/slug/[slug].js +40 -0
- package/dist/api/public/prompts/user/[username].d.ts +17 -0
- package/dist/api/public/prompts/user/[username].d.ts.map +1 -0
- package/dist/api/public/prompts/user/[username].js +51 -0
- package/dist/api/public/prompts.d.ts +15 -0
- package/dist/api/public/prompts.d.ts.map +1 -0
- package/dist/api/public/prompts.js +45 -0
- package/dist/api/public/token-packs.d.ts +11 -0
- package/dist/api/public/token-packs.d.ts.map +1 -0
- package/dist/api/public/token-packs.js +25 -0
- package/dist/api/public/token-pricing.d.ts +44 -0
- package/dist/api/public/token-pricing.d.ts.map +1 -0
- package/dist/api/public/token-pricing.js +168 -0
- package/dist/api/public/v1/_lib/artifacts.d.ts +52 -0
- package/dist/api/public/v1/_lib/artifacts.d.ts.map +1 -0
- package/dist/api/public/v1/_lib/artifacts.js +217 -0
- package/dist/api/public/v1/_lib/auth.d.ts +43 -0
- package/dist/api/public/v1/_lib/auth.d.ts.map +1 -0
- package/dist/api/public/v1/_lib/auth.js +108 -0
- package/dist/api/public/v1/_lib/errors.d.ts +17 -0
- package/dist/api/public/v1/_lib/errors.d.ts.map +1 -0
- package/dist/api/public/v1/_lib/errors.js +16 -0
- package/dist/api/public/v1/_lib/log.d.ts +29 -0
- package/dist/api/public/v1/_lib/log.d.ts.map +1 -0
- package/dist/api/public/v1/_lib/log.js +68 -0
- package/dist/api/public/v1/_lib/quota.d.ts +24 -0
- package/dist/api/public/v1/_lib/quota.d.ts.map +1 -0
- package/dist/api/public/v1/_lib/quota.js +118 -0
- package/dist/api/public/v1/_lib/router.d.ts +54 -0
- package/dist/api/public/v1/_lib/router.d.ts.map +1 -0
- package/dist/api/public/v1/_lib/router.js +119 -0
- package/dist/api/public/v1/connect.d.ts +20 -0
- package/dist/api/public/v1/connect.d.ts.map +1 -0
- package/dist/api/public/v1/connect.js +119 -0
- package/dist/api/public/v1/doc.d.ts +239 -0
- package/dist/api/public/v1/doc.d.ts.map +1 -0
- package/dist/api/public/v1/doc.js +253 -0
- package/dist/api/public/v1/history/[id].d.ts +92 -0
- package/dist/api/public/v1/history/[id].d.ts.map +1 -0
- package/dist/api/public/v1/history/[id].js +176 -0
- package/dist/api/public/v1/history.d.ts +30 -0
- package/dist/api/public/v1/history.d.ts.map +1 -0
- package/dist/api/public/v1/history.js +142 -0
- package/dist/api/public/v1/image-ai.d.ts +24 -0
- package/dist/api/public/v1/image-ai.d.ts.map +1 -0
- package/dist/api/public/v1/image-ai.js +233 -0
- package/dist/api/public/v1/prompts.d.ts +19 -0
- package/dist/api/public/v1/prompts.d.ts.map +1 -0
- package/dist/api/public/v1/prompts.js +107 -0
- package/dist/api/public/v1/provider.d.ts +16 -0
- package/dist/api/public/v1/provider.d.ts.map +1 -0
- package/dist/api/public/v1/provider.js +130 -0
- package/dist/api/public/v1/purchase.d.ts +11 -0
- package/dist/api/public/v1/purchase.d.ts.map +1 -0
- package/dist/api/public/v1/purchase.js +18 -0
- package/dist/api/public/v1/status.d.ts +35 -0
- package/dist/api/public/v1/status.d.ts.map +1 -0
- package/dist/api/public/v1/status.js +163 -0
- package/dist/api/public/v1/text-ai.d.ts +26 -0
- package/dist/api/public/v1/text-ai.d.ts.map +1 -0
- package/dist/api/public/v1/text-ai.js +239 -0
- package/dist/api/public/webhook.d.ts.map +1 -1
- package/dist/api/public/webhook.js +50 -39
- package/dist/api/track-usage.d.ts +12 -0
- package/dist/api/track-usage.d.ts.map +1 -0
- package/dist/api/track-usage.js +37 -0
- package/dist/components/Doc.d.ts.map +1 -1
- package/dist/components/Doc.js +1 -1
- package/dist/components/DocUsageCustom.js +6 -6
- package/dist/components/admin/UserTokenTab.d.ts.map +1 -1
- package/dist/components/admin/UserTokenTab.js +170 -23
- package/dist/components/auth/AuthDashboardAi.d.ts +2 -0
- package/dist/components/auth/AuthDashboardAi.d.ts.map +1 -0
- package/dist/components/auth/AuthDashboardAi.js +53 -0
- package/dist/docs/REFACTORING_BILLING_GUIDE.d.ts +277 -0
- package/dist/docs/REFACTORING_BILLING_GUIDE.d.ts.map +1 -0
- package/dist/docs/REFACTORING_BILLING_GUIDE.js +276 -0
- package/dist/index.d.ts +15 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -1
- package/dist/scripts/migrate-tokens-to-wallet.d.ts +13 -0
- package/dist/scripts/migrate-tokens-to-wallet.d.ts.map +1 -0
- package/dist/scripts/migrate-tokens-to-wallet.js +165 -0
- package/dist/server/__tests__/billing.test.d.ts +5 -0
- package/dist/server/__tests__/billing.test.d.ts.map +1 -0
- package/dist/server/__tests__/billing.test.js +223 -0
- package/dist/server/ai-client.d.ts +59 -0
- package/dist/server/ai-client.d.ts.map +1 -0
- package/dist/server/ai-client.js +111 -0
- package/dist/server/ai-generation-service.d.ts +66 -0
- package/dist/server/ai-generation-service.d.ts.map +1 -0
- package/dist/server/ai-generation-service.js +274 -0
- package/dist/server/billing.d.ts +200 -0
- package/dist/server/billing.d.ts.map +1 -0
- package/dist/server/billing.js +488 -0
- package/dist/server/gateway-service.d.ts +13 -0
- package/dist/server/gateway-service.d.ts.map +1 -0
- package/dist/server/gateway-service.js +161 -0
- package/dist/server/global-settings.d.ts +16 -0
- package/dist/server/global-settings.d.ts.map +1 -0
- package/dist/server/global-settings.js +42 -0
- package/dist/server/model-filter.d.ts +25 -0
- package/dist/server/model-filter.d.ts.map +1 -0
- package/dist/server/model-filter.js +240 -0
- package/dist/server/ocr.d.ts +39 -0
- package/dist/server/ocr.d.ts.map +1 -0
- package/dist/server/ocr.js +280 -0
- package/dist/server/openai-client.d.ts +19 -0
- package/dist/server/openai-client.d.ts.map +1 -0
- package/dist/server/openai-client.js +26 -0
- package/dist/server/pricing-config.d.ts +18 -0
- package/dist/server/pricing-config.d.ts.map +1 -0
- package/dist/server/pricing-config.js +94 -0
- package/dist/server/pricing-validator.d.ts +41 -0
- package/dist/server/pricing-validator.d.ts.map +1 -0
- package/dist/server/pricing-validator.js +113 -0
- package/dist/server/pricing.d.ts +121 -0
- package/dist/server/pricing.d.ts.map +1 -0
- package/dist/server/pricing.js +225 -0
- package/dist/server/quota.d.ts +66 -0
- package/dist/server/quota.d.ts.map +1 -0
- package/dist/server/quota.js +538 -0
- package/dist/server/wallet-repair.d.ts +32 -0
- package/dist/server/wallet-repair.d.ts.map +1 -0
- package/dist/server/wallet-repair.js +189 -0
- package/dist/server.d.ts +13 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +87 -16
- package/dist/sitemap/handlers/prompts.d.ts +6 -0
- package/dist/sitemap/handlers/prompts.d.ts.map +1 -0
- package/dist/sitemap/handlers/prompts.js +72 -0
- package/dist/sitemap/handlers/users.d.ts +6 -0
- package/dist/sitemap/handlers/users.d.ts.map +1 -0
- package/dist/sitemap/handlers/users.js +80 -0
- package/dist/sitemap/manifest.d.ts +8 -0
- package/dist/sitemap/manifest.d.ts.map +1 -0
- package/dist/sitemap/manifest.js +27 -0
- package/dist/types/gateway.d.ts +40 -0
- package/dist/types/gateway.d.ts.map +1 -0
- package/dist/types/gateway.js +4 -0
- package/dist/types/quota.d.ts +74 -0
- package/dist/types/quota.d.ts.map +1 -0
- package/dist/types/quota.js +11 -0
- package/dist/utils/date.d.ts +7 -0
- package/dist/utils/date.d.ts.map +1 -0
- package/dist/utils/date.js +17 -0
- package/dist/web/admin/AdminTokenPacksPage.js +1 -1
- package/dist/web/admin/BillingAnalyticsPage.d.ts +2 -0
- package/dist/web/admin/BillingAnalyticsPage.d.ts.map +1 -0
- package/dist/web/admin/BillingAnalyticsPage.js +141 -0
- package/dist/web/admin/GlobalAISettingsPage.d.ts +2 -0
- package/dist/web/admin/GlobalAISettingsPage.d.ts.map +1 -0
- package/dist/web/admin/GlobalAISettingsPage.js +93 -0
- package/dist/web/admin/UserTokenPage.d.ts.map +1 -1
- package/dist/web/admin/UserTokenPage.js +20 -7
- package/dist/web/auth/AISettingsPage.d.ts +2 -0
- package/dist/web/auth/AISettingsPage.d.ts.map +1 -0
- package/dist/web/auth/AISettingsPage.js +258 -0
- package/dist/web/auth/APIKeysPage.d.ts +2 -0
- package/dist/web/auth/APIKeysPage.d.ts.map +1 -0
- package/dist/web/auth/APIKeysPage.js +154 -0
- package/dist/web/auth/HistoryPage.d.ts +2 -0
- package/dist/web/auth/HistoryPage.d.ts.map +1 -0
- package/dist/web/auth/HistoryPage.js +279 -0
- package/dist/web/auth/PromptsPage.d.ts +5 -0
- package/dist/web/auth/PromptsPage.d.ts.map +1 -0
- package/dist/web/auth/PromptsPage.js +137 -0
- package/dist/web/auth/TokenPage.d.ts.map +1 -1
- package/dist/web/auth/TokenPage.js +88 -31
- package/dist/web/auth/UsageAndTokensPage.d.ts +2 -0
- package/dist/web/auth/UsageAndTokensPage.d.ts.map +1 -0
- package/dist/web/auth/UsageAndTokensPage.js +157 -0
- package/dist/web/auth/UsagePage.d.ts +2 -0
- package/dist/web/auth/UsagePage.d.ts.map +1 -0
- package/dist/web/auth/UsagePage.js +62 -0
- package/dist/web/auth/components/ApiKeyFilterSelect.d.ts +13 -0
- package/dist/web/auth/components/ApiKeyFilterSelect.d.ts.map +1 -0
- package/dist/web/auth/components/ApiKeyFilterSelect.js +16 -0
- package/dist/web/auth/components/ModelUsageTable.d.ts +19 -0
- package/dist/web/auth/components/ModelUsageTable.d.ts.map +1 -0
- package/dist/web/auth/components/ModelUsageTable.js +37 -0
- package/dist/web/auth/components/PurchaseButton.d.ts +7 -0
- package/dist/web/auth/components/PurchaseButton.d.ts.map +1 -0
- package/dist/web/auth/components/PurchaseButton.js +13 -0
- package/dist/web/auth/components/TokenHistoryCard.d.ts +20 -0
- package/dist/web/auth/components/TokenHistoryCard.d.ts.map +1 -0
- package/dist/web/auth/components/TokenHistoryCard.js +76 -0
- package/dist/web/auth/components/TokenKpiGrid.d.ts +24 -0
- package/dist/web/auth/components/TokenKpiGrid.d.ts.map +1 -0
- package/dist/web/auth/components/TokenKpiGrid.js +38 -0
- package/dist/web/auth/components/UsageByDayChart.d.ts +11 -0
- package/dist/web/auth/components/UsageByDayChart.d.ts.map +1 -0
- package/dist/web/auth/components/UsageByDayChart.js +32 -0
- package/dist/web/auth/components/UsageByModelBarChart.d.ts +12 -0
- package/dist/web/auth/components/UsageByModelBarChart.d.ts.map +1 -0
- package/dist/web/auth/components/UsageByModelBarChart.js +32 -0
- package/dist/web/auth/components/WalletStatusCard.d.ts +9 -0
- package/dist/web/auth/components/WalletStatusCard.d.ts.map +1 -0
- package/dist/web/auth/components/WalletStatusCard.js +50 -0
- package/dist/web/components/ImageGenerative.d.ts +3 -1
- package/dist/web/components/ImageGenerative.d.ts.map +1 -1
- package/dist/web/components/ImageGenerative.js +139 -52
- package/dist/web/components/TextareaGenerative.d.ts +3 -1
- package/dist/web/components/TextareaGenerative.d.ts.map +1 -1
- package/dist/web/components/TextareaGenerative.js +10 -5
- package/dist/web/public/PromptDetailPage.d.ts +25 -0
- package/dist/web/public/PromptDetailPage.d.ts.map +1 -0
- package/dist/web/public/PromptDetailPage.js +71 -0
- package/dist/web/public/PromptDetailPageServer.d.ts +15 -0
- package/dist/web/public/PromptDetailPageServer.d.ts.map +1 -0
- package/dist/web/public/PromptDetailPageServer.js +68 -0
- package/dist/web/public/PublicPromptsPage.d.ts +5 -0
- package/dist/web/public/PublicPromptsPage.d.ts.map +1 -0
- package/dist/web/public/PublicPromptsPage.js +110 -0
- package/dist/web/public/PurchaseTokensPage.d.ts +2 -0
- package/dist/web/public/PurchaseTokensPage.d.ts.map +1 -0
- package/dist/web/public/PurchaseTokensPage.js +98 -0
- package/dist/web/public/UserAvatar.d.ts +13 -0
- package/dist/web/public/UserAvatar.d.ts.map +1 -0
- package/dist/web/public/UserAvatar.js +13 -0
- package/dist/web/public/UserDetailPageServer.d.ts +15 -0
- package/dist/web/public/UserDetailPageServer.d.ts.map +1 -0
- package/dist/web/public/UserDetailPageServer.js +31 -0
- package/dist/web/public/UserPromptsPage.d.ts +9 -0
- package/dist/web/public/UserPromptsPage.d.ts.map +1 -0
- package/dist/web/public/UserPromptsPage.js +112 -0
- package/dist/web/public/UserPromptsPageServer.d.ts +15 -0
- package/dist/web/public/UserPromptsPageServer.d.ts.map +1 -0
- package/dist/web/public/UserPromptsPageServer.js +31 -0
- package/package.json +18 -9
- package/supabase/migrations/20251125000000_ai_tokens.sql +7 -0
- package/supabase/migrations/20260123100002_user_token_quota_monthly copy.sql +173 -0
- package/supabase/migrations/20260128100003_update_and_add_table.sql +368 -0
- package/supabase/migrations/20260128120000_seed_providers_models.sql +78 -0
- package/supabase/migrations/20260128131405_add_api_key_id_to_ledgers.sql +41 -0
- package/supabase/migrations/20260128140000_ai_artifacts_storage.sql +99 -0
- package/supabase/migrations/20260128140002_ai_user_settings.sql +57 -0
- package/supabase/migrations/20260128150000_drop_ai_user_settings.sql +21 -0
- package/supabase/migrations/20260128160000_wallet_billing_system.sql +192 -0
- package/supabase/migrations/20260128160001_wallet_rpc_functions.sql +165 -0
- package/supabase/migrations/20260128170000_add_pack_coef_to_token_packs.sql +30 -0
- package/supabase/migrations/20260129120000_wallet_view_rpc.sql +41 -0
- package/supabase/migrations/20260129220003_update_pack_margins.sql +31 -0
- package/supabase/migrations/20260129330004_ai_user_prompts.sql +151 -0
- package/supabase/migrations/20260129330005_ai_prompts_ip_tracking.sql +92 -0
- package/supabase/migrations/20260129330006_ai_prompts_slug.sql +64 -0
- package/supabase/migrations/20260129330007_ai_prompts_view_slug.sql +26 -0
- package/supabase/migrations/20260129440000_ai_prompts_view_username.sql +33 -0
- package/supabase/migrations/20260129450000_ai_prompts_add_lang.sql +40 -0
- package/supabase/migrations/20260131000000_extract_model_prompt_in_ledger.sql +92 -0
- package/supabase/migrations/20260131140000_fix_duplicate_purchases.sql +64 -0
- package/supabase/migrations/20260201120000_module-ai_default_models.sql +63 -0
- package/supabase/migrations/20260201130000_module-ai_remove_provider_tables.sql +17 -0
- package/supabase/migrations-down/20251217120000_user_token_quota_monthly.sql +34 -0
- 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
|
-
//
|
|
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:
|
|
45
|
-
cancelPath:
|
|
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
|
-
|
|
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;
|
|
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
|
-
|
|
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;
|
|
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
|
|
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
|
-
|
|
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"}
|