@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.
Files changed (353) hide show
  1. package/next.config.ts +1 -2
  2. package/package.json +17 -17
  3. package/src/__tests__/account-switcher.test.tsx +21 -20
  4. package/src/__tests__/activity-page.test.tsx +2 -6
  5. package/src/__tests__/add-payment-method-dialog.test.tsx +9 -32
  6. package/src/__tests__/admin-api.test.ts +1 -6
  7. package/src/__tests__/admin-gpu-api.test.ts +1 -3
  8. package/src/__tests__/admin-marketplace-api.test.ts +1 -4
  9. package/src/__tests__/admin-middleware.test.ts +76 -83
  10. package/src/__tests__/affiliate-dashboard.test.tsx +3 -3
  11. package/src/__tests__/api-401-redirect.test.ts +46 -9
  12. package/src/__tests__/api-client.test.ts +3 -5
  13. package/src/__tests__/api-config.test.ts +22 -42
  14. package/src/__tests__/api-fleet-resources.test.ts +1 -2
  15. package/src/__tests__/api-fleet-trpc.test.ts +2 -8
  16. package/src/__tests__/api-null-guards.test.ts +3 -1
  17. package/src/__tests__/audit-log-table-pagination.test.tsx +2 -6
  18. package/src/__tests__/auth-password-reset.test.tsx +7 -21
  19. package/src/__tests__/auth-redirect.test.tsx +8 -2
  20. package/src/__tests__/auth.test.tsx +25 -23
  21. package/src/__tests__/auto-topup-card.test.tsx +4 -12
  22. package/src/__tests__/backups-tab.test.tsx +3 -4
  23. package/src/__tests__/billing-layout-nav-hidden.test.tsx +5 -37
  24. package/src/__tests__/billing-payment-org-invoices.test.tsx +2 -18
  25. package/src/__tests__/billing.test.tsx +8 -39
  26. package/src/__tests__/bot-settings/resources-tab.test.tsx +1 -3
  27. package/src/__tests__/bot-settings/storage-tab.test.tsx +1 -3
  28. package/src/__tests__/bot-settings/vps-upgrade-card.test.tsx +1 -3
  29. package/src/__tests__/bot-settings-restart.test.tsx +1 -3
  30. package/src/__tests__/bot-settings.test.tsx +2 -6
  31. package/src/__tests__/brand.test.ts +6 -26
  32. package/src/__tests__/buy-credits-panel.test.tsx +1 -3
  33. package/src/__tests__/buy-crypto-credits-panel.test.tsx +101 -119
  34. package/src/__tests__/capability-conflicts.test.ts +2 -8
  35. package/src/__tests__/capability-resolver.test.tsx +2 -12
  36. package/src/__tests__/channel-wizard.test.tsx +4 -17
  37. package/src/__tests__/chat/chat-panel.test.tsx +1 -4
  38. package/src/__tests__/chat-store.test.ts +5 -15
  39. package/src/__tests__/command-center.test.tsx +10 -12
  40. package/src/__tests__/compliance-retention-edit.test.tsx +3 -6
  41. package/src/__tests__/confirmation-tracker.test.tsx +3 -18
  42. package/src/__tests__/coupon-input.test.tsx +1 -3
  43. package/src/__tests__/create-instance.test.tsx +1 -3
  44. package/src/__tests__/credit-balance.test.tsx +4 -12
  45. package/src/__tests__/credits.test.tsx +32 -85
  46. package/src/__tests__/email-verification-banner.test.tsx +2 -6
  47. package/src/__tests__/error-boundaries.test.tsx +0 -1
  48. package/src/__tests__/fetch-pricing.test.ts +2 -1
  49. package/src/__tests__/field-oauth.test.tsx +2 -6
  50. package/src/__tests__/fixtures/mock-manifests-data.js +1 -3
  51. package/src/__tests__/fixtures/mock-manifests.ts +2 -4
  52. package/src/__tests__/fleet-health-timestamp.test.tsx +1 -8
  53. package/src/__tests__/fleet-health-update.test.tsx +1 -8
  54. package/src/__tests__/gpu-dashboard.test.tsx +2 -6
  55. package/src/__tests__/instance-detail.test.tsx +3 -9
  56. package/src/__tests__/instance-list.test.tsx +1 -5
  57. package/src/__tests__/layout-snapshots.test.tsx +64 -11
  58. package/src/__tests__/marketplace-admin.test.tsx +2 -6
  59. package/src/__tests__/marketplace.test.tsx +11 -35
  60. package/src/__tests__/merge-api-rates.test.ts +1 -6
  61. package/src/__tests__/middleware.test.ts +32 -219
  62. package/src/__tests__/next-config-headers.test.ts +1 -3
  63. package/src/__tests__/notifications.test.tsx +4 -11
  64. package/src/__tests__/oauth-buttons.test.tsx +36 -59
  65. package/src/__tests__/oauth-error-mapping.test.tsx +2 -6
  66. package/src/__tests__/observability.test.tsx +23 -36
  67. package/src/__tests__/onboarding-page.test.tsx +4 -6
  68. package/src/__tests__/org-billing-api.test.tsx +1 -6
  69. package/src/__tests__/plugin-install-flow.test.tsx +28 -58
  70. package/src/__tests__/plugin-registry.test.tsx +3 -11
  71. package/src/__tests__/plugin-tool-sync.test.ts +1 -3
  72. package/src/__tests__/plugins-catalog-error.test.tsx +2 -6
  73. package/src/__tests__/plugins-toggle-race.test.tsx +3 -5
  74. package/src/__tests__/portfolio-chart.test.tsx +2 -6
  75. package/src/__tests__/promotion-form.test.tsx +2 -6
  76. package/src/__tests__/promotions-list.test.tsx +1 -3
  77. package/src/__tests__/provider-key-api.test.ts +2 -1
  78. package/src/__tests__/resend-verification-button.test.tsx +8 -24
  79. package/src/__tests__/secrets-audit-pagination.test.tsx +1 -3
  80. package/src/__tests__/settings.test.tsx +11 -21
  81. package/src/__tests__/setup-checklist.test.tsx +3 -9
  82. package/src/__tests__/setup.ts +25 -6
  83. package/src/__tests__/snapshot-api.test.ts +2 -1
  84. package/src/__tests__/step-superpowers.test.tsx +1 -3
  85. package/src/__tests__/tenant-context.test.tsx +1 -6
  86. package/src/__tests__/tenant-keys-api.test.ts +3 -4
  87. package/src/__tests__/tenant-table-pagination.test.tsx +2 -6
  88. package/src/__tests__/terminal-log-cleanup.test.tsx +0 -1
  89. package/src/__tests__/transaction-history.test.tsx +190 -238
  90. package/src/__tests__/trpc-types.test.ts +2 -6
  91. package/src/__tests__/use-chat.test.ts +1 -3
  92. package/src/__tests__/use-plugin-setup-chat-stale-closure.test.ts +1 -4
  93. package/src/__tests__/use-sidecar-bridge.test.tsx +105 -0
  94. package/src/__tests__/use-webmcp.test.ts +1 -3
  95. package/src/__tests__/validate-elevenlabs-key.test.ts +2 -1
  96. package/src/__tests__/verify-page.test.tsx +4 -13
  97. package/src/__tests__/verify-redirect.test.tsx +2 -6
  98. package/src/app/(auth)/error.tsx +1 -7
  99. package/src/app/(auth)/forgot-password/page.tsx +4 -18
  100. package/src/app/(auth)/login/page.tsx +5 -22
  101. package/src/app/(auth)/reset-password/page.tsx +2 -12
  102. package/src/app/(auth)/signup/page.tsx +10 -44
  103. package/src/app/(auth)/verify/page.tsx +47 -0
  104. package/src/app/(dashboard)/billing/credits/page.tsx +14 -67
  105. package/src/app/(dashboard)/billing/error.tsx +2 -10
  106. package/src/app/(dashboard)/billing/layout.tsx +12 -62
  107. package/src/app/(dashboard)/billing/payment/page.tsx +17 -68
  108. package/src/app/(dashboard)/billing/plans/page.tsx +3 -9
  109. package/src/app/(dashboard)/billing/usage/hosted/page.tsx +8 -25
  110. package/src/app/(dashboard)/billing/usage/page.tsx +63 -103
  111. package/src/app/(dashboard)/changesets/[id]/changeset-detail-client.tsx +9 -27
  112. package/src/app/(dashboard)/changesets/[id]/error.tsx +2 -6
  113. package/src/app/(dashboard)/changesets/error.tsx +1 -7
  114. package/src/app/(dashboard)/chat/page.tsx +2 -6
  115. package/src/app/(dashboard)/dashboard/network/page.tsx +5 -19
  116. package/src/app/(dashboard)/error.tsx +1 -7
  117. package/src/app/(dashboard)/layout.tsx +15 -36
  118. package/src/app/(dashboard)/marketplace/[plugin]/page.tsx +14 -51
  119. package/src/app/(dashboard)/marketplace/error.tsx +1 -7
  120. package/src/app/(dashboard)/marketplace/page.tsx +6 -27
  121. package/src/app/(dashboard)/not-found.tsx +2 -5
  122. package/src/app/(dashboard)/onboarding/page.tsx +5 -22
  123. package/src/app/(dashboard)/settings/account/page.tsx +1 -6
  124. package/src/app/(dashboard)/settings/activity/page.tsx +8 -34
  125. package/src/app/(dashboard)/settings/api-keys/page.tsx +15 -60
  126. package/src/app/(dashboard)/settings/brain/page.tsx +9 -31
  127. package/src/app/(dashboard)/settings/error.tsx +2 -10
  128. package/src/app/(dashboard)/settings/notifications/page.tsx +2 -6
  129. package/src/app/(dashboard)/settings/org/page.tsx +13 -56
  130. package/src/app/(dashboard)/settings/page.tsx +1 -0
  131. package/src/app/(dashboard)/settings/profile/page.tsx +126 -73
  132. package/src/app/(dashboard)/settings/providers/page.tsx +21 -78
  133. package/src/app/(dashboard)/settings/secrets/page.tsx +13 -58
  134. package/src/app/(dashboard)/settings/security/page.tsx +31 -111
  135. package/src/app/admin/email-templates/email-templates-client.tsx +15 -58
  136. package/src/app/admin/error.tsx +1 -7
  137. package/src/app/admin/fleet-updates/error.tsx +1 -7
  138. package/src/app/admin/fleet-updates/fleet-updates-client.tsx +10 -50
  139. package/src/app/admin/layout.tsx +4 -0
  140. package/src/app/admin/payment-methods/page.tsx +9 -38
  141. package/src/app/admin/products/error.tsx +2 -7
  142. package/src/app/admin/products/page.tsx +1 -4
  143. package/src/app/admin/promotions/[id]/page.tsx +9 -38
  144. package/src/app/admin/promotions/page.tsx +9 -36
  145. package/src/app/admin/rate-overrides/page.tsx +9 -45
  146. package/src/app/auth/callback/[provider]/page.tsx +1 -8
  147. package/src/app/auth/verify/page.tsx +9 -36
  148. package/src/app/channels/error.tsx +2 -10
  149. package/src/app/channels/layout.tsx +9 -0
  150. package/src/app/channels/page.tsx +8 -20
  151. package/src/app/channels/setup/[plugin]/page.tsx +3 -5
  152. package/src/app/error.tsx +1 -7
  153. package/src/app/fleet/error.tsx +1 -7
  154. package/src/app/fleet/layout.tsx +5 -0
  155. package/src/app/fleet/settings/page.tsx +1 -3
  156. package/src/app/global-error.tsx +2 -10
  157. package/src/app/globals.css +1 -4
  158. package/src/app/instances/[id]/instance-detail-client.tsx +51 -125
  159. package/src/app/instances/error.tsx +2 -10
  160. package/src/app/instances/instance-list-client.tsx +20 -69
  161. package/src/app/instances/layout.tsx +9 -0
  162. package/src/app/instances/new/create-instance-client.tsx +10 -31
  163. package/src/app/layout.tsx +2 -10
  164. package/src/app/not-found.tsx +1 -3
  165. package/src/app/page.tsx +1 -2
  166. package/src/app/plugins/error.tsx +2 -10
  167. package/src/app/plugins/layout.tsx +5 -0
  168. package/src/app/plugins/page.tsx +16 -48
  169. package/src/app/pricing/error.tsx +1 -7
  170. package/src/app/privacy/page.tsx +93 -150
  171. package/src/app/status/error.tsx +1 -7
  172. package/src/app/terms/page.tsx +89 -144
  173. package/src/components/account-switcher.tsx +25 -52
  174. package/src/components/admin/accounting-dashboard.tsx +1 -3
  175. package/src/components/admin/admin-guard.tsx +1 -3
  176. package/src/components/admin/admin-nav.tsx +1 -3
  177. package/src/components/admin/affiliate-dashboard.tsx +25 -94
  178. package/src/components/admin/audit-log-table.tsx +13 -49
  179. package/src/components/admin/billing-health-dashboard.tsx +7 -25
  180. package/src/components/admin/bulk-actions-bar.test.tsx +1 -7
  181. package/src/components/admin/bulk-actions-bar.tsx +1 -3
  182. package/src/components/admin/bulk-export-dialog.test.tsx +1 -7
  183. package/src/components/admin/bulk-export-dialog.tsx +6 -32
  184. package/src/components/admin/bulk-grant-dialog.test.tsx +2 -6
  185. package/src/components/admin/bulk-grant-dialog.tsx +4 -15
  186. package/src/components/admin/bulk-preview-dialog.tsx +3 -12
  187. package/src/components/admin/bulk-reactivate-dialog.tsx +1 -7
  188. package/src/components/admin/bulk-select-all-banner.tsx +1 -6
  189. package/src/components/admin/bulk-suspend-dialog.tsx +5 -12
  190. package/src/components/admin/bulk-undo-toast.tsx +1 -2
  191. package/src/components/admin/compliance-dashboard.tsx +31 -101
  192. package/src/components/admin/gpu-dashboard.tsx +21 -70
  193. package/src/components/admin/grant-credits-dialog.tsx +4 -17
  194. package/src/components/admin/incident-dashboard.tsx +10 -25
  195. package/src/components/admin/inference-dashboard.tsx +14 -54
  196. package/src/components/admin/marketplace-admin.tsx +18 -60
  197. package/src/components/admin/migrations-dashboard.tsx +9 -42
  198. package/src/components/admin/onboarding-dashboard.tsx +14 -64
  199. package/src/components/admin/pool-config-dashboard.tsx +4 -10
  200. package/src/components/admin/products/fleet-form.tsx +2 -11
  201. package/src/components/admin/products/nav-editor.tsx +3 -10
  202. package/src/components/admin/promotions/promotion-form.tsx +9 -42
  203. package/src/components/admin/roles-dashboard.tsx +7 -34
  204. package/src/components/admin/suspend-dialog.tsx +4 -11
  205. package/src/components/admin/tenant-notes-panel.tsx +1 -3
  206. package/src/components/admin/tenant-row-actions.tsx +4 -20
  207. package/src/components/admin/tenant-table.tsx +12 -49
  208. package/src/components/auth/auth-redirect.tsx +11 -3
  209. package/src/components/auth/email-verification-result-banner.tsx +1 -3
  210. package/src/components/auth/resend-verification-button.tsx +2 -10
  211. package/src/components/auth/wopr-wordmark.tsx +1 -3
  212. package/src/components/billing/add-payment-method-dialog.tsx +1 -2
  213. package/src/components/billing/affiliate-dashboard.tsx +4 -16
  214. package/src/components/billing/amount-selector.tsx +1 -3
  215. package/src/components/billing/auto-topup-card.tsx +2 -11
  216. package/src/components/billing/buy-credits-panel.tsx +4 -14
  217. package/src/components/billing/byok-callout.tsx +6 -8
  218. package/src/components/billing/confirmation-tracker.tsx +4 -14
  219. package/src/components/billing/credit-balance-badge.tsx +22 -0
  220. package/src/components/billing/credit-balance.tsx +3 -9
  221. package/src/components/billing/crypto-checkout.tsx +5 -24
  222. package/src/components/billing/degraded-state-banner.tsx +1 -3
  223. package/src/components/billing/deposit-view.tsx +301 -41
  224. package/src/components/billing/dividend-banner.tsx +1 -3
  225. package/src/components/billing/dividend-eligibility.tsx +3 -12
  226. package/src/components/billing/dividend-pool-stats.tsx +6 -20
  227. package/src/components/billing/first-dividend-dialog.tsx +2 -2
  228. package/src/components/billing/org-billing-page.tsx +8 -31
  229. package/src/components/billing/payment-method-picker.tsx +2 -10
  230. package/src/components/billing/suspension-banner.tsx +2 -7
  231. package/src/components/billing/transaction-history.tsx +10 -58
  232. package/src/components/billing/unified-checkout.tsx +547 -0
  233. package/src/components/bot-settings/backups-tab.tsx +9 -33
  234. package/src/components/bot-settings/bot-settings-client.tsx +32 -134
  235. package/src/components/bot-settings/resources-tab.tsx +2 -9
  236. package/src/components/bot-settings/storage-tab.tsx +19 -48
  237. package/src/components/bot-settings/vps-info-panel.tsx +3 -11
  238. package/src/components/bot-settings/vps-upgrade-card.tsx +3 -4
  239. package/src/components/brand-hydrator.tsx +13 -0
  240. package/src/components/channel-wizard/field-interactive.tsx +1 -3
  241. package/src/components/channel-wizard/field-qr.tsx +10 -39
  242. package/src/components/channel-wizard/step-renderer.tsx +5 -28
  243. package/src/components/channel-wizard/wizard.tsx +6 -31
  244. package/src/components/chat/chat-message.tsx +1 -4
  245. package/src/components/chat/chat-panel.tsx +4 -18
  246. package/src/components/chat/chat-widget.tsx +3 -14
  247. package/src/components/dashboard/command-center.tsx +15 -61
  248. package/src/components/fleet/update-settings-card.tsx +7 -23
  249. package/src/components/instance-update-banner.tsx +130 -0
  250. package/src/components/instances/friends-tab.test.tsx +2 -9
  251. package/src/components/instances/friends-tab.tsx +18 -74
  252. package/src/components/instances/update-available-badge.tsx +2 -11
  253. package/src/components/landing/hero.tsx +3 -9
  254. package/src/components/landing/landing-page.tsx +1 -3
  255. package/src/components/landing/portfolio-chart.tsx +4 -9
  256. package/src/components/landing/story-sections.tsx +1 -3
  257. package/src/components/landing/terminal-sequence.tsx +4 -17
  258. package/src/components/marketplace/empty-state.tsx +2 -6
  259. package/src/components/marketplace/first-visit-hero.tsx +1 -3
  260. package/src/components/marketplace/install-wizard.tsx +20 -77
  261. package/src/components/marketplace/marketplace-tabs.tsx +1 -4
  262. package/src/components/marketplace/plugin-card.tsx +2 -9
  263. package/src/components/marketplace/superpower-content.tsx +1 -3
  264. package/src/components/marketplace/terminal-search.tsx +2 -8
  265. package/src/components/oauth-buttons.tsx +29 -14
  266. package/src/components/observability/fleet-health.tsx +5 -18
  267. package/src/components/observability/health-overview.tsx +7 -20
  268. package/src/components/observability/logs-viewer.tsx +8 -32
  269. package/src/components/observability/metrics-dashboard.tsx +2 -15
  270. package/src/components/onboarding/fallback-setup.tsx +6 -25
  271. package/src/components/onboarding/setup-checklist.tsx +18 -51
  272. package/src/components/onboarding/step-superpowers.tsx +1 -4
  273. package/src/components/plugin-setup/setup-chat-panel.tsx +6 -22
  274. package/src/components/pricing/dividend-calculator.tsx +6 -12
  275. package/src/components/pricing/dividend-stats.tsx +5 -17
  276. package/src/components/pricing/pricing-page.tsx +17 -36
  277. package/src/components/settings/create-org-wizard.tsx +2 -5
  278. package/src/components/sidebar.tsx +7 -42
  279. package/src/components/sidecar-frame.tsx +78 -0
  280. package/src/components/status/status-page.tsx +6 -28
  281. package/src/components/ui/alert-dialog.tsx +8 -25
  282. package/src/components/ui/badge.tsx +2 -8
  283. package/src/components/ui/banner.tsx +1 -6
  284. package/src/components/ui/card.tsx +5 -24
  285. package/src/components/ui/checkbox.tsx +1 -5
  286. package/src/components/ui/collapsible.tsx +3 -8
  287. package/src/components/ui/dialog.tsx +4 -10
  288. package/src/components/ui/dropdown-menu.tsx +9 -18
  289. package/src/components/ui/form.tsx +2 -16
  290. package/src/components/ui/popover.tsx +3 -23
  291. package/src/components/ui/progress.tsx +1 -5
  292. package/src/components/ui/radio-group.tsx +3 -15
  293. package/src/components/ui/select.tsx +4 -17
  294. package/src/components/ui/sheet.tsx +5 -19
  295. package/src/components/ui/skeleton.tsx +1 -7
  296. package/src/components/ui/table.tsx +5 -22
  297. package/src/components/ui/tabs.tsx +3 -13
  298. package/src/components/ui/tooltip.tsx +1 -1
  299. package/src/components/unified-sidebar.tsx +493 -0
  300. package/src/hooks/__tests__/use-fleet-sse.test.ts +1 -4
  301. package/src/hooks/__tests__/use-save-queue.test.ts +2 -8
  302. package/src/hooks/use-credit-balance.ts +27 -0
  303. package/src/hooks/use-my-org-role.ts +1 -3
  304. package/src/hooks/use-plugin-registry.ts +8 -14
  305. package/src/hooks/use-plugin-setup-chat.ts +2 -5
  306. package/src/hooks/use-sidecar-bridge.tsx +148 -0
  307. package/src/hooks/use-webmcp.ts +1 -4
  308. package/src/lib/__tests__/admin-api.test.ts +1 -3
  309. package/src/lib/__tests__/api-bot-crud.test.ts +8 -18
  310. package/src/lib/__tests__/api-fetch.test.ts +4 -16
  311. package/src/lib/__tests__/org-billing-api.test.ts +1 -3
  312. package/src/lib/__tests__/pricing-data.test.ts +0 -8
  313. package/src/lib/__tests__/settings-api.test.ts +1 -3
  314. package/src/lib/admin-affiliate-api.ts +2 -7
  315. package/src/lib/admin-api.ts +6 -26
  316. package/src/lib/admin-incident-api.ts +11 -19
  317. package/src/lib/admin-marketplace-api.ts +1 -5
  318. package/src/lib/api-config.test.ts +5 -50
  319. package/src/lib/api.ts +143 -122
  320. package/src/lib/auth-client.ts +1 -2
  321. package/src/lib/bot-settings-data.ts +11 -36
  322. package/src/lib/brand-config.ts +56 -115
  323. package/src/lib/brand.ts +2 -15
  324. package/src/lib/chat/use-chat.ts +2 -7
  325. package/src/lib/cost-comparison-data.test.ts +1 -3
  326. package/src/lib/cost-comparison-data.ts +1 -4
  327. package/src/lib/errors.ts +1 -4
  328. package/src/lib/fetch-utils.test.ts +26 -9
  329. package/src/lib/fetch-utils.ts +40 -11
  330. package/src/lib/logger.ts +2 -0
  331. package/src/lib/marketplace-data.ts +3 -11
  332. package/src/lib/oauth-errors.ts +2 -4
  333. package/src/lib/onboarding-data.ts +3 -11
  334. package/src/lib/org-api.ts +2 -10
  335. package/src/lib/org-billing-api.ts +5 -19
  336. package/src/lib/plugin/tool-definitions.ts +1 -2
  337. package/src/lib/require-auth.ts +57 -0
  338. package/src/lib/settings-api.ts +1 -4
  339. package/src/lib/sidecar-routes.ts +43 -0
  340. package/src/lib/trpc-server.ts +49 -0
  341. package/src/lib/trpc-types.ts +4 -6
  342. package/src/lib/trpc.tsx +12 -4
  343. package/src/lib/validate-redirect-url.ts +1 -4
  344. package/src/lib/webmcp/marketplace-onboarding-tools.ts +6 -16
  345. package/src/lib/webmcp/register.ts +1 -4
  346. package/src/lib/webmcp/tools.ts +2 -9
  347. package/src/proxy.ts +35 -212
  348. package/src/types/missing-deps.d.ts +2 -8
  349. package/tsconfig.json +1 -8
  350. package/biome.json +0 -52
  351. package/src/__tests__/__snapshots__/layout-snapshots.test.tsx.snap +0 -741
  352. package/src/__tests__/billing-byok-callout.test.tsx +0 -76
  353. package/src/lib/__tests__/__snapshots__/pricing-data.test.ts.snap +0 -112
@@ -33,22 +33,9 @@ import {
33
33
  DropdownMenuTrigger,
34
34
  } from "@/components/ui/dropdown-menu";
35
35
  import { Input } from "@/components/ui/input";
36
- import {
37
- Select,
38
- SelectContent,
39
- SelectItem,
40
- SelectTrigger,
41
- SelectValue,
42
- } from "@/components/ui/select";
36
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
43
37
  import { Skeleton } from "@/components/ui/skeleton";
44
- import {
45
- Table,
46
- TableBody,
47
- TableCell,
48
- TableHead,
49
- TableHeader,
50
- TableRow,
51
- } from "@/components/ui/table";
38
+ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
52
39
  import { useImageStatus } from "@/hooks/use-image-status";
53
40
  import type { BotStatusResponse, Instance, InstanceStatus } from "@/lib/api";
54
41
  import {
@@ -165,10 +152,7 @@ export function InstanceListClient() {
165
152
  onChange={(e) => setSearch(e.target.value)}
166
153
  className="max-w-sm"
167
154
  />
168
- <Select
169
- value={statusFilter}
170
- onValueChange={(v) => setStatusFilter(v as InstanceStatus | "all")}
171
- >
155
+ <Select value={statusFilter} onValueChange={(v) => setStatusFilter(v as InstanceStatus | "all")}>
172
156
  <SelectTrigger className="w-[160px]">
173
157
  <SelectValue placeholder="All statuses" />
174
158
  </SelectTrigger>
@@ -268,17 +252,12 @@ export function InstanceListClient() {
268
252
  {filtered.map((inst) => (
269
253
  <TableRow
270
254
  key={inst.id}
271
- className={cn(
272
- "border-l-2 border-transparent transition-colors",
273
- "hover:bg-muted/50",
274
- {
275
- "border-l-emerald-500/30 hover:border-l-emerald-500":
276
- inst.status === "running",
277
- "hover:border-l-zinc-500": inst.status === "stopped",
278
- "hover:border-l-yellow-500": inst.status === "degraded",
279
- "hover:border-l-red-500": inst.status === "error",
280
- },
281
- )}
255
+ className={cn("border-l-2 border-transparent transition-colors", "hover:bg-muted/50", {
256
+ "border-l-emerald-500/30 hover:border-l-emerald-500": inst.status === "running",
257
+ "hover:border-l-zinc-500": inst.status === "stopped",
258
+ "hover:border-l-yellow-500": inst.status === "degraded",
259
+ "hover:border-l-red-500": inst.status === "error",
260
+ })}
282
261
  >
283
262
  <TableCell>
284
263
  <Link href={`/instances/${inst.id}`} className="font-medium hover:underline">
@@ -288,17 +267,11 @@ export function InstanceListClient() {
288
267
  <TableCell>
289
268
  <div className="flex items-center gap-2">
290
269
  <StatusBadge status={inst.status} />
291
- <InstanceUpdateBadge
292
- instanceId={inst.id}
293
- instanceName={inst.name}
294
- onUpdated={refetch}
295
- />
270
+ <InstanceUpdateBadge instanceId={inst.id} instanceName={inst.name} onUpdated={refetch} />
296
271
  </div>
297
272
  </TableCell>
298
273
  <TableCell className="text-muted-foreground">{inst.provider}</TableCell>
299
- <TableCell className="text-muted-foreground">
300
- {formatUptime(inst.uptime)}
301
- </TableCell>
274
+ <TableCell className="text-muted-foreground">{formatUptime(inst.uptime)}</TableCell>
302
275
  <TableCell className="text-muted-foreground">{inst.plugins.length}</TableCell>
303
276
  <TableCell>
304
277
  <InstanceRowActions
@@ -333,9 +306,8 @@ export function InstanceListClient() {
333
306
  <DialogHeader>
334
307
  <DialogTitle>Destroy {destroyTarget?.name} permanently?</DialogTitle>
335
308
  <DialogDescription>
336
- This action is permanent and cannot be undone. The instance and all its data will be
337
- destroyed. Type <strong className="text-foreground">{destroyTarget?.name}</strong> to
338
- confirm.
309
+ This action is permanent and cannot be undone. The instance and all its data will be destroyed. Type{" "}
310
+ <strong className="text-foreground">{destroyTarget?.name}</strong> to confirm.
339
311
  </DialogDescription>
340
312
  </DialogHeader>
341
313
 
@@ -399,8 +371,7 @@ export function InstanceListClient() {
399
371
  <DialogHeader>
400
372
  <DialogTitle>Rename instance</DialogTitle>
401
373
  <DialogDescription>
402
- Enter a new name for <strong className="text-foreground">{renameTarget?.name}</strong>
403
- .
374
+ Enter a new name for <strong className="text-foreground">{renameTarget?.name}</strong>.
404
375
  </DialogDescription>
405
376
  </DialogHeader>
406
377
  <Input
@@ -409,12 +380,7 @@ export function InstanceListClient() {
409
380
  value={renameValue}
410
381
  onChange={(e) => setRenameValue(e.target.value)}
411
382
  onKeyDown={(e) => {
412
- if (
413
- e.key === "Enter" &&
414
- renameValue.trim() &&
415
- renameValue.trim() !== renameTarget?.name
416
- )
417
- handleRename();
383
+ if (e.key === "Enter" && renameValue.trim() && renameValue.trim() !== renameTarget?.name) handleRename();
418
384
  }}
419
385
  disabled={renameLoading}
420
386
  />
@@ -431,9 +397,7 @@ export function InstanceListClient() {
431
397
  Cancel
432
398
  </Button>
433
399
  <Button
434
- disabled={
435
- renameLoading || !renameValue.trim() || renameValue.trim() === renameTarget?.name
436
- }
400
+ disabled={renameLoading || !renameValue.trim() || renameValue.trim() === renameTarget?.name}
437
401
  onClick={handleRename}
438
402
  aria-label="Save"
439
403
  >
@@ -494,16 +458,8 @@ export function InstanceRowActions({
494
458
  </DropdownMenuItem>
495
459
  <DropdownMenuSeparator />
496
460
  {updateAvailable && (
497
- <DropdownMenuItem
498
- className="text-amber-500"
499
- onClick={() => setConfirmPull(true)}
500
- disabled={pulling}
501
- >
502
- {pulling ? (
503
- <Loader2 className="mr-2 size-4 animate-spin" />
504
- ) : (
505
- <ArrowDownToLine className="mr-2 size-4" />
506
- )}
461
+ <DropdownMenuItem className="text-amber-500" onClick={() => setConfirmPull(true)} disabled={pulling}>
462
+ {pulling ? <Loader2 className="mr-2 size-4 animate-spin" /> : <ArrowDownToLine className="mr-2 size-4" />}
507
463
  {pulling ? "Pulling..." : "Pull Update"}
508
464
  </DropdownMenuItem>
509
465
  )}
@@ -513,9 +469,7 @@ export function InstanceRowActions({
513
469
  {(inst.status === "running" || inst.status === "degraded") && (
514
470
  <>
515
471
  <DropdownMenuItem onClick={() => onAction(inst.id, "stop")}>Stop</DropdownMenuItem>
516
- <DropdownMenuItem onClick={() => onAction(inst.id, "restart")}>
517
- Restart
518
- </DropdownMenuItem>
472
+ <DropdownMenuItem onClick={() => onAction(inst.id, "restart")}>Restart</DropdownMenuItem>
519
473
  </>
520
474
  )}
521
475
  <DropdownMenuSeparator />
@@ -559,10 +513,7 @@ function InstanceUpdateBadge({
559
513
  onUpdated?: () => void;
560
514
  }) {
561
515
  const { updateAvailable } = useImageStatus(instanceId);
562
- const { data: changelog } = trpc.fleet.getChangelog.useQuery(
563
- { instanceId },
564
- { enabled: updateAvailable },
565
- );
516
+ const { data: changelog } = trpc.fleet.getChangelog.useQuery({ instanceId }, { enabled: updateAvailable });
566
517
 
567
518
  if (!updateAvailable) return null;
568
519
 
@@ -0,0 +1,9 @@
1
+ "use client";
2
+
3
+ import { useRequireAuth } from "@/lib/require-auth";
4
+
5
+ export default function InstancesLayout({ children }: { children: React.ReactNode }) {
6
+ const { isPending, isAuthed } = useRequireAuth();
7
+ if (isPending || !isAuthed) return null;
8
+ return <>{children}</>;
9
+ }
@@ -9,13 +9,7 @@ import { Button } from "@/components/ui/button";
9
9
  import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
10
10
  import { Input } from "@/components/ui/input";
11
11
  import { Label } from "@/components/ui/label";
12
- import {
13
- Select,
14
- SelectContent,
15
- SelectItem,
16
- SelectTrigger,
17
- SelectValue,
18
- } from "@/components/ui/select";
12
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
19
13
  import { Separator } from "@/components/ui/separator";
20
14
  import { usePluginRegistry } from "@/hooks/use-plugin-registry";
21
15
  import { createInstance } from "@/lib/api";
@@ -78,9 +72,7 @@ export function CreateInstanceClient() {
78
72
  }
79
73
 
80
74
  function toggleChannel(ch: string) {
81
- setSelectedChannels((prev) =>
82
- prev.includes(ch) ? prev.filter((c) => c !== ch) : [...prev, ch],
83
- );
75
+ setSelectedChannels((prev) => (prev.includes(ch) ? prev.filter((c) => c !== ch) : [...prev, ch]));
84
76
  }
85
77
 
86
78
  function togglePlugin(p: string) {
@@ -144,14 +136,10 @@ export function CreateInstanceClient() {
144
136
  animate={{ opacity: 1, y: 0 }}
145
137
  transition={{ delay: 0.2 }}
146
138
  >
147
- Your instance <span className="font-medium text-terminal">&ldquo;{name}&rdquo;</span> has
148
- been created successfully.
139
+ Your instance <span className="font-medium text-terminal">&ldquo;{name}&rdquo;</span> has been created
140
+ successfully.
149
141
  </motion.p>
150
- <motion.div
151
- initial={{ opacity: 0, y: 8 }}
152
- animate={{ opacity: 1, y: 0 }}
153
- transition={{ delay: 0.3 }}
154
- >
142
+ <motion.div initial={{ opacity: 0, y: 8 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.3 }}>
155
143
  <Button variant="terminal" asChild>
156
144
  <Link href="/instances">Back to Instances</Link>
157
145
  </Button>
@@ -179,9 +167,7 @@ export function CreateInstanceClient() {
179
167
  >
180
168
  <div>
181
169
  <h1 className="text-2xl font-bold tracking-tight">Create Instance</h1>
182
- <p className="text-sm text-muted-foreground">
183
- Launch a new {productName()} bot. Pick a preset or go custom.
184
- </p>
170
+ <p className="text-sm text-muted-foreground">Launch a new {productName()} bot. Pick a preset or go custom.</p>
185
171
  </div>
186
172
 
187
173
  {/* Instance Name (required, above presets) */}
@@ -211,9 +197,7 @@ export function CreateInstanceClient() {
211
197
  {/* Preset (optional) */}
212
198
  <div className="space-y-3">
213
199
  <div>
214
- <div className="font-mono text-xs uppercase tracking-[0.3em] text-terminal/60">
215
- QUICK START
216
- </div>
200
+ <div className="font-mono text-xs uppercase tracking-[0.3em] text-terminal/60">QUICK START</div>
217
201
  <h2 className="text-sm font-medium text-muted-foreground">
218
202
  Select a preset to auto-fill, or skip to configure manually
219
203
  </h2>
@@ -230,8 +214,7 @@ export function CreateInstanceClient() {
230
214
  className={cn(
231
215
  "relative cursor-pointer transition-all hover:border-terminal/40 hover:shadow-[0_0_8px_rgba(0,255,65,0.15)]",
232
216
  "border-l-2",
233
- selectedPreset === preset.id &&
234
- "border-terminal bg-terminal/5 shadow-[0_0_12px_rgba(0,255,65,0.2)]",
217
+ selectedPreset === preset.id && "border-terminal bg-terminal/5 shadow-[0_0_12px_rgba(0,255,65,0.2)]",
235
218
  )}
236
219
  style={{
237
220
  borderLeftColor: PRESET_ACCENT_COLORS[preset.id] ?? "transparent",
@@ -288,12 +271,8 @@ export function CreateInstanceClient() {
288
271
  {/* Configuration */}
289
272
  <div className="space-y-4">
290
273
  <div>
291
- <div className="font-mono text-xs uppercase tracking-[0.3em] text-terminal/60">
292
- CONFIGURATION
293
- </div>
294
- <h2 className="text-sm font-medium text-muted-foreground">
295
- Fine-tune your instance settings
296
- </h2>
274
+ <div className="font-mono text-xs uppercase tracking-[0.3em] text-terminal/60">CONFIGURATION</div>
275
+ <h2 className="text-sm font-medium text-muted-foreground">Fine-tune your instance settings</h2>
297
276
  </div>
298
277
 
299
278
  <div className="space-y-2">
@@ -30,9 +30,7 @@ export const metadata: Metadata = {
30
30
  title: `${brand.productName} — AI Agent Platform`,
31
31
  description: `${brand.tagline} ${brand.price ? `${brand.price}.` : ""} ${brand.domain}`,
32
32
  url: SITE_URL,
33
- images: [
34
- { url: "/og", width: 1200, height: 630, alt: `${brand.productName} — AI Agent Platform` },
35
- ],
33
+ images: [{ url: "/og", width: 1200, height: 630, alt: `${brand.productName} — AI Agent Platform` }],
36
34
  },
37
35
  twitter: {
38
36
  card: "summary_large_image",
@@ -66,13 +64,7 @@ export default async function RootLayout({
66
64
  <head>{nonce && <meta property="csp-nonce" content={nonce} />}</head>
67
65
  <body className={`${jetbrainsMono.variable} antialiased`}>
68
66
  <MotionConfig nonce={nonce}>
69
- <ThemeProvider
70
- attribute="class"
71
- defaultTheme="dark"
72
- enableSystem
73
- disableTransitionOnChange
74
- nonce={nonce}
75
- >
67
+ <ThemeProvider attribute="class" defaultTheme="dark" enableSystem disableTransitionOnChange nonce={nonce}>
76
68
  <TRPCProvider initialTenantId={initialTenantId}>
77
69
  {children}
78
70
  <Toaster
@@ -12,9 +12,7 @@ export default function NotFound() {
12
12
  <div className="flex items-center gap-3">
13
13
  <SearchXIcon aria-hidden="true" className="size-6 text-muted-foreground" />
14
14
  <div>
15
- <p className="text-xs font-semibold uppercase tracking-widest text-muted-foreground">
16
- {brandName()}
17
- </p>
15
+ <p className="text-xs font-semibold uppercase tracking-widest text-muted-foreground">{brandName()}</p>
18
16
  <CardTitle className="text-xl">404</CardTitle>
19
17
  </div>
20
18
  </div>
package/src/app/page.tsx CHANGED
@@ -5,8 +5,7 @@ import { getBrandConfig } from "@/lib/brand-config";
5
5
 
6
6
  const brand = getBrandConfig();
7
7
 
8
- const desc =
9
- brand.tagline || `A ${brand.price || "$5/month"} supercomputer that runs your business.`;
8
+ const desc = brand.tagline || `A ${brand.price || "$5/month"} supercomputer that runs your business.`;
10
9
 
11
10
  export const metadata: Metadata = {
12
11
  title: `${brand.productName} — ${brand.tagline}`,
@@ -8,13 +8,7 @@ import { logger } from "@/lib/logger";
8
8
 
9
9
  const log = logger("error-boundary:plugins");
10
10
 
11
- export default function PluginsError({
12
- error,
13
- reset,
14
- }: {
15
- error: Error & { digest?: string };
16
- reset: () => void;
17
- }) {
11
+ export default function PluginsError({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {
18
12
  const [showDetails, setShowDetails] = useState(false);
19
13
  const isDev = process.env.NODE_ENV === "development";
20
14
 
@@ -32,9 +26,7 @@ export default function PluginsError({
32
26
  </div>
33
27
  </CardHeader>
34
28
  <CardContent className="space-y-4">
35
- <p className="text-muted-foreground">
36
- Something went wrong loading plugins. This may be a temporary issue.
37
- </p>
29
+ <p className="text-muted-foreground">Something went wrong loading plugins. This may be a temporary issue.</p>
38
30
  {isDev && (
39
31
  <Button
40
32
  type="button"
@@ -1,10 +1,15 @@
1
+ "use client";
2
+
1
3
  import { Sidebar } from "@/components/sidebar";
4
+ import { useRequireAuth } from "@/lib/require-auth";
2
5
 
3
6
  export default function PluginsLayout({
4
7
  children,
5
8
  }: Readonly<{
6
9
  children: React.ReactNode;
7
10
  }>) {
11
+ const { isPending, isAuthed } = useRequireAuth();
12
+ if (isPending || !isAuthed) return null;
8
13
  return (
9
14
  <div className="flex h-screen">
10
15
  <Sidebar />
@@ -10,13 +10,7 @@ import { Badge } from "@/components/ui/badge";
10
10
  import { Button } from "@/components/ui/button";
11
11
  import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
12
12
  import { Input } from "@/components/ui/input";
13
- import {
14
- Select,
15
- SelectContent,
16
- SelectItem,
17
- SelectTrigger,
18
- SelectValue,
19
- } from "@/components/ui/select";
13
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
20
14
  import { Skeleton } from "@/components/ui/skeleton";
21
15
  import { Switch } from "@/components/ui/switch";
22
16
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
@@ -170,9 +164,7 @@ export default function PluginsPage() {
170
164
  setToggleError(null);
171
165
 
172
166
  // Optimistic update
173
- setInstalled((prev) =>
174
- prev.map((p) => (p.pluginId === pluginId ? { ...p, enabled: newEnabled } : p)),
175
- );
167
+ setInstalled((prev) => prev.map((p) => (p.pluginId === pluginId ? { ...p, enabled: newEnabled } : p)));
176
168
 
177
169
  try {
178
170
  await togglePluginEnabled(selectedBotId, pluginId, newEnabled);
@@ -181,9 +173,7 @@ export default function PluginsPage() {
181
173
  setInstalled(refreshed);
182
174
  } catch {
183
175
  // Revert on failure
184
- setInstalled((prev) =>
185
- prev.map((p) => (p.pluginId === pluginId ? { ...p, enabled: previousEnabled } : p)),
186
- );
176
+ setInstalled((prev) => prev.map((p) => (p.pluginId === pluginId ? { ...p, enabled: previousEnabled } : p)));
187
177
  setToggleError("Failed to update plugin. Please try again.");
188
178
  } finally {
189
179
  togglingRef.current = null;
@@ -221,10 +211,7 @@ export default function PluginsPage() {
221
211
 
222
212
  const installedTotal = installedManifests.length;
223
213
  const installedStart = (installedPage - 1) * PLUGINS_PAGE_SIZE;
224
- const pagedInstalled = installedManifests.slice(
225
- installedStart,
226
- installedStart + PLUGINS_PAGE_SIZE,
227
- );
214
+ const pagedInstalled = installedManifests.slice(installedStart, installedStart + PLUGINS_PAGE_SIZE);
228
215
 
229
216
  const catalogTotal = availablePlugins.length;
230
217
  const catalogStart = (catalogPage - 1) * PLUGINS_PAGE_SIZE;
@@ -268,17 +255,14 @@ export default function PluginsPage() {
268
255
  <div className="mb-8">
269
256
  <h1 className="text-2xl font-bold tracking-widest uppercase">PLUGINS</h1>
270
257
  <p className="mt-2 text-muted-foreground">
271
- Manage installed plugins and discover new ones for your {getBrandConfig().productName}{" "}
272
- instances.
258
+ Manage installed plugins and discover new ones for your {getBrandConfig().productName} instances.
273
259
  </p>
274
260
  </div>
275
261
 
276
262
  {botsLoading ? (
277
263
  <Skeleton className="mb-6 h-9 w-64" />
278
264
  ) : bots.length === 0 ? (
279
- <p className="mb-6 text-sm text-muted-foreground">
280
- No bots found. Create a bot first to manage plugins.
281
- </p>
265
+ <p className="mb-6 text-sm text-muted-foreground">No bots found. Create a bot first to manage plugins.</p>
282
266
  ) : (
283
267
  <div className="mb-6 flex items-center gap-3">
284
268
  <label htmlFor="bot-select" className="text-sm font-medium text-muted-foreground">
@@ -307,16 +291,10 @@ export default function PluginsPage() {
307
291
 
308
292
  <Tabs defaultValue="installed">
309
293
  <TabsList variant="line">
310
- <TabsTrigger
311
- value="installed"
312
- className="data-[state=active]:text-terminal after:bg-terminal"
313
- >
294
+ <TabsTrigger value="installed" className="data-[state=active]:text-terminal after:bg-terminal">
314
295
  Installed ({installed.length})
315
296
  </TabsTrigger>
316
- <TabsTrigger
317
- value="catalog"
318
- className="data-[state=active]:text-terminal after:bg-terminal"
319
- >
297
+ <TabsTrigger value="catalog" className="data-[state=active]:text-terminal after:bg-terminal">
320
298
  Catalog
321
299
  </TabsTrigger>
322
300
  </TabsList>
@@ -329,9 +307,7 @@ export default function PluginsPage() {
329
307
  )}
330
308
  {installedTotal === 0 ? (
331
309
  <div className="flex h-40 flex-col items-center justify-center gap-3 rounded-sm border border-dashed border-terminal/20">
332
- <p className="font-mono text-sm text-terminal/60">
333
- &gt; NO PLUGINS INSTALLED. YOUR ARSENAL IS EMPTY.
334
- </p>
310
+ <p className="font-mono text-sm text-terminal/60">&gt; NO PLUGINS INSTALLED. YOUR ARSENAL IS EMPTY.</p>
335
311
  <Button
336
312
  variant="outline"
337
313
  size="sm"
@@ -377,9 +353,7 @@ export default function PluginsPage() {
377
353
  {item.enabled ? "Active" : "Disabled"}
378
354
  </Badge>
379
355
  </div>
380
- <CardDescription className="mt-1 line-clamp-2">
381
- {manifest.description}
382
- </CardDescription>
356
+ <CardDescription className="mt-1 line-clamp-2">{manifest.description}</CardDescription>
383
357
  </div>
384
358
  </div>
385
359
  </CardHeader>
@@ -394,8 +368,7 @@ export default function PluginsPage() {
394
368
  className="h-7 px-2 text-xs font-mono uppercase tracking-wider text-terminal hover:bg-terminal/10"
395
369
  disabled={!selectedBotId}
396
370
  onClick={() =>
397
- selectedBotId &&
398
- setupChat.openSetup(item.pluginId, manifest.name, selectedBotId)
371
+ selectedBotId && setupChat.openSetup(item.pluginId, manifest.name, selectedBotId)
399
372
  }
400
373
  >
401
374
  <Settings className="mr-1 h-3 w-3" />
@@ -421,8 +394,8 @@ export default function PluginsPage() {
421
394
  {installedTotal > PLUGINS_PAGE_SIZE && (
422
395
  <div className="mt-4 flex items-center justify-between text-xs text-muted-foreground font-mono">
423
396
  <span>
424
- Showing {installedStart + 1}-
425
- {Math.min(installedStart + PLUGINS_PAGE_SIZE, installedTotal)} of {installedTotal}
397
+ Showing {installedStart + 1}-{Math.min(installedStart + PLUGINS_PAGE_SIZE, installedTotal)} of{" "}
398
+ {installedTotal}
426
399
  </span>
427
400
  <div className="flex gap-2">
428
401
  <Button
@@ -481,9 +454,7 @@ export default function PluginsPage() {
481
454
  </div>
482
455
  ) : catalogError ? (
483
456
  <div className="flex h-40 flex-col items-center justify-center gap-3 rounded-sm border border-dashed border-red-500/25 bg-red-500/5">
484
- <p className="font-mono text-sm text-red-500">
485
- &gt; CATALOG LOAD FAILED. CHECK CONNECTION AND RETRY.
486
- </p>
457
+ <p className="font-mono text-sm text-red-500">&gt; CATALOG LOAD FAILED. CHECK CONNECTION AND RETRY.</p>
487
458
  <Button
488
459
  variant="outline"
489
460
  size="sm"
@@ -532,9 +503,7 @@ export default function PluginsPage() {
532
503
  v{plugin.version}
533
504
  </Badge>
534
505
  </div>
535
- <CardDescription className="mt-1 line-clamp-2">
536
- {plugin.description}
537
- </CardDescription>
506
+ <CardDescription className="mt-1 line-clamp-2">{plugin.description}</CardDescription>
538
507
  </div>
539
508
  </div>
540
509
  </CardHeader>
@@ -573,8 +542,7 @@ export default function PluginsPage() {
573
542
  {catalogTotal > PLUGINS_PAGE_SIZE && (
574
543
  <div className="flex items-center justify-between text-xs text-muted-foreground font-mono">
575
544
  <span>
576
- Showing {catalogStart + 1}-
577
- {Math.min(catalogStart + PLUGINS_PAGE_SIZE, catalogTotal)} of {catalogTotal}
545
+ Showing {catalogStart + 1}-{Math.min(catalogStart + PLUGINS_PAGE_SIZE, catalogTotal)} of {catalogTotal}
578
546
  </span>
579
547
  <div className="flex gap-2">
580
548
  <Button
@@ -8,13 +8,7 @@ import { logger } from "@/lib/logger";
8
8
 
9
9
  const log = logger("error-boundary:pricing");
10
10
 
11
- export default function PricingError({
12
- error,
13
- reset,
14
- }: {
15
- error: Error & { digest?: string };
16
- reset: () => void;
17
- }) {
11
+ export default function PricingError({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {
18
12
  const [showDetails, setShowDetails] = useState(false);
19
13
  const isDev = process.env.NODE_ENV === "development";
20
14