@wopr-network/platform-ui-core 1.27.8 → 1.27.9
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/next.config.ts +1 -2
- package/package.json +17 -17
- package/src/__tests__/account-switcher.test.tsx +21 -20
- package/src/__tests__/activity-page.test.tsx +2 -6
- package/src/__tests__/add-payment-method-dialog.test.tsx +9 -32
- package/src/__tests__/admin-api.test.ts +1 -6
- package/src/__tests__/admin-gpu-api.test.ts +1 -3
- package/src/__tests__/admin-marketplace-api.test.ts +1 -4
- package/src/__tests__/admin-middleware.test.ts +76 -83
- package/src/__tests__/affiliate-dashboard.test.tsx +3 -3
- package/src/__tests__/api-401-redirect.test.ts +46 -9
- package/src/__tests__/api-client.test.ts +3 -5
- package/src/__tests__/api-config.test.ts +22 -42
- package/src/__tests__/api-fleet-resources.test.ts +1 -2
- package/src/__tests__/api-fleet-trpc.test.ts +2 -8
- package/src/__tests__/api-null-guards.test.ts +3 -1
- package/src/__tests__/audit-log-table-pagination.test.tsx +2 -6
- package/src/__tests__/auth-password-reset.test.tsx +7 -21
- package/src/__tests__/auth-redirect.test.tsx +8 -2
- package/src/__tests__/auth.test.tsx +25 -23
- package/src/__tests__/auto-topup-card.test.tsx +4 -12
- package/src/__tests__/backups-tab.test.tsx +3 -4
- package/src/__tests__/billing-layout-nav-hidden.test.tsx +5 -37
- package/src/__tests__/billing-payment-org-invoices.test.tsx +2 -18
- package/src/__tests__/billing.test.tsx +8 -39
- package/src/__tests__/bot-settings/resources-tab.test.tsx +1 -3
- package/src/__tests__/bot-settings/storage-tab.test.tsx +1 -3
- package/src/__tests__/bot-settings/vps-upgrade-card.test.tsx +1 -3
- package/src/__tests__/bot-settings-restart.test.tsx +1 -3
- package/src/__tests__/bot-settings.test.tsx +2 -6
- package/src/__tests__/brand.test.ts +6 -26
- package/src/__tests__/buy-credits-panel.test.tsx +1 -3
- package/src/__tests__/buy-crypto-credits-panel.test.tsx +101 -119
- package/src/__tests__/capability-conflicts.test.ts +2 -8
- package/src/__tests__/capability-resolver.test.tsx +2 -12
- package/src/__tests__/channel-wizard.test.tsx +4 -17
- package/src/__tests__/chat/chat-panel.test.tsx +1 -4
- package/src/__tests__/chat-store.test.ts +5 -15
- package/src/__tests__/command-center.test.tsx +10 -12
- package/src/__tests__/compliance-retention-edit.test.tsx +3 -6
- package/src/__tests__/confirmation-tracker.test.tsx +3 -18
- package/src/__tests__/coupon-input.test.tsx +1 -3
- package/src/__tests__/create-instance.test.tsx +1 -3
- package/src/__tests__/credit-balance.test.tsx +4 -12
- package/src/__tests__/credits.test.tsx +32 -85
- package/src/__tests__/email-verification-banner.test.tsx +2 -6
- package/src/__tests__/error-boundaries.test.tsx +0 -1
- package/src/__tests__/fetch-pricing.test.ts +2 -1
- package/src/__tests__/field-oauth.test.tsx +2 -6
- package/src/__tests__/fixtures/mock-manifests-data.js +1 -3
- package/src/__tests__/fixtures/mock-manifests.ts +2 -4
- package/src/__tests__/fleet-health-timestamp.test.tsx +1 -8
- package/src/__tests__/fleet-health-update.test.tsx +1 -8
- package/src/__tests__/gpu-dashboard.test.tsx +2 -6
- package/src/__tests__/instance-detail.test.tsx +3 -9
- package/src/__tests__/instance-list.test.tsx +1 -5
- package/src/__tests__/layout-snapshots.test.tsx +64 -11
- package/src/__tests__/marketplace-admin.test.tsx +2 -6
- package/src/__tests__/marketplace.test.tsx +11 -35
- package/src/__tests__/merge-api-rates.test.ts +1 -6
- package/src/__tests__/middleware.test.ts +32 -219
- package/src/__tests__/next-config-headers.test.ts +1 -3
- package/src/__tests__/notifications.test.tsx +4 -11
- package/src/__tests__/oauth-buttons.test.tsx +36 -59
- package/src/__tests__/oauth-error-mapping.test.tsx +2 -6
- package/src/__tests__/observability.test.tsx +23 -36
- package/src/__tests__/onboarding-page.test.tsx +4 -6
- package/src/__tests__/org-billing-api.test.tsx +1 -6
- package/src/__tests__/plugin-install-flow.test.tsx +28 -58
- package/src/__tests__/plugin-registry.test.tsx +3 -11
- package/src/__tests__/plugin-tool-sync.test.ts +1 -3
- package/src/__tests__/plugins-catalog-error.test.tsx +2 -6
- package/src/__tests__/plugins-toggle-race.test.tsx +3 -5
- package/src/__tests__/portfolio-chart.test.tsx +2 -6
- package/src/__tests__/promotion-form.test.tsx +2 -6
- package/src/__tests__/promotions-list.test.tsx +1 -3
- package/src/__tests__/provider-key-api.test.ts +2 -1
- package/src/__tests__/resend-verification-button.test.tsx +8 -24
- package/src/__tests__/secrets-audit-pagination.test.tsx +1 -3
- package/src/__tests__/settings.test.tsx +11 -21
- package/src/__tests__/setup-checklist.test.tsx +3 -9
- package/src/__tests__/setup.ts +25 -6
- package/src/__tests__/snapshot-api.test.ts +2 -1
- package/src/__tests__/step-superpowers.test.tsx +1 -3
- package/src/__tests__/tenant-context.test.tsx +1 -6
- package/src/__tests__/tenant-keys-api.test.ts +3 -4
- package/src/__tests__/tenant-table-pagination.test.tsx +2 -6
- package/src/__tests__/terminal-log-cleanup.test.tsx +0 -1
- package/src/__tests__/transaction-history.test.tsx +190 -238
- package/src/__tests__/trpc-types.test.ts +2 -6
- package/src/__tests__/use-chat.test.ts +1 -3
- package/src/__tests__/use-plugin-setup-chat-stale-closure.test.ts +1 -4
- package/src/__tests__/use-sidecar-bridge.test.tsx +105 -0
- package/src/__tests__/use-webmcp.test.ts +1 -3
- package/src/__tests__/validate-elevenlabs-key.test.ts +2 -1
- package/src/__tests__/verify-page.test.tsx +4 -13
- package/src/__tests__/verify-redirect.test.tsx +2 -6
- package/src/app/(auth)/error.tsx +1 -7
- package/src/app/(auth)/forgot-password/page.tsx +4 -18
- package/src/app/(auth)/login/page.tsx +5 -22
- package/src/app/(auth)/reset-password/page.tsx +2 -12
- package/src/app/(auth)/signup/page.tsx +10 -44
- package/src/app/(auth)/verify/page.tsx +47 -0
- package/src/app/(dashboard)/billing/credits/page.tsx +14 -67
- package/src/app/(dashboard)/billing/error.tsx +2 -10
- package/src/app/(dashboard)/billing/layout.tsx +12 -62
- package/src/app/(dashboard)/billing/payment/page.tsx +17 -68
- package/src/app/(dashboard)/billing/plans/page.tsx +3 -9
- package/src/app/(dashboard)/billing/usage/hosted/page.tsx +8 -25
- package/src/app/(dashboard)/billing/usage/page.tsx +63 -103
- package/src/app/(dashboard)/changesets/[id]/changeset-detail-client.tsx +9 -27
- package/src/app/(dashboard)/changesets/[id]/error.tsx +2 -6
- package/src/app/(dashboard)/changesets/error.tsx +1 -7
- package/src/app/(dashboard)/chat/page.tsx +2 -6
- package/src/app/(dashboard)/dashboard/network/page.tsx +5 -19
- package/src/app/(dashboard)/error.tsx +1 -7
- package/src/app/(dashboard)/layout.tsx +15 -36
- package/src/app/(dashboard)/marketplace/[plugin]/page.tsx +14 -51
- package/src/app/(dashboard)/marketplace/error.tsx +1 -7
- package/src/app/(dashboard)/marketplace/page.tsx +6 -27
- package/src/app/(dashboard)/not-found.tsx +2 -5
- package/src/app/(dashboard)/onboarding/page.tsx +5 -22
- package/src/app/(dashboard)/settings/account/page.tsx +1 -6
- package/src/app/(dashboard)/settings/activity/page.tsx +8 -34
- package/src/app/(dashboard)/settings/api-keys/page.tsx +15 -60
- package/src/app/(dashboard)/settings/brain/page.tsx +9 -31
- package/src/app/(dashboard)/settings/error.tsx +2 -10
- package/src/app/(dashboard)/settings/notifications/page.tsx +2 -6
- package/src/app/(dashboard)/settings/org/page.tsx +13 -56
- package/src/app/(dashboard)/settings/page.tsx +1 -0
- package/src/app/(dashboard)/settings/profile/page.tsx +126 -73
- package/src/app/(dashboard)/settings/providers/page.tsx +21 -78
- package/src/app/(dashboard)/settings/secrets/page.tsx +13 -58
- package/src/app/(dashboard)/settings/security/page.tsx +31 -111
- package/src/app/admin/email-templates/email-templates-client.tsx +15 -58
- package/src/app/admin/error.tsx +1 -7
- package/src/app/admin/fleet-updates/error.tsx +1 -7
- package/src/app/admin/fleet-updates/fleet-updates-client.tsx +10 -50
- package/src/app/admin/layout.tsx +4 -0
- package/src/app/admin/payment-methods/page.tsx +9 -38
- package/src/app/admin/products/error.tsx +2 -7
- package/src/app/admin/products/page.tsx +1 -4
- package/src/app/admin/promotions/[id]/page.tsx +9 -38
- package/src/app/admin/promotions/page.tsx +9 -36
- package/src/app/admin/rate-overrides/page.tsx +9 -45
- package/src/app/auth/callback/[provider]/page.tsx +1 -8
- package/src/app/auth/verify/page.tsx +9 -36
- package/src/app/channels/error.tsx +2 -10
- package/src/app/channels/layout.tsx +9 -0
- package/src/app/channels/page.tsx +8 -20
- package/src/app/channels/setup/[plugin]/page.tsx +3 -5
- package/src/app/error.tsx +1 -7
- package/src/app/fleet/error.tsx +1 -7
- package/src/app/fleet/layout.tsx +5 -0
- package/src/app/fleet/settings/page.tsx +1 -3
- package/src/app/global-error.tsx +2 -10
- package/src/app/globals.css +1 -4
- package/src/app/instances/[id]/instance-detail-client.tsx +51 -125
- package/src/app/instances/error.tsx +2 -10
- package/src/app/instances/instance-list-client.tsx +20 -69
- package/src/app/instances/layout.tsx +9 -0
- package/src/app/instances/new/create-instance-client.tsx +10 -31
- package/src/app/layout.tsx +2 -10
- package/src/app/not-found.tsx +1 -3
- package/src/app/page.tsx +1 -2
- package/src/app/plugins/error.tsx +2 -10
- package/src/app/plugins/layout.tsx +5 -0
- package/src/app/plugins/page.tsx +16 -48
- package/src/app/pricing/error.tsx +1 -7
- package/src/app/privacy/page.tsx +93 -150
- package/src/app/status/error.tsx +1 -7
- package/src/app/terms/page.tsx +89 -144
- package/src/components/account-switcher.tsx +25 -52
- package/src/components/admin/accounting-dashboard.tsx +1 -3
- package/src/components/admin/admin-guard.tsx +1 -3
- package/src/components/admin/admin-nav.tsx +1 -3
- package/src/components/admin/affiliate-dashboard.tsx +25 -94
- package/src/components/admin/audit-log-table.tsx +13 -49
- package/src/components/admin/billing-health-dashboard.tsx +7 -25
- package/src/components/admin/bulk-actions-bar.test.tsx +1 -7
- package/src/components/admin/bulk-actions-bar.tsx +1 -3
- package/src/components/admin/bulk-export-dialog.test.tsx +1 -7
- package/src/components/admin/bulk-export-dialog.tsx +6 -32
- package/src/components/admin/bulk-grant-dialog.test.tsx +2 -6
- package/src/components/admin/bulk-grant-dialog.tsx +4 -15
- package/src/components/admin/bulk-preview-dialog.tsx +3 -12
- package/src/components/admin/bulk-reactivate-dialog.tsx +1 -7
- package/src/components/admin/bulk-select-all-banner.tsx +1 -6
- package/src/components/admin/bulk-suspend-dialog.tsx +5 -12
- package/src/components/admin/bulk-undo-toast.tsx +1 -2
- package/src/components/admin/compliance-dashboard.tsx +31 -101
- package/src/components/admin/gpu-dashboard.tsx +21 -70
- package/src/components/admin/grant-credits-dialog.tsx +4 -17
- package/src/components/admin/incident-dashboard.tsx +10 -25
- package/src/components/admin/inference-dashboard.tsx +14 -54
- package/src/components/admin/marketplace-admin.tsx +18 -60
- package/src/components/admin/migrations-dashboard.tsx +9 -42
- package/src/components/admin/onboarding-dashboard.tsx +14 -64
- package/src/components/admin/pool-config-dashboard.tsx +4 -10
- package/src/components/admin/products/fleet-form.tsx +2 -11
- package/src/components/admin/products/nav-editor.tsx +3 -10
- package/src/components/admin/promotions/promotion-form.tsx +9 -42
- package/src/components/admin/roles-dashboard.tsx +7 -34
- package/src/components/admin/suspend-dialog.tsx +4 -11
- package/src/components/admin/tenant-notes-panel.tsx +1 -3
- package/src/components/admin/tenant-row-actions.tsx +4 -20
- package/src/components/admin/tenant-table.tsx +12 -49
- package/src/components/auth/auth-redirect.tsx +11 -3
- package/src/components/auth/email-verification-result-banner.tsx +1 -3
- package/src/components/auth/resend-verification-button.tsx +2 -10
- package/src/components/auth/wopr-wordmark.tsx +1 -3
- package/src/components/billing/add-payment-method-dialog.tsx +1 -2
- package/src/components/billing/affiliate-dashboard.tsx +4 -16
- package/src/components/billing/amount-selector.tsx +1 -3
- package/src/components/billing/auto-topup-card.tsx +2 -11
- package/src/components/billing/buy-credits-panel.tsx +4 -14
- package/src/components/billing/byok-callout.tsx +6 -8
- package/src/components/billing/confirmation-tracker.tsx +4 -14
- package/src/components/billing/credit-balance-badge.tsx +22 -0
- package/src/components/billing/credit-balance.tsx +3 -9
- package/src/components/billing/crypto-checkout.tsx +5 -24
- package/src/components/billing/degraded-state-banner.tsx +1 -3
- package/src/components/billing/deposit-view.tsx +301 -41
- package/src/components/billing/dividend-banner.tsx +1 -3
- package/src/components/billing/dividend-eligibility.tsx +3 -12
- package/src/components/billing/dividend-pool-stats.tsx +6 -20
- package/src/components/billing/first-dividend-dialog.tsx +2 -2
- package/src/components/billing/org-billing-page.tsx +8 -31
- package/src/components/billing/payment-method-picker.tsx +2 -10
- package/src/components/billing/suspension-banner.tsx +2 -7
- package/src/components/billing/transaction-history.tsx +10 -58
- package/src/components/billing/unified-checkout.tsx +547 -0
- package/src/components/bot-settings/backups-tab.tsx +9 -33
- package/src/components/bot-settings/bot-settings-client.tsx +32 -134
- package/src/components/bot-settings/resources-tab.tsx +2 -9
- package/src/components/bot-settings/storage-tab.tsx +19 -48
- package/src/components/bot-settings/vps-info-panel.tsx +3 -11
- package/src/components/bot-settings/vps-upgrade-card.tsx +3 -4
- package/src/components/brand-hydrator.tsx +13 -0
- package/src/components/channel-wizard/field-interactive.tsx +1 -3
- package/src/components/channel-wizard/field-qr.tsx +10 -39
- package/src/components/channel-wizard/step-renderer.tsx +5 -28
- package/src/components/channel-wizard/wizard.tsx +6 -31
- package/src/components/chat/chat-message.tsx +1 -4
- package/src/components/chat/chat-panel.tsx +4 -18
- package/src/components/chat/chat-widget.tsx +3 -14
- package/src/components/dashboard/command-center.tsx +15 -61
- package/src/components/fleet/update-settings-card.tsx +7 -23
- package/src/components/instance-update-banner.tsx +130 -0
- package/src/components/instances/friends-tab.test.tsx +2 -9
- package/src/components/instances/friends-tab.tsx +18 -74
- package/src/components/instances/update-available-badge.tsx +2 -11
- package/src/components/landing/hero.tsx +3 -9
- package/src/components/landing/landing-page.tsx +1 -3
- package/src/components/landing/portfolio-chart.tsx +4 -9
- package/src/components/landing/story-sections.tsx +1 -3
- package/src/components/landing/terminal-sequence.tsx +4 -17
- package/src/components/marketplace/empty-state.tsx +2 -6
- package/src/components/marketplace/first-visit-hero.tsx +1 -3
- package/src/components/marketplace/install-wizard.tsx +20 -77
- package/src/components/marketplace/marketplace-tabs.tsx +1 -4
- package/src/components/marketplace/plugin-card.tsx +2 -9
- package/src/components/marketplace/superpower-content.tsx +1 -3
- package/src/components/marketplace/terminal-search.tsx +2 -8
- package/src/components/oauth-buttons.tsx +29 -14
- package/src/components/observability/fleet-health.tsx +5 -18
- package/src/components/observability/health-overview.tsx +7 -20
- package/src/components/observability/logs-viewer.tsx +8 -32
- package/src/components/observability/metrics-dashboard.tsx +2 -15
- package/src/components/onboarding/fallback-setup.tsx +6 -25
- package/src/components/onboarding/setup-checklist.tsx +18 -51
- package/src/components/onboarding/step-superpowers.tsx +1 -4
- package/src/components/plugin-setup/setup-chat-panel.tsx +6 -22
- package/src/components/pricing/dividend-calculator.tsx +6 -12
- package/src/components/pricing/dividend-stats.tsx +5 -17
- package/src/components/pricing/pricing-page.tsx +17 -36
- package/src/components/settings/create-org-wizard.tsx +2 -5
- package/src/components/sidebar.tsx +7 -42
- package/src/components/sidecar-frame.tsx +78 -0
- package/src/components/status/status-page.tsx +6 -28
- package/src/components/ui/alert-dialog.tsx +8 -25
- package/src/components/ui/badge.tsx +2 -8
- package/src/components/ui/banner.tsx +1 -6
- package/src/components/ui/card.tsx +5 -24
- package/src/components/ui/checkbox.tsx +1 -5
- package/src/components/ui/collapsible.tsx +3 -8
- package/src/components/ui/dialog.tsx +4 -10
- package/src/components/ui/dropdown-menu.tsx +9 -18
- package/src/components/ui/form.tsx +2 -16
- package/src/components/ui/popover.tsx +3 -23
- package/src/components/ui/progress.tsx +1 -5
- package/src/components/ui/radio-group.tsx +3 -15
- package/src/components/ui/select.tsx +4 -17
- package/src/components/ui/sheet.tsx +5 -19
- package/src/components/ui/skeleton.tsx +1 -7
- package/src/components/ui/table.tsx +5 -22
- package/src/components/ui/tabs.tsx +3 -13
- package/src/components/ui/tooltip.tsx +1 -1
- package/src/components/unified-sidebar.tsx +493 -0
- package/src/hooks/__tests__/use-fleet-sse.test.ts +1 -4
- package/src/hooks/__tests__/use-save-queue.test.ts +2 -8
- package/src/hooks/use-credit-balance.ts +27 -0
- package/src/hooks/use-my-org-role.ts +1 -3
- package/src/hooks/use-plugin-registry.ts +8 -14
- package/src/hooks/use-plugin-setup-chat.ts +2 -5
- package/src/hooks/use-sidecar-bridge.tsx +148 -0
- package/src/hooks/use-webmcp.ts +1 -4
- package/src/lib/__tests__/admin-api.test.ts +1 -3
- package/src/lib/__tests__/api-bot-crud.test.ts +8 -18
- package/src/lib/__tests__/api-fetch.test.ts +4 -16
- package/src/lib/__tests__/org-billing-api.test.ts +1 -3
- package/src/lib/__tests__/pricing-data.test.ts +0 -8
- package/src/lib/__tests__/settings-api.test.ts +1 -3
- package/src/lib/admin-affiliate-api.ts +2 -7
- package/src/lib/admin-api.ts +6 -26
- package/src/lib/admin-incident-api.ts +11 -19
- package/src/lib/admin-marketplace-api.ts +1 -5
- package/src/lib/api-config.test.ts +5 -50
- package/src/lib/api.ts +143 -122
- package/src/lib/auth-client.ts +1 -2
- package/src/lib/bot-settings-data.ts +11 -36
- package/src/lib/brand-config.ts +56 -115
- package/src/lib/brand.ts +2 -15
- package/src/lib/chat/use-chat.ts +2 -7
- package/src/lib/cost-comparison-data.test.ts +1 -3
- package/src/lib/cost-comparison-data.ts +1 -4
- package/src/lib/errors.ts +1 -4
- package/src/lib/fetch-utils.test.ts +26 -9
- package/src/lib/fetch-utils.ts +40 -11
- package/src/lib/logger.ts +2 -0
- package/src/lib/marketplace-data.ts +3 -11
- package/src/lib/oauth-errors.ts +2 -4
- package/src/lib/onboarding-data.ts +3 -11
- package/src/lib/org-api.ts +2 -10
- package/src/lib/org-billing-api.ts +5 -19
- package/src/lib/plugin/tool-definitions.ts +1 -2
- package/src/lib/require-auth.ts +57 -0
- package/src/lib/settings-api.ts +1 -4
- package/src/lib/sidecar-routes.ts +43 -0
- package/src/lib/trpc-server.ts +49 -0
- package/src/lib/trpc-types.ts +4 -6
- package/src/lib/trpc.tsx +12 -4
- package/src/lib/validate-redirect-url.ts +1 -4
- package/src/lib/webmcp/marketplace-onboarding-tools.ts +6 -16
- package/src/lib/webmcp/register.ts +1 -4
- package/src/lib/webmcp/tools.ts +2 -9
- package/src/proxy.ts +35 -212
- package/src/types/missing-deps.d.ts +2 -8
- package/tsconfig.json +1 -8
- package/biome.json +0 -52
- package/src/__tests__/__snapshots__/layout-snapshots.test.tsx.snap +0 -741
- package/src/__tests__/billing-byok-callout.test.tsx +0 -76
- package/src/lib/__tests__/__snapshots__/pricing-data.test.ts.snap +0 -112
|
@@ -237,14 +237,9 @@ export function BotSettingsClient({ botId }: { botId: string }) {
|
|
|
237
237
|
<Button variant="ghost" size="sm" asChild>
|
|
238
238
|
<Link href="/dashboard">← Back to Fleet</Link>
|
|
239
239
|
</Button>
|
|
240
|
-
<div
|
|
241
|
-
className={`transition-all duration-500 ${statusChanged ? "ring-2 ring-terminal/30 rounded-full" : ""}`}
|
|
242
|
-
>
|
|
240
|
+
<div className={`transition-all duration-500 ${statusChanged ? "ring-2 ring-terminal/30 rounded-full" : ""}`}>
|
|
243
241
|
{actionPending && pendingAction === "restart" ? (
|
|
244
|
-
<Badge
|
|
245
|
-
variant="outline"
|
|
246
|
-
className="gap-1.5 bg-yellow-500/15 text-yellow-500 border-yellow-500/25"
|
|
247
|
-
>
|
|
242
|
+
<Badge variant="outline" className="gap-1.5 bg-yellow-500/15 text-yellow-500 border-yellow-500/25">
|
|
248
243
|
<Loader2 className="size-3 animate-spin" />
|
|
249
244
|
Restarting
|
|
250
245
|
</Badge>
|
|
@@ -255,12 +250,7 @@ export function BotSettingsClient({ botId }: { botId: string }) {
|
|
|
255
250
|
<h1 className="text-2xl font-bold tracking-tight">{settings.identity.name}</h1>
|
|
256
251
|
<div className="flex gap-2 ml-auto">
|
|
257
252
|
{(settings.status === "stopped" || settings.status === "archived") && (
|
|
258
|
-
<Button
|
|
259
|
-
size="sm"
|
|
260
|
-
variant="terminal"
|
|
261
|
-
disabled={actionPending}
|
|
262
|
-
onClick={() => handleAction("start")}
|
|
263
|
-
>
|
|
253
|
+
<Button size="sm" variant="terminal" disabled={actionPending} onClick={() => handleAction("start")}>
|
|
264
254
|
{actionPending && pendingAction === "start" ? (
|
|
265
255
|
<Loader2 className="size-4 animate-spin" />
|
|
266
256
|
) : (
|
|
@@ -285,12 +275,7 @@ export function BotSettingsClient({ botId }: { botId: string }) {
|
|
|
285
275
|
)}
|
|
286
276
|
Stop
|
|
287
277
|
</Button>
|
|
288
|
-
<Button
|
|
289
|
-
size="sm"
|
|
290
|
-
variant="outline"
|
|
291
|
-
disabled={actionPending}
|
|
292
|
-
onClick={() => handleAction("restart")}
|
|
293
|
-
>
|
|
278
|
+
<Button size="sm" variant="outline" disabled={actionPending} onClick={() => handleAction("restart")}>
|
|
294
279
|
<RotateCw
|
|
295
280
|
className={`size-3.5 ${actionPending && pendingAction === "restart" ? "animate-spin" : ""}`}
|
|
296
281
|
/>
|
|
@@ -523,11 +508,7 @@ function BrainTab({
|
|
|
523
508
|
[botId, settings, onUpdate],
|
|
524
509
|
);
|
|
525
510
|
|
|
526
|
-
const {
|
|
527
|
-
enqueue: enqueueModelSave,
|
|
528
|
-
saving: savingModel,
|
|
529
|
-
error: modelSaveError,
|
|
530
|
-
} = useSaveQueue(saveModelFn);
|
|
511
|
+
const { enqueue: enqueueModelSave, saving: savingModel, error: modelSaveError } = useSaveQueue(saveModelFn);
|
|
531
512
|
|
|
532
513
|
useEffect(() => {
|
|
533
514
|
if (modelSaveError) setBrainError(modelSaveError);
|
|
@@ -650,15 +631,7 @@ function BrainTab({
|
|
|
650
631
|
|
|
651
632
|
// --- Tab 3: Channels ---
|
|
652
633
|
|
|
653
|
-
function ChannelsTab({
|
|
654
|
-
settings,
|
|
655
|
-
botId,
|
|
656
|
-
onUpdate,
|
|
657
|
-
}: {
|
|
658
|
-
settings: BotSettings;
|
|
659
|
-
botId: string;
|
|
660
|
-
onUpdate: () => void;
|
|
661
|
-
}) {
|
|
634
|
+
function ChannelsTab({ settings, botId, onUpdate }: { settings: BotSettings; botId: string; onUpdate: () => void }) {
|
|
662
635
|
const router = useRouter();
|
|
663
636
|
const [disconnecting, setDisconnecting] = useState<string | null>(null);
|
|
664
637
|
const [channelError, setChannelError] = useState<string | null>(null);
|
|
@@ -683,9 +656,7 @@ function ChannelsTab({
|
|
|
683
656
|
<div className="max-w-2xl space-y-6">
|
|
684
657
|
<div>
|
|
685
658
|
<h2 className="text-xl font-bold">Channels</h2>
|
|
686
|
-
<p className="text-sm text-muted-foreground">
|
|
687
|
-
Connected channels and available integrations.
|
|
688
|
-
</p>
|
|
659
|
+
<p className="text-sm text-muted-foreground">Connected channels and available integrations.</p>
|
|
689
660
|
</div>
|
|
690
661
|
|
|
691
662
|
<div className="space-y-3">
|
|
@@ -719,9 +690,7 @@ function ChannelsTab({
|
|
|
719
690
|
<Card>
|
|
720
691
|
<CardHeader>
|
|
721
692
|
<CardTitle>Add More Channels</CardTitle>
|
|
722
|
-
<CardDescription>
|
|
723
|
-
Your {productName()} works everywhere you do. All channels are free.
|
|
724
|
-
</CardDescription>
|
|
693
|
+
<CardDescription>Your {productName()} works everywhere you do. All channels are free.</CardDescription>
|
|
725
694
|
</CardHeader>
|
|
726
695
|
<CardContent>
|
|
727
696
|
<div className="flex flex-wrap gap-3">
|
|
@@ -865,17 +834,11 @@ function ConfigureChannelDialog({
|
|
|
865
834
|
{Object.entries(config).map(([key, value]) => (
|
|
866
835
|
<div key={key} className="space-y-2">
|
|
867
836
|
<Label htmlFor={`channel-cfg-${key}`}>{key}</Label>
|
|
868
|
-
<Input
|
|
869
|
-
id={`channel-cfg-${key}`}
|
|
870
|
-
value={value}
|
|
871
|
-
onChange={(e) => updateField(key, e.target.value)}
|
|
872
|
-
/>
|
|
837
|
+
<Input id={`channel-cfg-${key}`} value={value} onChange={(e) => updateField(key, e.target.value)} />
|
|
873
838
|
</div>
|
|
874
839
|
))}
|
|
875
840
|
{Object.keys(config).length === 0 && !error && (
|
|
876
|
-
<p className="text-sm text-muted-foreground">
|
|
877
|
-
No configurable settings for this channel.
|
|
878
|
-
</p>
|
|
841
|
+
<p className="text-sm text-muted-foreground">No configurable settings for this channel.</p>
|
|
879
842
|
)}
|
|
880
843
|
</div>
|
|
881
844
|
)}
|
|
@@ -895,15 +858,7 @@ function ConfigureChannelDialog({
|
|
|
895
858
|
|
|
896
859
|
// --- Tab 4: Superpowers ---
|
|
897
860
|
|
|
898
|
-
function SuperpowersTab({
|
|
899
|
-
settings,
|
|
900
|
-
botId,
|
|
901
|
-
onUpdate,
|
|
902
|
-
}: {
|
|
903
|
-
settings: BotSettings;
|
|
904
|
-
botId: string;
|
|
905
|
-
onUpdate: () => void;
|
|
906
|
-
}) {
|
|
861
|
+
function SuperpowersTab({ settings, botId, onUpdate }: { settings: BotSettings; botId: string; onUpdate: () => void }) {
|
|
907
862
|
const [activating, setActivating] = useState<string | null>(null);
|
|
908
863
|
const [activateError, setActivateError] = useState<string | null>(null);
|
|
909
864
|
const [configuringSuperpower, setConfiguringSuperpower] = useState<ActiveSuperpower | null>(null);
|
|
@@ -925,22 +880,14 @@ function SuperpowersTab({
|
|
|
925
880
|
<div className="space-y-6">
|
|
926
881
|
<div>
|
|
927
882
|
<h2 className="text-xl font-bold">Superpowers</h2>
|
|
928
|
-
<p className="text-sm text-muted-foreground">
|
|
929
|
-
Capabilities that make your bot extraordinary.
|
|
930
|
-
</p>
|
|
883
|
+
<p className="text-sm text-muted-foreground">Capabilities that make your bot extraordinary.</p>
|
|
931
884
|
</div>
|
|
932
885
|
|
|
933
886
|
{/* Active superpowers */}
|
|
934
887
|
<div className="space-y-3">
|
|
935
|
-
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wider">
|
|
936
|
-
Active
|
|
937
|
-
</h3>
|
|
888
|
+
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wider">Active</h3>
|
|
938
889
|
{(settings.activeSuperpowers ?? []).map((sp) => (
|
|
939
|
-
<ActiveSuperpowerCard
|
|
940
|
-
key={sp.id}
|
|
941
|
-
superpower={sp}
|
|
942
|
-
onConfigure={() => setConfiguringSuperpower(sp)}
|
|
943
|
-
/>
|
|
890
|
+
<ActiveSuperpowerCard key={sp.id} superpower={sp} onConfigure={() => setConfiguringSuperpower(sp)} />
|
|
944
891
|
))}
|
|
945
892
|
</div>
|
|
946
893
|
|
|
@@ -1042,17 +989,11 @@ function ConfigureSuperpowerDialog({
|
|
|
1042
989
|
{Object.entries(config).map(([key, value]) => (
|
|
1043
990
|
<div key={key} className="space-y-2">
|
|
1044
991
|
<Label htmlFor={`sp-cfg-${key}`}>{key}</Label>
|
|
1045
|
-
<Input
|
|
1046
|
-
id={`sp-cfg-${key}`}
|
|
1047
|
-
value={value}
|
|
1048
|
-
onChange={(e) => updateField(key, e.target.value)}
|
|
1049
|
-
/>
|
|
992
|
+
<Input id={`sp-cfg-${key}`} value={value} onChange={(e) => updateField(key, e.target.value)} />
|
|
1050
993
|
</div>
|
|
1051
994
|
))}
|
|
1052
995
|
{Object.keys(config).length === 0 && !error && (
|
|
1053
|
-
<p className="text-sm text-muted-foreground">
|
|
1054
|
-
No configurable settings for this superpower.
|
|
1055
|
-
</p>
|
|
996
|
+
<p className="text-sm text-muted-foreground">No configurable settings for this superpower.</p>
|
|
1056
997
|
)}
|
|
1057
998
|
</div>
|
|
1058
999
|
)}
|
|
@@ -1070,13 +1011,7 @@ function ConfigureSuperpowerDialog({
|
|
|
1070
1011
|
);
|
|
1071
1012
|
}
|
|
1072
1013
|
|
|
1073
|
-
function ActiveSuperpowerCard({
|
|
1074
|
-
superpower,
|
|
1075
|
-
onConfigure,
|
|
1076
|
-
}: {
|
|
1077
|
-
superpower: ActiveSuperpower;
|
|
1078
|
-
onConfigure: () => void;
|
|
1079
|
-
}) {
|
|
1014
|
+
function ActiveSuperpowerCard({ superpower, onConfigure }: { superpower: ActiveSuperpower; onConfigure: () => void }) {
|
|
1080
1015
|
return (
|
|
1081
1016
|
<Card>
|
|
1082
1017
|
<CardContent className="flex items-center justify-between p-4">
|
|
@@ -1086,8 +1021,7 @@ function ActiveSuperpowerCard({
|
|
|
1086
1021
|
<Badge variant="outline">{superpower.mode === "hosted" ? "Hosted" : "BYOK"}</Badge>
|
|
1087
1022
|
</div>
|
|
1088
1023
|
<p className="text-sm text-muted-foreground">
|
|
1089
|
-
{superpower.usageCount} {superpower.usageLabel} ·{
|
|
1090
|
-
<CreditDetailed value={superpower.spend} /> spent
|
|
1024
|
+
{superpower.usageCount} {superpower.usageLabel} · <CreditDetailed value={superpower.spend} /> spent
|
|
1091
1025
|
</p>
|
|
1092
1026
|
<p className="text-xs text-muted-foreground">
|
|
1093
1027
|
Provider: {superpower.provider} · {superpower.model}
|
|
@@ -1132,15 +1066,7 @@ function AvailableSuperpowerCard({
|
|
|
1132
1066
|
|
|
1133
1067
|
// --- Tab 5: Plugins ---
|
|
1134
1068
|
|
|
1135
|
-
function PluginsTab({
|
|
1136
|
-
settings,
|
|
1137
|
-
botId,
|
|
1138
|
-
onUpdate,
|
|
1139
|
-
}: {
|
|
1140
|
-
settings: BotSettings;
|
|
1141
|
-
botId: string;
|
|
1142
|
-
onUpdate: () => void;
|
|
1143
|
-
}) {
|
|
1069
|
+
function PluginsTab({ settings, botId, onUpdate }: { settings: BotSettings; botId: string; onUpdate: () => void }) {
|
|
1144
1070
|
const [togglingPlugin, setTogglingPlugin] = useState<string | null>(null);
|
|
1145
1071
|
const [installingPlugin, setInstallingPlugin] = useState<string | null>(null);
|
|
1146
1072
|
const [pluginError, setPluginError] = useState<string | null>(null);
|
|
@@ -1197,9 +1123,7 @@ function PluginsTab({
|
|
|
1197
1123
|
|
|
1198
1124
|
{/* Installed */}
|
|
1199
1125
|
<div className="space-y-3">
|
|
1200
|
-
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wider">
|
|
1201
|
-
Installed
|
|
1202
|
-
</h3>
|
|
1126
|
+
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wider">Installed</h3>
|
|
1203
1127
|
{(settings.installedPlugins ?? []).map((plugin) => (
|
|
1204
1128
|
<InstalledPluginCard
|
|
1205
1129
|
key={plugin.id}
|
|
@@ -1216,9 +1140,7 @@ function PluginsTab({
|
|
|
1216
1140
|
|
|
1217
1141
|
{/* Discover */}
|
|
1218
1142
|
<div className="space-y-3">
|
|
1219
|
-
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wider">
|
|
1220
|
-
Discover Plugins
|
|
1221
|
-
</h3>
|
|
1143
|
+
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wider">Discover Plugins</h3>
|
|
1222
1144
|
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
1223
1145
|
{(settings.discoverPlugins ?? []).map((plugin) => (
|
|
1224
1146
|
<DiscoverPluginCard
|
|
@@ -1247,8 +1169,7 @@ function PluginsTab({
|
|
|
1247
1169
|
<DialogHeader>
|
|
1248
1170
|
<DialogTitle>Uninstall {confirmUninstall.name}?</DialogTitle>
|
|
1249
1171
|
<DialogDescription>
|
|
1250
|
-
This will remove the plugin and its configuration from your bot. This action cannot
|
|
1251
|
-
be undone.
|
|
1172
|
+
This will remove the plugin and its configuration from your bot. This action cannot be undone.
|
|
1252
1173
|
</DialogDescription>
|
|
1253
1174
|
</DialogHeader>
|
|
1254
1175
|
<DialogFooter>
|
|
@@ -1348,17 +1269,11 @@ function ConfigurePluginDialog({
|
|
|
1348
1269
|
{Object.entries(config).map(([key, value]) => (
|
|
1349
1270
|
<div key={key} className="space-y-2">
|
|
1350
1271
|
<Label htmlFor={`plugin-cfg-${key}`}>{key}</Label>
|
|
1351
|
-
<Input
|
|
1352
|
-
id={`plugin-cfg-${key}`}
|
|
1353
|
-
value={value}
|
|
1354
|
-
onChange={(e) => updateField(key, e.target.value)}
|
|
1355
|
-
/>
|
|
1272
|
+
<Input id={`plugin-cfg-${key}`} value={value} onChange={(e) => updateField(key, e.target.value)} />
|
|
1356
1273
|
</div>
|
|
1357
1274
|
))}
|
|
1358
1275
|
{Object.keys(config).length === 0 && !error && (
|
|
1359
|
-
<p className="text-sm text-muted-foreground">
|
|
1360
|
-
No configurable settings for this plugin.
|
|
1361
|
-
</p>
|
|
1276
|
+
<p className="text-sm text-muted-foreground">No configurable settings for this plugin.</p>
|
|
1362
1277
|
)}
|
|
1363
1278
|
</div>
|
|
1364
1279
|
)}
|
|
@@ -1395,10 +1310,7 @@ function InstalledPluginCard({
|
|
|
1395
1310
|
<div className="space-y-1">
|
|
1396
1311
|
<div className="flex items-center gap-2">
|
|
1397
1312
|
<span className="font-medium">{plugin.name}</span>
|
|
1398
|
-
<Badge
|
|
1399
|
-
variant="outline"
|
|
1400
|
-
className={PLUGIN_STATUS_STYLES[plugin.status] ?? DEFAULT_STATUS_STYLE}
|
|
1401
|
-
>
|
|
1313
|
+
<Badge variant="outline" className={PLUGIN_STATUS_STYLES[plugin.status] ?? DEFAULT_STATUS_STYLE}>
|
|
1402
1314
|
{plugin.status === "active" ? "Active" : "Disabled"}
|
|
1403
1315
|
</Badge>
|
|
1404
1316
|
</div>
|
|
@@ -1483,8 +1395,8 @@ function UsageTab({ settings }: { settings: BotSettings }) {
|
|
|
1483
1395
|
<Card>
|
|
1484
1396
|
<CardContent className="space-y-4 p-4">
|
|
1485
1397
|
<div className="text-sm text-muted-foreground">
|
|
1486
|
-
This week: {formatCreditStandard(usage.totalSpend)} of{
|
|
1487
|
-
|
|
1398
|
+
This week: {formatCreditStandard(usage.totalSpend)} of {formatCreditStandard(usage.creditBalance)} remaining
|
|
1399
|
+
credits
|
|
1488
1400
|
</div>
|
|
1489
1401
|
<Progress value={spendPercent} className="h-2" />
|
|
1490
1402
|
</CardContent>
|
|
@@ -1528,10 +1440,7 @@ function UsageTab({ settings }: { settings: BotSettings }) {
|
|
|
1528
1440
|
className="flex flex-1 flex-col items-center gap-1"
|
|
1529
1441
|
title={`${point.date}: ${formatCreditDetailed(point.spend)}`}
|
|
1530
1442
|
>
|
|
1531
|
-
<div
|
|
1532
|
-
className="w-full rounded-t bg-primary/60"
|
|
1533
|
-
style={{ height: `${height}%` }}
|
|
1534
|
-
/>
|
|
1443
|
+
<div className="w-full rounded-t bg-primary/60" style={{ height: `${height}%` }} />
|
|
1535
1444
|
<span className="text-[10px] text-muted-foreground">{point.date.slice(-2)}</span>
|
|
1536
1445
|
</div>
|
|
1537
1446
|
);
|
|
@@ -1565,15 +1474,7 @@ function UsageTab({ settings }: { settings: BotSettings }) {
|
|
|
1565
1474
|
|
|
1566
1475
|
// --- Tab 7: Danger Zone ---
|
|
1567
1476
|
|
|
1568
|
-
function DangerZoneTab({
|
|
1569
|
-
settings,
|
|
1570
|
-
botId,
|
|
1571
|
-
onUpdate,
|
|
1572
|
-
}: {
|
|
1573
|
-
settings: BotSettings;
|
|
1574
|
-
botId: string;
|
|
1575
|
-
onUpdate: () => void;
|
|
1576
|
-
}) {
|
|
1477
|
+
function DangerZoneTab({ settings, botId, onUpdate }: { settings: BotSettings; botId: string; onUpdate: () => void }) {
|
|
1577
1478
|
const router = useRouter();
|
|
1578
1479
|
const [confirmAction, setConfirmAction] = useState<"stop" | "archive" | "delete" | null>(null);
|
|
1579
1480
|
const [confirmText, setConfirmText] = useState("");
|
|
@@ -1633,9 +1534,7 @@ function DangerZoneTab({
|
|
|
1633
1534
|
<div className="max-w-2xl space-y-6">
|
|
1634
1535
|
<div>
|
|
1635
1536
|
<h2 className="text-xl font-bold text-destructive">Danger Zone</h2>
|
|
1636
|
-
<p className="text-sm text-muted-foreground">
|
|
1637
|
-
Irreversible and destructive actions. Proceed with caution.
|
|
1638
|
-
</p>
|
|
1537
|
+
<p className="text-sm text-muted-foreground">Irreversible and destructive actions. Proceed with caution.</p>
|
|
1639
1538
|
</div>
|
|
1640
1539
|
|
|
1641
1540
|
<div className="space-y-4">
|
|
@@ -1669,9 +1568,8 @@ function DangerZoneTab({
|
|
|
1669
1568
|
"This will remove your bot from the fleet. Config and memories are kept for 30 days. You can restore it within that window."}
|
|
1670
1569
|
{confirmAction === "delete" && (
|
|
1671
1570
|
<>
|
|
1672
|
-
This action is permanent and cannot be undone. All data, memories, and
|
|
1673
|
-
|
|
1674
|
-
<strong className="text-foreground">{botName}</strong> to confirm.
|
|
1571
|
+
This action is permanent and cannot be undone. All data, memories, and configuration will be
|
|
1572
|
+
destroyed. Type <strong className="text-foreground">{botName}</strong> to confirm.
|
|
1675
1573
|
</>
|
|
1676
1574
|
)}
|
|
1677
1575
|
</DialogDescription>
|
|
@@ -64,7 +64,6 @@ export function ResourcesTab({ botId }: { botId: string }) {
|
|
|
64
64
|
const [applying, setApplying] = useState(false);
|
|
65
65
|
const [error, setError] = useState<string | null>(null);
|
|
66
66
|
|
|
67
|
-
// biome-ignore lint/suspicious/noEmptyBlockStatements: initial no-op placeholder replaced in useEffect
|
|
68
67
|
const retryRef = useRef<() => void>(() => {});
|
|
69
68
|
|
|
70
69
|
useEffect(() => {
|
|
@@ -153,9 +152,7 @@ export function ResourcesTab({ botId }: { botId: string }) {
|
|
|
153
152
|
<span>{tier.cpu}</span>
|
|
154
153
|
</div>
|
|
155
154
|
<div className="text-sm font-medium">
|
|
156
|
-
{tier.dailyCost === 0
|
|
157
|
-
? "Included"
|
|
158
|
-
: `+${tier.dailyCost} credits/day (${tier.monthlyCost})`}
|
|
155
|
+
{tier.dailyCost === 0 ? "Included" : `+${tier.dailyCost} credits/day (${tier.monthlyCost})`}
|
|
159
156
|
</div>
|
|
160
157
|
{!isCurrent && (
|
|
161
158
|
<Button
|
|
@@ -163,11 +160,7 @@ export function ResourcesTab({ botId }: { botId: string }) {
|
|
|
163
160
|
variant={tier.key === "standard" ? "outline" : "default"}
|
|
164
161
|
onClick={() => setConfirmTier(tier)}
|
|
165
162
|
>
|
|
166
|
-
{currentTier === null
|
|
167
|
-
? "Select"
|
|
168
|
-
: tierIndex < currentTierIndex
|
|
169
|
-
? "Downgrade"
|
|
170
|
-
: "Upgrade"}
|
|
163
|
+
{currentTier === null ? "Select" : tierIndex < currentTierIndex ? "Downgrade" : "Upgrade"}
|
|
171
164
|
</Button>
|
|
172
165
|
)}
|
|
173
166
|
</CardContent>
|
|
@@ -13,12 +13,7 @@ import {
|
|
|
13
13
|
DialogTitle,
|
|
14
14
|
} from "@/components/ui/dialog";
|
|
15
15
|
import { Progress } from "@/components/ui/progress";
|
|
16
|
-
import {
|
|
17
|
-
getStorageTier,
|
|
18
|
-
getStorageUsage,
|
|
19
|
-
type StorageUsage,
|
|
20
|
-
setStorageTier,
|
|
21
|
-
} from "@/lib/bot-settings-data";
|
|
16
|
+
import { getStorageTier, getStorageUsage, type StorageUsage, setStorageTier } from "@/lib/bot-settings-data";
|
|
22
17
|
|
|
23
18
|
const STORAGE_TIERS = [
|
|
24
19
|
{
|
|
@@ -73,10 +68,7 @@ export function StorageTab({ botId }: { botId: string }) {
|
|
|
73
68
|
async function load() {
|
|
74
69
|
setLoading(true);
|
|
75
70
|
try {
|
|
76
|
-
const [tierResult, usageResult] = await Promise.all([
|
|
77
|
-
getStorageTier(botId),
|
|
78
|
-
getStorageUsage(botId),
|
|
79
|
-
]);
|
|
71
|
+
const [tierResult, usageResult] = await Promise.all([getStorageTier(botId), getStorageUsage(botId)]);
|
|
80
72
|
if (!cancelled) {
|
|
81
73
|
setCurrentTier(tierResult.tier as TierKey);
|
|
82
74
|
setUsage(usageResult);
|
|
@@ -109,11 +101,7 @@ export function StorageTab({ botId }: { botId: string }) {
|
|
|
109
101
|
}
|
|
110
102
|
|
|
111
103
|
if (loading) {
|
|
112
|
-
return
|
|
113
|
-
<div className="flex h-40 items-center justify-center text-muted-foreground">
|
|
114
|
-
Loading storage info...
|
|
115
|
-
</div>
|
|
116
|
-
);
|
|
104
|
+
return <div className="flex h-40 items-center justify-center text-muted-foreground">Loading storage info...</div>;
|
|
117
105
|
}
|
|
118
106
|
|
|
119
107
|
const tierInfo = STORAGE_TIERS.find((t) => t.key === currentTier) ?? STORAGE_TIERS[0];
|
|
@@ -125,16 +113,13 @@ export function StorageTab({ botId }: { botId: string }) {
|
|
|
125
113
|
const pendingTierInfo = pendingTier ? STORAGE_TIERS.find((t) => t.key === pendingTier) : null;
|
|
126
114
|
const isDowngrade =
|
|
127
115
|
pendingTier !== null &&
|
|
128
|
-
STORAGE_TIERS.findIndex((t) => t.key === pendingTier) <
|
|
129
|
-
STORAGE_TIERS.findIndex((t) => t.key === currentTier);
|
|
116
|
+
STORAGE_TIERS.findIndex((t) => t.key === pendingTier) < STORAGE_TIERS.findIndex((t) => t.key === currentTier);
|
|
130
117
|
|
|
131
118
|
return (
|
|
132
119
|
<div className="max-w-2xl space-y-6">
|
|
133
120
|
<div>
|
|
134
121
|
<h2 className="text-xl font-bold">Storage</h2>
|
|
135
|
-
<p className="text-sm text-muted-foreground">
|
|
136
|
-
Persistent storage for bot memories, files, and data.
|
|
137
|
-
</p>
|
|
122
|
+
<p className="text-sm text-muted-foreground">Persistent storage for bot memories, files, and data.</p>
|
|
138
123
|
</div>
|
|
139
124
|
|
|
140
125
|
{/* Usage bar */}
|
|
@@ -142,23 +127,15 @@ export function StorageTab({ botId }: { botId: string }) {
|
|
|
142
127
|
<CardContent className="space-y-3 p-4">
|
|
143
128
|
<div className="flex items-center justify-between text-sm">
|
|
144
129
|
<span className="font-medium">
|
|
145
|
-
{usage ? formatBytes(usedBytes) : "Usage unavailable"} of {tierInfo.storageLimitGb} GB
|
|
146
|
-
used
|
|
130
|
+
{usage ? formatBytes(usedBytes) : "Usage unavailable"} of {tierInfo.storageLimitGb} GB used
|
|
147
131
|
</span>
|
|
148
132
|
{usage && (
|
|
149
|
-
<span className={usageHigh ? "text-amber-500" : "text-muted-foreground"}>
|
|
150
|
-
{usagePercent.toFixed(0)}%
|
|
151
|
-
</span>
|
|
133
|
+
<span className={usageHigh ? "text-amber-500" : "text-muted-foreground"}>{usagePercent.toFixed(0)}%</span>
|
|
152
134
|
)}
|
|
153
135
|
</div>
|
|
154
|
-
<Progress
|
|
155
|
-
value={usage ? usagePercent : 0}
|
|
156
|
-
className={`h-2 ${usageHigh ? "[&>div]:bg-amber-500" : ""}`}
|
|
157
|
-
/>
|
|
136
|
+
<Progress value={usage ? usagePercent : 0} className={`h-2 ${usageHigh ? "[&>div]:bg-amber-500" : ""}`} />
|
|
158
137
|
{!usage && (
|
|
159
|
-
<p className="text-xs text-muted-foreground">
|
|
160
|
-
Disk usage is only available while the bot is running.
|
|
161
|
-
</p>
|
|
138
|
+
<p className="text-xs text-muted-foreground">Disk usage is only available while the bot is running.</p>
|
|
162
139
|
)}
|
|
163
140
|
</CardContent>
|
|
164
141
|
</Card>
|
|
@@ -168,9 +145,7 @@ export function StorageTab({ botId }: { botId: string }) {
|
|
|
168
145
|
|
|
169
146
|
{/* Tier cards */}
|
|
170
147
|
<div className="space-y-3">
|
|
171
|
-
<h3 className="text-sm font-semibold uppercase tracking-wider text-muted-foreground">
|
|
172
|
-
Storage Tiers
|
|
173
|
-
</h3>
|
|
148
|
+
<h3 className="text-sm font-semibold uppercase tracking-wider text-muted-foreground">Storage Tiers</h3>
|
|
174
149
|
<div className="grid gap-3 sm:grid-cols-2">
|
|
175
150
|
{STORAGE_TIERS.map((tier) => {
|
|
176
151
|
const isActive = tier.key === currentTier;
|
|
@@ -178,9 +153,7 @@ export function StorageTab({ botId }: { botId: string }) {
|
|
|
178
153
|
<Card
|
|
179
154
|
key={tier.key}
|
|
180
155
|
className={`cursor-pointer transition-colors ${
|
|
181
|
-
isActive
|
|
182
|
-
? "border-primary bg-primary/5"
|
|
183
|
-
: "hover:border-primary/50 hover:bg-accent/30"
|
|
156
|
+
isActive ? "border-primary bg-primary/5" : "hover:border-primary/50 hover:bg-accent/30"
|
|
184
157
|
}`}
|
|
185
158
|
onClick={() => {
|
|
186
159
|
if (!isActive) setPendingTier(tier.key);
|
|
@@ -203,8 +176,8 @@ export function StorageTab({ botId }: { botId: string }) {
|
|
|
203
176
|
})}
|
|
204
177
|
</div>
|
|
205
178
|
<p className="text-xs text-muted-foreground">
|
|
206
|
-
Storage costs are billed daily from your credit balance. Downgrades take effect
|
|
207
|
-
|
|
179
|
+
Storage costs are billed daily from your credit balance. Downgrades take effect immediately but do not delete
|
|
180
|
+
existing data.
|
|
208
181
|
</p>
|
|
209
182
|
</div>
|
|
210
183
|
|
|
@@ -218,17 +191,15 @@ export function StorageTab({ botId }: { botId: string }) {
|
|
|
218
191
|
<DialogDescription>
|
|
219
192
|
{isDowngrade ? (
|
|
220
193
|
<>
|
|
221
|
-
Downgrading to <strong>{pendingTierInfo?.label}</strong> (
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
limit.
|
|
194
|
+
Downgrading to <strong>{pendingTierInfo?.label}</strong> ({pendingTierInfo?.storageLimitGb} GB) takes
|
|
195
|
+
effect immediately. Existing data is not deleted, but the bot will be unable to write new data once it
|
|
196
|
+
exceeds the new limit.
|
|
225
197
|
</>
|
|
226
198
|
) : (
|
|
227
199
|
<>
|
|
228
|
-
Upgrading to <strong>{pendingTierInfo?.label}</strong> (
|
|
229
|
-
{pendingTierInfo?.
|
|
230
|
-
|
|
231
|
-
cost, billed from your balance.
|
|
200
|
+
Upgrading to <strong>{pendingTierInfo?.label}</strong> ({pendingTierInfo?.storageLimitGb} GB) adds{" "}
|
|
201
|
+
<strong>{pendingTierInfo?.dailyCostCents}¢ per day</strong> to this bot's credit cost, billed from
|
|
202
|
+
your balance.
|
|
232
203
|
</>
|
|
233
204
|
)}
|
|
234
205
|
</DialogDescription>
|
|
@@ -36,9 +36,7 @@ export function VpsInfoPanel({ botId }: VpsPanelProps) {
|
|
|
36
36
|
<Card className="border-destructive/30">
|
|
37
37
|
<CardContent className="flex items-center gap-2 py-4">
|
|
38
38
|
<Server className="size-5 text-destructive" />
|
|
39
|
-
<p className="text-sm text-destructive">
|
|
40
|
-
Failed to load VPS info. Please try again later.
|
|
41
|
-
</p>
|
|
39
|
+
<p className="text-sm text-destructive">Failed to load VPS info. Please try again later.</p>
|
|
42
40
|
</CardContent>
|
|
43
41
|
</Card>
|
|
44
42
|
);
|
|
@@ -111,20 +109,14 @@ export function VpsInfoPanel({ botId }: VpsPanelProps) {
|
|
|
111
109
|
onClick={handleCopy}
|
|
112
110
|
title="Copy SSH command"
|
|
113
111
|
>
|
|
114
|
-
{copied ?
|
|
115
|
-
<CheckCircle className="size-4 text-terminal" />
|
|
116
|
-
) : (
|
|
117
|
-
<Copy className="size-4" />
|
|
118
|
-
)}
|
|
112
|
+
{copied ? <CheckCircle className="size-4 text-terminal" /> : <Copy className="size-4" />}
|
|
119
113
|
</Button>
|
|
120
114
|
</div>
|
|
121
115
|
</div>
|
|
122
116
|
)}
|
|
123
117
|
|
|
124
118
|
{!vps.sshConnectionString && vps.status === "active" && (
|
|
125
|
-
<p className="text-sm text-muted-foreground">
|
|
126
|
-
SSH access is being provisioned. Check back shortly.
|
|
127
|
-
</p>
|
|
119
|
+
<p className="text-sm text-muted-foreground">SSH access is being provisioned. Check back shortly.</p>
|
|
128
120
|
)}
|
|
129
121
|
</CardContent>
|
|
130
122
|
</Card>
|
|
@@ -68,8 +68,7 @@ export function VpsUpgradeCard({ botId }: VpsUpgradeCardProps) {
|
|
|
68
68
|
</Badge>
|
|
69
69
|
</div>
|
|
70
70
|
<CardDescription>
|
|
71
|
-
Get a dedicated persistent container with fixed monthly pricing — no per-credit billing
|
|
72
|
-
for compute.
|
|
71
|
+
Get a dedicated persistent container with fixed monthly pricing — no per-credit billing for compute.
|
|
73
72
|
</CardDescription>
|
|
74
73
|
</CardHeader>
|
|
75
74
|
<CardContent className="flex flex-col gap-4">
|
|
@@ -97,8 +96,8 @@ export function VpsUpgradeCard({ botId }: VpsUpgradeCardProps) {
|
|
|
97
96
|
{error && <p className="text-sm text-destructive">{error}</p>}
|
|
98
97
|
|
|
99
98
|
<p className="text-xs text-muted-foreground">
|
|
100
|
-
Your bot will experience brief downtime during the container upgrade. You will be
|
|
101
|
-
|
|
99
|
+
Your bot will experience brief downtime during the container upgrade. You will be redirected to Stripe
|
|
100
|
+
Checkout to complete the subscription.
|
|
102
101
|
</p>
|
|
103
102
|
|
|
104
103
|
<Button onClick={handleUpgrade} disabled={loading} className="w-full sm:w-auto">
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { type BrandConfig, setBrandConfig } from "@/lib/brand-config";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Client component that hydrates the brand config from server-fetched data.
|
|
7
|
+
* Renders nothing — just calls setBrandConfig() during module evaluation
|
|
8
|
+
* so all client components see the DB-driven config.
|
|
9
|
+
*/
|
|
10
|
+
export function BrandHydrator({ config }: { config: Partial<BrandConfig> }) {
|
|
11
|
+
setBrandConfig(config);
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
@@ -33,9 +33,7 @@ export function FieldInteractive({ field, value, onChange, error }: FieldInterac
|
|
|
33
33
|
)}
|
|
34
34
|
>
|
|
35
35
|
<span className="flex-1">{option.label}</span>
|
|
36
|
-
{value === option.value &&
|
|
37
|
-
<span className="text-primary text-xs font-medium">Selected</span>
|
|
38
|
-
)}
|
|
36
|
+
{value === option.value && <span className="text-primary text-xs font-medium">Selected</span>}
|
|
39
37
|
</Button>
|
|
40
38
|
))}
|
|
41
39
|
</div>
|