@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
|
@@ -6,12 +6,7 @@ import { useRef } from "react";
|
|
|
6
6
|
import { Badge } from "@/components/ui/badge";
|
|
7
7
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
|
8
8
|
import { brandName } from "@/lib/brand-config";
|
|
9
|
-
import {
|
|
10
|
-
formatInstallCount,
|
|
11
|
-
getCapabilityColor,
|
|
12
|
-
hasHostedOption,
|
|
13
|
-
type PluginManifest,
|
|
14
|
-
} from "@/lib/marketplace-data";
|
|
9
|
+
import { formatInstallCount, getCapabilityColor, hasHostedOption, type PluginManifest } from "@/lib/marketplace-data";
|
|
15
10
|
|
|
16
11
|
interface PluginCardProps {
|
|
17
12
|
plugin: PluginManifest;
|
|
@@ -85,9 +80,7 @@ export function PluginCard({ plugin, index = 0, installed = false }: PluginCardP
|
|
|
85
80
|
v{plugin.version}
|
|
86
81
|
</Badge>
|
|
87
82
|
</div>
|
|
88
|
-
<CardDescription className="mt-1 line-clamp-2">
|
|
89
|
-
{plugin.description}
|
|
90
|
-
</CardDescription>
|
|
83
|
+
<CardDescription className="mt-1 line-clamp-2">{plugin.description}</CardDescription>
|
|
91
84
|
</div>
|
|
92
85
|
</div>
|
|
93
86
|
</CardHeader>
|
|
@@ -61,9 +61,7 @@ const mdComponents = {
|
|
|
61
61
|
em: ({ children }: ComponentPropsWithoutRef<"em">) => (
|
|
62
62
|
<em className="text-lg text-muted-foreground not-italic font-light">{children}</em>
|
|
63
63
|
),
|
|
64
|
-
ul: ({ children }: ComponentPropsWithoutRef<"ul">) =>
|
|
65
|
-
<ul className="space-y-2 ml-1">{children}</ul>
|
|
66
|
-
),
|
|
64
|
+
ul: ({ children }: ComponentPropsWithoutRef<"ul">) => <ul className="space-y-2 ml-1">{children}</ul>,
|
|
67
65
|
li: ({ children }: ComponentPropsWithoutRef<"li">) => (
|
|
68
66
|
<li className="flex items-start gap-2 text-sm leading-relaxed">
|
|
69
67
|
<span className="mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-primary/60" />
|
|
@@ -11,11 +11,7 @@ interface TerminalSearchProps {
|
|
|
11
11
|
placeholder?: string;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export function TerminalSearch({
|
|
15
|
-
value,
|
|
16
|
-
onChange,
|
|
17
|
-
placeholder = "Search plugins...",
|
|
18
|
-
}: TerminalSearchProps) {
|
|
14
|
+
export function TerminalSearch({ value, onChange, placeholder = "Search plugins..." }: TerminalSearchProps) {
|
|
19
15
|
const [focused, setFocused] = useState(false);
|
|
20
16
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
21
17
|
|
|
@@ -23,9 +19,7 @@ export function TerminalSearch({
|
|
|
23
19
|
<search
|
|
24
20
|
className={cn(
|
|
25
21
|
"flex items-center gap-2 rounded-sm border px-3 py-2 font-mono text-sm transition-all max-w-sm cursor-text",
|
|
26
|
-
focused
|
|
27
|
-
? "border-primary shadow-[0_0_8px_rgba(0,255,65,0.15)]"
|
|
28
|
-
: "border-input hover:border-primary/40",
|
|
22
|
+
focused ? "border-primary shadow-[0_0_8px_rgba(0,255,65,0.15)]" : "border-input hover:border-primary/40",
|
|
29
23
|
)}
|
|
30
24
|
onClick={() => inputRef.current?.focus()}
|
|
31
25
|
onKeyDown={(e) => {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useState } from "react";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
4
|
import { Button } from "@/components/ui/button";
|
|
5
5
|
import { Separator } from "@/components/ui/separator";
|
|
6
|
+
import { API_BASE_URL } from "@/lib/api-config";
|
|
6
7
|
import { signIn } from "@/lib/auth-client";
|
|
7
|
-
import { trpc } from "@/lib/trpc";
|
|
8
8
|
|
|
9
9
|
const providerLabels: Record<string, string> = {
|
|
10
10
|
github: "GitHub",
|
|
@@ -14,25 +14,42 @@ const providerLabels: Record<string, string> = {
|
|
|
14
14
|
|
|
15
15
|
interface OAuthButtonsProps {
|
|
16
16
|
callbackUrl?: string;
|
|
17
|
+
productSlug?: string;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
export function OAuthButtons({ callbackUrl = "/" }: OAuthButtonsProps) {
|
|
20
|
+
export function OAuthButtons({ callbackUrl = "/", productSlug }: OAuthButtonsProps) {
|
|
20
21
|
const [loading, setLoading] = useState<string | null>(null);
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
)
|
|
22
|
+
const [enabledProviders, setEnabledProviders] = useState<string[] | null>(null);
|
|
23
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
// Don't pass slug — let the server resolve from Origin header
|
|
27
|
+
const url = productSlug
|
|
28
|
+
? `${API_BASE_URL}/auth/providers?slug=${encodeURIComponent(productSlug)}`
|
|
29
|
+
: `${API_BASE_URL}/auth/providers`;
|
|
30
|
+
fetch(url)
|
|
31
|
+
.then((r) => r.json())
|
|
32
|
+
.then((data) => setEnabledProviders(Array.isArray(data) ? data : []))
|
|
33
|
+
.catch(() => setEnabledProviders([]))
|
|
34
|
+
.finally(() => setIsLoading(false));
|
|
35
|
+
}, [productSlug]);
|
|
25
36
|
|
|
26
37
|
async function handleOAuth(provider: string) {
|
|
27
38
|
setLoading(provider);
|
|
28
39
|
try {
|
|
29
|
-
const absoluteCallback = callbackUrl.startsWith("http")
|
|
30
|
-
|
|
31
|
-
: `${window.location.origin}${callbackUrl}`;
|
|
32
|
-
await signIn.social({
|
|
40
|
+
const absoluteCallback = callbackUrl.startsWith("http") ? callbackUrl : `${window.location.origin}${callbackUrl}`;
|
|
41
|
+
const result = await signIn.social({
|
|
33
42
|
provider,
|
|
34
43
|
callbackURL: absoluteCallback,
|
|
44
|
+
fetchOptions: { redirect: "manual" },
|
|
35
45
|
});
|
|
46
|
+
// BetterAuth returns { url, redirect } — navigate the browser explicitly
|
|
47
|
+
// fetch() can't follow cross-origin redirects to GitHub, so we must do it ourselves
|
|
48
|
+
const url = (result as { data?: { url?: string } })?.data?.url ?? (result as { url?: string })?.url;
|
|
49
|
+
if (url) {
|
|
50
|
+
window.location.href = url;
|
|
51
|
+
return; // page navigates away
|
|
52
|
+
}
|
|
36
53
|
} catch {
|
|
37
54
|
// signIn.social redirects on success; failure here means the redirect didn't happen
|
|
38
55
|
} finally {
|
|
@@ -48,9 +65,7 @@ export function OAuthButtons({ callbackUrl = "/" }: OAuthButtonsProps) {
|
|
|
48
65
|
<>
|
|
49
66
|
<div className="relative my-4 flex items-center">
|
|
50
67
|
<Separator className="flex-1" />
|
|
51
|
-
<span className="mx-3 text-xs uppercase tracking-wider text-muted-foreground">
|
|
52
|
-
or continue with
|
|
53
|
-
</span>
|
|
68
|
+
<span className="mx-3 text-xs uppercase tracking-wider text-muted-foreground">or continue with</span>
|
|
54
69
|
<Separator className="flex-1" />
|
|
55
70
|
</div>
|
|
56
71
|
<div className="flex flex-col gap-2">
|
|
@@ -6,13 +6,7 @@ import Link from "next/link";
|
|
|
6
6
|
import { useEffect, useMemo, useState } from "react";
|
|
7
7
|
import { Button } from "@/components/ui/button";
|
|
8
8
|
import { Card, CardContent } from "@/components/ui/card";
|
|
9
|
-
import {
|
|
10
|
-
Select,
|
|
11
|
-
SelectContent,
|
|
12
|
-
SelectItem,
|
|
13
|
-
SelectTrigger,
|
|
14
|
-
SelectValue,
|
|
15
|
-
} from "@/components/ui/select";
|
|
9
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
16
10
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
17
11
|
import { useImageStatus } from "@/hooks/use-image-status";
|
|
18
12
|
import type { BotStatusResponse, FleetInstance, HealthStatus } from "@/lib/api";
|
|
@@ -149,8 +143,7 @@ export function FleetHealth() {
|
|
|
149
143
|
|
|
150
144
|
const filtered = sorted.filter((inst) => {
|
|
151
145
|
if (statusFilter === "healthy") return inst.health === "healthy";
|
|
152
|
-
if (statusFilter === "attention")
|
|
153
|
-
return inst.health === "degraded" || inst.health === "unhealthy";
|
|
146
|
+
if (statusFilter === "attention") return inst.health === "degraded" || inst.health === "unhealthy";
|
|
154
147
|
return true;
|
|
155
148
|
});
|
|
156
149
|
|
|
@@ -215,9 +208,7 @@ export function FleetHealth() {
|
|
|
215
208
|
<div className="flex flex-col gap-3 border-b border-terminal/20 pb-4 sm:flex-row sm:items-center sm:gap-6">
|
|
216
209
|
<div className="flex items-baseline gap-2">
|
|
217
210
|
<span className="text-3xl font-bold tabular-nums font-mono">{instances.length}</span>
|
|
218
|
-
<span className="text-sm text-muted-foreground">
|
|
219
|
-
{instances.length === 1 ? "instance" : "instances"}
|
|
220
|
-
</span>
|
|
211
|
+
<span className="text-sm text-muted-foreground">{instances.length === 1 ? "instance" : "instances"}</span>
|
|
221
212
|
</div>
|
|
222
213
|
|
|
223
214
|
<div className="flex flex-wrap items-center gap-4 text-sm font-mono">
|
|
@@ -283,18 +274,14 @@ export function FleetHealth() {
|
|
|
283
274
|
</Button>
|
|
284
275
|
|
|
285
276
|
{lastUpdated && (
|
|
286
|
-
<span className="text-xs text-muted-foreground font-mono">
|
|
287
|
-
Updated {formatRelativeTime(lastUpdated)}
|
|
288
|
-
</span>
|
|
277
|
+
<span className="text-xs text-muted-foreground font-mono">Updated {formatRelativeTime(lastUpdated)}</span>
|
|
289
278
|
)}
|
|
290
279
|
</div>
|
|
291
280
|
|
|
292
281
|
{/* Instance Grid */}
|
|
293
282
|
{filtered.length === 0 && instances.length === 0 ? (
|
|
294
283
|
<div className="rounded-sm border border-terminal/20 bg-terminal/5 px-6 py-12 text-center font-mono">
|
|
295
|
-
<p className="text-terminal">
|
|
296
|
-
> FLEET EMPTY. NO {productName().toUpperCase()} UNITS DEPLOYED.
|
|
297
|
-
</p>
|
|
284
|
+
<p className="text-terminal">> FLEET EMPTY. NO {productName().toUpperCase()} UNITS DEPLOYED.</p>
|
|
298
285
|
<Link
|
|
299
286
|
href="/instances/new"
|
|
300
287
|
className="mt-4 inline-block text-sm text-muted-foreground underline underline-offset-4 hover:text-terminal"
|
|
@@ -106,9 +106,7 @@ export function HealthOverview({ instanceId }: { instanceId: string }) {
|
|
|
106
106
|
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
|
107
107
|
<Card>
|
|
108
108
|
<CardHeader className="pb-2">
|
|
109
|
-
<CardTitle className="text-xs font-medium text-muted-foreground">
|
|
110
|
-
Health Status
|
|
111
|
-
</CardTitle>
|
|
109
|
+
<CardTitle className="text-xs font-medium text-muted-foreground">Health Status</CardTitle>
|
|
112
110
|
</CardHeader>
|
|
113
111
|
<CardContent>
|
|
114
112
|
<HealthBadge status={health.status} />
|
|
@@ -124,16 +122,12 @@ export function HealthOverview({ instanceId }: { instanceId: string }) {
|
|
|
124
122
|
</Card>
|
|
125
123
|
<Card>
|
|
126
124
|
<CardHeader className="pb-2">
|
|
127
|
-
<CardTitle className="text-xs font-medium text-muted-foreground">
|
|
128
|
-
Active Sessions
|
|
129
|
-
</CardTitle>
|
|
125
|
+
<CardTitle className="text-xs font-medium text-muted-foreground">Active Sessions</CardTitle>
|
|
130
126
|
</CardHeader>
|
|
131
127
|
<CardContent>
|
|
132
128
|
<p className="text-lg font-semibold">
|
|
133
129
|
{health.activeSessions}{" "}
|
|
134
|
-
<span className="text-sm font-normal text-muted-foreground">
|
|
135
|
-
/ {health.totalSessions} total
|
|
136
|
-
</span>
|
|
130
|
+
<span className="text-sm font-normal text-muted-foreground">/ {health.totalSessions} total</span>
|
|
137
131
|
</p>
|
|
138
132
|
</CardContent>
|
|
139
133
|
</Card>
|
|
@@ -179,9 +173,7 @@ export function HealthOverview({ instanceId }: { instanceId: string }) {
|
|
|
179
173
|
key={provider.name}
|
|
180
174
|
className={cn(
|
|
181
175
|
"border",
|
|
182
|
-
provider.available
|
|
183
|
-
? "bg-emerald-500/5 border-emerald-500/25"
|
|
184
|
-
: "bg-red-500/5 border-red-500/25",
|
|
176
|
+
provider.available ? "bg-emerald-500/5 border-emerald-500/25" : "bg-red-500/5 border-red-500/25",
|
|
185
177
|
)}
|
|
186
178
|
>
|
|
187
179
|
<CardContent className="flex items-center justify-between p-4">
|
|
@@ -217,6 +209,7 @@ export function HealthOverview({ instanceId }: { instanceId: string }) {
|
|
|
217
209
|
const c = healthColors[entry.status];
|
|
218
210
|
return (
|
|
219
211
|
<div
|
|
212
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: static list, index key is safe
|
|
220
213
|
key={`${entry.timestamp}-${i}`}
|
|
221
214
|
className={cn("h-8 flex-1 rounded-sm", c.dot)}
|
|
222
215
|
title={`${new Date(entry.timestamp).toLocaleTimeString()} - ${entry.status}`}
|
|
@@ -225,16 +218,10 @@ export function HealthOverview({ instanceId }: { instanceId: string }) {
|
|
|
225
218
|
})}
|
|
226
219
|
</div>
|
|
227
220
|
<div className="mt-2 flex justify-between text-xs text-muted-foreground">
|
|
221
|
+
<span>{health.history.length > 0 ? new Date(health.history[0].timestamp).toLocaleTimeString() : ""}</span>
|
|
228
222
|
<span>
|
|
229
223
|
{health.history.length > 0
|
|
230
|
-
? new Date(health.history[
|
|
231
|
-
: ""}
|
|
232
|
-
</span>
|
|
233
|
-
<span>
|
|
234
|
-
{health.history.length > 0
|
|
235
|
-
? new Date(
|
|
236
|
-
health.history[health.history.length - 1].timestamp,
|
|
237
|
-
).toLocaleTimeString()
|
|
224
|
+
? new Date(health.history[health.history.length - 1].timestamp).toLocaleTimeString()
|
|
238
225
|
: ""}
|
|
239
226
|
</span>
|
|
240
227
|
</div>
|
|
@@ -5,13 +5,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
|
|
|
5
5
|
import { Button } from "@/components/ui/button";
|
|
6
6
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
7
7
|
import { Input } from "@/components/ui/input";
|
|
8
|
-
import {
|
|
9
|
-
Select,
|
|
10
|
-
SelectContent,
|
|
11
|
-
SelectItem,
|
|
12
|
-
SelectTrigger,
|
|
13
|
-
SelectValue,
|
|
14
|
-
} from "@/components/ui/select";
|
|
8
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
15
9
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
16
10
|
import type { LogEntry, LogLevel } from "@/lib/api";
|
|
17
11
|
import { getInstanceLogs } from "@/lib/api";
|
|
@@ -129,11 +123,7 @@ export function LogsViewer({ instanceId }: { instanceId: string }) {
|
|
|
129
123
|
)}
|
|
130
124
|
</div>
|
|
131
125
|
|
|
132
|
-
<Button
|
|
133
|
-
variant={autoScroll ? "terminal" : "outline"}
|
|
134
|
-
size="sm"
|
|
135
|
-
onClick={() => setAutoScroll(!autoScroll)}
|
|
136
|
-
>
|
|
126
|
+
<Button variant={autoScroll ? "terminal" : "outline"} size="sm" onClick={() => setAutoScroll(!autoScroll)}>
|
|
137
127
|
{autoScroll ? "Auto-scroll ON" : "Auto-scroll OFF"}
|
|
138
128
|
</Button>
|
|
139
129
|
</div>
|
|
@@ -154,19 +144,14 @@ export function LogsViewer({ instanceId }: { instanceId: string }) {
|
|
|
154
144
|
<Card>
|
|
155
145
|
<CardHeader className="pb-2">
|
|
156
146
|
<CardTitle className="text-sm">
|
|
157
|
-
Real-time Logs
|
|
158
|
-
<span className="font-normal text-muted-foreground">({filtered.length} entries)</span>
|
|
147
|
+
Real-time Logs <span className="font-normal text-muted-foreground">({filtered.length} entries)</span>
|
|
159
148
|
</CardTitle>
|
|
160
149
|
</CardHeader>
|
|
161
150
|
<CardContent>
|
|
162
151
|
{loading && logs.length === 0 ? (
|
|
163
152
|
<div className="h-[400px] space-y-2 rounded-md bg-zinc-950 p-4">
|
|
164
153
|
{Array.from({ length: 12 }, (_, n) => `sk-${n}`).map((skId, i) => (
|
|
165
|
-
<Skeleton
|
|
166
|
-
key={skId}
|
|
167
|
-
className="h-4 bg-zinc-800"
|
|
168
|
-
style={{ width: `${60 + ((i * 17) % 40)}%` }}
|
|
169
|
-
/>
|
|
154
|
+
<Skeleton key={skId} className="h-4 bg-zinc-800" style={{ width: `${60 + ((i * 17) % 40)}%` }} />
|
|
170
155
|
))}
|
|
171
156
|
</div>
|
|
172
157
|
) : (
|
|
@@ -180,25 +165,16 @@ export function LogsViewer({ instanceId }: { instanceId: string }) {
|
|
|
180
165
|
{filtered.length === 0 ? (
|
|
181
166
|
<div className="flex h-full flex-col items-center justify-center">
|
|
182
167
|
<p className="text-zinc-500">No logs match the current filters.</p>
|
|
183
|
-
<p className="mt-1 text-zinc-600">
|
|
184
|
-
Try broadening your search or changing the level filter.
|
|
185
|
-
</p>
|
|
168
|
+
<p className="mt-1 text-zinc-600">Try broadening your search or changing the level filter.</p>
|
|
186
169
|
</div>
|
|
187
170
|
) : (
|
|
188
171
|
filtered.map((log) => (
|
|
189
172
|
<div
|
|
190
173
|
key={log.id}
|
|
191
|
-
className={cn(
|
|
192
|
-
"flex gap-3 rounded px-2 py-1 hover:bg-zinc-900",
|
|
193
|
-
levelBgColors[log.level],
|
|
194
|
-
)}
|
|
174
|
+
className={cn("flex gap-3 rounded px-2 py-1 hover:bg-zinc-900", levelBgColors[log.level])}
|
|
195
175
|
>
|
|
196
|
-
<span className="shrink-0 text-zinc-600">
|
|
197
|
-
|
|
198
|
-
</span>
|
|
199
|
-
<span
|
|
200
|
-
className={cn("w-12 shrink-0 text-right uppercase", levelColors[log.level])}
|
|
201
|
-
>
|
|
176
|
+
<span className="shrink-0 text-zinc-600">{new Date(log.timestamp).toLocaleTimeString()}</span>
|
|
177
|
+
<span className={cn("w-12 shrink-0 text-right uppercase", levelColors[log.level])}>
|
|
202
178
|
{log.level}
|
|
203
179
|
</span>
|
|
204
180
|
<span className="shrink-0 text-zinc-500">[{log.source}]</span>
|
|
@@ -2,17 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { AlertTriangleIcon, RefreshCw } from "lucide-react";
|
|
4
4
|
import { useCallback, useEffect, useState } from "react";
|
|
5
|
-
import {
|
|
6
|
-
Bar,
|
|
7
|
-
BarChart,
|
|
8
|
-
CartesianGrid,
|
|
9
|
-
Line,
|
|
10
|
-
LineChart,
|
|
11
|
-
ResponsiveContainer,
|
|
12
|
-
Tooltip,
|
|
13
|
-
XAxis,
|
|
14
|
-
YAxis,
|
|
15
|
-
} from "recharts";
|
|
5
|
+
import { Bar, BarChart, CartesianGrid, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
|
|
16
6
|
import { Button } from "@/components/ui/button";
|
|
17
7
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
18
8
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
@@ -192,10 +182,7 @@ export function MetricsDashboard({ instanceId }: { instanceId: string }) {
|
|
|
192
182
|
</ResponsiveContainer>
|
|
193
183
|
<div className="mt-3 space-y-1">
|
|
194
184
|
{metrics.tokenUsage.map((t) => (
|
|
195
|
-
<div
|
|
196
|
-
key={t.provider}
|
|
197
|
-
className="flex justify-between text-xs text-muted-foreground"
|
|
198
|
-
>
|
|
185
|
+
<div key={t.provider} className="flex justify-between text-xs text-muted-foreground">
|
|
199
186
|
<span className="capitalize">{t.provider}</span>
|
|
200
187
|
<span className="font-medium text-foreground">${t.totalCost.toFixed(2)}</span>
|
|
201
188
|
</div>
|
|
@@ -6,13 +6,7 @@ import { Button } from "@/components/ui/button";
|
|
|
6
6
|
import { Card, CardContent } from "@/components/ui/card";
|
|
7
7
|
import { Input } from "@/components/ui/input";
|
|
8
8
|
import { Label } from "@/components/ui/label";
|
|
9
|
-
import {
|
|
10
|
-
Select,
|
|
11
|
-
SelectContent,
|
|
12
|
-
SelectItem,
|
|
13
|
-
SelectTrigger,
|
|
14
|
-
SelectValue,
|
|
15
|
-
} from "@/components/ui/select";
|
|
9
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
16
10
|
import { quickSetup } from "@/lib/api";
|
|
17
11
|
import { brandName } from "@/lib/brand-config";
|
|
18
12
|
import { markOnboardingComplete } from "@/lib/onboarding-store";
|
|
@@ -69,20 +63,13 @@ export function FallbackSetup() {
|
|
|
69
63
|
<CardContent className="p-6">
|
|
70
64
|
<div className="flex items-center gap-2 mb-1">
|
|
71
65
|
<AlertTriangle className="h-4 w-4 text-chart-3" />
|
|
72
|
-
<h2 className="text-sm font-mono uppercase tracking-[0.2em] text-chart-3">
|
|
73
|
-
MANUAL OVERRIDE
|
|
74
|
-
</h2>
|
|
66
|
+
<h2 className="text-sm font-mono uppercase tracking-[0.2em] text-chart-3">MANUAL OVERRIDE</h2>
|
|
75
67
|
</div>
|
|
76
|
-
<p className="text-xs text-muted-foreground mb-6">
|
|
77
|
-
Platform {brandName()} unavailable. Configure manually.
|
|
78
|
-
</p>
|
|
68
|
+
<p className="text-xs text-muted-foreground mb-6">Platform {brandName()} unavailable. Configure manually.</p>
|
|
79
69
|
|
|
80
70
|
<form onSubmit={handleSubmit} className="space-y-4">
|
|
81
71
|
<div className="space-y-2">
|
|
82
|
-
<Label
|
|
83
|
-
htmlFor="fallback-api-key"
|
|
84
|
-
className="text-xs uppercase tracking-wider text-muted-foreground"
|
|
85
|
-
>
|
|
72
|
+
<Label htmlFor="fallback-api-key" className="text-xs uppercase tracking-wider text-muted-foreground">
|
|
86
73
|
API KEY
|
|
87
74
|
</Label>
|
|
88
75
|
<Input
|
|
@@ -97,17 +84,11 @@ export function FallbackSetup() {
|
|
|
97
84
|
</div>
|
|
98
85
|
|
|
99
86
|
<div className="space-y-2">
|
|
100
|
-
<Label
|
|
101
|
-
htmlFor="fallback-channel"
|
|
102
|
-
className="text-xs uppercase tracking-wider text-muted-foreground"
|
|
103
|
-
>
|
|
87
|
+
<Label htmlFor="fallback-channel" className="text-xs uppercase tracking-wider text-muted-foreground">
|
|
104
88
|
CHANNEL
|
|
105
89
|
</Label>
|
|
106
90
|
<Select value={channel} onValueChange={setChannel}>
|
|
107
|
-
<SelectTrigger
|
|
108
|
-
id="fallback-channel"
|
|
109
|
-
className="bg-secondary border-border font-mono text-sm"
|
|
110
|
-
>
|
|
91
|
+
<SelectTrigger id="fallback-channel" className="bg-secondary border-border font-mono text-sm">
|
|
111
92
|
<SelectValue placeholder="Select channel" />
|
|
112
93
|
</SelectTrigger>
|
|
113
94
|
<SelectContent>
|
|
@@ -60,18 +60,13 @@ const SUPERPOWER_TO_CAPABILITY: Record<string, string> = {
|
|
|
60
60
|
"text-gen": "text-gen",
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
-
function resolveSuperpowerStatuses(
|
|
64
|
-
selectedIds: string[],
|
|
65
|
-
capabilities: CapabilitySetting[],
|
|
66
|
-
): SuperpowerStatus[] {
|
|
63
|
+
function resolveSuperpowerStatuses(selectedIds: string[], capabilities: CapabilitySetting[]): SuperpowerStatus[] {
|
|
67
64
|
return selectedIds.map((id) => {
|
|
68
65
|
const sp = superpowers.find((s) => s.id === id);
|
|
69
66
|
const capName = SUPERPOWER_TO_CAPABILITY[id];
|
|
70
67
|
const cap = capName ? capabilities.find((c) => c.capability === capName) : undefined;
|
|
71
68
|
|
|
72
|
-
const ready = cap
|
|
73
|
-
? cap.mode === "hosted" || (cap.mode === "byok" && cap.keyStatus === "valid")
|
|
74
|
-
: !sp?.requiresKey;
|
|
69
|
+
const ready = cap ? cap.mode === "hosted" || (cap.mode === "byok" && cap.keyStatus === "valid") : !sp?.requiresKey;
|
|
75
70
|
|
|
76
71
|
return {
|
|
77
72
|
id,
|
|
@@ -90,9 +85,7 @@ export function SetupChecklist() {
|
|
|
90
85
|
const [creditBalance, setCreditBalance] = useState<string | null>(null);
|
|
91
86
|
const [loading, setLoading] = useState(true);
|
|
92
87
|
const [hasInstances, setHasInstances] = useState(false);
|
|
93
|
-
const [connectedChannels, setConnectedChannels] = useState<Map<string, ChannelInfo["status"]>>(
|
|
94
|
-
new Map(),
|
|
95
|
-
);
|
|
88
|
+
const [connectedChannels, setConnectedChannels] = useState<Map<string, ChannelInfo["status"]>>(new Map());
|
|
96
89
|
const [capabilities, setCapabilities] = useState<CapabilitySetting[]>([]);
|
|
97
90
|
const [allChannels, setAllChannels] = useState<PluginOption[]>(channelPlugins);
|
|
98
91
|
|
|
@@ -106,13 +99,12 @@ export function SetupChecklist() {
|
|
|
106
99
|
|
|
107
100
|
async function load() {
|
|
108
101
|
try {
|
|
109
|
-
const [instancesResult, creditsResult, capabilitiesResult, marketplaceResult] =
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
]);
|
|
102
|
+
const [instancesResult, creditsResult, capabilitiesResult, marketplaceResult] = await Promise.allSettled([
|
|
103
|
+
listInstances(),
|
|
104
|
+
getCreditBalance(),
|
|
105
|
+
listCapabilities(),
|
|
106
|
+
listMarketplacePlugins(),
|
|
107
|
+
]);
|
|
116
108
|
if (cancelled) return;
|
|
117
109
|
|
|
118
110
|
if (instancesResult.status === "fulfilled") {
|
|
@@ -134,9 +126,7 @@ export function SetupChecklist() {
|
|
|
134
126
|
|
|
135
127
|
// Fetch channel connection status for each instance
|
|
136
128
|
const channelMap = new Map<string, ChannelInfo["status"]>();
|
|
137
|
-
const channelFetches = instances.map((inst) =>
|
|
138
|
-
listChannels(inst.id).catch(() => [] as ChannelInfo[]),
|
|
139
|
-
);
|
|
129
|
+
const channelFetches = instances.map((inst) => listChannels(inst.id).catch(() => [] as ChannelInfo[]));
|
|
140
130
|
const channelResults = await Promise.all(channelFetches);
|
|
141
131
|
if (!cancelled) {
|
|
142
132
|
for (const channelList of channelResults) {
|
|
@@ -223,12 +213,7 @@ export function SetupChecklist() {
|
|
|
223
213
|
<CardHeader className="pb-2">
|
|
224
214
|
<div className="flex items-center justify-between">
|
|
225
215
|
<CardTitle className="text-base">Let's get your {productName()} running</CardTitle>
|
|
226
|
-
<Button
|
|
227
|
-
data-onboarding-id="dashboard.checklist.dismiss"
|
|
228
|
-
variant="ghost"
|
|
229
|
-
size="xs"
|
|
230
|
-
onClick={handleDismiss}
|
|
231
|
-
>
|
|
216
|
+
<Button data-onboarding-id="dashboard.checklist.dismiss" variant="ghost" size="xs" onClick={handleDismiss}>
|
|
232
217
|
Dismiss
|
|
233
218
|
</Button>
|
|
234
219
|
</div>
|
|
@@ -237,20 +222,12 @@ export function SetupChecklist() {
|
|
|
237
222
|
{/* Channels */}
|
|
238
223
|
{channels.length > 0 && (
|
|
239
224
|
<section>
|
|
240
|
-
<h3 className="mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
241
|
-
Channels
|
|
242
|
-
</h3>
|
|
225
|
+
<h3 className="mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">Channels</h3>
|
|
243
226
|
<div className="space-y-1.5">
|
|
244
227
|
{channels.map((ch) => (
|
|
245
|
-
<div
|
|
246
|
-
key={ch.id}
|
|
247
|
-
className="flex items-center justify-between rounded-sm px-3 py-2 text-sm"
|
|
248
|
-
>
|
|
228
|
+
<div key={ch.id} className="flex items-center justify-between rounded-sm px-3 py-2 text-sm">
|
|
249
229
|
<div className="flex items-center gap-2">
|
|
250
|
-
<span
|
|
251
|
-
className="inline-block size-2 rounded-full"
|
|
252
|
-
style={{ backgroundColor: ch.color }}
|
|
253
|
-
/>
|
|
230
|
+
<span className="inline-block size-2 rounded-full" style={{ backgroundColor: ch.color }} />
|
|
254
231
|
<span className="font-medium">{ch.name}</span>
|
|
255
232
|
</div>
|
|
256
233
|
{ch.ready ? (
|
|
@@ -275,20 +252,12 @@ export function SetupChecklist() {
|
|
|
275
252
|
{/* Superpowers */}
|
|
276
253
|
{powers.length > 0 && (
|
|
277
254
|
<section>
|
|
278
|
-
<h3 className="mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
279
|
-
Superpowers
|
|
280
|
-
</h3>
|
|
255
|
+
<h3 className="mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">Superpowers</h3>
|
|
281
256
|
<div className="space-y-1.5">
|
|
282
257
|
{powers.map((sp) => (
|
|
283
|
-
<div
|
|
284
|
-
key={sp.id}
|
|
285
|
-
className="flex items-center justify-between rounded-sm px-3 py-2 text-sm"
|
|
286
|
-
>
|
|
258
|
+
<div key={sp.id} className="flex items-center justify-between rounded-sm px-3 py-2 text-sm">
|
|
287
259
|
<div className="flex items-center gap-2">
|
|
288
|
-
<span
|
|
289
|
-
className="inline-block size-2 rounded-full"
|
|
290
|
-
style={{ backgroundColor: sp.color }}
|
|
291
|
-
/>
|
|
260
|
+
<span className="inline-block size-2 rounded-full" style={{ backgroundColor: sp.color }} />
|
|
292
261
|
<span className="font-medium">{sp.name}</span>
|
|
293
262
|
</div>
|
|
294
263
|
{sp.ready ? (
|
|
@@ -312,9 +281,7 @@ export function SetupChecklist() {
|
|
|
312
281
|
|
|
313
282
|
{/* Credits */}
|
|
314
283
|
<section>
|
|
315
|
-
<h3 className="mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
316
|
-
Credits
|
|
317
|
-
</h3>
|
|
284
|
+
<h3 className="mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">Credits</h3>
|
|
318
285
|
<div className="flex items-center gap-2 rounded-sm px-3 py-2 text-sm">
|
|
319
286
|
<span className="font-medium">Balance</span>
|
|
320
287
|
<Badge variant="secondary">{creditBalance ?? "$0.00"}</Badge>
|
|
@@ -53,10 +53,7 @@ export function StepSuperpowers({
|
|
|
53
53
|
return (
|
|
54
54
|
<div className="space-y-6">
|
|
55
55
|
<div className="text-center space-y-2">
|
|
56
|
-
<div
|
|
57
|
-
className="inline-block font-mono text-xs tracking-[0.3em] text-terminal uppercase"
|
|
58
|
-
aria-hidden="true"
|
|
59
|
-
>
|
|
56
|
+
<div className="inline-block font-mono text-xs tracking-[0.3em] text-terminal uppercase" aria-hidden="true">
|
|
60
57
|
STEP {stepNumber} {"//"} {stepCode}
|
|
61
58
|
</div>
|
|
62
59
|
<h2 className="text-2xl font-bold tracking-tight">Give your {productName()} superpowers</h2>
|
|
@@ -6,13 +6,7 @@ import { useEffect, useRef } from "react";
|
|
|
6
6
|
import { ChatInput } from "@/components/chat/chat-input";
|
|
7
7
|
import { ChatMessage } from "@/components/chat/chat-message";
|
|
8
8
|
import { Button } from "@/components/ui/button";
|
|
9
|
-
import {
|
|
10
|
-
Sheet,
|
|
11
|
-
SheetContent,
|
|
12
|
-
SheetDescription,
|
|
13
|
-
SheetHeader,
|
|
14
|
-
SheetTitle,
|
|
15
|
-
} from "@/components/ui/sheet";
|
|
9
|
+
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "@/components/ui/sheet";
|
|
16
10
|
import type { ChatMessage as ChatMessageType } from "@/lib/chat/types";
|
|
17
11
|
|
|
18
12
|
interface SetupChatPanelProps {
|
|
@@ -73,9 +67,7 @@ export function SetupChatPanel({
|
|
|
73
67
|
{/* Messages area */}
|
|
74
68
|
<div className="flex-1 space-y-3 overflow-y-auto px-4 py-4">
|
|
75
69
|
{messages.length === 0 && !isConnected && (
|
|
76
|
-
<p className="font-mono text-sm text-terminal/60 animate-pulse">
|
|
77
|
-
> Initializing setup...
|
|
78
|
-
</p>
|
|
70
|
+
<p className="font-mono text-sm text-terminal/60 animate-pulse">> Initializing setup...</p>
|
|
79
71
|
)}
|
|
80
72
|
|
|
81
73
|
<AnimatePresence initial={false}>
|
|
@@ -94,19 +86,13 @@ export function SetupChatPanel({
|
|
|
94
86
|
>
|
|
95
87
|
{msg.role === "bot" ? (
|
|
96
88
|
<div className="flex gap-2">
|
|
97
|
-
<span className="mt-0.5 font-mono text-sm text-terminal/40 select-none">
|
|
98
|
-
>
|
|
99
|
-
</span>
|
|
89
|
+
<span className="mt-0.5 font-mono text-sm text-terminal/40 select-none">></span>
|
|
100
90
|
<p className="font-mono text-sm leading-relaxed text-terminal">{msg.content}</p>
|
|
101
91
|
</div>
|
|
102
92
|
) : msg.role === "event" ? (
|
|
103
93
|
<div className="flex gap-2">
|
|
104
|
-
<span className="mt-0.5 font-mono text-sm text-destructive/60 select-none">
|
|
105
|
-
|
|
106
|
-
</span>
|
|
107
|
-
<p className="font-mono text-sm leading-relaxed text-destructive">
|
|
108
|
-
{msg.content}
|
|
109
|
-
</p>
|
|
94
|
+
<span className="mt-0.5 font-mono text-sm text-destructive/60 select-none">!</span>
|
|
95
|
+
<p className="font-mono text-sm leading-relaxed text-destructive">{msg.content}</p>
|
|
110
96
|
</div>
|
|
111
97
|
) : (
|
|
112
98
|
<ChatMessage message={msg} />
|
|
@@ -150,9 +136,7 @@ export function SetupChatPanel({
|
|
|
150
136
|
className="flex flex-col items-center justify-center gap-2 py-4"
|
|
151
137
|
>
|
|
152
138
|
<CheckCircle2 className="h-8 w-8 text-terminal" />
|
|
153
|
-
<span className="font-mono text-sm uppercase tracking-wider text-terminal">
|
|
154
|
-
Setup complete
|
|
155
|
-
</span>
|
|
139
|
+
<span className="font-mono text-sm uppercase tracking-wider text-terminal">Setup complete</span>
|
|
156
140
|
</motion.div>
|
|
157
141
|
)}
|
|
158
142
|
</AnimatePresence>
|