@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,173 @@
|
|
|
1
|
+
-- ===========================================================================
|
|
2
|
+
-- Module: @lastbrain/module-ai
|
|
3
|
+
-- Migration: 20251217120000_user_token_quota_monthly.sql
|
|
4
|
+
-- Description: Monthly token quota for Pro plan (non-cumulative)
|
|
5
|
+
-- ===========================================================================
|
|
6
|
+
|
|
7
|
+
-- ===========================================================================
|
|
8
|
+
-- Table: public.user_token_quota_monthly
|
|
9
|
+
-- Manages monthly included tokens for subscription plans (Pro, Premium, etc.)
|
|
10
|
+
-- Separate from purchased tokens (user_token_ledger)
|
|
11
|
+
-- ===========================================================================
|
|
12
|
+
CREATE TABLE IF NOT EXISTS public.user_token_quota_monthly (
|
|
13
|
+
owner_id uuid PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
14
|
+
|
|
15
|
+
-- Plan information
|
|
16
|
+
plan text NOT NULL DEFAULT 'free', -- 'free', 'pro', 'premium', etc.
|
|
17
|
+
|
|
18
|
+
-- Quota configuration
|
|
19
|
+
default_included_tokens bigint NOT NULL DEFAULT 0, -- Default tokens for plan
|
|
20
|
+
custom_included_tokens bigint NULL, -- Admin override (nullable)
|
|
21
|
+
effective_included_tokens bigint NOT NULL DEFAULT 0, -- Actual quota for period
|
|
22
|
+
|
|
23
|
+
-- Usage tracking
|
|
24
|
+
used_included_tokens bigint NOT NULL DEFAULT 0, -- Tokens consumed this period
|
|
25
|
+
|
|
26
|
+
-- Period management (from Stripe subscription)
|
|
27
|
+
period_start timestamptz NULL,
|
|
28
|
+
period_end timestamptz NULL,
|
|
29
|
+
|
|
30
|
+
-- Metadata
|
|
31
|
+
subscription_id text NULL, -- Stripe subscription ID
|
|
32
|
+
source text NOT NULL DEFAULT 'stripe', -- 'stripe', 'manual', etc.
|
|
33
|
+
|
|
34
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
35
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
36
|
+
|
|
37
|
+
-- Constraints
|
|
38
|
+
CHECK (used_included_tokens >= 0),
|
|
39
|
+
CHECK (used_included_tokens <= effective_included_tokens),
|
|
40
|
+
CHECK (default_included_tokens >= 0),
|
|
41
|
+
CHECK (custom_included_tokens IS NULL OR custom_included_tokens >= 0),
|
|
42
|
+
CHECK (effective_included_tokens >= 0)
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
-- ===========================================================================
|
|
46
|
+
-- Indexes
|
|
47
|
+
-- ===========================================================================
|
|
48
|
+
CREATE INDEX IF NOT EXISTS idx_user_token_quota_monthly_owner ON public.user_token_quota_monthly(owner_id);
|
|
49
|
+
CREATE INDEX IF NOT EXISTS idx_user_token_quota_monthly_plan ON public.user_token_quota_monthly(plan);
|
|
50
|
+
CREATE INDEX IF NOT EXISTS idx_user_token_quota_monthly_period ON public.user_token_quota_monthly(period_start, period_end);
|
|
51
|
+
CREATE INDEX IF NOT EXISTS idx_user_token_quota_monthly_subscription ON public.user_token_quota_monthly(subscription_id) WHERE subscription_id IS NOT NULL;
|
|
52
|
+
|
|
53
|
+
-- ===========================================================================
|
|
54
|
+
-- Table: public.user_token_quota_ledger
|
|
55
|
+
-- Audit log for quota usage (separate from purchased tokens)
|
|
56
|
+
-- ===========================================================================
|
|
57
|
+
CREATE TABLE IF NOT EXISTS public.user_token_quota_ledger (
|
|
58
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
59
|
+
owner_id uuid NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
60
|
+
|
|
61
|
+
-- Usage details
|
|
62
|
+
tokens_used bigint NOT NULL CHECK (tokens_used > 0), -- Always positive
|
|
63
|
+
model text NULL, -- AI model used
|
|
64
|
+
prompt text NULL, -- Prompt used
|
|
65
|
+
|
|
66
|
+
-- Context
|
|
67
|
+
period_start timestamptz NOT NULL, -- Period this usage belongs to
|
|
68
|
+
period_end timestamptz NOT NULL,
|
|
69
|
+
|
|
70
|
+
-- Metadata
|
|
71
|
+
meta jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
72
|
+
|
|
73
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
-- ===========================================================================
|
|
77
|
+
-- Indexes for ledger
|
|
78
|
+
-- ===========================================================================
|
|
79
|
+
CREATE INDEX IF NOT EXISTS idx_user_token_quota_ledger_owner ON public.user_token_quota_ledger(owner_id);
|
|
80
|
+
CREATE INDEX IF NOT EXISTS idx_user_token_quota_ledger_owner_created ON public.user_token_quota_ledger(owner_id, created_at DESC);
|
|
81
|
+
CREATE INDEX IF NOT EXISTS idx_user_token_quota_ledger_period ON public.user_token_quota_ledger(period_start, period_end);
|
|
82
|
+
|
|
83
|
+
-- ===========================================================================
|
|
84
|
+
-- RLS (Row Level Security) - user_token_quota_monthly
|
|
85
|
+
-- ===========================================================================
|
|
86
|
+
ALTER TABLE public.user_token_quota_monthly ENABLE ROW LEVEL SECURITY;
|
|
87
|
+
|
|
88
|
+
-- Users can view their own quota
|
|
89
|
+
DROP POLICY IF EXISTS user_token_quota_monthly_select_own ON public.user_token_quota_monthly;
|
|
90
|
+
CREATE POLICY user_token_quota_monthly_select_own
|
|
91
|
+
ON public.user_token_quota_monthly
|
|
92
|
+
FOR SELECT
|
|
93
|
+
USING (
|
|
94
|
+
owner_id = (SELECT auth.uid())
|
|
95
|
+
OR is_superadmin((SELECT auth.uid()))
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
-- Only superadmins can insert/update/delete
|
|
99
|
+
DROP POLICY IF EXISTS user_token_quota_monthly_admin_all ON public.user_token_quota_monthly;
|
|
100
|
+
CREATE POLICY user_token_quota_monthly_admin_all
|
|
101
|
+
ON public.user_token_quota_monthly
|
|
102
|
+
FOR ALL
|
|
103
|
+
USING (is_superadmin((SELECT auth.uid())));
|
|
104
|
+
|
|
105
|
+
-- ===========================================================================
|
|
106
|
+
-- RLS (Row Level Security) - user_token_quota_ledger
|
|
107
|
+
-- ===========================================================================
|
|
108
|
+
ALTER TABLE public.user_token_quota_ledger ENABLE ROW LEVEL SECURITY;
|
|
109
|
+
|
|
110
|
+
-- Users can view their own quota usage history
|
|
111
|
+
DROP POLICY IF EXISTS user_token_quota_ledger_select_own ON public.user_token_quota_ledger;
|
|
112
|
+
CREATE POLICY user_token_quota_ledger_select_own
|
|
113
|
+
ON public.user_token_quota_ledger
|
|
114
|
+
FOR SELECT
|
|
115
|
+
USING (
|
|
116
|
+
owner_id = (SELECT auth.uid())
|
|
117
|
+
OR is_superadmin((SELECT auth.uid()))
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
-- Service role can insert (via API)
|
|
121
|
+
-- No direct user insert allowed
|
|
122
|
+
|
|
123
|
+
-- Only superadmins can update/delete
|
|
124
|
+
DROP POLICY IF EXISTS user_token_quota_ledger_admin_all ON public.user_token_quota_ledger;
|
|
125
|
+
CREATE POLICY user_token_quota_ledger_admin_all
|
|
126
|
+
ON public.user_token_quota_ledger
|
|
127
|
+
FOR ALL
|
|
128
|
+
USING (is_superadmin((SELECT auth.uid())));
|
|
129
|
+
|
|
130
|
+
-- ===========================================================================
|
|
131
|
+
-- Trigger for updated_at
|
|
132
|
+
-- ===========================================================================
|
|
133
|
+
DROP TRIGGER IF EXISTS set_user_token_quota_monthly_updated_at ON public.user_token_quota_monthly;
|
|
134
|
+
CREATE TRIGGER set_user_token_quota_monthly_updated_at
|
|
135
|
+
BEFORE UPDATE ON public.user_token_quota_monthly
|
|
136
|
+
FOR EACH ROW
|
|
137
|
+
EXECUTE FUNCTION public.set_updated_at();
|
|
138
|
+
|
|
139
|
+
-- ===========================================================================
|
|
140
|
+
-- Helper function: Get plan default quota
|
|
141
|
+
-- ===========================================================================
|
|
142
|
+
CREATE OR REPLACE FUNCTION public.get_plan_default_tokens(plan_name text)
|
|
143
|
+
RETURNS bigint
|
|
144
|
+
LANGUAGE plpgsql
|
|
145
|
+
STABLE
|
|
146
|
+
AS $$
|
|
147
|
+
BEGIN
|
|
148
|
+
RETURN CASE plan_name
|
|
149
|
+
WHEN 'pro' THEN 100000
|
|
150
|
+
WHEN 'premium' THEN 500000
|
|
151
|
+
WHEN 'enterprise' THEN 2000000
|
|
152
|
+
ELSE 0
|
|
153
|
+
END;
|
|
154
|
+
END;
|
|
155
|
+
$$;
|
|
156
|
+
|
|
157
|
+
-- ===========================================================================
|
|
158
|
+
-- Grants
|
|
159
|
+
-- ===========================================================================
|
|
160
|
+
GRANT SELECT ON public.user_token_quota_monthly TO authenticated;
|
|
161
|
+
GRANT SELECT ON public.user_token_quota_ledger TO authenticated;
|
|
162
|
+
GRANT ALL ON public.user_token_quota_monthly TO service_role;
|
|
163
|
+
GRANT ALL ON public.user_token_quota_ledger TO service_role;
|
|
164
|
+
|
|
165
|
+
-- ===========================================================================
|
|
166
|
+
-- Comments
|
|
167
|
+
-- ===========================================================================
|
|
168
|
+
COMMENT ON TABLE public.user_token_quota_monthly IS 'Monthly token quota for subscription plans (non-cumulative, resets each period)';
|
|
169
|
+
COMMENT ON TABLE public.user_token_quota_ledger IS 'Audit log for monthly quota usage (separate from purchased tokens)';
|
|
170
|
+
COMMENT ON COLUMN public.user_token_quota_monthly.default_included_tokens IS 'Default tokens for the plan (100K for Pro, 500K for Premium)';
|
|
171
|
+
COMMENT ON COLUMN public.user_token_quota_monthly.custom_included_tokens IS 'Admin override for custom quota per owner';
|
|
172
|
+
COMMENT ON COLUMN public.user_token_quota_monthly.effective_included_tokens IS 'Actual quota for current period (custom or default)';
|
|
173
|
+
COMMENT ON COLUMN public.user_token_quota_monthly.used_included_tokens IS 'Tokens consumed from quota this period';
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
-- module-ai: add external API primitives (api keys, AI settings, call logs)
|
|
2
|
+
-- and extend token ledgers for multi-provider usage.
|
|
3
|
+
|
|
4
|
+
begin;
|
|
5
|
+
|
|
6
|
+
-- -----------------------------------------------------------------------------
|
|
7
|
+
-- 1) Fix user_token_ledger type check (allow signup_bonus)
|
|
8
|
+
-- -----------------------------------------------------------------------------
|
|
9
|
+
alter table public.user_token_ledger
|
|
10
|
+
drop constraint if exists user_token_ledger_type_check;
|
|
11
|
+
|
|
12
|
+
alter table public.user_token_ledger
|
|
13
|
+
add constraint user_token_ledger_type_check
|
|
14
|
+
check (
|
|
15
|
+
type = any (
|
|
16
|
+
array[
|
|
17
|
+
'purchase'::text,
|
|
18
|
+
'gift'::text,
|
|
19
|
+
'use'::text,
|
|
20
|
+
'adjust'::text,
|
|
21
|
+
'signup_bonus'::text
|
|
22
|
+
]
|
|
23
|
+
)
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
-- -----------------------------------------------------------------------------
|
|
27
|
+
-- 2) Add provider columns to ledgers (for multi-provider routing)
|
|
28
|
+
-- -----------------------------------------------------------------------------
|
|
29
|
+
alter table public.user_token_ledger
|
|
30
|
+
add column if not exists provider text null;
|
|
31
|
+
|
|
32
|
+
alter table public.user_token_quota_ledger
|
|
33
|
+
add column if not exists provider text null;
|
|
34
|
+
|
|
35
|
+
-- Helpful indexes for provider/model breakdowns
|
|
36
|
+
create index if not exists idx_user_token_ledger_owner_provider_ts
|
|
37
|
+
on public.user_token_ledger (owner_id, provider, ts desc);
|
|
38
|
+
|
|
39
|
+
create index if not exists idx_user_token_quota_ledger_owner_provider_created
|
|
40
|
+
on public.user_token_quota_ledger (owner_id, provider, created_at desc);
|
|
41
|
+
|
|
42
|
+
-- -----------------------------------------------------------------------------
|
|
43
|
+
-- 3) API Keys table (external access)
|
|
44
|
+
-- -----------------------------------------------------------------------------
|
|
45
|
+
create table if not exists public.api_keys (
|
|
46
|
+
id uuid primary key default gen_random_uuid(),
|
|
47
|
+
owner_id uuid not null references auth.users(id) on delete cascade,
|
|
48
|
+
|
|
49
|
+
-- Display name for dashboard
|
|
50
|
+
name text not null,
|
|
51
|
+
|
|
52
|
+
-- Never store the raw key. Store only a hash + a small prefix for UI.
|
|
53
|
+
key_hash text not null,
|
|
54
|
+
prefix text not null,
|
|
55
|
+
|
|
56
|
+
-- dev/prod segregation
|
|
57
|
+
env text not null default 'prod',
|
|
58
|
+
|
|
59
|
+
-- scopes like ["text","image","status","metrics"]
|
|
60
|
+
scopes jsonb not null default '[]'::jsonb,
|
|
61
|
+
|
|
62
|
+
-- safety limits (enforced server-side)
|
|
63
|
+
rate_limit_rpm integer not null default 60,
|
|
64
|
+
daily_token_limit bigint null,
|
|
65
|
+
|
|
66
|
+
is_active boolean not null default true,
|
|
67
|
+
last_used_at timestamptz null,
|
|
68
|
+
|
|
69
|
+
created_at timestamptz not null default now()
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
create unique index if not exists idx_api_keys_key_hash_unique
|
|
73
|
+
on public.api_keys (key_hash);
|
|
74
|
+
|
|
75
|
+
create index if not exists idx_api_keys_owner
|
|
76
|
+
on public.api_keys (owner_id);
|
|
77
|
+
|
|
78
|
+
create index if not exists idx_api_keys_owner_created
|
|
79
|
+
on public.api_keys (owner_id, created_at desc);
|
|
80
|
+
|
|
81
|
+
create index if not exists idx_api_keys_prefix
|
|
82
|
+
on public.api_keys (prefix);
|
|
83
|
+
|
|
84
|
+
-- -----------------------------------------------------------------------------
|
|
85
|
+
-- 4) User AI settings (default provider/model + limits)
|
|
86
|
+
-- -----------------------------------------------------------------------------
|
|
87
|
+
create table if not exists public.user_ai_settings (
|
|
88
|
+
owner_id uuid primary key references auth.users(id) on delete cascade,
|
|
89
|
+
|
|
90
|
+
mode text not null default 'auto',
|
|
91
|
+
|
|
92
|
+
default_text_provider text null,
|
|
93
|
+
default_text_model text null,
|
|
94
|
+
|
|
95
|
+
default_image_provider text null,
|
|
96
|
+
default_image_model text null,
|
|
97
|
+
|
|
98
|
+
max_tokens_per_call integer null,
|
|
99
|
+
|
|
100
|
+
-- optional allowlist: [{"provider":"openai","models":[...]}]
|
|
101
|
+
allowed_models jsonb not null default '[]'::jsonb,
|
|
102
|
+
|
|
103
|
+
created_at timestamptz not null default now(),
|
|
104
|
+
updated_at timestamptz not null default now()
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
create index if not exists idx_user_ai_settings_mode
|
|
108
|
+
on public.user_ai_settings (mode);
|
|
109
|
+
|
|
110
|
+
-- -----------------------------------------------------------------------------
|
|
111
|
+
-- 5) AI call log (observability + usage breakdown)
|
|
112
|
+
-- Note: do NOT store raw prompts/payloads here.
|
|
113
|
+
-- -----------------------------------------------------------------------------
|
|
114
|
+
create table if not exists public.ai_call_log (
|
|
115
|
+
id uuid primary key default gen_random_uuid(),
|
|
116
|
+
owner_id uuid not null references auth.users(id) on delete cascade,
|
|
117
|
+
api_key_id uuid null references public.api_keys(id) on delete set null,
|
|
118
|
+
|
|
119
|
+
endpoint text not null, -- text|image|status|metrics
|
|
120
|
+
provider text null,
|
|
121
|
+
model text null,
|
|
122
|
+
|
|
123
|
+
tokens_in integer null,
|
|
124
|
+
tokens_out integer null,
|
|
125
|
+
tokens_total integer null,
|
|
126
|
+
|
|
127
|
+
latency_ms integer null,
|
|
128
|
+
status_code integer not null default 200,
|
|
129
|
+
error_code text null,
|
|
130
|
+
|
|
131
|
+
-- safe metadata only (request_id, sizes, etc.)
|
|
132
|
+
meta jsonb not null default '{}'::jsonb,
|
|
133
|
+
|
|
134
|
+
created_at timestamptz not null default now()
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
create index if not exists idx_ai_call_log_owner_created
|
|
138
|
+
on public.ai_call_log (owner_id, created_at desc);
|
|
139
|
+
|
|
140
|
+
create index if not exists idx_ai_call_log_owner_model
|
|
141
|
+
on public.ai_call_log (owner_id, provider, model);
|
|
142
|
+
|
|
143
|
+
create index if not exists idx_ai_call_log_api_key
|
|
144
|
+
on public.ai_call_log (api_key_id);
|
|
145
|
+
|
|
146
|
+
-- -----------------------------------------------------------------------------
|
|
147
|
+
-- 6) RLS
|
|
148
|
+
-- -----------------------------------------------------------------------------
|
|
149
|
+
alter table public.api_keys enable row level security;
|
|
150
|
+
alter table public.user_ai_settings enable row level security;
|
|
151
|
+
alter table public.ai_call_log enable row level security;
|
|
152
|
+
|
|
153
|
+
-- api_keys: owners can manage their keys
|
|
154
|
+
drop policy if exists api_keys_select_own on public.api_keys;
|
|
155
|
+
create policy api_keys_select_own
|
|
156
|
+
on public.api_keys for select
|
|
157
|
+
using (
|
|
158
|
+
owner_id = auth.uid() OR is_superadmin(auth.uid())
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
drop policy if exists api_keys_insert_own on public.api_keys;
|
|
162
|
+
create policy api_keys_insert_own
|
|
163
|
+
on public.api_keys for insert
|
|
164
|
+
with check (
|
|
165
|
+
owner_id = auth.uid() OR is_superadmin(auth.uid())
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
drop policy if exists api_keys_update_own on public.api_keys;
|
|
169
|
+
create policy api_keys_update_own
|
|
170
|
+
on public.api_keys for update
|
|
171
|
+
using (
|
|
172
|
+
owner_id = auth.uid() OR is_superadmin(auth.uid())
|
|
173
|
+
)
|
|
174
|
+
with check (
|
|
175
|
+
owner_id = auth.uid() OR is_superadmin(auth.uid())
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
drop policy if exists api_keys_delete_own on public.api_keys;
|
|
179
|
+
create policy api_keys_delete_own
|
|
180
|
+
on public.api_keys for delete
|
|
181
|
+
using (
|
|
182
|
+
owner_id = auth.uid() OR is_superadmin(auth.uid())
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
-- user_ai_settings: owners can read/write their settings row
|
|
186
|
+
drop policy if exists user_ai_settings_select_own on public.user_ai_settings;
|
|
187
|
+
create policy user_ai_settings_select_own
|
|
188
|
+
on public.user_ai_settings for select
|
|
189
|
+
using (
|
|
190
|
+
owner_id = auth.uid() OR is_superadmin(auth.uid())
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
drop policy if exists user_ai_settings_insert_own on public.user_ai_settings;
|
|
194
|
+
create policy user_ai_settings_insert_own
|
|
195
|
+
on public.user_ai_settings for insert
|
|
196
|
+
with check (
|
|
197
|
+
owner_id = auth.uid() OR is_superadmin(auth.uid())
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
drop policy if exists user_ai_settings_update_own on public.user_ai_settings;
|
|
201
|
+
create policy user_ai_settings_update_own
|
|
202
|
+
on public.user_ai_settings for update
|
|
203
|
+
using (
|
|
204
|
+
owner_id = auth.uid() OR is_superadmin(auth.uid())
|
|
205
|
+
)
|
|
206
|
+
with check (
|
|
207
|
+
owner_id = auth.uid() OR is_superadmin(auth.uid())
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
-- ai_call_log: owners can read their logs. Inserts are expected from server/service role.
|
|
211
|
+
drop policy if exists ai_call_log_select_own on public.ai_call_log;
|
|
212
|
+
create policy ai_call_log_select_own
|
|
213
|
+
on public.ai_call_log for select
|
|
214
|
+
using (
|
|
215
|
+
owner_id = auth.uid() OR is_superadmin(auth.uid())
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
-- Optional: allow authenticated inserts (useful for internal calls without service role)
|
|
219
|
+
drop policy if exists ai_call_log_insert_own on public.ai_call_log;
|
|
220
|
+
create policy ai_call_log_insert_own
|
|
221
|
+
on public.ai_call_log for insert
|
|
222
|
+
with check (
|
|
223
|
+
owner_id = auth.uid() OR is_superadmin(auth.uid())
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
-- -----------------------------------------------------------------------------
|
|
227
|
+
-- 7) updated_at maintenance for user_ai_settings
|
|
228
|
+
-- -----------------------------------------------------------------------------
|
|
229
|
+
create or replace function public.set_updated_at()
|
|
230
|
+
returns trigger
|
|
231
|
+
language plpgsql
|
|
232
|
+
as $$
|
|
233
|
+
begin
|
|
234
|
+
new.updated_at = now();
|
|
235
|
+
return new;
|
|
236
|
+
end;
|
|
237
|
+
$$;
|
|
238
|
+
|
|
239
|
+
drop trigger if exists trg_user_ai_settings_updated_at on public.user_ai_settings;
|
|
240
|
+
create trigger trg_user_ai_settings_updated_at
|
|
241
|
+
before update on public.user_ai_settings
|
|
242
|
+
for each row execute function public.set_updated_at();
|
|
243
|
+
|
|
244
|
+
-- -----------------------------------------------------------------------------
|
|
245
|
+
-- 8) Providers & models catalog (what LastBrain exposes to clients)
|
|
246
|
+
-- -----------------------------------------------------------------------------
|
|
247
|
+
create table if not exists public.ai_providers (
|
|
248
|
+
key text primary key, -- e.g. openai, anthropic, mistral, groq
|
|
249
|
+
name text not null,
|
|
250
|
+
|
|
251
|
+
is_active boolean not null default true,
|
|
252
|
+
|
|
253
|
+
supports_text boolean not null default true,
|
|
254
|
+
supports_image boolean not null default false,
|
|
255
|
+
|
|
256
|
+
meta jsonb not null default '{}'::jsonb,
|
|
257
|
+
|
|
258
|
+
created_at timestamptz not null default now(),
|
|
259
|
+
updated_at timestamptz not null default now()
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
create index if not exists idx_ai_providers_active
|
|
263
|
+
on public.ai_providers (is_active);
|
|
264
|
+
|
|
265
|
+
create table if not exists public.ai_provider_models (
|
|
266
|
+
id uuid primary key default gen_random_uuid(),
|
|
267
|
+
provider_key text not null references public.ai_providers(key) on delete cascade,
|
|
268
|
+
|
|
269
|
+
model text not null,
|
|
270
|
+
kind text not null, -- text|image
|
|
271
|
+
|
|
272
|
+
is_active boolean not null default true,
|
|
273
|
+
|
|
274
|
+
-- pricing conversion: how many LastBrain tokens to charge per provider token
|
|
275
|
+
input_token_factor numeric null,
|
|
276
|
+
output_token_factor numeric null,
|
|
277
|
+
|
|
278
|
+
-- for image models, you may charge a fixed cost per generation
|
|
279
|
+
image_cost_tokens bigint null,
|
|
280
|
+
|
|
281
|
+
max_output_tokens integer null,
|
|
282
|
+
|
|
283
|
+
meta jsonb not null default '{}'::jsonb,
|
|
284
|
+
|
|
285
|
+
created_at timestamptz not null default now(),
|
|
286
|
+
updated_at timestamptz not null default now(),
|
|
287
|
+
|
|
288
|
+
constraint ai_provider_models_kind_check check (kind = any (array['text'::text,'image'::text]))
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
create unique index if not exists idx_ai_provider_models_unique
|
|
292
|
+
on public.ai_provider_models (provider_key, model, kind);
|
|
293
|
+
|
|
294
|
+
create index if not exists idx_ai_provider_models_active
|
|
295
|
+
on public.ai_provider_models (is_active, kind);
|
|
296
|
+
|
|
297
|
+
create index if not exists idx_ai_provider_models_provider
|
|
298
|
+
on public.ai_provider_models (provider_key);
|
|
299
|
+
|
|
300
|
+
-- RLS
|
|
301
|
+
alter table public.ai_providers enable row level security;
|
|
302
|
+
alter table public.ai_provider_models enable row level security;
|
|
303
|
+
|
|
304
|
+
-- Public read (authenticated) for discovery endpoints; superadmin can manage.
|
|
305
|
+
drop policy if exists ai_providers_select on public.ai_providers;
|
|
306
|
+
create policy ai_providers_select
|
|
307
|
+
on public.ai_providers for select
|
|
308
|
+
using (true);
|
|
309
|
+
|
|
310
|
+
-- Only superadmin can write
|
|
311
|
+
|
|
312
|
+
drop policy if exists ai_providers_insert on public.ai_providers;
|
|
313
|
+
create policy ai_providers_insert
|
|
314
|
+
on public.ai_providers for insert
|
|
315
|
+
with check (is_superadmin(auth.uid()));
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
drop policy if exists ai_providers_update on public.ai_providers;
|
|
319
|
+
create policy ai_providers_update
|
|
320
|
+
on public.ai_providers for update
|
|
321
|
+
using (is_superadmin(auth.uid()))
|
|
322
|
+
with check (is_superadmin(auth.uid()));
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
drop policy if exists ai_providers_delete on public.ai_providers;
|
|
326
|
+
create policy ai_providers_delete
|
|
327
|
+
on public.ai_providers for delete
|
|
328
|
+
using (is_superadmin(auth.uid()));
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
drop policy if exists ai_provider_models_select on public.ai_provider_models;
|
|
332
|
+
create policy ai_provider_models_select
|
|
333
|
+
on public.ai_provider_models for select
|
|
334
|
+
using (true);
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
drop policy if exists ai_provider_models_insert on public.ai_provider_models;
|
|
338
|
+
create policy ai_provider_models_insert
|
|
339
|
+
on public.ai_provider_models for insert
|
|
340
|
+
with check (is_superadmin(auth.uid()));
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
drop policy if exists ai_provider_models_update on public.ai_provider_models;
|
|
344
|
+
create policy ai_provider_models_update
|
|
345
|
+
on public.ai_provider_models for update
|
|
346
|
+
using (is_superadmin(auth.uid()))
|
|
347
|
+
with check (is_superadmin(auth.uid()));
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
drop policy if exists ai_provider_models_delete on public.ai_provider_models;
|
|
351
|
+
create policy ai_provider_models_delete
|
|
352
|
+
on public.ai_provider_models for delete
|
|
353
|
+
using (is_superadmin(auth.uid()));
|
|
354
|
+
|
|
355
|
+
-- updated_at triggers
|
|
356
|
+
|
|
357
|
+
drop trigger if exists trg_ai_providers_updated_at on public.ai_providers;
|
|
358
|
+
create trigger trg_ai_providers_updated_at
|
|
359
|
+
before update on public.ai_providers
|
|
360
|
+
for each row execute function public.set_updated_at();
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
drop trigger if exists trg_ai_provider_models_updated_at on public.ai_provider_models;
|
|
364
|
+
create trigger trg_ai_provider_models_updated_at
|
|
365
|
+
before update on public.ai_provider_models
|
|
366
|
+
for each row execute function public.set_updated_at();
|
|
367
|
+
|
|
368
|
+
commit;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
-- Seed initial AI providers and models for public API v1
|
|
2
|
+
-- This script should be run after the main migration (20260128100003_update_and_add_table.sql)
|
|
3
|
+
-- Updated to support Vercel AI Gateway provider/model notation
|
|
4
|
+
|
|
5
|
+
begin;
|
|
6
|
+
|
|
7
|
+
-- Insert OpenAI provider (if not exists)
|
|
8
|
+
insert into public.ai_providers (key, name, is_active, supports_text, supports_image)
|
|
9
|
+
values ('openai', 'OpenAI', true, true, true)
|
|
10
|
+
on conflict (key) do update
|
|
11
|
+
set name = excluded.name,
|
|
12
|
+
is_active = excluded.is_active,
|
|
13
|
+
supports_text = excluded.supports_text,
|
|
14
|
+
supports_image = excluded.supports_image;
|
|
15
|
+
|
|
16
|
+
-- Insert OpenAI text models
|
|
17
|
+
-- Note: Vercel AI uses provider/model format like "openai/gpt-4o-mini"
|
|
18
|
+
-- We store just the model name here and construct the full ID at runtime
|
|
19
|
+
insert into public.ai_provider_models (provider_key, model, kind, is_active, input_token_factor, output_token_factor, max_output_tokens)
|
|
20
|
+
values
|
|
21
|
+
('openai', 'gpt-4o-mini', 'text', true, 1.0, 1.0, 16384),
|
|
22
|
+
('openai', 'gpt-4o', 'text', true, 2.5, 10.0, 16384),
|
|
23
|
+
('openai', 'gpt-4-turbo', 'text', true, 10.0, 30.0, 4096),
|
|
24
|
+
('openai', 'gpt-3.5-turbo', 'text', true, 0.5, 1.5, 4096)
|
|
25
|
+
on conflict (provider_key, model, kind) do update
|
|
26
|
+
set is_active = excluded.is_active,
|
|
27
|
+
input_token_factor = excluded.input_token_factor,
|
|
28
|
+
output_token_factor = excluded.output_token_factor,
|
|
29
|
+
max_output_tokens = excluded.max_output_tokens;
|
|
30
|
+
|
|
31
|
+
-- Insert OpenAI image models
|
|
32
|
+
insert into public.ai_provider_models (provider_key, model, kind, is_active, image_cost_tokens)
|
|
33
|
+
values
|
|
34
|
+
('openai', 'dall-e-3', 'image', true, 6000),
|
|
35
|
+
('openai', 'dall-e-2', 'image', true, 5000),
|
|
36
|
+
('openai', 'gpt-image-1', 'image', true, 6000)
|
|
37
|
+
on conflict (provider_key, model, kind) do update
|
|
38
|
+
set is_active = excluded.is_active,
|
|
39
|
+
image_cost_tokens = excluded.image_cost_tokens;
|
|
40
|
+
|
|
41
|
+
-- Insert Anthropic provider (for future use with Vercel AI)
|
|
42
|
+
insert into public.ai_providers (key, name, is_active, supports_text, supports_image)
|
|
43
|
+
values ('anthropic', 'Anthropic (Claude)', false, true, false)
|
|
44
|
+
on conflict (key) do nothing;
|
|
45
|
+
|
|
46
|
+
-- Insert Mistral provider (for future use with Vercel AI)
|
|
47
|
+
insert into public.ai_providers (key, name, is_active, supports_text, supports_image)
|
|
48
|
+
values ('mistral', 'Mistral AI', false, true, false)
|
|
49
|
+
on conflict (key) do nothing;
|
|
50
|
+
|
|
51
|
+
-- Insert Google provider (Gemini models)
|
|
52
|
+
insert into public.ai_providers (key, name, is_active, supports_text, supports_image)
|
|
53
|
+
values ('google', 'Google (Gemini)', true, true, true)
|
|
54
|
+
on conflict (key) do update
|
|
55
|
+
set name = excluded.name,
|
|
56
|
+
is_active = excluded.is_active,
|
|
57
|
+
supports_text = excluded.supports_text,
|
|
58
|
+
supports_image = excluded.supports_image;
|
|
59
|
+
|
|
60
|
+
-- Insert Google image model for Gemini
|
|
61
|
+
insert into public.ai_provider_models (provider_key, model, kind, is_active, image_cost_tokens)
|
|
62
|
+
values
|
|
63
|
+
('google', 'gemini-2.5-flash-image', 'image', true, 3000)
|
|
64
|
+
on conflict (provider_key, model, kind) do update
|
|
65
|
+
set is_active = excluded.is_active,
|
|
66
|
+
image_cost_tokens = excluded.image_cost_tokens;
|
|
67
|
+
|
|
68
|
+
-- Add gpt-4.1-mini to OpenAI models
|
|
69
|
+
insert into public.ai_provider_models (provider_key, model, kind, is_active, input_token_factor, output_token_factor, max_output_tokens)
|
|
70
|
+
values
|
|
71
|
+
('openai', 'gpt-4.1-mini', 'text', true, 1.0, 1.0, 16384)
|
|
72
|
+
on conflict (provider_key, model, kind) do update
|
|
73
|
+
set is_active = excluded.is_active,
|
|
74
|
+
input_token_factor = excluded.input_token_factor,
|
|
75
|
+
output_token_factor = excluded.output_token_factor,
|
|
76
|
+
max_output_tokens = excluded.max_output_tokens;
|
|
77
|
+
|
|
78
|
+
commit;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
-- module-ai: add api_key_id to ledger tables for tracking API key usage
|
|
2
|
+
|
|
3
|
+
begin;
|
|
4
|
+
|
|
5
|
+
-- -----------------------------------------------------------------------------
|
|
6
|
+
-- Add api_key_id column to user_token_ledger
|
|
7
|
+
-- -----------------------------------------------------------------------------
|
|
8
|
+
alter table public.user_token_ledger
|
|
9
|
+
add column if not exists api_key_id uuid null
|
|
10
|
+
references public.api_keys(id) on delete set null;
|
|
11
|
+
|
|
12
|
+
comment on column public.user_token_ledger.api_key_id is
|
|
13
|
+
'Reference to the API key used for this transaction (null for manual/admin operations)';
|
|
14
|
+
|
|
15
|
+
-- Index for filtering by API key
|
|
16
|
+
create index if not exists idx_user_token_ledger_api_key_id
|
|
17
|
+
on public.user_token_ledger (api_key_id, ts desc);
|
|
18
|
+
|
|
19
|
+
-- Composite index for owner + api_key filtering
|
|
20
|
+
create index if not exists idx_user_token_ledger_owner_api_key
|
|
21
|
+
on public.user_token_ledger (owner_id, api_key_id, ts desc);
|
|
22
|
+
|
|
23
|
+
-- -----------------------------------------------------------------------------
|
|
24
|
+
-- Add api_key_id column to user_token_quota_ledger
|
|
25
|
+
-- -----------------------------------------------------------------------------
|
|
26
|
+
alter table public.user_token_quota_ledger
|
|
27
|
+
add column if not exists api_key_id uuid null
|
|
28
|
+
references public.api_keys(id) on delete set null;
|
|
29
|
+
|
|
30
|
+
comment on column public.user_token_quota_ledger.api_key_id is
|
|
31
|
+
'Reference to the API key used for this quota transaction (null for manual/admin operations)';
|
|
32
|
+
|
|
33
|
+
-- Index for filtering by API key
|
|
34
|
+
create index if not exists idx_user_token_quota_ledger_api_key_id
|
|
35
|
+
on public.user_token_quota_ledger (api_key_id, created_at desc);
|
|
36
|
+
|
|
37
|
+
-- Composite index for owner + api_key filtering
|
|
38
|
+
create index if not exists idx_user_token_quota_ledger_owner_api_key
|
|
39
|
+
on public.user_token_quota_ledger (owner_id, api_key_id, created_at desc);
|
|
40
|
+
|
|
41
|
+
commit;
|