@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
|
@@ -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
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"
|
|
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
|
|
12
|
+
if (amount === 0) {
|
|
8
13
|
return {
|
|
9
14
|
success: false,
|
|
10
15
|
balance: 0,
|
|
11
|
-
error: "Le montant
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 @@
|
|
|
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 @@
|
|
|
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"}
|