@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
|
@@ -16,12 +16,7 @@ vi.mock("@/lib/api", () => ({
|
|
|
16
16
|
}));
|
|
17
17
|
|
|
18
18
|
import type { AutoAcceptConfig, DiscoveredBot, Friend, FriendRequest } from "@/lib/api";
|
|
19
|
-
import {
|
|
20
|
-
getAutoAcceptConfig,
|
|
21
|
-
listDiscoveredBots,
|
|
22
|
-
listFriendRequests,
|
|
23
|
-
listFriends,
|
|
24
|
-
} from "@/lib/api";
|
|
19
|
+
import { getAutoAcceptConfig, listDiscoveredBots, listFriendRequests, listFriends } from "@/lib/api";
|
|
25
20
|
import { FriendsTab } from "./friends-tab";
|
|
26
21
|
|
|
27
22
|
const mockListFriends = listFriends as ReturnType<typeof vi.fn>;
|
|
@@ -88,9 +83,7 @@ describe("FriendsTab", () => {
|
|
|
88
83
|
|
|
89
84
|
render(<FriendsTab instanceId={INSTANCE_ID} />);
|
|
90
85
|
await waitFor(() => {
|
|
91
|
-
expect(
|
|
92
|
-
screen.getByText("No friends yet. Discover bots on the network below."),
|
|
93
|
-
).toBeInTheDocument();
|
|
86
|
+
expect(screen.getByText("No friends yet. Discover bots on the network below.")).toBeInTheDocument();
|
|
94
87
|
});
|
|
95
88
|
});
|
|
96
89
|
|
|
@@ -11,14 +11,7 @@ import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover
|
|
|
11
11
|
import { Separator } from "@/components/ui/separator";
|
|
12
12
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
13
13
|
import { Switch } from "@/components/ui/switch";
|
|
14
|
-
import {
|
|
15
|
-
Table,
|
|
16
|
-
TableBody,
|
|
17
|
-
TableCell,
|
|
18
|
-
TableHead,
|
|
19
|
-
TableHeader,
|
|
20
|
-
TableRow,
|
|
21
|
-
} from "@/components/ui/table";
|
|
14
|
+
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
|
22
15
|
import type { AutoAcceptConfig, DiscoveredBot, Friend, FriendRequest } from "@/lib/api";
|
|
23
16
|
import {
|
|
24
17
|
acceptFriendRequest,
|
|
@@ -143,16 +136,12 @@ export function FriendsTab({ instanceId }: { instanceId: string }) {
|
|
|
143
136
|
setActionError(null);
|
|
144
137
|
const updated = current.includes(cap) ? current.filter((c) => c !== cap) : [...current, cap];
|
|
145
138
|
// Optimistic update
|
|
146
|
-
setFriends((prev) =>
|
|
147
|
-
prev.map((f) => (f.id === friendId ? { ...f, sharedCapabilities: updated } : f)),
|
|
148
|
-
);
|
|
139
|
+
setFriends((prev) => prev.map((f) => (f.id === friendId ? { ...f, sharedCapabilities: updated } : f)));
|
|
149
140
|
try {
|
|
150
141
|
await updateFriendCapabilities(instanceId, friendId, updated);
|
|
151
142
|
} catch (err) {
|
|
152
143
|
// Rollback
|
|
153
|
-
setFriends((prev) =>
|
|
154
|
-
prev.map((f) => (f.id === friendId ? { ...f, sharedCapabilities: current } : f)),
|
|
155
|
-
);
|
|
144
|
+
setFriends((prev) => prev.map((f) => (f.id === friendId ? { ...f, sharedCapabilities: current } : f)));
|
|
156
145
|
setActionError(toUserMessage(err, "Failed to update capabilities"));
|
|
157
146
|
}
|
|
158
147
|
}
|
|
@@ -196,12 +185,7 @@ export function FriendsTab({ instanceId }: { instanceId: string }) {
|
|
|
196
185
|
return (
|
|
197
186
|
<div className="space-y-6">
|
|
198
187
|
{Array.from({ length: 4 }, (_, i) => `friends-sk-${i}`).map((skId, i) => (
|
|
199
|
-
<motion.div
|
|
200
|
-
key={skId}
|
|
201
|
-
initial={{ opacity: 0 }}
|
|
202
|
-
animate={{ opacity: 1 }}
|
|
203
|
-
transition={{ delay: i * 0.05 }}
|
|
204
|
-
>
|
|
188
|
+
<motion.div key={skId} initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: i * 0.05 }}>
|
|
205
189
|
<Skeleton className="h-24 w-full rounded-sm" />
|
|
206
190
|
</motion.div>
|
|
207
191
|
))}
|
|
@@ -211,9 +195,7 @@ export function FriendsTab({ instanceId }: { instanceId: string }) {
|
|
|
211
195
|
|
|
212
196
|
if (error) {
|
|
213
197
|
return (
|
|
214
|
-
<div className="rounded-md border border-red-500/25 bg-red-500/10 px-4 py-3 text-sm text-red-500">
|
|
215
|
-
{error}
|
|
216
|
-
</div>
|
|
198
|
+
<div className="rounded-md border border-red-500/25 bg-red-500/10 px-4 py-3 text-sm text-red-500">{error}</div>
|
|
217
199
|
);
|
|
218
200
|
}
|
|
219
201
|
|
|
@@ -269,9 +251,7 @@ export function FriendsTab({ instanceId }: { instanceId: string }) {
|
|
|
269
251
|
transition={{ duration: 0.15 }}
|
|
270
252
|
className="transition-colors hover:bg-muted/50 even:bg-muted/20 border-b last:border-b-0"
|
|
271
253
|
>
|
|
272
|
-
<TableCell className="font-medium text-sm text-foreground">
|
|
273
|
-
{friend.name}
|
|
274
|
-
</TableCell>
|
|
254
|
+
<TableCell className="font-medium text-sm text-foreground">{friend.name}</TableCell>
|
|
275
255
|
<TableCell>
|
|
276
256
|
<FriendStatusBadge status={friend.status} />
|
|
277
257
|
</TableCell>
|
|
@@ -285,13 +265,7 @@ export function FriendsTab({ instanceId }: { instanceId: string }) {
|
|
|
285
265
|
key={cap}
|
|
286
266
|
variant="outline"
|
|
287
267
|
className="rounded-sm border-terminal/20 bg-terminal/5 text-terminal-dim text-xs px-1.5 py-0.5 cursor-pointer hover:bg-terminal/10 transition-colors duration-150"
|
|
288
|
-
onClick={() =>
|
|
289
|
-
handleToggleCapability(
|
|
290
|
-
friend.id,
|
|
291
|
-
friend.sharedCapabilities,
|
|
292
|
-
cap,
|
|
293
|
-
)
|
|
294
|
-
}
|
|
268
|
+
onClick={() => handleToggleCapability(friend.id, friend.sharedCapabilities, cap)}
|
|
295
269
|
>
|
|
296
270
|
{cap} <X className="ml-0.5 size-3 inline" />
|
|
297
271
|
</Badge>
|
|
@@ -299,9 +273,7 @@ export function FriendsTab({ instanceId }: { instanceId: string }) {
|
|
|
299
273
|
)}
|
|
300
274
|
<CapabilityAddPopover
|
|
301
275
|
existing={friend.sharedCapabilities}
|
|
302
|
-
onAdd={(cap) =>
|
|
303
|
-
handleToggleCapability(friend.id, friend.sharedCapabilities, cap)
|
|
304
|
-
}
|
|
276
|
+
onAdd={(cap) => handleToggleCapability(friend.id, friend.sharedCapabilities, cap)}
|
|
305
277
|
/>
|
|
306
278
|
</div>
|
|
307
279
|
</TableCell>
|
|
@@ -367,9 +339,7 @@ export function FriendsTab({ instanceId }: { instanceId: string }) {
|
|
|
367
339
|
transition={{ duration: 0.15 }}
|
|
368
340
|
className="transition-colors hover:bg-muted/50 border-l-2 border-l-terminal border-b last:border-b-0"
|
|
369
341
|
>
|
|
370
|
-
<TableCell className="font-medium text-sm text-foreground">
|
|
371
|
-
{req.fromName}
|
|
372
|
-
</TableCell>
|
|
342
|
+
<TableCell className="font-medium text-sm text-foreground">{req.fromName}</TableCell>
|
|
373
343
|
<TableCell className="hidden md:table-cell text-xs text-muted-foreground">
|
|
374
344
|
{formatRelativeTime(req.createdAt)}
|
|
375
345
|
</TableCell>
|
|
@@ -429,9 +399,7 @@ export function FriendsTab({ instanceId }: { instanceId: string }) {
|
|
|
429
399
|
transition={{ duration: 0.15 }}
|
|
430
400
|
className="transition-colors hover:bg-muted/50 opacity-80 border-b last:border-b-0"
|
|
431
401
|
>
|
|
432
|
-
<TableCell className="font-medium text-sm text-foreground">
|
|
433
|
-
{req.toName}
|
|
434
|
-
</TableCell>
|
|
402
|
+
<TableCell className="font-medium text-sm text-foreground">{req.toName}</TableCell>
|
|
435
403
|
<TableCell className="hidden md:table-cell text-xs text-muted-foreground">
|
|
436
404
|
{formatRelativeTime(req.createdAt)}
|
|
437
405
|
</TableCell>
|
|
@@ -474,15 +442,13 @@ export function FriendsTab({ instanceId }: { instanceId: string }) {
|
|
|
474
442
|
<div className="flex flex-col items-center justify-center py-8 gap-3">
|
|
475
443
|
<Radio className="size-12 text-muted-foreground/50" />
|
|
476
444
|
<p className="text-sm text-muted-foreground italic">
|
|
477
|
-
No bots discovered on the network. Your bot may need to be online to discover
|
|
478
|
-
peers.
|
|
445
|
+
No bots discovered on the network. Your bot may need to be online to discover peers.
|
|
479
446
|
</p>
|
|
480
447
|
</div>
|
|
481
448
|
) : (
|
|
482
449
|
<div className="rounded-sm border">
|
|
483
450
|
<div className="px-3 py-1.5 border-b text-xs text-muted-foreground">
|
|
484
|
-
Showing {discovered.length} bot{discovered.length !== 1 ? "s" : ""} on your local
|
|
485
|
-
network
|
|
451
|
+
Showing {discovered.length} bot{discovered.length !== 1 ? "s" : ""} on your local network
|
|
486
452
|
</div>
|
|
487
453
|
<Table>
|
|
488
454
|
<TableHeader>
|
|
@@ -494,13 +460,8 @@ export function FriendsTab({ instanceId }: { instanceId: string }) {
|
|
|
494
460
|
</TableHeader>
|
|
495
461
|
<TableBody>
|
|
496
462
|
{discovered.map((bot) => (
|
|
497
|
-
<TableRow
|
|
498
|
-
|
|
499
|
-
className="transition-colors hover:bg-terminal/5 even:bg-muted/20"
|
|
500
|
-
>
|
|
501
|
-
<TableCell className="font-medium text-sm text-foreground">
|
|
502
|
-
{bot.name}
|
|
503
|
-
</TableCell>
|
|
463
|
+
<TableRow key={bot.id} className="transition-colors hover:bg-terminal/5 even:bg-muted/20">
|
|
464
|
+
<TableCell className="font-medium text-sm text-foreground">{bot.name}</TableCell>
|
|
504
465
|
<TableCell className="hidden md:table-cell">
|
|
505
466
|
<div className="flex flex-wrap gap-1">
|
|
506
467
|
{bot.capabilities.map((cap) => (
|
|
@@ -516,12 +477,7 @@ export function FriendsTab({ instanceId }: { instanceId: string }) {
|
|
|
516
477
|
</TableCell>
|
|
517
478
|
<TableCell className="text-right">
|
|
518
479
|
{sendingTo === bot.id ? (
|
|
519
|
-
<Button
|
|
520
|
-
size="sm"
|
|
521
|
-
variant="ghost"
|
|
522
|
-
className="text-muted-foreground"
|
|
523
|
-
disabled
|
|
524
|
-
>
|
|
480
|
+
<Button size="sm" variant="ghost" className="text-muted-foreground" disabled>
|
|
525
481
|
<Loader2 className="size-3.5 animate-spin md:mr-1" />
|
|
526
482
|
<span className="hidden md:inline">Pending...</span>
|
|
527
483
|
</Button>
|
|
@@ -585,10 +541,7 @@ export function FriendsTab({ instanceId }: { instanceId: string }) {
|
|
|
585
541
|
>
|
|
586
542
|
<div className="bg-secondary rounded-sm p-4 mt-3 space-y-3">
|
|
587
543
|
<div className="space-y-1">
|
|
588
|
-
<label
|
|
589
|
-
htmlFor="cap-rules"
|
|
590
|
-
className="text-xs font-medium text-muted-foreground"
|
|
591
|
-
>
|
|
544
|
+
<label htmlFor="cap-rules" className="text-xs font-medium text-muted-foreground">
|
|
592
545
|
Required capabilities (comma-separated)
|
|
593
546
|
</label>
|
|
594
547
|
<Input
|
|
@@ -601,10 +554,7 @@ export function FriendsTab({ instanceId }: { instanceId: string }) {
|
|
|
601
554
|
/>
|
|
602
555
|
</div>
|
|
603
556
|
<div className="space-y-1">
|
|
604
|
-
<label
|
|
605
|
-
htmlFor="max-friends"
|
|
606
|
-
className="text-xs font-medium text-muted-foreground"
|
|
607
|
-
>
|
|
557
|
+
<label htmlFor="max-friends" className="text-xs font-medium text-muted-foreground">
|
|
608
558
|
Max friends
|
|
609
559
|
</label>
|
|
610
560
|
<Input
|
|
@@ -658,13 +608,7 @@ function FriendStatusBadge({ status }: { status: "online" | "offline" | "unknown
|
|
|
658
608
|
);
|
|
659
609
|
}
|
|
660
610
|
|
|
661
|
-
function CapabilityAddPopover({
|
|
662
|
-
existing,
|
|
663
|
-
onAdd,
|
|
664
|
-
}: {
|
|
665
|
-
existing: string[];
|
|
666
|
-
onAdd: (cap: string) => void;
|
|
667
|
-
}) {
|
|
611
|
+
function CapabilityAddPopover({ existing, onAdd }: { existing: string[]; onAdd: (cap: string) => void }) {
|
|
668
612
|
const [value, setValue] = useState("");
|
|
669
613
|
|
|
670
614
|
function handleAdd() {
|
|
@@ -36,12 +36,7 @@ interface UpdateAvailableBadgeProps {
|
|
|
36
36
|
onUpdated?: () => void;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
export function UpdateAvailableBadge({
|
|
40
|
-
instanceId,
|
|
41
|
-
instanceName,
|
|
42
|
-
changelog,
|
|
43
|
-
onUpdated,
|
|
44
|
-
}: UpdateAvailableBadgeProps) {
|
|
39
|
+
export function UpdateAvailableBadge({ instanceId, instanceName, changelog, onUpdated }: UpdateAvailableBadgeProps) {
|
|
45
40
|
const [pulling, setPulling] = useState(false);
|
|
46
41
|
|
|
47
42
|
async function handleUpdate() {
|
|
@@ -96,11 +91,7 @@ export function UpdateAvailableBadge({
|
|
|
96
91
|
|
|
97
92
|
<AlertDialogFooter>
|
|
98
93
|
<AlertDialogCancel>Later</AlertDialogCancel>
|
|
99
|
-
<AlertDialogAction
|
|
100
|
-
onClick={handleUpdate}
|
|
101
|
-
disabled={pulling}
|
|
102
|
-
className="bg-amber-600 hover:bg-amber-700"
|
|
103
|
-
>
|
|
94
|
+
<AlertDialogAction onClick={handleUpdate} disabled={pulling} className="bg-amber-600 hover:bg-amber-700">
|
|
104
95
|
{pulling ? (
|
|
105
96
|
<>
|
|
106
97
|
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
|
@@ -18,10 +18,7 @@ export function Hero() {
|
|
|
18
18
|
/>
|
|
19
19
|
|
|
20
20
|
{/* Radial glow pulse */}
|
|
21
|
-
<div
|
|
22
|
-
className="pointer-events-none absolute inset-0 flex items-center justify-center"
|
|
23
|
-
aria-hidden="true"
|
|
24
|
-
>
|
|
21
|
+
<div className="pointer-events-none absolute inset-0 flex items-center justify-center" aria-hidden="true">
|
|
25
22
|
<div className="animate-gentle-pulse h-[600px] w-[600px] rounded-full bg-terminal/5 blur-[120px]" />
|
|
26
23
|
</div>
|
|
27
24
|
|
|
@@ -34,8 +31,7 @@ export function Hero() {
|
|
|
34
31
|
</h1>
|
|
35
32
|
|
|
36
33
|
<p className="mt-8 max-w-2xl text-lg text-muted-foreground md:text-xl">
|
|
37
|
-
A $5/month supercomputer that runs your business. No really. We know because we run ours
|
|
38
|
-
on one.
|
|
34
|
+
A $5/month supercomputer that runs your business. No really. We know because we run ours on one.
|
|
39
35
|
</p>
|
|
40
36
|
|
|
41
37
|
<div className="mt-12 flex flex-col items-center gap-4 sm:flex-row">
|
|
@@ -44,9 +40,7 @@ export function Hero() {
|
|
|
44
40
|
</Button>
|
|
45
41
|
</div>
|
|
46
42
|
|
|
47
|
-
<span className="mt-4 text-sm text-muted-foreground">
|
|
48
|
-
Starting at $5/month. Less than Netflix.
|
|
49
|
-
</span>
|
|
43
|
+
<span className="mt-4 text-sm text-muted-foreground">Starting at $5/month. Less than Netflix.</span>
|
|
50
44
|
</div>
|
|
51
45
|
</section>
|
|
52
46
|
);
|
|
@@ -15,9 +15,7 @@ function CtaBlock({ className }: { className?: string }) {
|
|
|
15
15
|
<Button variant="terminal" size="lg" asChild>
|
|
16
16
|
<Link href="/signup">Start for free</Link>
|
|
17
17
|
</Button>
|
|
18
|
-
<span className="mt-4 font-mono text-xs text-terminal/40">
|
|
19
|
-
Your {productName()} is waiting.
|
|
20
|
-
</span>
|
|
18
|
+
<span className="mt-4 font-mono text-xs text-terminal/40">Your {productName()} is waiting.</span>
|
|
21
19
|
</div>
|
|
22
20
|
);
|
|
23
21
|
}
|
|
@@ -136,8 +136,7 @@ export function PortfolioChart({ onMilestoneRef, onFadeStartRef }: PortfolioChar
|
|
|
136
136
|
// Wire milestone ref
|
|
137
137
|
useEffect(() => {
|
|
138
138
|
if (onMilestoneRef && "current" in onMilestoneRef) {
|
|
139
|
-
(onMilestoneRef as React.MutableRefObject<((label: string) => void) | null>).current =
|
|
140
|
-
handleMilestone;
|
|
139
|
+
(onMilestoneRef as React.MutableRefObject<((label: string) => void) | null>).current = handleMilestone;
|
|
141
140
|
}
|
|
142
141
|
return () => {
|
|
143
142
|
if (onMilestoneRef && "current" in onMilestoneRef) {
|
|
@@ -222,15 +221,12 @@ export function PortfolioChart({ onMilestoneRef, onFadeStartRef }: PortfolioChar
|
|
|
222
221
|
// Smooth the viewport anchor — EMA tracks trend, not raw noise
|
|
223
222
|
// Faster at start (less history), slower as chart matures
|
|
224
223
|
const emaAlpha = Math.max(0.02, 0.15 - s.milestoneCount * 0.002);
|
|
225
|
-
s.smoothedValue =
|
|
226
|
-
s.count < 2 ? s.value : s.smoothedValue * (1 - emaAlpha) + s.value * emaAlpha;
|
|
224
|
+
s.smoothedValue = s.count < 2 ? s.value : s.smoothedValue * (1 - emaAlpha) + s.value * emaAlpha;
|
|
227
225
|
|
|
228
226
|
// Viewport — zooms in gently early, then zooms WAY out as milestones accumulate
|
|
229
227
|
const yRange = 30 + s.milestoneCount * 8;
|
|
230
228
|
const xSpan =
|
|
231
|
-
s.milestoneCount < 30
|
|
232
|
-
? Math.max(300, 500 - s.milestoneCount * 4)
|
|
233
|
-
: 380 + (s.milestoneCount - 30) * 150;
|
|
229
|
+
s.milestoneCount < 30 ? Math.max(300, 500 - s.milestoneCount * 4) : 380 + (s.milestoneCount - 30) * 150;
|
|
234
230
|
const xRight = s.t;
|
|
235
231
|
const xLeft = s.t - xSpan;
|
|
236
232
|
|
|
@@ -274,8 +270,7 @@ export function PortfolioChart({ onMilestoneRef, onFadeStartRef }: PortfolioChar
|
|
|
274
270
|
|
|
275
271
|
// End-of-sequence fade: triggered when terminal enters final-typing.
|
|
276
272
|
const FADE_DURATION = 2000; // ms
|
|
277
|
-
const lineAlpha =
|
|
278
|
-
s.fadeStartTime < 0 ? 1 : Math.max(0, 1 - (now - s.fadeStartTime) / FADE_DURATION);
|
|
273
|
+
const lineAlpha = s.fadeStartTime < 0 ? 1 : Math.max(0, 1 - (now - s.fadeStartTime) / FADE_DURATION);
|
|
279
274
|
|
|
280
275
|
if (lineAlpha > 0.01) {
|
|
281
276
|
// Layer 1: Bloom
|
|
@@ -40,9 +40,7 @@ export function StorySections() {
|
|
|
40
40
|
}}
|
|
41
41
|
>
|
|
42
42
|
<h2 className="font-mono text-lg font-bold text-terminal sm:text-xl">{story.heading}</h2>
|
|
43
|
-
<p className="mt-4 font-mono text-sm leading-relaxed text-terminal/60 sm:text-base">
|
|
44
|
-
{story.body}
|
|
45
|
-
</p>
|
|
43
|
+
<p className="mt-4 font-mono text-sm leading-relaxed text-terminal/60 sm:text-base">{story.body}</p>
|
|
46
44
|
</motion.div>
|
|
47
45
|
))}
|
|
48
46
|
</section>
|
|
@@ -58,15 +58,7 @@ function getTextBlur(lineIndex: number): number {
|
|
|
58
58
|
return Math.min(8, Math.max(0, (lineIndex - 18) * 0.22));
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
type AnimState =
|
|
62
|
-
| "idle"
|
|
63
|
-
| "typing"
|
|
64
|
-
| "pause"
|
|
65
|
-
| "backspacing"
|
|
66
|
-
| "final-typing"
|
|
67
|
-
| "cursor-death"
|
|
68
|
-
| "blinking"
|
|
69
|
-
| "done";
|
|
61
|
+
type AnimState = "idle" | "typing" | "pause" | "backspacing" | "final-typing" | "cursor-death" | "blinking" | "done";
|
|
70
62
|
|
|
71
63
|
export function TerminalSequence({ onComplete, onMilestone, onFadeStart }: TerminalSequenceProps) {
|
|
72
64
|
const [lines, setLines] = useState<string[]>([]);
|
|
@@ -345,10 +337,7 @@ export function TerminalSequence({ onComplete, onMilestone, onFadeStart }: Termi
|
|
|
345
337
|
/>
|
|
346
338
|
|
|
347
339
|
{/* Radial glow pulse */}
|
|
348
|
-
<div
|
|
349
|
-
className="pointer-events-none absolute inset-0 flex items-center justify-center"
|
|
350
|
-
aria-hidden="true"
|
|
351
|
-
>
|
|
340
|
+
<div className="pointer-events-none absolute inset-0 flex items-center justify-center" aria-hidden="true">
|
|
352
341
|
<div className="animate-gentle-pulse h-[600px] w-[600px] rounded-full bg-terminal/5 blur-[120px]" />
|
|
353
342
|
</div>
|
|
354
343
|
|
|
@@ -379,10 +368,8 @@ export function TerminalSequence({ onComplete, onMilestone, onFadeStart }: Termi
|
|
|
379
368
|
old lines overflow upward and are clipped + faded by the mask */}
|
|
380
369
|
<div className="absolute bottom-0 flex w-full flex-col">
|
|
381
370
|
{lines.map((line, i) => (
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
className={animationDone ? "text-terminal" : "text-terminal/30"}
|
|
385
|
-
>
|
|
371
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: static list, index key is safe
|
|
372
|
+
<div key={`${i}-${line}`} className={animationDone ? "text-terminal" : "text-terminal/30"}>
|
|
386
373
|
{line || "\u00A0"}
|
|
387
374
|
</div>
|
|
388
375
|
))}
|
|
@@ -31,16 +31,12 @@ export function MarketplaceEmptyState({ hasSearch, searchTerm }: EmptyStateProps
|
|
|
31
31
|
{hasSearch ? (
|
|
32
32
|
<>
|
|
33
33
|
<p className="text-lg font-medium">No results for “{searchTerm}”</p>
|
|
34
|
-
<p className="mt-1 text-sm text-muted-foreground">
|
|
35
|
-
Try a different search term or browse by category.
|
|
36
|
-
</p>
|
|
34
|
+
<p className="mt-1 text-sm text-muted-foreground">Try a different search term or browse by category.</p>
|
|
37
35
|
</>
|
|
38
36
|
) : (
|
|
39
37
|
<>
|
|
40
38
|
<p className="text-lg font-medium">Your {productName()} could do more...</p>
|
|
41
|
-
<p className="mt-1 text-sm text-muted-foreground">
|
|
42
|
-
Add plugins to give your bot superpowers.
|
|
43
|
-
</p>
|
|
39
|
+
<p className="mt-1 text-sm text-muted-foreground">Add plugins to give your bot superpowers.</p>
|
|
44
40
|
<div className="mt-6 flex flex-wrap justify-center gap-3">
|
|
45
41
|
{suggestedPlugins.map((p) => (
|
|
46
42
|
<Link
|
|
@@ -85,9 +85,7 @@ export function FirstVisitHero({ superpowers, onDismiss }: FirstVisitHeroProps)
|
|
|
85
85
|
{sp.name[0]}
|
|
86
86
|
</div>
|
|
87
87
|
<h2 className="text-lg font-bold">{sp.superpowerHeadline ?? sp.name}</h2>
|
|
88
|
-
<p className="mt-1 text-sm text-muted-foreground">
|
|
89
|
-
{sp.superpowerTagline ?? sp.description}
|
|
90
|
-
</p>
|
|
88
|
+
<p className="mt-1 text-sm text-muted-foreground">{sp.superpowerTagline ?? sp.description}</p>
|
|
91
89
|
</div>
|
|
92
90
|
</motion.button>
|
|
93
91
|
))}
|
|
@@ -6,24 +6,11 @@ import { z } from "zod";
|
|
|
6
6
|
import { CapabilityProviderPicker } from "@/components/capability/CapabilityResolver";
|
|
7
7
|
import { Badge } from "@/components/ui/badge";
|
|
8
8
|
import { Button } from "@/components/ui/button";
|
|
9
|
-
import {
|
|
10
|
-
Card,
|
|
11
|
-
CardContent,
|
|
12
|
-
CardDescription,
|
|
13
|
-
CardFooter,
|
|
14
|
-
CardHeader,
|
|
15
|
-
CardTitle,
|
|
16
|
-
} from "@/components/ui/card";
|
|
9
|
+
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
|
17
10
|
import { Input } from "@/components/ui/input";
|
|
18
11
|
import { Label } from "@/components/ui/label";
|
|
19
12
|
import { Progress } from "@/components/ui/progress";
|
|
20
|
-
import {
|
|
21
|
-
Select,
|
|
22
|
-
SelectContent,
|
|
23
|
-
SelectItem,
|
|
24
|
-
SelectTrigger,
|
|
25
|
-
SelectValue,
|
|
26
|
-
} from "@/components/ui/select";
|
|
13
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
27
14
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
28
15
|
import { Switch } from "@/components/ui/switch";
|
|
29
16
|
import { useCapabilityMeta } from "@/hooks/use-capability-meta";
|
|
@@ -143,12 +130,7 @@ export function InstallWizard({ plugin, onComplete, onCancel }: InstallWizardPro
|
|
|
143
130
|
|
|
144
131
|
// Auto-skip conflicts phase if no conflicts and not loading
|
|
145
132
|
useEffect(() => {
|
|
146
|
-
if (
|
|
147
|
-
currentPhase === "conflicts" &&
|
|
148
|
-
conflicts.length === 0 &&
|
|
149
|
-
!conflictsLoading &&
|
|
150
|
-
!conflictsError
|
|
151
|
-
) {
|
|
133
|
+
if (currentPhase === "conflicts" && conflicts.length === 0 && !conflictsLoading && !conflictsError) {
|
|
152
134
|
setCurrentPhaseIndex((i) => i + 1);
|
|
153
135
|
}
|
|
154
136
|
}, [currentPhase, conflicts, conflictsLoading, conflictsError]);
|
|
@@ -159,8 +141,7 @@ export function InstallWizard({ plugin, onComplete, onCancel }: InstallWizardPro
|
|
|
159
141
|
const stepsBeforeSetup = phases.filter(
|
|
160
142
|
(p) => p !== "setup" && p !== "complete" && phases.indexOf(p) < currentPhaseIndex,
|
|
161
143
|
).length;
|
|
162
|
-
const totalSteps =
|
|
163
|
-
phases.filter((p) => p !== "setup" && p !== "complete").length + setupSteps.length + 1;
|
|
144
|
+
const totalSteps = phases.filter((p) => p !== "setup" && p !== "complete").length + setupSteps.length + 1;
|
|
164
145
|
const currentStepNumber =
|
|
165
146
|
currentPhase === "setup"
|
|
166
147
|
? stepsBeforeSetup + setupStepIndex + 1
|
|
@@ -218,9 +199,7 @@ export function InstallWizard({ plugin, onComplete, onCancel }: InstallWizardPro
|
|
|
218
199
|
} else {
|
|
219
200
|
// Object-level errors (refinements, superRefine, union discriminants) have empty path.
|
|
220
201
|
// Collect under _form so they render in a general error area.
|
|
221
|
-
stepErrors._form = stepErrors._form
|
|
222
|
-
? `${stepErrors._form}. ${issue.message}`
|
|
223
|
-
: issue.message;
|
|
202
|
+
stepErrors._form = stepErrors._form ? `${stepErrors._form}. ${issue.message}` : issue.message;
|
|
224
203
|
}
|
|
225
204
|
}
|
|
226
205
|
setErrors(stepErrors);
|
|
@@ -347,9 +326,7 @@ export function InstallWizard({ plugin, onComplete, onCancel }: InstallWizardPro
|
|
|
347
326
|
error={conflictsError}
|
|
348
327
|
plugin={plugin}
|
|
349
328
|
overrides={primaryOverrides}
|
|
350
|
-
onChoose={(capability, pluginId) =>
|
|
351
|
-
setPrimaryOverrides((prev) => ({ ...prev, [capability]: pluginId }))
|
|
352
|
-
}
|
|
329
|
+
onChoose={(capability, pluginId) => setPrimaryOverrides((prev) => ({ ...prev, [capability]: pluginId }))}
|
|
353
330
|
/>
|
|
354
331
|
)}
|
|
355
332
|
{currentPhase === "providers" && (
|
|
@@ -360,12 +337,7 @@ export function InstallWizard({ plugin, onComplete, onCancel }: InstallWizardPro
|
|
|
360
337
|
/>
|
|
361
338
|
)}
|
|
362
339
|
{currentPhase === "setup" && currentSetupStep && (
|
|
363
|
-
<SetupStepForm
|
|
364
|
-
step={currentSetupStep}
|
|
365
|
-
values={values}
|
|
366
|
-
errors={errors}
|
|
367
|
-
onChange={handleChange}
|
|
368
|
-
/>
|
|
340
|
+
<SetupStepForm step={currentSetupStep} values={values} errors={errors} onChange={handleChange} />
|
|
369
341
|
)}
|
|
370
342
|
{currentPhase === "complete" && (
|
|
371
343
|
<div className="py-4 text-center">
|
|
@@ -373,9 +345,7 @@ export function InstallWizard({ plugin, onComplete, onCancel }: InstallWizardPro
|
|
|
373
345
|
<span className="text-2xl text-emerald-500">✓</span>
|
|
374
346
|
</div>
|
|
375
347
|
<p className="font-medium">Plugin installed successfully</p>
|
|
376
|
-
<p className="mt-1 text-sm text-muted-foreground">
|
|
377
|
-
{plugin.name} is now active on your instance.
|
|
378
|
-
</p>
|
|
348
|
+
<p className="mt-1 text-sm text-muted-foreground">{plugin.name} is now active on your instance.</p>
|
|
379
349
|
</div>
|
|
380
350
|
)}
|
|
381
351
|
</CardContent>
|
|
@@ -383,28 +353,16 @@ export function InstallWizard({ plugin, onComplete, onCancel }: InstallWizardPro
|
|
|
383
353
|
<CardFooter className="flex justify-between">
|
|
384
354
|
<div>
|
|
385
355
|
{isFirstStep ? (
|
|
386
|
-
<Button
|
|
387
|
-
data-onboarding-id="marketplace.wizard.cancel"
|
|
388
|
-
variant="ghost"
|
|
389
|
-
onClick={onCancel}
|
|
390
|
-
>
|
|
356
|
+
<Button data-onboarding-id="marketplace.wizard.cancel" variant="ghost" onClick={onCancel}>
|
|
391
357
|
Cancel
|
|
392
358
|
</Button>
|
|
393
359
|
) : (
|
|
394
|
-
<Button
|
|
395
|
-
data-onboarding-id="marketplace.wizard.back"
|
|
396
|
-
variant="ghost"
|
|
397
|
-
onClick={handleBack}
|
|
398
|
-
>
|
|
360
|
+
<Button data-onboarding-id="marketplace.wizard.back" variant="ghost" onClick={handleBack}>
|
|
399
361
|
Back
|
|
400
362
|
</Button>
|
|
401
363
|
)}
|
|
402
364
|
</div>
|
|
403
|
-
<Button
|
|
404
|
-
data-onboarding-id="marketplace.wizard.continue"
|
|
405
|
-
onClick={handleNext}
|
|
406
|
-
disabled={isContinueDisabled}
|
|
407
|
-
>
|
|
365
|
+
<Button data-onboarding-id="marketplace.wizard.continue" onClick={handleNext} disabled={isContinueDisabled}>
|
|
408
366
|
{currentPhase === "complete" ? "Done" : "Continue"}
|
|
409
367
|
</Button>
|
|
410
368
|
</CardFooter>
|
|
@@ -471,9 +429,7 @@ function BotSelector({
|
|
|
471
429
|
onClick={() => onSelect(bot.id)}
|
|
472
430
|
className={cn(
|
|
473
431
|
"w-full rounded-lg border p-3 text-left h-auto transition-colors hover:bg-transparent",
|
|
474
|
-
selectedBotId === bot.id
|
|
475
|
-
? "border-primary bg-primary/5"
|
|
476
|
-
: "border-border hover:border-primary/50",
|
|
432
|
+
selectedBotId === bot.id ? "border-primary bg-primary/5" : "border-border hover:border-primary/50",
|
|
477
433
|
)}
|
|
478
434
|
>
|
|
479
435
|
<div className="flex items-center justify-between">
|
|
@@ -535,9 +491,7 @@ function RequirementsCheck({ plugin, botId }: { plugin: PluginManifest; botId: s
|
|
|
535
491
|
|
|
536
492
|
return (
|
|
537
493
|
<div className="space-y-3">
|
|
538
|
-
<p className="text-sm text-muted-foreground">
|
|
539
|
-
This plugin requires the following dependencies:
|
|
540
|
-
</p>
|
|
494
|
+
<p className="text-sm text-muted-foreground">This plugin requires the following dependencies:</p>
|
|
541
495
|
{isLoading ? (
|
|
542
496
|
<div className="space-y-2">
|
|
543
497
|
<p className="text-xs text-muted-foreground">Checking installed plugins...</p>
|
|
@@ -558,18 +512,14 @@ function RequirementsCheck({ plugin, botId }: { plugin: PluginManifest; botId: s
|
|
|
558
512
|
<Badge variant="outline" className="text-[10px]">
|
|
559
513
|
{req.id}
|
|
560
514
|
</Badge>
|
|
561
|
-
{req.status === "missing" &&
|
|
562
|
-
<span className="text-xs text-destructive">Not installed</span>
|
|
563
|
-
)}
|
|
515
|
+
{req.status === "missing" && <span className="text-xs text-destructive">Not installed</span>}
|
|
564
516
|
</li>
|
|
565
517
|
))}
|
|
566
518
|
</ul>
|
|
567
519
|
)}
|
|
568
520
|
{!isLoading && results.some((r) => r.status === "missing") && (
|
|
569
521
|
<div className="mt-3 rounded-sm border border-destructive/25 bg-destructive/5 p-3">
|
|
570
|
-
<p className="text-sm text-destructive">
|
|
571
|
-
Install the missing dependencies before continuing.
|
|
572
|
-
</p>
|
|
522
|
+
<p className="text-sm text-destructive">Install the missing dependencies before continuing.</p>
|
|
573
523
|
</div>
|
|
574
524
|
)}
|
|
575
525
|
{plugin.install.length > 0 && (
|
|
@@ -608,9 +558,7 @@ function SetupStepForm({
|
|
|
608
558
|
Open external link
|
|
609
559
|
</a>
|
|
610
560
|
)}
|
|
611
|
-
{!step.instruction && !step.externalUrl &&
|
|
612
|
-
<p className="text-sm text-muted-foreground">{step.description}</p>
|
|
613
|
-
)}
|
|
561
|
+
{!step.instruction && !step.externalUrl && <p className="text-sm text-muted-foreground">{step.description}</p>}
|
|
614
562
|
</div>
|
|
615
563
|
);
|
|
616
564
|
}
|
|
@@ -679,8 +627,8 @@ function CapabilityConflicts({
|
|
|
679
627
|
<div className="rounded-sm border border-amber-500/25 bg-amber-500/5 p-3">
|
|
680
628
|
<p className="text-sm font-medium text-amber-500">Capability Conflict Detected</p>
|
|
681
629
|
<p className="mt-1 text-xs text-muted-foreground">
|
|
682
|
-
{plugin.name} provides capabilities already provided by installed plugins. Choose which
|
|
683
|
-
|
|
630
|
+
{plugin.name} provides capabilities already provided by installed plugins. Choose which plugin should be the
|
|
631
|
+
primary provider for each.
|
|
684
632
|
</p>
|
|
685
633
|
</div>
|
|
686
634
|
{conflicts.map((conflict) => {
|
|
@@ -689,10 +637,7 @@ function CapabilityConflicts({
|
|
|
689
637
|
return (
|
|
690
638
|
<div key={conflict.capability} className="rounded-sm border p-4">
|
|
691
639
|
<div className="mb-3 flex items-center gap-2">
|
|
692
|
-
<Badge
|
|
693
|
-
variant="outline"
|
|
694
|
-
className={cn("text-[10px]", capColor.bg, capColor.text, capColor.border)}
|
|
695
|
-
>
|
|
640
|
+
<Badge variant="outline" className={cn("text-[10px]", capColor.bg, capColor.text, capColor.border)}>
|
|
696
641
|
{conflict.capability}
|
|
697
642
|
</Badge>
|
|
698
643
|
<span className="text-sm text-muted-foreground">provided by both plugins</span>
|
|
@@ -740,9 +685,7 @@ function ConfigFieldInput({
|
|
|
740
685
|
<div className="flex items-center justify-between">
|
|
741
686
|
<div>
|
|
742
687
|
<Label>{field.label}</Label>
|
|
743
|
-
{field.description &&
|
|
744
|
-
<p className="text-xs text-muted-foreground">{field.description}</p>
|
|
745
|
-
)}
|
|
688
|
+
{field.description && <p className="text-xs text-muted-foreground">{field.description}</p>}
|
|
746
689
|
</div>
|
|
747
690
|
<Switch
|
|
748
691
|
checked={value === true || value === "true"}
|
|
@@ -38,10 +38,7 @@ export function MarketplaceTabs({ selected, onSelect, counts }: MarketplaceTabsP
|
|
|
38
38
|
)}
|
|
39
39
|
<Badge
|
|
40
40
|
variant={isSelected ? "default" : "outline"}
|
|
41
|
-
className={cn(
|
|
42
|
-
"relative cursor-pointer text-xs font-medium transition-colors",
|
|
43
|
-
isSelected && "shadow-sm",
|
|
44
|
-
)}
|
|
41
|
+
className={cn("relative cursor-pointer text-xs font-medium transition-colors", isSelected && "shadow-sm")}
|
|
45
42
|
>
|
|
46
43
|
{tab.label}
|
|
47
44
|
{count > 0 && <span className="ml-1 opacity-60">{count}</span>}
|