@wopr-network/platform-ui-core 1.27.7 → 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 +14 -17
- 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
|
@@ -5,22 +5,20 @@ import { CameraIcon, CheckIcon } from "lucide-react";
|
|
|
5
5
|
import { type FormEvent, useCallback, useEffect, useRef, useState } from "react";
|
|
6
6
|
import { Button } from "@/components/ui/button";
|
|
7
7
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
|
8
|
-
import {
|
|
9
|
-
Dialog,
|
|
10
|
-
DialogClose,
|
|
11
|
-
DialogContent,
|
|
12
|
-
DialogDescription,
|
|
13
|
-
DialogFooter,
|
|
14
|
-
DialogHeader,
|
|
15
|
-
DialogTitle,
|
|
16
|
-
DialogTrigger,
|
|
17
|
-
} from "@/components/ui/dialog";
|
|
18
8
|
import { Input } from "@/components/ui/input";
|
|
19
9
|
import { Label } from "@/components/ui/label";
|
|
20
10
|
import { Separator } from "@/components/ui/separator";
|
|
21
11
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
22
|
-
import type { UserProfile } from "@/lib/api";
|
|
23
|
-
import {
|
|
12
|
+
import type { Instance, UserProfile } from "@/lib/api";
|
|
13
|
+
import {
|
|
14
|
+
changePassword,
|
|
15
|
+
controlInstance,
|
|
16
|
+
deleteAccount,
|
|
17
|
+
getProfile,
|
|
18
|
+
listInstances,
|
|
19
|
+
updateProfile,
|
|
20
|
+
uploadAvatar,
|
|
21
|
+
} from "@/lib/api";
|
|
24
22
|
import { linkSocial, listAccounts, unlinkAccount } from "@/lib/auth-client";
|
|
25
23
|
|
|
26
24
|
export default function ProfilePage() {
|
|
@@ -45,6 +43,9 @@ export default function ProfilePage() {
|
|
|
45
43
|
const [changingPw, setChangingPw] = useState(false);
|
|
46
44
|
|
|
47
45
|
const [deleteConfirm, setDeleteConfirm] = useState("");
|
|
46
|
+
const [resetConfirm, setResetConfirm] = useState("");
|
|
47
|
+
const [instances, setInstances] = useState<Instance[]>([]);
|
|
48
|
+
const [resetting, setResetting] = useState(false);
|
|
48
49
|
const [uploading, setUploading] = useState(false);
|
|
49
50
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
50
51
|
const saveSuccessTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
@@ -67,15 +68,16 @@ export default function ProfilePage() {
|
|
|
67
68
|
setEmail(p.email);
|
|
68
69
|
try {
|
|
69
70
|
const accounts = await listAccounts();
|
|
70
|
-
const providerIds = ((accounts.data ?? []) as { providerId: string }[]).map(
|
|
71
|
-
(a) => a.providerId,
|
|
72
|
-
);
|
|
71
|
+
const providerIds = ((accounts.data ?? []) as { providerId: string }[]).map((a) => a.providerId);
|
|
73
72
|
const providers = new Set<string>(providerIds);
|
|
74
73
|
setConnectedProviders(providers);
|
|
75
74
|
} catch {
|
|
76
|
-
setConnectedProviders(
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
setConnectedProviders(new Set(p.oauthConnections.filter((c) => c.connected).map((c) => c.provider)));
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
setInstances(await listInstances());
|
|
79
|
+
} catch {
|
|
80
|
+
// Non-fatal — instances may not be available
|
|
79
81
|
}
|
|
80
82
|
} catch {
|
|
81
83
|
setLoadError(true);
|
|
@@ -176,11 +178,39 @@ export default function ProfilePage() {
|
|
|
176
178
|
}
|
|
177
179
|
}
|
|
178
180
|
|
|
181
|
+
async function handleResetInstance() {
|
|
182
|
+
setResetting(true);
|
|
183
|
+
setError(null);
|
|
184
|
+
try {
|
|
185
|
+
for (const inst of instances) {
|
|
186
|
+
try {
|
|
187
|
+
await controlInstance(inst.id, "destroy");
|
|
188
|
+
} catch {
|
|
189
|
+
// Instance may already be gone
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
window.location.href = "/dashboard";
|
|
193
|
+
} catch {
|
|
194
|
+
setError("Failed to reset instance. Please try again.");
|
|
195
|
+
} finally {
|
|
196
|
+
setResetting(false);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
179
200
|
async function handleDelete() {
|
|
180
201
|
setError(null);
|
|
181
202
|
try {
|
|
203
|
+
for (const inst of instances) {
|
|
204
|
+
try {
|
|
205
|
+
await controlInstance(inst.id, "destroy");
|
|
206
|
+
} catch {
|
|
207
|
+
// Instance may already be gone
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// 2. Delete account (sessions, DB rows)
|
|
182
211
|
await deleteAccount();
|
|
183
|
-
|
|
212
|
+
// 3. Sign out and redirect to home
|
|
213
|
+
window.location.href = "/";
|
|
184
214
|
} catch {
|
|
185
215
|
setError("Failed to delete account. Please try again.");
|
|
186
216
|
}
|
|
@@ -222,8 +252,8 @@ export default function ProfilePage() {
|
|
|
222
252
|
return (
|
|
223
253
|
<div className="max-w-2xl space-y-6">
|
|
224
254
|
<div>
|
|
225
|
-
<h1 className="text-2xl font-bold tracking-tight">
|
|
226
|
-
<p className="text-sm text-muted-foreground">Manage your account
|
|
255
|
+
<h1 className="text-2xl font-bold tracking-tight">Settings</h1>
|
|
256
|
+
<p className="text-sm text-muted-foreground">Manage your profile, security, and account</p>
|
|
227
257
|
</div>
|
|
228
258
|
|
|
229
259
|
<AnimatePresence>
|
|
@@ -254,11 +284,7 @@ export default function ProfilePage() {
|
|
|
254
284
|
>
|
|
255
285
|
{profile.avatarUrl ? (
|
|
256
286
|
// biome-ignore lint/performance/noImgElement: external avatar URL — domain not configured for next/image
|
|
257
|
-
<img
|
|
258
|
-
src={profile.avatarUrl}
|
|
259
|
-
alt={profile.name}
|
|
260
|
-
className="size-full object-cover"
|
|
261
|
-
/>
|
|
287
|
+
<img src={profile.avatarUrl} alt={profile.name} className="size-full object-cover" />
|
|
262
288
|
) : (
|
|
263
289
|
<span className="text-xl font-semibold text-muted-foreground">
|
|
264
290
|
{profile.name.charAt(0).toUpperCase()}
|
|
@@ -292,12 +318,7 @@ export default function ProfilePage() {
|
|
|
292
318
|
<form onSubmit={handleSaveProfile} className="flex flex-col gap-4">
|
|
293
319
|
<div className="flex flex-col gap-2">
|
|
294
320
|
<Label htmlFor="profile-name">Display name</Label>
|
|
295
|
-
<Input
|
|
296
|
-
id="profile-name"
|
|
297
|
-
value={name}
|
|
298
|
-
onChange={(e) => setName(e.target.value)}
|
|
299
|
-
required
|
|
300
|
-
/>
|
|
321
|
+
<Input id="profile-name" value={name} onChange={(e) => setName(e.target.value)} required />
|
|
301
322
|
</div>
|
|
302
323
|
<div className="flex flex-col gap-2">
|
|
303
324
|
<Label htmlFor="profile-email">Email</Label>
|
|
@@ -336,12 +357,7 @@ export default function ProfilePage() {
|
|
|
336
357
|
Saved
|
|
337
358
|
</motion.span>
|
|
338
359
|
) : (
|
|
339
|
-
<motion.span
|
|
340
|
-
key="save"
|
|
341
|
-
initial={{ opacity: 0 }}
|
|
342
|
-
animate={{ opacity: 1 }}
|
|
343
|
-
exit={{ opacity: 0 }}
|
|
344
|
-
>
|
|
360
|
+
<motion.span key="save" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}>
|
|
345
361
|
{saving ? "Saving..." : "Save changes"}
|
|
346
362
|
</motion.span>
|
|
347
363
|
)}
|
|
@@ -415,12 +431,7 @@ export default function ProfilePage() {
|
|
|
415
431
|
Changed
|
|
416
432
|
</motion.span>
|
|
417
433
|
) : (
|
|
418
|
-
<motion.span
|
|
419
|
-
key="default"
|
|
420
|
-
initial={{ opacity: 0 }}
|
|
421
|
-
animate={{ opacity: 1 }}
|
|
422
|
-
exit={{ opacity: 0 }}
|
|
423
|
-
>
|
|
434
|
+
<motion.span key="default" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}>
|
|
424
435
|
{changingPw ? "Changing..." : "Change password"}
|
|
425
436
|
</motion.span>
|
|
426
437
|
)}
|
|
@@ -445,9 +456,7 @@ export default function ProfilePage() {
|
|
|
445
456
|
<Button
|
|
446
457
|
variant={connected ? "outline" : "default"}
|
|
447
458
|
size="sm"
|
|
448
|
-
onClick={() =>
|
|
449
|
-
connected ? handleOauthDisconnect(provider) : handleOauthConnect(provider)
|
|
450
|
-
}
|
|
459
|
+
onClick={() => (connected ? handleOauthDisconnect(provider) : handleOauthConnect(provider))}
|
|
451
460
|
>
|
|
452
461
|
{connected ? "Disconnect" : "Connect"}
|
|
453
462
|
</Button>
|
|
@@ -465,6 +474,53 @@ export default function ProfilePage() {
|
|
|
465
474
|
<Separator className="flex-1 bg-destructive/30" />
|
|
466
475
|
</div>
|
|
467
476
|
|
|
477
|
+
{instances.length > 0 && (
|
|
478
|
+
<Card className="border-destructive/50 bg-destructive/5">
|
|
479
|
+
<CardHeader>
|
|
480
|
+
<CardTitle className="text-destructive">Reset Instance</CardTitle>
|
|
481
|
+
<CardDescription>
|
|
482
|
+
Destroy all running instances and start fresh. Your account, credits, and settings are preserved.
|
|
483
|
+
</CardDescription>
|
|
484
|
+
</CardHeader>
|
|
485
|
+
<CardContent className="space-y-4">
|
|
486
|
+
{resetConfirm === "" ? (
|
|
487
|
+
<Button variant="destructive" onClick={() => setResetConfirm("pending")}>
|
|
488
|
+
Reset instance
|
|
489
|
+
</Button>
|
|
490
|
+
) : (
|
|
491
|
+
<div className="rounded-lg border border-destructive/50 bg-destructive/10 p-4 space-y-3">
|
|
492
|
+
<p className="text-sm text-destructive font-medium">
|
|
493
|
+
This will permanently destroy{" "}
|
|
494
|
+
{instances.length === 1 ? "your instance" : `all ${instances.length} instances`} and their data (agent
|
|
495
|
+
history, issues, documents). Your account and credits are kept.
|
|
496
|
+
</p>
|
|
497
|
+
<p className="text-sm text-muted-foreground">
|
|
498
|
+
Type <strong className="text-destructive">reset</strong> to confirm.
|
|
499
|
+
</p>
|
|
500
|
+
<Input
|
|
501
|
+
placeholder="reset"
|
|
502
|
+
value={resetConfirm === "pending" ? "" : resetConfirm}
|
|
503
|
+
onChange={(e) => setResetConfirm(e.target.value)}
|
|
504
|
+
autoFocus
|
|
505
|
+
/>
|
|
506
|
+
<div className="flex gap-2">
|
|
507
|
+
<Button variant="outline" onClick={() => setResetConfirm("")}>
|
|
508
|
+
Cancel
|
|
509
|
+
</Button>
|
|
510
|
+
<Button
|
|
511
|
+
variant="destructive"
|
|
512
|
+
disabled={resetConfirm !== "reset" || resetting}
|
|
513
|
+
onClick={handleResetInstance}
|
|
514
|
+
>
|
|
515
|
+
{resetting ? "Destroying..." : "Confirm reset"}
|
|
516
|
+
</Button>
|
|
517
|
+
</div>
|
|
518
|
+
</div>
|
|
519
|
+
)}
|
|
520
|
+
</CardContent>
|
|
521
|
+
</Card>
|
|
522
|
+
)}
|
|
523
|
+
|
|
468
524
|
<Card className="border-destructive/50 bg-destructive/5">
|
|
469
525
|
<CardHeader>
|
|
470
526
|
<CardTitle className="text-destructive">Delete Account</CardTitle>
|
|
@@ -472,38 +528,35 @@ export default function ProfilePage() {
|
|
|
472
528
|
Permanently delete your account and all associated data. This action cannot be undone.
|
|
473
529
|
</CardDescription>
|
|
474
530
|
</CardHeader>
|
|
475
|
-
<CardContent>
|
|
476
|
-
|
|
477
|
-
<
|
|
478
|
-
|
|
479
|
-
</
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
</
|
|
487
|
-
</
|
|
531
|
+
<CardContent className="space-y-4">
|
|
532
|
+
{deleteConfirm === "" ? (
|
|
533
|
+
<Button variant="destructive" onClick={() => setDeleteConfirm("pending")}>
|
|
534
|
+
Delete account
|
|
535
|
+
</Button>
|
|
536
|
+
) : (
|
|
537
|
+
<div className="rounded-lg border border-destructive/50 bg-destructive/10 p-4 space-y-3">
|
|
538
|
+
<p className="text-sm text-destructive font-medium">
|
|
539
|
+
This will permanently delete your account, all instances, and data. This cannot be undone.
|
|
540
|
+
</p>
|
|
541
|
+
<p className="text-sm text-muted-foreground">
|
|
542
|
+
Type <strong className="text-destructive">delete my account</strong> to confirm.
|
|
543
|
+
</p>
|
|
488
544
|
<Input
|
|
489
545
|
placeholder="delete my account"
|
|
490
|
-
value={deleteConfirm}
|
|
546
|
+
value={deleteConfirm === "pending" ? "" : deleteConfirm}
|
|
491
547
|
onChange={(e) => setDeleteConfirm(e.target.value)}
|
|
548
|
+
autoFocus
|
|
492
549
|
/>
|
|
493
|
-
<
|
|
494
|
-
<
|
|
495
|
-
|
|
496
|
-
</
|
|
497
|
-
<Button
|
|
498
|
-
variant="destructive"
|
|
499
|
-
disabled={deleteConfirm !== "delete my account"}
|
|
500
|
-
onClick={handleDelete}
|
|
501
|
-
>
|
|
550
|
+
<div className="flex gap-2">
|
|
551
|
+
<Button variant="outline" onClick={() => setDeleteConfirm("")}>
|
|
552
|
+
Cancel
|
|
553
|
+
</Button>
|
|
554
|
+
<Button variant="destructive" disabled={deleteConfirm !== "delete my account"} onClick={handleDelete}>
|
|
502
555
|
Delete permanently
|
|
503
556
|
</Button>
|
|
504
|
-
</
|
|
505
|
-
</
|
|
506
|
-
|
|
557
|
+
</div>
|
|
558
|
+
</div>
|
|
559
|
+
)}
|
|
507
560
|
</CardContent>
|
|
508
561
|
</Card>
|
|
509
562
|
</div>
|
|
@@ -21,22 +21,10 @@ import {
|
|
|
21
21
|
import { Input } from "@/components/ui/input";
|
|
22
22
|
import { Label } from "@/components/ui/label";
|
|
23
23
|
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
|
24
|
-
import {
|
|
25
|
-
Select,
|
|
26
|
-
SelectContent,
|
|
27
|
-
SelectItem,
|
|
28
|
-
SelectTrigger,
|
|
29
|
-
SelectValue,
|
|
30
|
-
} from "@/components/ui/select";
|
|
24
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
31
25
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
32
26
|
import { useCapabilityMeta } from "@/hooks/use-capability-meta";
|
|
33
|
-
import type {
|
|
34
|
-
CapabilityMetaEntry,
|
|
35
|
-
CapabilityMode,
|
|
36
|
-
CapabilityName,
|
|
37
|
-
CapabilitySetting,
|
|
38
|
-
ProviderKey,
|
|
39
|
-
} from "@/lib/api";
|
|
27
|
+
import type { CapabilityMetaEntry, CapabilityMode, CapabilityName, CapabilitySetting, ProviderKey } from "@/lib/api";
|
|
40
28
|
import {
|
|
41
29
|
getBillingInfo,
|
|
42
30
|
getCreditBalance,
|
|
@@ -47,11 +35,7 @@ import {
|
|
|
47
35
|
updateProviderModel,
|
|
48
36
|
} from "@/lib/api";
|
|
49
37
|
import { brandName } from "@/lib/brand-config";
|
|
50
|
-
import {
|
|
51
|
-
listCapabilities,
|
|
52
|
-
testProviderKey as testCapabilityViaTrpc,
|
|
53
|
-
updateCapability,
|
|
54
|
-
} from "@/lib/settings-api";
|
|
38
|
+
import { listCapabilities, testProviderKey as testCapabilityViaTrpc, updateCapability } from "@/lib/settings-api";
|
|
55
39
|
import { cn } from "@/lib/utils";
|
|
56
40
|
|
|
57
41
|
// --- Helpers ---
|
|
@@ -193,10 +177,7 @@ export default function ProvidersPage() {
|
|
|
193
177
|
setTestCapResult((prev) => ({ ...prev, [capability]: "fail" }));
|
|
194
178
|
}
|
|
195
179
|
setTestingCap(null);
|
|
196
|
-
testCapResultTimer.current = setTimeout(
|
|
197
|
-
() => setTestCapResult((prev) => ({ ...prev, [capability]: null })),
|
|
198
|
-
2000,
|
|
199
|
-
);
|
|
180
|
+
testCapResultTimer.current = setTimeout(() => setTestCapResult((prev) => ({ ...prev, [capability]: null })), 2000);
|
|
200
181
|
}
|
|
201
182
|
|
|
202
183
|
async function handleTest(id: string) {
|
|
@@ -214,10 +195,7 @@ export default function ProvidersPage() {
|
|
|
214
195
|
const provs = await listProviderKeys();
|
|
215
196
|
setProviders(provs);
|
|
216
197
|
setTesting(null);
|
|
217
|
-
testResultTimer.current = setTimeout(
|
|
218
|
-
() => setTestResult((prev) => ({ ...prev, [id]: null })),
|
|
219
|
-
2000,
|
|
220
|
-
);
|
|
198
|
+
testResultTimer.current = setTimeout(() => setTestResult((prev) => ({ ...prev, [id]: null })), 2000);
|
|
221
199
|
}
|
|
222
200
|
|
|
223
201
|
async function handleRemove(id: string, providerName: string) {
|
|
@@ -279,8 +257,7 @@ export default function ProvidersPage() {
|
|
|
279
257
|
<div>
|
|
280
258
|
<h1 className="text-2xl font-bold tracking-tight">Provider Settings</h1>
|
|
281
259
|
<p className="text-sm text-muted-foreground">
|
|
282
|
-
Choose {brandName()} Hosted or Bring Your Own Key for each capability. Changes take effect
|
|
283
|
-
immediately.
|
|
260
|
+
Choose {brandName()} Hosted or Bring Your Own Key for each capability. Changes take effect immediately.
|
|
284
261
|
</p>
|
|
285
262
|
</div>
|
|
286
263
|
|
|
@@ -329,10 +306,7 @@ export default function ProvidersPage() {
|
|
|
329
306
|
<RadioGroupItem value="hosted" id={`mode-${capName}-hosted`} className="mt-1" />
|
|
330
307
|
<div className="flex-1">
|
|
331
308
|
<div className="flex items-center gap-2">
|
|
332
|
-
<Label
|
|
333
|
-
htmlFor={`mode-${capName}-hosted`}
|
|
334
|
-
className="text-sm font-medium cursor-pointer"
|
|
335
|
-
>
|
|
309
|
+
<Label htmlFor={`mode-${capName}-hosted`} className="text-sm font-medium cursor-pointer">
|
|
336
310
|
{brandName()} Hosted
|
|
337
311
|
</Label>
|
|
338
312
|
<Badge variant="outline">{meta.pricing}</Badge>
|
|
@@ -350,15 +324,10 @@ export default function ProvidersPage() {
|
|
|
350
324
|
>
|
|
351
325
|
<RadioGroupItem value="byok" id={`mode-${capName}-byok`} className="mt-1" />
|
|
352
326
|
<div className="flex-1">
|
|
353
|
-
<Label
|
|
354
|
-
htmlFor={`mode-${capName}-byok`}
|
|
355
|
-
className="text-sm font-medium cursor-pointer"
|
|
356
|
-
>
|
|
327
|
+
<Label htmlFor={`mode-${capName}-byok`} className="text-sm font-medium cursor-pointer">
|
|
357
328
|
Bring Your Own Key
|
|
358
329
|
</Label>
|
|
359
|
-
{cap?.provider && (
|
|
360
|
-
<span className="ml-2 text-xs text-muted-foreground">({cap.provider})</span>
|
|
361
|
-
)}
|
|
330
|
+
{cap?.provider && <span className="ml-2 text-xs text-muted-foreground">({cap.provider})</span>}
|
|
362
331
|
</div>
|
|
363
332
|
</div>
|
|
364
333
|
</RadioGroup>
|
|
@@ -375,21 +344,15 @@ export default function ProvidersPage() {
|
|
|
375
344
|
{cap?.maskedKey && (
|
|
376
345
|
<div className="flex items-center gap-2">
|
|
377
346
|
<code className="text-xs text-muted-foreground">{cap.maskedKey}</code>
|
|
378
|
-
{cap.keyStatus && (
|
|
379
|
-
<Badge variant={keyStatusVariant(cap.keyStatus)}>{cap.keyStatus}</Badge>
|
|
380
|
-
)}
|
|
347
|
+
{cap.keyStatus && <Badge variant={keyStatusVariant(cap.keyStatus)}>{cap.keyStatus}</Badge>}
|
|
381
348
|
</div>
|
|
382
349
|
)}
|
|
383
350
|
<div className="flex gap-2">
|
|
384
351
|
<Input
|
|
385
352
|
type="password"
|
|
386
|
-
placeholder={
|
|
387
|
-
cap?.maskedKey ? "Enter new key to replace" : "Enter your API key"
|
|
388
|
-
}
|
|
353
|
+
placeholder={cap?.maskedKey ? "Enter new key to replace" : "Enter your API key"}
|
|
389
354
|
value={byokKey}
|
|
390
|
-
onChange={(e) =>
|
|
391
|
-
setByokKeys((prev) => ({ ...prev, [capName]: e.target.value }))
|
|
392
|
-
}
|
|
355
|
+
onChange={(e) => setByokKeys((prev) => ({ ...prev, [capName]: e.target.value }))}
|
|
393
356
|
className="flex-1"
|
|
394
357
|
aria-label={`${meta.label} API key`}
|
|
395
358
|
/>
|
|
@@ -433,11 +396,7 @@ export default function ProvidersPage() {
|
|
|
433
396
|
>
|
|
434
397
|
<AnimatePresence mode="wait">
|
|
435
398
|
{isTesting ? (
|
|
436
|
-
<motion.span
|
|
437
|
-
key="testing"
|
|
438
|
-
initial={{ opacity: 0 }}
|
|
439
|
-
animate={{ opacity: 1 }}
|
|
440
|
-
>
|
|
399
|
+
<motion.span key="testing" initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
|
|
441
400
|
Testing...
|
|
442
401
|
</motion.span>
|
|
443
402
|
) : capTestResult === "success" ? (
|
|
@@ -461,11 +420,7 @@ export default function ProvidersPage() {
|
|
|
461
420
|
Failed
|
|
462
421
|
</motion.span>
|
|
463
422
|
) : (
|
|
464
|
-
<motion.span
|
|
465
|
-
key="idle"
|
|
466
|
-
initial={{ opacity: 0 }}
|
|
467
|
-
animate={{ opacity: 1 }}
|
|
468
|
-
>
|
|
423
|
+
<motion.span key="idle" initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
|
|
469
424
|
Test Key
|
|
470
425
|
</motion.span>
|
|
471
426
|
)}
|
|
@@ -494,8 +449,7 @@ export default function ProvidersPage() {
|
|
|
494
449
|
<div className="border-t pt-8">
|
|
495
450
|
<h2 className="text-xl font-bold tracking-tight">Provider Keys</h2>
|
|
496
451
|
<p className="text-sm text-muted-foreground">
|
|
497
|
-
Manage your BYOK API keys directly. Keys are stored securely and never leave your
|
|
498
|
-
environment.
|
|
452
|
+
Manage your BYOK API keys directly. Keys are stored securely and never leave your environment.
|
|
499
453
|
</p>
|
|
500
454
|
</div>
|
|
501
455
|
|
|
@@ -516,9 +470,7 @@ export default function ProvidersPage() {
|
|
|
516
470
|
<CardTitle>{provider.provider}</CardTitle>
|
|
517
471
|
</div>
|
|
518
472
|
<Badge variant={providerKeyStatusVariant(provider.status)}>
|
|
519
|
-
{provider.status === "unchecked" && !provider.maskedKey
|
|
520
|
-
? "Not configured"
|
|
521
|
-
: provider.status}
|
|
473
|
+
{provider.status === "unchecked" && !provider.maskedKey ? "Not configured" : provider.status}
|
|
522
474
|
</Badge>
|
|
523
475
|
</div>
|
|
524
476
|
{provider.maskedKey && (
|
|
@@ -533,10 +485,7 @@ export default function ProvidersPage() {
|
|
|
533
485
|
<>
|
|
534
486
|
<div className="flex flex-col gap-2">
|
|
535
487
|
<Label htmlFor={`model-${provider.id}`}>Default model</Label>
|
|
536
|
-
<Select
|
|
537
|
-
value={provider.defaultModel ?? ""}
|
|
538
|
-
onValueChange={(v) => handleModelChange(provider.id, v)}
|
|
539
|
-
>
|
|
488
|
+
<Select value={provider.defaultModel ?? ""} onValueChange={(v) => handleModelChange(provider.id, v)}>
|
|
540
489
|
<SelectTrigger id={`model-${provider.id}`} className="w-full">
|
|
541
490
|
<SelectValue placeholder="Select a model" />
|
|
542
491
|
</SelectTrigger>
|
|
@@ -558,11 +507,7 @@ export default function ProvidersPage() {
|
|
|
558
507
|
>
|
|
559
508
|
<AnimatePresence mode="wait">
|
|
560
509
|
{testing === provider.id ? (
|
|
561
|
-
<motion.span
|
|
562
|
-
key="testing"
|
|
563
|
-
initial={{ opacity: 0 }}
|
|
564
|
-
animate={{ opacity: 1 }}
|
|
565
|
-
>
|
|
510
|
+
<motion.span key="testing" initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
|
|
566
511
|
Testing...
|
|
567
512
|
</motion.span>
|
|
568
513
|
) : testResult[provider.id] === "success" ? (
|
|
@@ -656,8 +601,8 @@ function BillingGateDialog({
|
|
|
656
601
|
Enable {brandName()} Hosted for {meta.label}?
|
|
657
602
|
</DialogTitle>
|
|
658
603
|
<DialogDescription>
|
|
659
|
-
{brandName()} Hosted for {meta.label.toLowerCase()} costs {meta.pricing}. This will be
|
|
660
|
-
|
|
604
|
+
{brandName()} Hosted for {meta.label.toLowerCase()} costs {meta.pricing}. This will be billed to your
|
|
605
|
+
payment method on file.
|
|
661
606
|
</DialogDescription>
|
|
662
607
|
</DialogHeader>
|
|
663
608
|
|
|
@@ -810,9 +755,7 @@ function RotateKeyDialog({ provider, onSaved }: { provider: ProviderKey; onSaved
|
|
|
810
755
|
<DialogContent>
|
|
811
756
|
<DialogHeader>
|
|
812
757
|
<DialogTitle>Rotate {provider.provider} Key</DialogTitle>
|
|
813
|
-
<DialogDescription>
|
|
814
|
-
Paste your new API key. The old key will be replaced after validation.
|
|
815
|
-
</DialogDescription>
|
|
758
|
+
<DialogDescription>Paste your new API key. The old key will be replaced after validation.</DialogDescription>
|
|
816
759
|
</DialogHeader>
|
|
817
760
|
<form onSubmit={handleSubmit} className="flex flex-col gap-4">
|
|
818
761
|
<div className="flex flex-col gap-2">
|
|
@@ -18,22 +18,9 @@ import {
|
|
|
18
18
|
} from "@/components/ui/dialog";
|
|
19
19
|
import { Input } from "@/components/ui/input";
|
|
20
20
|
import { Label } from "@/components/ui/label";
|
|
21
|
-
import {
|
|
22
|
-
Select,
|
|
23
|
-
SelectContent,
|
|
24
|
-
SelectItem,
|
|
25
|
-
SelectTrigger,
|
|
26
|
-
SelectValue,
|
|
27
|
-
} from "@/components/ui/select";
|
|
21
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
28
22
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
29
|
-
import {
|
|
30
|
-
Table,
|
|
31
|
-
TableBody,
|
|
32
|
-
TableCell,
|
|
33
|
-
TableHead,
|
|
34
|
-
TableHeader,
|
|
35
|
-
TableRow,
|
|
36
|
-
} from "@/components/ui/table";
|
|
23
|
+
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
|
37
24
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
|
38
25
|
import {
|
|
39
26
|
createSecret,
|
|
@@ -141,9 +128,7 @@ export default function SecretsPage() {
|
|
|
141
128
|
<div className="flex items-center justify-between">
|
|
142
129
|
<div>
|
|
143
130
|
<h1 className="text-2xl font-bold tracking-tight">Secrets Vault</h1>
|
|
144
|
-
<p className="text-sm text-muted-foreground">
|
|
145
|
-
Manage encrypted credentials for plugins and integrations
|
|
146
|
-
</p>
|
|
131
|
+
<p className="text-sm text-muted-foreground">Manage encrypted credentials for plugins and integrations</p>
|
|
147
132
|
</div>
|
|
148
133
|
<CreateSecretDialog
|
|
149
134
|
onCreated={(plaintextValue) => {
|
|
@@ -167,29 +152,18 @@ export default function SecretsPage() {
|
|
|
167
152
|
Your new secret has been created. Copy it now -- it will not be shown again.
|
|
168
153
|
</p>
|
|
169
154
|
<div className="flex items-center gap-2">
|
|
170
|
-
<code className="flex-1 rounded bg-muted px-3 py-2 text-sm font-mono break-all">
|
|
171
|
-
{revealedValue}
|
|
172
|
-
</code>
|
|
155
|
+
<code className="flex-1 rounded bg-muted px-3 py-2 text-sm font-mono break-all">{revealedValue}</code>
|
|
173
156
|
<Tooltip open={copied}>
|
|
174
157
|
<TooltipTrigger asChild>
|
|
175
158
|
<Button variant="outline" size="sm" onClick={handleCopy}>
|
|
176
|
-
{copied ?
|
|
177
|
-
<CheckIcon className="size-4" />
|
|
178
|
-
) : (
|
|
179
|
-
<CopyIcon className="size-4" />
|
|
180
|
-
)}
|
|
159
|
+
{copied ? <CheckIcon className="size-4" /> : <CopyIcon className="size-4" />}
|
|
181
160
|
{copied ? "Copied" : "Copy"}
|
|
182
161
|
</Button>
|
|
183
162
|
</TooltipTrigger>
|
|
184
163
|
<TooltipContent>Copied!</TooltipContent>
|
|
185
164
|
</Tooltip>
|
|
186
165
|
</div>
|
|
187
|
-
<Button
|
|
188
|
-
variant="ghost"
|
|
189
|
-
size="sm"
|
|
190
|
-
className="mt-2"
|
|
191
|
-
onClick={() => setRevealedValue(null)}
|
|
192
|
-
>
|
|
166
|
+
<Button variant="ghost" size="sm" className="mt-2" onClick={() => setRevealedValue(null)}>
|
|
193
167
|
Dismiss
|
|
194
168
|
</Button>
|
|
195
169
|
</CardContent>
|
|
@@ -280,9 +254,7 @@ export default function SecretsPage() {
|
|
|
280
254
|
key={secret.id}
|
|
281
255
|
secret={secret}
|
|
282
256
|
isAuditExpanded={expandedAudit === secret.id}
|
|
283
|
-
onToggleAudit={() =>
|
|
284
|
-
setExpandedAudit(expandedAudit === secret.id ? null : secret.id)
|
|
285
|
-
}
|
|
257
|
+
onToggleAudit={() => setExpandedAudit(expandedAudit === secret.id ? null : secret.id)}
|
|
286
258
|
onRotate={() => handleRotate(secret.id)}
|
|
287
259
|
onDelete={() => handleDelete(secret.id)}
|
|
288
260
|
/>
|
|
@@ -332,12 +304,7 @@ function SecretRow({
|
|
|
332
304
|
<div className="flex items-center gap-1">
|
|
333
305
|
<Tooltip>
|
|
334
306
|
<TooltipTrigger asChild>
|
|
335
|
-
<Button
|
|
336
|
-
variant="ghost"
|
|
337
|
-
size="icon-sm"
|
|
338
|
-
aria-label="Access log"
|
|
339
|
-
onClick={onToggleAudit}
|
|
340
|
-
>
|
|
307
|
+
<Button variant="ghost" size="icon-sm" aria-label="Access log" onClick={onToggleAudit}>
|
|
341
308
|
<HistoryIcon className="size-4" />
|
|
342
309
|
</Button>
|
|
343
310
|
</TooltipTrigger>
|
|
@@ -399,9 +366,7 @@ function AuditPanel({ secretId }: { secretId: string }) {
|
|
|
399
366
|
|
|
400
367
|
return (
|
|
401
368
|
<div className="px-4 py-3 space-y-2">
|
|
402
|
-
<p className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
|
|
403
|
-
Access Log
|
|
404
|
-
</p>
|
|
369
|
+
<p className="text-xs font-medium text-muted-foreground uppercase tracking-wider">Access Log</p>
|
|
405
370
|
{loading ? (
|
|
406
371
|
<div className="space-y-2">
|
|
407
372
|
{Array.from({ length: 3 }, (_, i) => `audit-sk-${i}`).map((id) => (
|
|
@@ -409,9 +374,7 @@ function AuditPanel({ secretId }: { secretId: string }) {
|
|
|
409
374
|
))}
|
|
410
375
|
</div>
|
|
411
376
|
) : unavailable ? (
|
|
412
|
-
<p className="py-4 text-center text-xs text-muted-foreground">
|
|
413
|
-
Audit log not available yet.
|
|
414
|
-
</p>
|
|
377
|
+
<p className="py-4 text-center text-xs text-muted-foreground">Audit log not available yet.</p>
|
|
415
378
|
) : entries.length === 0 ? (
|
|
416
379
|
<p className="py-4 text-center text-xs text-muted-foreground">No access recorded yet.</p>
|
|
417
380
|
) : (
|
|
@@ -580,8 +543,7 @@ function RotateDialog({ secretName, onRotate }: { secretName: string; onRotate:
|
|
|
580
543
|
<DialogHeader>
|
|
581
544
|
<DialogTitle>Rotate Secret</DialogTitle>
|
|
582
545
|
<DialogDescription>
|
|
583
|
-
Generate a new value for <strong>{secretName}</strong>. The current value will be
|
|
584
|
-
immediately invalidated.
|
|
546
|
+
Generate a new value for <strong>{secretName}</strong>. The current value will be immediately invalidated.
|
|
585
547
|
</DialogDescription>
|
|
586
548
|
</DialogHeader>
|
|
587
549
|
<div className="rounded-sm border border-chart-3/20 bg-chart-3/10 px-3 py-2 text-sm text-chart-3">
|
|
@@ -606,13 +568,7 @@ function RotateDialog({ secretName, onRotate }: { secretName: string; onRotate:
|
|
|
606
568
|
);
|
|
607
569
|
}
|
|
608
570
|
|
|
609
|
-
function DeleteSecretDialog({
|
|
610
|
-
secretName,
|
|
611
|
-
onDelete,
|
|
612
|
-
}: {
|
|
613
|
-
secretName: string;
|
|
614
|
-
onDelete: () => void;
|
|
615
|
-
}) {
|
|
571
|
+
function DeleteSecretDialog({ secretName, onDelete }: { secretName: string; onDelete: () => void }) {
|
|
616
572
|
const [open, setOpen] = useState(false);
|
|
617
573
|
|
|
618
574
|
return (
|
|
@@ -631,8 +587,7 @@ function DeleteSecretDialog({
|
|
|
631
587
|
<DialogHeader>
|
|
632
588
|
<DialogTitle>Delete Secret</DialogTitle>
|
|
633
589
|
<DialogDescription>
|
|
634
|
-
Are you sure you want to delete <strong>{secretName}</strong>? This action cannot be
|
|
635
|
-
undone.
|
|
590
|
+
Are you sure you want to delete <strong>{secretName}</strong>? This action cannot be undone.
|
|
636
591
|
</DialogDescription>
|
|
637
592
|
</DialogHeader>
|
|
638
593
|
<div className="rounded-sm border border-destructive/20 bg-destructive/10 px-3 py-2 text-sm text-destructive">
|