@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,279 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useState, useEffect } from "react";
|
|
4
|
+
import { Card, CardBody, CardHeader, Button, Table, TableHeader, TableColumn, TableBody, TableRow, TableCell, Spinner, addToast, Chip, Select, SelectItem, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, FileManager, Textarea, CopyButton, Image, } from "@lastbrain/ui";
|
|
5
|
+
import { History, Trash2, Eye, Download, FolderOpen, Ban } from "lucide-react";
|
|
6
|
+
import { useAuth, useModuleTranslation } from "@lastbrain/core";
|
|
7
|
+
import { logger } from "@lastbrain/core";
|
|
8
|
+
export function HistoryPage() {
|
|
9
|
+
const t = useModuleTranslation("ai");
|
|
10
|
+
const { user } = useAuth();
|
|
11
|
+
const [artifacts, setArtifacts] = useState([]);
|
|
12
|
+
const [loading, setLoading] = useState(true);
|
|
13
|
+
const [kindFilter, setKindFilter] = useState("all");
|
|
14
|
+
const [selectedArtifact, setSelectedArtifact] = useState(null);
|
|
15
|
+
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
16
|
+
const [loadingDetail, setLoadingDetail] = useState(false);
|
|
17
|
+
const [hasMore, setHasMore] = useState(false);
|
|
18
|
+
const [cursor, setCursor] = useState();
|
|
19
|
+
const [isFileManagerOpen, setIsFileManagerOpen] = useState(false);
|
|
20
|
+
const [filePath, setFilePath] = useState("");
|
|
21
|
+
const [imageUrls, setImageUrls] = useState(new Map());
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (user?.id) {
|
|
24
|
+
fetchArtifacts();
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
setLoading(false);
|
|
28
|
+
}
|
|
29
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
30
|
+
}, [kindFilter, user?.id]);
|
|
31
|
+
const fetchArtifacts = async (nextCursor) => {
|
|
32
|
+
if (!user) {
|
|
33
|
+
setLoading(false);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
setLoading(true);
|
|
38
|
+
// Get API key for auth
|
|
39
|
+
const apiKeysResponse = await fetch("/api/ai/auth/api-keys");
|
|
40
|
+
if (!apiKeysResponse.ok) {
|
|
41
|
+
throw new Error("Failed to get API keys");
|
|
42
|
+
}
|
|
43
|
+
const keysData = await apiKeysResponse.json();
|
|
44
|
+
const apiKeys = keysData.data || [];
|
|
45
|
+
if (apiKeys.length === 0) {
|
|
46
|
+
addToast({
|
|
47
|
+
color: "warning",
|
|
48
|
+
title: t("history.toast_no_api_key"),
|
|
49
|
+
});
|
|
50
|
+
setLoading(false);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const apiKey = apiKeys[0]; // Use first available key
|
|
54
|
+
// Fetch artifacts
|
|
55
|
+
const params = new URLSearchParams({
|
|
56
|
+
kind: kindFilter,
|
|
57
|
+
limit: "20",
|
|
58
|
+
});
|
|
59
|
+
if (nextCursor) {
|
|
60
|
+
params.append("cursor", nextCursor);
|
|
61
|
+
}
|
|
62
|
+
const response = await fetch(`/api/public/v1/history?${params.toString()}`, {
|
|
63
|
+
headers: {
|
|
64
|
+
Authorization: `Bearer ${apiKey.key || apiKey.prefix}...`,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
if (!response.ok) {
|
|
68
|
+
throw new Error("Failed to fetch history");
|
|
69
|
+
}
|
|
70
|
+
const data = await response.json();
|
|
71
|
+
if (nextCursor) {
|
|
72
|
+
setArtifacts((prev) => [...prev, ...data.items]);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
setArtifacts(data.items);
|
|
76
|
+
}
|
|
77
|
+
setHasMore(data.pagination.has_more);
|
|
78
|
+
setCursor(data.pagination.next_cursor);
|
|
79
|
+
// Load signed URLs for images
|
|
80
|
+
const imageArtifacts = data.items.filter((item) => item.kind === "image" && item.has_storage);
|
|
81
|
+
for (const artifact of imageArtifacts) {
|
|
82
|
+
loadImageUrl(artifact.id);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
logger.error("Failed to fetch artifacts", error);
|
|
87
|
+
addToast({
|
|
88
|
+
color: "danger",
|
|
89
|
+
title: t("history.toast_load_failed"),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
setLoading(false);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const loadImageUrl = async (artifactId) => {
|
|
97
|
+
try {
|
|
98
|
+
const apiKeysResponse = await fetch("/api/ai/auth/api-keys");
|
|
99
|
+
const keysData = await apiKeysResponse.json();
|
|
100
|
+
const apiKeys = keysData.data || [];
|
|
101
|
+
const apiKey = apiKeys[0];
|
|
102
|
+
const response = await fetch(`/api/public/v1/history/${artifactId}`, {
|
|
103
|
+
headers: {
|
|
104
|
+
Authorization: `Bearer ${apiKey.key || apiKey.prefix}...`,
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
if (response.ok) {
|
|
108
|
+
const data = await response.json();
|
|
109
|
+
if (data.artifact.download_url) {
|
|
110
|
+
setImageUrls((prev) => new Map(prev).set(artifactId, data.artifact.download_url));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
logger.debug("Failed to load image URL", error);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
const viewArtifact = async (id) => {
|
|
119
|
+
try {
|
|
120
|
+
setLoadingDetail(true);
|
|
121
|
+
setIsModalOpen(true);
|
|
122
|
+
// Get API key
|
|
123
|
+
const apiKeysResponse = await fetch("/api/ai/auth/api-keys");
|
|
124
|
+
const keysData = await apiKeysResponse.json();
|
|
125
|
+
const apiKeys = keysData.data || [];
|
|
126
|
+
const apiKey = apiKeys[0];
|
|
127
|
+
const response = await fetch(`/api/public/v1/history/${id}`, {
|
|
128
|
+
headers: {
|
|
129
|
+
Authorization: `Bearer ${apiKey.key || apiKey.prefix}...`,
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
if (!response.ok) {
|
|
133
|
+
throw new Error("Failed to fetch artifact detail");
|
|
134
|
+
}
|
|
135
|
+
const data = await response.json();
|
|
136
|
+
setSelectedArtifact(data.artifact);
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
logger.error("Failed to fetch artifact detail", error);
|
|
140
|
+
addToast({
|
|
141
|
+
color: "danger",
|
|
142
|
+
title: t("history.toast_artifact_failed"),
|
|
143
|
+
});
|
|
144
|
+
setIsModalOpen(false);
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
setLoadingDetail(false);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
const deleteArtifact = async (id) => {
|
|
151
|
+
if (!confirm(t("history.confirm_delete")))
|
|
152
|
+
return;
|
|
153
|
+
try {
|
|
154
|
+
// Get API key
|
|
155
|
+
const apiKeysResponse = await fetch("/api/ai/auth/api-keys");
|
|
156
|
+
const keysData = await apiKeysResponse.json();
|
|
157
|
+
const apiKeys = keysData.data || [];
|
|
158
|
+
const apiKey = apiKeys[0];
|
|
159
|
+
const response = await fetch(`/api/public/v1/history/${id}`, {
|
|
160
|
+
method: "DELETE",
|
|
161
|
+
headers: {
|
|
162
|
+
Authorization: `Bearer ${apiKey.key || apiKey.prefix}...`,
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
if (!response.ok) {
|
|
166
|
+
throw new Error("Failed to delete artifact");
|
|
167
|
+
}
|
|
168
|
+
addToast({
|
|
169
|
+
color: "success",
|
|
170
|
+
title: t("history.toast_delete_success"),
|
|
171
|
+
});
|
|
172
|
+
// Refresh list
|
|
173
|
+
fetchArtifacts();
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
logger.error("Failed to delete artifact", error);
|
|
177
|
+
addToast({
|
|
178
|
+
color: "danger",
|
|
179
|
+
title: t("history.toast_delete_failed"),
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
const downloadArtifact = async (id) => {
|
|
184
|
+
try {
|
|
185
|
+
// Get API key
|
|
186
|
+
const apiKeysResponse = await fetch("/api/ai/auth/api-keys");
|
|
187
|
+
const keysData = await apiKeysResponse.json();
|
|
188
|
+
const apiKeys = keysData.data || [];
|
|
189
|
+
const apiKey = apiKeys[0];
|
|
190
|
+
const response = await fetch(`/api/public/v1/history/${id}`, {
|
|
191
|
+
headers: {
|
|
192
|
+
Authorization: `Bearer ${apiKey.key || apiKey.prefix}...`,
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
if (!response.ok) {
|
|
196
|
+
throw new Error("Failed to get download URL");
|
|
197
|
+
}
|
|
198
|
+
const data = await response.json();
|
|
199
|
+
if (data.artifact.download_url) {
|
|
200
|
+
window.open(data.artifact.download_url, "_blank");
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
addToast({
|
|
204
|
+
color: "warning",
|
|
205
|
+
title: t("history.toast_no_download_url"),
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
logger.error("Failed to download artifact", error);
|
|
211
|
+
addToast({
|
|
212
|
+
color: "danger",
|
|
213
|
+
title: t("history.toast_download_failed"),
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
const openInFileManager = (artifact) => {
|
|
218
|
+
// Extract path from artifact
|
|
219
|
+
const date = new Date(artifact.created_at);
|
|
220
|
+
setFilePath(artifact.storage_path.split("/").slice(0, -1).join("/"));
|
|
221
|
+
setIsFileManagerOpen(true);
|
|
222
|
+
};
|
|
223
|
+
const formatDate = (dateString) => {
|
|
224
|
+
return new Date(dateString).toLocaleString();
|
|
225
|
+
};
|
|
226
|
+
const formatSize = (bytes) => {
|
|
227
|
+
if (!bytes)
|
|
228
|
+
return "N/A";
|
|
229
|
+
const kb = bytes / 1024;
|
|
230
|
+
if (kb < 1024)
|
|
231
|
+
return `${kb.toFixed(1)} KB`;
|
|
232
|
+
return `${(kb / 1024).toFixed(1)} MB`;
|
|
233
|
+
};
|
|
234
|
+
const getKindColor = (kind) => {
|
|
235
|
+
switch (kind) {
|
|
236
|
+
case "text":
|
|
237
|
+
return "primary";
|
|
238
|
+
case "image":
|
|
239
|
+
return "secondary";
|
|
240
|
+
case "pdf":
|
|
241
|
+
return "warning";
|
|
242
|
+
case "file":
|
|
243
|
+
return "default";
|
|
244
|
+
default:
|
|
245
|
+
return "default";
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
return (_jsxs("div", { className: "container mx-auto py-8 space-y-6", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { className: "flex flex-row items-center justify-between", children: [_jsxs("div", { children: [_jsxs("h1", { className: "text-2xl font-bold flex items-center gap-2", children: [_jsx(History, { size: 24 }), t("history.page_title")] }), _jsx("p", { className: "text-sm text-gray-600", children: t("history.page_subtitle") })] }), _jsxs(Select, { label: t("history.filter_label"), size: "sm", selectedKeys: [kindFilter], onSelectionChange: (keys) => {
|
|
249
|
+
const selected = Array.from(keys)[0];
|
|
250
|
+
setKindFilter(selected ? String(selected) : "all");
|
|
251
|
+
}, className: "max-w-xs", children: [_jsx(SelectItem, { children: t("history.filter_all") }, "all"), _jsx(SelectItem, { children: t("history.filter_text") }, "text"), _jsx(SelectItem, { children: t("history.filter_image") }, "image"), _jsx(SelectItem, { children: t("history.filter_pdf") }, "pdf"), _jsx(SelectItem, { children: t("history.filter_file") }, "file")] })] }), _jsx(CardBody, { children: artifacts.length === 0 && !loading ? (_jsxs("div", { className: "text-center py-8", children: [_jsx(History, { size: 48, className: "mx-auto text-gray-400 mb-4" }), _jsx("p", { className: "text-gray-600 mb-4", children: t("history.no_artifacts") }), _jsx("p", { className: "text-sm text-gray-500", dangerouslySetInnerHTML: {
|
|
252
|
+
__html: t("history.no_artifacts_desc"),
|
|
253
|
+
} })] })) : artifacts.length > 0 ? (_jsxs(_Fragment, { children: [_jsxs(Table, { "aria-label": "Artifacts history", children: [_jsxs(TableHeader, { children: [_jsx(TableColumn, { children: " " }), _jsx(TableColumn, { children: t("history.table_type") }), _jsx(TableColumn, { children: t("history.table_model") }), _jsx(TableColumn, { children: t("history.table_tokens") }), _jsx(TableColumn, { children: t("history.table_size") }), _jsx(TableColumn, { children: t("history.table_date") }), _jsx(TableColumn, { align: "end", children: t("history.table_actions") })] }), _jsx(TableBody, { children: artifacts.map((artifact) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: artifact.kind === "image" &&
|
|
254
|
+
imageUrls.has(artifact.id) ? (_jsx(Image, { src: imageUrls.get(artifact.id), alt: "Thumbnail", className: "w-12 h-12 object-cover rounded" })) : (_jsx("div", { className: "w-12 h-12 bg-background rounded flex items-center justify-center", children: _jsx(Ban, { size: 16, className: "text-gray-400" }) })) }), _jsx(TableCell, { children: _jsx(Chip, { color: getKindColor(artifact.kind), variant: "flat", size: "sm", children: artifact.kind }) }), _jsx(TableCell, { children: _jsxs("div", { className: "flex flex-col", children: [_jsx("span", { className: "text-sm font-medium", children: artifact.model || "N/A" }), _jsx("span", { className: "text-xs text-gray-500", children: artifact.provider || "" })] }) }), _jsx(TableCell, { children: artifact.tokens_total?.toLocaleString() || "N/A" }), _jsx(TableCell, { children: artifact.has_storage
|
|
255
|
+
? formatSize(artifact.size_bytes)
|
|
256
|
+
: "—" }), _jsx(TableCell, { children: _jsx("span", { className: "text-xs", children: formatDate(artifact.created_at) }) }), _jsx(TableCell, { children: _jsxs("div", { className: "flex justify-end gap-2", children: [_jsx(Button, { size: "sm", variant: "light", isIconOnly: true, onPress: () => viewArtifact(artifact.id), children: _jsx(Eye, { size: 16 }) }), artifact.has_storage && (_jsxs(_Fragment, { children: [_jsx(Button, { size: "sm", variant: "light", isIconOnly: true, onPress: () => downloadArtifact(artifact.id), children: _jsx(Download, { size: 16 }) }), _jsx(Button, { size: "sm", variant: "light", isIconOnly: true, onPress: () => openInFileManager(artifact), children: _jsx(FolderOpen, { size: 16 }) })] })), _jsx(Button, { size: "sm", variant: "light", color: "danger", isIconOnly: true, onPress: () => deleteArtifact(artifact.id), children: _jsx(Trash2, { size: 16 }) })] }) })] }, artifact.id))) })] }), hasMore && (_jsx("div", { className: "flex justify-center mt-4", children: _jsx(Button, { onPress: () => fetchArtifacts(cursor), disabled: loading, children: loading ? t("history.loading") : t("history.load_more") }) }))] })) : loading ? (_jsx("div", { className: "flex justify-center py-8", children: _jsx(Spinner, {}) })) : null })] }), _jsx(Modal, { isOpen: isModalOpen, onClose: () => {
|
|
257
|
+
setIsModalOpen(false);
|
|
258
|
+
setSelectedArtifact(null);
|
|
259
|
+
}, size: "3xl", backdrop: "blur", scrollBehavior: "inside", children: _jsxs(ModalContent, { children: [_jsx(ModalHeader, { children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { color: selectedArtifact
|
|
260
|
+
? getKindColor(selectedArtifact.kind)
|
|
261
|
+
: "default", variant: "flat", children: selectedArtifact?.kind }), _jsx("span", { children: t("history.modal_title") })] }) }), _jsx(ModalBody, { children: loadingDetail ? (_jsx("div", { className: "flex justify-center py-8", children: _jsx(Spinner, {}) })) : selectedArtifact ? (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "grid grid-cols-2 gap-4 text-sm", children: [_jsxs("div", { children: [_jsx("span", { className: "font-medium", children: t("history.modal_model") }), " ", selectedArtifact.model || "N/A"] }), _jsxs("div", { children: [_jsx("span", { className: "font-medium", children: t("history.modal_provider") }), " ", selectedArtifact.provider || "N/A"] }), _jsxs("div", { children: [_jsx("span", { className: "font-medium", children: t("history.modal_tokens") }), " ", selectedArtifact.tokens_total?.toLocaleString() || "N/A"] }), _jsxs("div", { children: [_jsx("span", { className: "font-medium", children: t("history.modal_date") }), " ", formatDate(selectedArtifact.created_at)] })] }), selectedArtifact.meta?.title && (_jsxs("div", { children: [_jsx("span", { className: "font-medium", children: t("history.modal_title_field") }), " ", selectedArtifact.meta.title] })), selectedArtifact.kind === "text" &&
|
|
262
|
+
selectedArtifact.text_content && (_jsxs("div", { children: [_jsx("h3", { className: "font-medium mb-2", children: t("history.modal_content") }), _jsx(Textarea, { className: "w-full p-4 text-sm", maxRows: 1000, defaultValue: selectedArtifact.text_content, endContent: _jsx(CopyButton, { content: selectedArtifact.text_content }) })] })), selectedArtifact.kind !== "text" &&
|
|
263
|
+
selectedArtifact.download_url && (_jsxs("div", { children: [_jsx(Image, { src: selectedArtifact.download_url, alt: "Artifact" }), _jsxs("div", { className: "mt-6 flex flex-col justify-end items-center", children: [_jsxs(Button, { color: "primary", startContent: _jsx(Download, { size: 20 }), onPress: () => window.open(selectedArtifact.download_url, "_blank"), children: [t("history.modal_download_button"), " ", selectedArtifact.kind] }), _jsx("p", { className: "text-xs text-gray-500 mt-2", children: t("history.modal_expires").replace("{seconds}", String(selectedArtifact.expires_in)) })] })] }))] })) : null }), _jsx(ModalFooter, { children: _jsx(Button, { variant: "light", onPress: () => {
|
|
264
|
+
setIsModalOpen(false);
|
|
265
|
+
setSelectedArtifact(null);
|
|
266
|
+
}, children: t("history.modal_close") }) })] }) }), _jsx(Modal, { isOpen: isFileManagerOpen, onClose: () => {
|
|
267
|
+
setIsFileManagerOpen(false);
|
|
268
|
+
setFilePath("");
|
|
269
|
+
}, size: "5xl", backdrop: "blur", children: _jsxs(ModalContent, { children: [_jsx(ModalHeader, { children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FolderOpen, { size: 20 }), _jsx("span", { children: t("history.file_manager_title") })] }) }), _jsx(ModalBody, { children: _jsx(FileManager, { bucket: "app", basePath: filePath, allowUpload: false, allowCreateFolder: false, initialView: "list" }) }), _jsxs(ModalFooter, { children: [_jsx(Button, { variant: "light", onPress: () => {
|
|
270
|
+
setIsFileManagerOpen(false);
|
|
271
|
+
setFilePath("");
|
|
272
|
+
}, children: t("history.modal_close") }), _jsx(Button, { color: "primary", onPress: () => {
|
|
273
|
+
navigator.clipboard.writeText(filePath);
|
|
274
|
+
addToast({
|
|
275
|
+
color: "success",
|
|
276
|
+
title: t("history.toast_path_copied"),
|
|
277
|
+
});
|
|
278
|
+
}, children: t("history.copy_path") })] })] }) })] }));
|
|
279
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PromptsPage.d.ts","sourceRoot":"","sources":["../../../src/web/auth/PromptsPage.tsx"],"names":[],"mappings":"AAAA;;GAEG;AA+CH,wBAAgB,WAAW,4CA4V1B"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PromptsPage - Manage user's AI prompts
|
|
3
|
+
*/
|
|
4
|
+
"use client";
|
|
5
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { useState, useEffect } from "react";
|
|
7
|
+
import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, useDisclosure, Spinner, Card, CardHeader, CardBody, Button, Input, Textarea, Switch, Chip, } from "@lastbrain/ui";
|
|
8
|
+
import { Sparkles, Plus, Edit, Trash2, Star, Image as ImageIcon, MessageSquare, Eye, } from "lucide-react";
|
|
9
|
+
import { useLanguage } from "@lastbrain/core";
|
|
10
|
+
export function PromptsPage() {
|
|
11
|
+
const [prompts, setPrompts] = useState([]);
|
|
12
|
+
const [loading, setLoading] = useState(true);
|
|
13
|
+
const [filter, setFilter] = useState("all");
|
|
14
|
+
const [editingPrompt, setEditingPrompt] = useState(null);
|
|
15
|
+
const { isOpen, onOpen, onClose } = useDisclosure();
|
|
16
|
+
const { lang } = useLanguage();
|
|
17
|
+
const [formData, setFormData] = useState({
|
|
18
|
+
title: "",
|
|
19
|
+
content: "",
|
|
20
|
+
type: "text",
|
|
21
|
+
is_public: false,
|
|
22
|
+
favorite: false,
|
|
23
|
+
tags: [],
|
|
24
|
+
});
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
fetchPrompts();
|
|
27
|
+
}, [filter]);
|
|
28
|
+
const fetchPrompts = async () => {
|
|
29
|
+
try {
|
|
30
|
+
setLoading(true);
|
|
31
|
+
const params = new URLSearchParams();
|
|
32
|
+
if (filter !== "all") {
|
|
33
|
+
params.append("type", filter);
|
|
34
|
+
}
|
|
35
|
+
const response = await fetch(`/api/ai/auth/prompts?${params}`);
|
|
36
|
+
const data = await response.json();
|
|
37
|
+
if (response.ok) {
|
|
38
|
+
setPrompts(data.prompts || []);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
console.error("Failed to fetch prompts:", error);
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
setLoading(false);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const openCreateModal = () => {
|
|
49
|
+
setEditingPrompt(null);
|
|
50
|
+
setFormData({
|
|
51
|
+
title: "",
|
|
52
|
+
content: "",
|
|
53
|
+
type: "text",
|
|
54
|
+
is_public: false,
|
|
55
|
+
favorite: false,
|
|
56
|
+
tags: [],
|
|
57
|
+
});
|
|
58
|
+
onOpen();
|
|
59
|
+
};
|
|
60
|
+
const openEditModal = (prompt) => {
|
|
61
|
+
setEditingPrompt(prompt);
|
|
62
|
+
setFormData({
|
|
63
|
+
title: prompt.title,
|
|
64
|
+
content: prompt.content,
|
|
65
|
+
type: prompt.type,
|
|
66
|
+
is_public: prompt.is_public,
|
|
67
|
+
favorite: prompt.favorite,
|
|
68
|
+
tags: prompt.tags || [],
|
|
69
|
+
});
|
|
70
|
+
onOpen();
|
|
71
|
+
};
|
|
72
|
+
const handleSave = async () => {
|
|
73
|
+
try {
|
|
74
|
+
if (editingPrompt) {
|
|
75
|
+
// Update
|
|
76
|
+
const response = await fetch("/api/ai/auth/prompts", {
|
|
77
|
+
method: "PUT",
|
|
78
|
+
headers: { "Content-Type": "application/json" },
|
|
79
|
+
body: JSON.stringify({ id: editingPrompt.id, lang, ...formData }),
|
|
80
|
+
});
|
|
81
|
+
if (response.ok) {
|
|
82
|
+
await fetchPrompts();
|
|
83
|
+
onClose();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
// Create
|
|
88
|
+
const response = await fetch("/api/ai/auth/prompts", {
|
|
89
|
+
method: "POST",
|
|
90
|
+
headers: { "Content-Type": "application/json" },
|
|
91
|
+
body: JSON.stringify(formData),
|
|
92
|
+
});
|
|
93
|
+
if (response.ok) {
|
|
94
|
+
await fetchPrompts();
|
|
95
|
+
onClose();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
console.error("Failed to save prompt:", error);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const handleDelete = async (id) => {
|
|
104
|
+
if (!confirm("Are you sure you want to delete this prompt?"))
|
|
105
|
+
return;
|
|
106
|
+
try {
|
|
107
|
+
const response = await fetch(`/api/ai/auth/prompts?id=${id}`, {
|
|
108
|
+
method: "DELETE",
|
|
109
|
+
});
|
|
110
|
+
if (response.ok) {
|
|
111
|
+
await fetchPrompts();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
console.error("Failed to delete prompt:", error);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
const toggleFavorite = async (prompt) => {
|
|
119
|
+
try {
|
|
120
|
+
const response = await fetch("/api/ai/auth/prompts", {
|
|
121
|
+
method: "PUT",
|
|
122
|
+
headers: { "Content-Type": "application/json" },
|
|
123
|
+
body: JSON.stringify({
|
|
124
|
+
id: prompt.id,
|
|
125
|
+
favorite: !prompt.favorite,
|
|
126
|
+
}),
|
|
127
|
+
});
|
|
128
|
+
if (response.ok) {
|
|
129
|
+
await fetchPrompts();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
console.error("Failed to toggle favorite:", error);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
return (_jsxs("div", { className: "space-y-6 mt-6", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsxs("h1", { className: "text-3xl font-bold flex items-center gap-2", children: [_jsx(Sparkles, { className: "w-8 h-8" }), "My AI Prompts"] }), _jsx("p", { className: "text-default-500 mt-2", children: "Save and manage your favorite AI prompts" })] }), _jsx(Button, { color: "primary", onPress: openCreateModal, startContent: _jsx(Plus, { className: "w-4 h-4" }), children: "New Prompt" })] }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { variant: filter === "all" ? "solid" : "bordered", onPress: () => setFilter("all"), children: "All" }), _jsx(Button, { variant: filter === "text" ? "solid" : "bordered", onPress: () => setFilter("text"), startContent: _jsx(MessageSquare, { className: "w-4 h-4" }), children: "Text" }), _jsx(Button, { variant: filter === "image" ? "solid" : "bordered", onPress: () => setFilter("image"), startContent: _jsx(ImageIcon, { className: "w-4 h-4" }), children: "Image" })] }), loading ? (_jsx("div", { className: "flex justify-center py-12", children: _jsx(Spinner, { size: "lg" }) })) : prompts.length === 0 ? (_jsx(Card, { children: _jsx(CardBody, { className: "text-center py-12", children: _jsx("p", { className: "text-default-500", children: "No prompts yet. Create your first one!" }) }) })) : (_jsx("div", { className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3", children: prompts.map((prompt) => (_jsxs(Card, { className: "hover:shadow-lg transition-shadow", children: [_jsxs(CardHeader, { className: "flex justify-between items-start", children: [_jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-2 mb-1", children: [prompt.type === "text" ? (_jsx(MessageSquare, { className: "w-4 h-4 text-primary" })) : (_jsx(ImageIcon, { className: "w-4 h-4 text-secondary" })), _jsx("h3", { className: "font-semibold text-lg", children: prompt.title })] }), _jsxs("div", { className: "flex gap-2 mt-2", children: [prompt.is_public && (_jsx(Chip, { size: "sm", color: "success", variant: "flat", startContent: _jsx(Eye, { className: "w-3 h-3" }), children: "Public" })), prompt.favorite && (_jsx(Chip, { size: "sm", color: "warning", variant: "flat", startContent: _jsx(Star, { className: "w-3 h-3" }), children: "Favorite" }))] })] }), _jsx(Button, { isIconOnly: true, size: "sm", variant: "light", onPress: () => toggleFavorite(prompt), children: _jsx(Star, { className: `w-4 h-4 ${prompt.favorite ? "fill-warning text-warning" : ""}` }) })] }), _jsxs(CardBody, { children: [_jsx("p", { className: "text-sm text-default-600 line-clamp-3 mb-4", children: prompt.content }), _jsxs("div", { className: "flex gap-2 justify-end", children: [_jsx(Button, { size: "sm", variant: "light", onPress: () => openEditModal(prompt), startContent: _jsx(Edit, { className: "w-3 h-3" }), children: "Edit" }), _jsx(Button, { size: "sm", variant: "light", color: "danger", onPress: () => handleDelete(prompt.id), startContent: _jsx(Trash2, { className: "w-3 h-3" }), children: "Delete" })] })] })] }, prompt.id))) })), _jsx(Modal, { isOpen: isOpen, onClose: onClose, size: "2xl", scrollBehavior: "inside", backdrop: "blur", children: _jsxs(ModalContent, { children: [_jsx(ModalHeader, { children: editingPrompt ? "Edit Prompt" : "Create New Prompt" }), _jsx(ModalBody, { children: _jsxs("div", { className: "space-y-4", children: [_jsx(Input, { label: "Title", placeholder: "Enter prompt title", value: formData.title, onValueChange: (value) => setFormData({ ...formData, title: value }) }), _jsx(Textarea, { label: "Content", placeholder: "Enter your prompt here...", value: formData.content, onValueChange: (value) => setFormData({ ...formData, content: value }), minRows: 5 }), _jsxs("div", { className: "flex gap-4", children: [_jsx(Button, { variant: formData.type === "text" ? "solid" : "bordered", onPress: () => setFormData({ ...formData, type: "text" }), startContent: _jsx(MessageSquare, { className: "w-4 h-4" }), children: "Text" }), _jsx(Button, { variant: formData.type === "image" ? "solid" : "bordered", onPress: () => setFormData({ ...formData, type: "image" }), startContent: _jsx(ImageIcon, { className: "w-4 h-4" }), children: "Image" })] }), _jsxs("div", { className: "flex gap-4", children: [_jsx(Switch, { isSelected: formData.is_public, onValueChange: (value) => setFormData({ ...formData, is_public: value }), children: "Make Public" }), _jsx(Switch, { isSelected: formData.favorite, onValueChange: (value) => setFormData({ ...formData, favorite: value }), children: "Favorite" })] })] }) }), _jsxs(ModalFooter, { children: [_jsx(Button, { variant: "light", onPress: onClose, children: "Cancel" }), _jsx(Button, { color: "primary", onPress: handleSave, children: editingPrompt ? "Update" : "Create" })] })] }) })] }));
|
|
137
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenPage.d.ts","sourceRoot":"","sources":["../../../src/web/auth/TokenPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TokenPage.d.ts","sourceRoot":"","sources":["../../../src/web/auth/TokenPage.tsx"],"names":[],"mappings":"AA6FA,wBAAgB,SAAS,4CAsrBxB"}
|