@wopr-network/platform-ui-core 1.0.0

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 (543) hide show
  1. package/.env.paperclip +18 -0
  2. package/.env.wopr +18 -0
  3. package/README.md +36 -0
  4. package/biome.json +52 -0
  5. package/next.config.ts +45 -0
  6. package/package.json +84 -0
  7. package/postcss.config.mjs +7 -0
  8. package/public/file.svg +1 -0
  9. package/public/globe.svg +1 -0
  10. package/public/window.svg +1 -0
  11. package/src/__tests__/__snapshots__/layout-snapshots.test.tsx.snap +741 -0
  12. package/src/__tests__/account-page-redirect.test.tsx +73 -0
  13. package/src/__tests__/account-switcher.test.tsx +85 -0
  14. package/src/__tests__/activity-page.test.tsx +176 -0
  15. package/src/__tests__/add-payment-method-dialog.test.tsx +160 -0
  16. package/src/__tests__/admin-api.test.ts +244 -0
  17. package/src/__tests__/admin-gpu-api.test.ts +188 -0
  18. package/src/__tests__/admin-guard.test.tsx +79 -0
  19. package/src/__tests__/admin-marketplace-api.test.ts +179 -0
  20. package/src/__tests__/admin-middleware.test.ts +157 -0
  21. package/src/__tests__/admin-tenant-table.test.tsx +95 -0
  22. package/src/__tests__/affiliate-dashboard.test.tsx +178 -0
  23. package/src/__tests__/api-401-redirect.test.ts +78 -0
  24. package/src/__tests__/api-client.test.ts +316 -0
  25. package/src/__tests__/api-config.test.ts +89 -0
  26. package/src/__tests__/api-control-instance.test.ts +69 -0
  27. package/src/__tests__/api-fleet-resources.test.ts +52 -0
  28. package/src/__tests__/api-fleet-trpc.test.ts +252 -0
  29. package/src/__tests__/api-get-instance-config.test.ts +41 -0
  30. package/src/__tests__/api-null-guards.test.ts +244 -0
  31. package/src/__tests__/api-rename-instance.test.ts +60 -0
  32. package/src/__tests__/api-update-instance-config.test.ts +60 -0
  33. package/src/__tests__/audit-log-table-pagination.test.tsx +136 -0
  34. package/src/__tests__/auth-client.test.ts +87 -0
  35. package/src/__tests__/auth-password-reset.test.tsx +435 -0
  36. package/src/__tests__/auth-redirect.test.tsx +60 -0
  37. package/src/__tests__/auth.test.tsx +269 -0
  38. package/src/__tests__/auto-topup-card.test.tsx +257 -0
  39. package/src/__tests__/backups-tab.test.tsx +221 -0
  40. package/src/__tests__/billing-byok-callout.test.tsx +76 -0
  41. package/src/__tests__/billing-layout-nav-hidden.test.tsx +47 -0
  42. package/src/__tests__/billing-payment-org-invoices.test.tsx +123 -0
  43. package/src/__tests__/billing.test.tsx +509 -0
  44. package/src/__tests__/bot-settings/resources-tab.test.tsx +119 -0
  45. package/src/__tests__/bot-settings/storage-tab.test.tsx +80 -0
  46. package/src/__tests__/bot-settings/vps-info-panel.test.tsx +108 -0
  47. package/src/__tests__/bot-settings/vps-upgrade-card.test.tsx +52 -0
  48. package/src/__tests__/bot-settings-data-control.test.ts +49 -0
  49. package/src/__tests__/bot-settings-restart.test.tsx +149 -0
  50. package/src/__tests__/bot-settings.test.tsx +678 -0
  51. package/src/__tests__/brand.test.ts +335 -0
  52. package/src/__tests__/buy-credits-panel.test.tsx +249 -0
  53. package/src/__tests__/buy-crypto-credits-panel.test.tsx +178 -0
  54. package/src/__tests__/capability-conflicts.test.ts +88 -0
  55. package/src/__tests__/capability-resolver.test.tsx +173 -0
  56. package/src/__tests__/changeset-detail.test.tsx +156 -0
  57. package/src/__tests__/channel-setup-logger.test.ts +22 -0
  58. package/src/__tests__/channel-setup-toast.test.tsx +60 -0
  59. package/src/__tests__/channel-wizard.test.tsx +505 -0
  60. package/src/__tests__/chat/ambient-dot.test.tsx +35 -0
  61. package/src/__tests__/chat/chat-input.test.tsx +78 -0
  62. package/src/__tests__/chat/chat-message.test.tsx +45 -0
  63. package/src/__tests__/chat/chat-panel.test.tsx +111 -0
  64. package/src/__tests__/chat/chat-widget.test.tsx +82 -0
  65. package/src/__tests__/chat-store.test.ts +87 -0
  66. package/src/__tests__/command-center.test.tsx +246 -0
  67. package/src/__tests__/compliance-retention-edit.test.tsx +134 -0
  68. package/src/__tests__/coupon-input.test.tsx +119 -0
  69. package/src/__tests__/create-instance.test.tsx +96 -0
  70. package/src/__tests__/create-org-wizard.test.tsx +200 -0
  71. package/src/__tests__/credit-balance.test.tsx +103 -0
  72. package/src/__tests__/credits.test.tsx +376 -0
  73. package/src/__tests__/csrf-middleware.test.ts +198 -0
  74. package/src/__tests__/degraded-state-banner.test.tsx +130 -0
  75. package/src/__tests__/dividend-calculator.test.tsx +20 -0
  76. package/src/__tests__/dividend-stats.test.tsx +64 -0
  77. package/src/__tests__/dividend.test.tsx +169 -0
  78. package/src/__tests__/dockerfile.test.ts +110 -0
  79. package/src/__tests__/email-verification-banner.test.tsx +64 -0
  80. package/src/__tests__/env-example.test.ts +25 -0
  81. package/src/__tests__/error-boundaries.test.tsx +64 -0
  82. package/src/__tests__/fetch-pricing.test.ts +121 -0
  83. package/src/__tests__/field-oauth.test.tsx +302 -0
  84. package/src/__tests__/fixtures/mock-manifests-data.js +372 -0
  85. package/src/__tests__/fixtures/mock-manifests.ts +24 -0
  86. package/src/__tests__/fleet-health-timestamp.test.tsx +101 -0
  87. package/src/__tests__/fleet-health-update.test.tsx +83 -0
  88. package/src/__tests__/format-credit.test.ts +58 -0
  89. package/src/__tests__/gpu-dashboard.test.tsx +236 -0
  90. package/src/__tests__/hosted-usage-date-range.test.tsx +54 -0
  91. package/src/__tests__/instance-detail.test.tsx +571 -0
  92. package/src/__tests__/instance-list.test.tsx +230 -0
  93. package/src/__tests__/landing-hero.test.tsx +27 -0
  94. package/src/__tests__/landing-nav.test.tsx +24 -0
  95. package/src/__tests__/layout-snapshots.test.tsx +167 -0
  96. package/src/__tests__/logger.test.ts +54 -0
  97. package/src/__tests__/login-page-redirect.test.tsx +142 -0
  98. package/src/__tests__/manifest-validation.test.ts +126 -0
  99. package/src/__tests__/marketplace-admin.test.tsx +151 -0
  100. package/src/__tests__/marketplace.test.tsx +609 -0
  101. package/src/__tests__/merge-api-rates.test.ts +70 -0
  102. package/src/__tests__/middleware.test.ts +690 -0
  103. package/src/__tests__/network-page.test.tsx +100 -0
  104. package/src/__tests__/next-config-headers.test.ts +28 -0
  105. package/src/__tests__/not-found.test.tsx +26 -0
  106. package/src/__tests__/notifications.test.tsx +128 -0
  107. package/src/__tests__/oauth-buttons.test.tsx +101 -0
  108. package/src/__tests__/oauth-error-mapping.test.tsx +97 -0
  109. package/src/__tests__/observability.test.tsx +541 -0
  110. package/src/__tests__/onboarding-data.test.ts +363 -0
  111. package/src/__tests__/onboarding-page.test.tsx +113 -0
  112. package/src/__tests__/onboarding-store.test.ts +121 -0
  113. package/src/__tests__/org-billing-api.test.tsx +70 -0
  114. package/src/__tests__/org-billing-null-guards.test.ts +64 -0
  115. package/src/__tests__/org-billing-page.test.tsx +124 -0
  116. package/src/__tests__/plugin-definition.test.ts +43 -0
  117. package/src/__tests__/plugin-install-flow.test.tsx +535 -0
  118. package/src/__tests__/plugin-registry.test.tsx +475 -0
  119. package/src/__tests__/plugin-setup/setup-chat-panel.test.ts +142 -0
  120. package/src/__tests__/plugin-setup/use-plugin-setup-chat.test.ts +49 -0
  121. package/src/__tests__/plugin-tool-definitions.test.ts +51 -0
  122. package/src/__tests__/plugin-tool-sync.test.ts +59 -0
  123. package/src/__tests__/portfolio-chart.test.tsx +24 -0
  124. package/src/__tests__/pricing.test.tsx +107 -0
  125. package/src/__tests__/promotion-form.test.tsx +180 -0
  126. package/src/__tests__/promotions-list.test.tsx +194 -0
  127. package/src/__tests__/provider-key-api.test.ts +134 -0
  128. package/src/__tests__/resend-verification-button.test.tsx +104 -0
  129. package/src/__tests__/sanitize-redirect-url.test.ts +47 -0
  130. package/src/__tests__/secrets-audit-pagination.test.tsx +139 -0
  131. package/src/__tests__/settings.test.tsx +937 -0
  132. package/src/__tests__/setup-checklist.test.tsx +274 -0
  133. package/src/__tests__/setup.ts +82 -0
  134. package/src/__tests__/smoke.test.tsx +10 -0
  135. package/src/__tests__/snapshot-api.test.ts +104 -0
  136. package/src/__tests__/status-api.test.ts +46 -0
  137. package/src/__tests__/status-badge.test.tsx +33 -0
  138. package/src/__tests__/status-colors.test.ts +83 -0
  139. package/src/__tests__/status-page.test.tsx +86 -0
  140. package/src/__tests__/step-superpowers.test.tsx +218 -0
  141. package/src/__tests__/story-sections.test.tsx +24 -0
  142. package/src/__tests__/superpower-content-sanitize.test.tsx +87 -0
  143. package/src/__tests__/superpower-content.test.tsx +44 -0
  144. package/src/__tests__/suspension-banner.test.tsx +140 -0
  145. package/src/__tests__/tenant-context.test.tsx +146 -0
  146. package/src/__tests__/tenant-keys-api.test.ts +114 -0
  147. package/src/__tests__/tenant-table-pagination.test.tsx +124 -0
  148. package/src/__tests__/terminal-log-cleanup.test.tsx +51 -0
  149. package/src/__tests__/terminal-sequence.test.tsx +28 -0
  150. package/src/__tests__/transaction-history.test.tsx +325 -0
  151. package/src/__tests__/trpc-types.test.ts +102 -0
  152. package/src/__tests__/use-capability-meta.test.ts +161 -0
  153. package/src/__tests__/use-chat.test.ts +616 -0
  154. package/src/__tests__/use-has-org.test.ts +44 -0
  155. package/src/__tests__/use-image-status.test.ts +77 -0
  156. package/src/__tests__/use-pagination-params.test.ts +88 -0
  157. package/src/__tests__/use-plugin-setup-chat-stale-closure.test.ts +53 -0
  158. package/src/__tests__/use-webmcp.test.ts +119 -0
  159. package/src/__tests__/validate-elevenlabs-key.test.ts +95 -0
  160. package/src/__tests__/validate-redirect-url.test.ts +61 -0
  161. package/src/__tests__/verify-page.test.tsx +140 -0
  162. package/src/__tests__/verify-redirect.test.tsx +41 -0
  163. package/src/__tests__/verify-result-banner.test.tsx +66 -0
  164. package/src/__tests__/webmcp-feature-detect.test.ts +54 -0
  165. package/src/__tests__/webmcp-hook.test.tsx +72 -0
  166. package/src/__tests__/webmcp-marketplace-onboarding-tools.test.ts +185 -0
  167. package/src/__tests__/webmcp-register.test.ts +103 -0
  168. package/src/__tests__/webmcp-set-provider.test.ts +47 -0
  169. package/src/__tests__/webmcp-tools.test.ts +348 -0
  170. package/src/app/(auth)/error.tsx +72 -0
  171. package/src/app/(auth)/forgot-password/page.tsx +137 -0
  172. package/src/app/(auth)/layout.tsx +14 -0
  173. package/src/app/(auth)/loading.tsx +26 -0
  174. package/src/app/(auth)/login/page.tsx +188 -0
  175. package/src/app/(auth)/reset-password/page.tsx +169 -0
  176. package/src/app/(auth)/signup/page.tsx +309 -0
  177. package/src/app/(dashboard)/billing/credits/page.tsx +209 -0
  178. package/src/app/(dashboard)/billing/error.tsx +72 -0
  179. package/src/app/(dashboard)/billing/layout.tsx +73 -0
  180. package/src/app/(dashboard)/billing/loading.tsx +41 -0
  181. package/src/app/(dashboard)/billing/payment/page.tsx +639 -0
  182. package/src/app/(dashboard)/billing/plans/page.tsx +58 -0
  183. package/src/app/(dashboard)/billing/referrals/page.tsx +7 -0
  184. package/src/app/(dashboard)/billing/usage/hosted/page.tsx +348 -0
  185. package/src/app/(dashboard)/billing/usage/page.tsx +663 -0
  186. package/src/app/(dashboard)/changesets/[id]/changeset-detail-client.tsx +400 -0
  187. package/src/app/(dashboard)/changesets/[id]/error.tsx +57 -0
  188. package/src/app/(dashboard)/changesets/[id]/loading.tsx +23 -0
  189. package/src/app/(dashboard)/changesets/[id]/page.tsx +10 -0
  190. package/src/app/(dashboard)/changesets/error.tsx +72 -0
  191. package/src/app/(dashboard)/changesets/page.tsx +10 -0
  192. package/src/app/(dashboard)/chat/page.tsx +74 -0
  193. package/src/app/(dashboard)/dashboard/bots/[id]/settings/page.tsx +10 -0
  194. package/src/app/(dashboard)/dashboard/network/page.tsx +97 -0
  195. package/src/app/(dashboard)/dashboard/page.tsx +13 -0
  196. package/src/app/(dashboard)/error.tsx +72 -0
  197. package/src/app/(dashboard)/layout.tsx +113 -0
  198. package/src/app/(dashboard)/loading.tsx +27 -0
  199. package/src/app/(dashboard)/marketplace/[plugin]/page.tsx +548 -0
  200. package/src/app/(dashboard)/marketplace/error.tsx +72 -0
  201. package/src/app/(dashboard)/marketplace/loading.tsx +27 -0
  202. package/src/app/(dashboard)/marketplace/page.tsx +268 -0
  203. package/src/app/(dashboard)/not-found.tsx +46 -0
  204. package/src/app/(dashboard)/onboarding/page.tsx +267 -0
  205. package/src/app/(dashboard)/settings/account/page.tsx +132 -0
  206. package/src/app/(dashboard)/settings/activity/page.tsx +280 -0
  207. package/src/app/(dashboard)/settings/api-keys/page.tsx +530 -0
  208. package/src/app/(dashboard)/settings/brain/page.tsx +412 -0
  209. package/src/app/(dashboard)/settings/error.tsx +72 -0
  210. package/src/app/(dashboard)/settings/layout.tsx +114 -0
  211. package/src/app/(dashboard)/settings/loading.tsx +31 -0
  212. package/src/app/(dashboard)/settings/notifications/page.tsx +216 -0
  213. package/src/app/(dashboard)/settings/org/page.tsx +617 -0
  214. package/src/app/(dashboard)/settings/profile/page.tsx +510 -0
  215. package/src/app/(dashboard)/settings/providers/page.tsx +842 -0
  216. package/src/app/(dashboard)/settings/secrets/page.tsx +658 -0
  217. package/src/app/(dashboard)/settings/security/page.tsx +1133 -0
  218. package/src/app/admin/accounting/loading.tsx +32 -0
  219. package/src/app/admin/accounting/page.tsx +5 -0
  220. package/src/app/admin/affiliates/loading.tsx +32 -0
  221. package/src/app/admin/affiliates/page.tsx +5 -0
  222. package/src/app/admin/audit/loading.tsx +32 -0
  223. package/src/app/admin/audit/page.tsx +5 -0
  224. package/src/app/admin/billing-health/loading.tsx +17 -0
  225. package/src/app/admin/billing-health/page.tsx +10 -0
  226. package/src/app/admin/compliance/page.tsx +5 -0
  227. package/src/app/admin/error.tsx +72 -0
  228. package/src/app/admin/gpu/loading.tsx +38 -0
  229. package/src/app/admin/gpu/page.tsx +5 -0
  230. package/src/app/admin/incidents/page.tsx +10 -0
  231. package/src/app/admin/inference/loading.tsx +32 -0
  232. package/src/app/admin/inference/page.tsx +5 -0
  233. package/src/app/admin/layout.tsx +44 -0
  234. package/src/app/admin/loading.tsx +32 -0
  235. package/src/app/admin/marketplace/loading.tsx +32 -0
  236. package/src/app/admin/marketplace/page.tsx +5 -0
  237. package/src/app/admin/migrations/loading.tsx +22 -0
  238. package/src/app/admin/migrations/page.tsx +5 -0
  239. package/src/app/admin/onboarding/loading.tsx +18 -0
  240. package/src/app/admin/onboarding/page.tsx +5 -0
  241. package/src/app/admin/promotions/[id]/edit/loading.tsx +16 -0
  242. package/src/app/admin/promotions/[id]/edit/page.tsx +56 -0
  243. package/src/app/admin/promotions/[id]/loading.tsx +15 -0
  244. package/src/app/admin/promotions/[id]/page.tsx +311 -0
  245. package/src/app/admin/promotions/loading.tsx +21 -0
  246. package/src/app/admin/promotions/new/loading.tsx +16 -0
  247. package/src/app/admin/promotions/new/page.tsx +12 -0
  248. package/src/app/admin/promotions/page.tsx +266 -0
  249. package/src/app/admin/rate-overrides/loading.tsx +17 -0
  250. package/src/app/admin/rate-overrides/page.tsx +290 -0
  251. package/src/app/admin/roles/loading.tsx +27 -0
  252. package/src/app/admin/roles/page.tsx +5 -0
  253. package/src/app/admin/tenants/loading.tsx +32 -0
  254. package/src/app/admin/tenants/page.tsx +5 -0
  255. package/src/app/apple-icon.tsx +32 -0
  256. package/src/app/auth/callback/[provider]/page.tsx +104 -0
  257. package/src/app/auth/verify/page.tsx +224 -0
  258. package/src/app/channels/error.tsx +72 -0
  259. package/src/app/channels/loading.tsx +29 -0
  260. package/src/app/channels/page.tsx +262 -0
  261. package/src/app/channels/setup/[plugin]/page.tsx +136 -0
  262. package/src/app/error.tsx +72 -0
  263. package/src/app/favicon.ico +0 -0
  264. package/src/app/fleet/error.tsx +72 -0
  265. package/src/app/fleet/health/page.tsx +9 -0
  266. package/src/app/fleet/layout.tsx +14 -0
  267. package/src/app/fleet/loading.tsx +33 -0
  268. package/src/app/fleet/page.tsx +5 -0
  269. package/src/app/global-error.tsx +96 -0
  270. package/src/app/globals.css +251 -0
  271. package/src/app/icon.svg +4 -0
  272. package/src/app/instances/[id]/instance-detail-client.tsx +1298 -0
  273. package/src/app/instances/[id]/page.tsx +10 -0
  274. package/src/app/instances/error.tsx +72 -0
  275. package/src/app/instances/instance-list-client.tsx +540 -0
  276. package/src/app/instances/loading.tsx +33 -0
  277. package/src/app/instances/new/create-instance-client.tsx +377 -0
  278. package/src/app/instances/new/page.tsx +9 -0
  279. package/src/app/instances/page.tsx +9 -0
  280. package/src/app/layout.tsx +83 -0
  281. package/src/app/not-found.tsx +38 -0
  282. package/src/app/og/route.tsx +50 -0
  283. package/src/app/page.tsx +39 -0
  284. package/src/app/plugins/error.tsx +72 -0
  285. package/src/app/plugins/layout.tsx +14 -0
  286. package/src/app/plugins/loading.tsx +30 -0
  287. package/src/app/plugins/page.tsx +555 -0
  288. package/src/app/pricing/error.tsx +72 -0
  289. package/src/app/pricing/loading.tsx +25 -0
  290. package/src/app/pricing/page.tsx +20 -0
  291. package/src/app/privacy/page.tsx +406 -0
  292. package/src/app/robots.ts +9 -0
  293. package/src/app/sitemap.ts +11 -0
  294. package/src/app/status/error.tsx +72 -0
  295. package/src/app/status/loading.tsx +21 -0
  296. package/src/app/status/page.tsx +20 -0
  297. package/src/app/terms/page.tsx +414 -0
  298. package/src/components/account-switcher.tsx +82 -0
  299. package/src/components/admin/accounting-dashboard.tsx +190 -0
  300. package/src/components/admin/admin-guard.tsx +36 -0
  301. package/src/components/admin/admin-nav.tsx +71 -0
  302. package/src/components/admin/affiliate-dashboard.tsx +564 -0
  303. package/src/components/admin/audit-log-table.tsx +336 -0
  304. package/src/components/admin/billing-health-dashboard.test.tsx +40 -0
  305. package/src/components/admin/billing-health-dashboard.tsx +416 -0
  306. package/src/components/admin/bulk-actions-bar.test.tsx +92 -0
  307. package/src/components/admin/bulk-actions-bar.tsx +80 -0
  308. package/src/components/admin/bulk-export-dialog.test.tsx +75 -0
  309. package/src/components/admin/bulk-export-dialog.tsx +189 -0
  310. package/src/components/admin/bulk-grant-dialog.test.tsx +81 -0
  311. package/src/components/admin/bulk-grant-dialog.tsx +147 -0
  312. package/src/components/admin/bulk-preview-dialog.test.tsx +72 -0
  313. package/src/components/admin/bulk-preview-dialog.tsx +106 -0
  314. package/src/components/admin/bulk-reactivate-dialog.test.tsx +51 -0
  315. package/src/components/admin/bulk-reactivate-dialog.tsx +55 -0
  316. package/src/components/admin/bulk-select-all-banner.test.tsx +36 -0
  317. package/src/components/admin/bulk-select-all-banner.tsx +44 -0
  318. package/src/components/admin/bulk-suspend-dialog.test.tsx +77 -0
  319. package/src/components/admin/bulk-suspend-dialog.tsx +129 -0
  320. package/src/components/admin/bulk-undo-toast.test.tsx +66 -0
  321. package/src/components/admin/bulk-undo-toast.tsx +121 -0
  322. package/src/components/admin/compliance-dashboard.tsx +1341 -0
  323. package/src/components/admin/gpu-dashboard.tsx +552 -0
  324. package/src/components/admin/grant-credits-dialog.tsx +121 -0
  325. package/src/components/admin/incident-dashboard.test.tsx +44 -0
  326. package/src/components/admin/incident-dashboard.tsx +717 -0
  327. package/src/components/admin/inference-dashboard.tsx +415 -0
  328. package/src/components/admin/marketplace-admin.tsx +765 -0
  329. package/src/components/admin/migrations-dashboard.tsx +404 -0
  330. package/src/components/admin/onboarding-dashboard.tsx +422 -0
  331. package/src/components/admin/promotions/promotion-form.tsx +440 -0
  332. package/src/components/admin/roles-dashboard.tsx +278 -0
  333. package/src/components/admin/suspend-dialog.tsx +98 -0
  334. package/src/components/admin/tenant-notes-panel.tsx +134 -0
  335. package/src/components/admin/tenant-row-actions.tsx +78 -0
  336. package/src/components/admin/tenant-table.tsx +339 -0
  337. package/src/components/auth/auth-error.tsx +22 -0
  338. package/src/components/auth/auth-redirect.tsx +18 -0
  339. package/src/components/auth/auth-shell.tsx +25 -0
  340. package/src/components/auth/email-verification-banner.tsx +25 -0
  341. package/src/components/auth/email-verification-result-banner.tsx +70 -0
  342. package/src/components/auth/resend-verification-button.tsx +94 -0
  343. package/src/components/auth/wopr-wordmark.tsx +19 -0
  344. package/src/components/billing/add-payment-method-dialog.tsx +267 -0
  345. package/src/components/billing/affiliate-dashboard.tsx +300 -0
  346. package/src/components/billing/auto-topup-card.tsx +432 -0
  347. package/src/components/billing/buy-credits-panel.tsx +180 -0
  348. package/src/components/billing/buy-crypto-credits-panel.tsx +96 -0
  349. package/src/components/billing/byok-callout.tsx +87 -0
  350. package/src/components/billing/coupon-input.tsx +86 -0
  351. package/src/components/billing/credit-balance.tsx +79 -0
  352. package/src/components/billing/degraded-state-banner.tsx +95 -0
  353. package/src/components/billing/dividend-banner.tsx +97 -0
  354. package/src/components/billing/dividend-eligibility.tsx +86 -0
  355. package/src/components/billing/dividend-pool-stats.tsx +86 -0
  356. package/src/components/billing/first-dividend-dialog.tsx +109 -0
  357. package/src/components/billing/low-balance-banner.tsx +50 -0
  358. package/src/components/billing/org-billing-page.tsx +360 -0
  359. package/src/components/billing/suspension-banner.tsx +53 -0
  360. package/src/components/billing/transaction-history.tsx +239 -0
  361. package/src/components/bot-settings/__tests__/bot-settings-client.test.tsx +205 -0
  362. package/src/components/bot-settings/backups-tab.tsx +377 -0
  363. package/src/components/bot-settings/bot-settings-client.tsx +1712 -0
  364. package/src/components/bot-settings/resources-tab.tsx +203 -0
  365. package/src/components/bot-settings/storage-tab.tsx +248 -0
  366. package/src/components/bot-settings/vps-info-panel.tsx +132 -0
  367. package/src/components/bot-settings/vps-upgrade-card.tsx +110 -0
  368. package/src/components/capability/CapabilityResolver.tsx +113 -0
  369. package/src/components/channel-wizard/field-interactive.tsx +48 -0
  370. package/src/components/channel-wizard/field-oauth.tsx +181 -0
  371. package/src/components/channel-wizard/field-paste.tsx +47 -0
  372. package/src/components/channel-wizard/field-qr.tsx +302 -0
  373. package/src/components/channel-wizard/index.ts +6 -0
  374. package/src/components/channel-wizard/step-renderer.tsx +103 -0
  375. package/src/components/channel-wizard/wizard.tsx +200 -0
  376. package/src/components/chat/ambient-dot.tsx +32 -0
  377. package/src/components/chat/chat-input.tsx +56 -0
  378. package/src/components/chat/chat-message.tsx +36 -0
  379. package/src/components/chat/chat-panel.tsx +138 -0
  380. package/src/components/chat/chat-widget.tsx +41 -0
  381. package/src/components/chat/index.ts +5 -0
  382. package/src/components/dashboard/command-center.tsx +614 -0
  383. package/src/components/instances/friends-tab.test.tsx +265 -0
  384. package/src/components/instances/friends-tab.tsx +721 -0
  385. package/src/components/landing/hero.tsx +53 -0
  386. package/src/components/landing/landing-nav.tsx +21 -0
  387. package/src/components/landing/landing-page.tsx +71 -0
  388. package/src/components/landing/portfolio-chart.tsx +349 -0
  389. package/src/components/landing/story-sections.tsx +50 -0
  390. package/src/components/landing/terminal-lines.ts +99 -0
  391. package/src/components/landing/terminal-sequence.tsx +453 -0
  392. package/src/components/landing/typing-effect.tsx +43 -0
  393. package/src/components/marketplace/category-filter.tsx +61 -0
  394. package/src/components/marketplace/empty-state.tsx +61 -0
  395. package/src/components/marketplace/featured-heroes.tsx +84 -0
  396. package/src/components/marketplace/first-visit-hero.tsx +110 -0
  397. package/src/components/marketplace/index.ts +9 -0
  398. package/src/components/marketplace/install-wizard.tsx +782 -0
  399. package/src/components/marketplace/marketplace-tabs.tsx +54 -0
  400. package/src/components/marketplace/plugin-card.tsx +129 -0
  401. package/src/components/marketplace/superpower-card.tsx +104 -0
  402. package/src/components/marketplace/superpower-content.tsx +117 -0
  403. package/src/components/marketplace/terminal-search.tsx +67 -0
  404. package/src/components/oauth-buttons.tsx +75 -0
  405. package/src/components/observability/fleet-health.tsx +370 -0
  406. package/src/components/observability/health-overview.tsx +246 -0
  407. package/src/components/observability/logs-viewer.tsx +215 -0
  408. package/src/components/observability/metrics-dashboard.tsx +288 -0
  409. package/src/components/onboarding/fallback-setup.tsx +137 -0
  410. package/src/components/onboarding/index.ts +3 -0
  411. package/src/components/onboarding/setup-checklist.tsx +333 -0
  412. package/src/components/onboarding/step-superpowers.tsx +122 -0
  413. package/src/components/plugin-setup/index.ts +1 -0
  414. package/src/components/plugin-setup/setup-chat-panel.tsx +188 -0
  415. package/src/components/pricing/dividend-calculator.tsx +47 -0
  416. package/src/components/pricing/dividend-stats.tsx +117 -0
  417. package/src/components/pricing/pricing-page.tsx +229 -0
  418. package/src/components/settings/create-org-wizard.tsx +225 -0
  419. package/src/components/sidebar.tsx +202 -0
  420. package/src/components/status/status-page.tsx +209 -0
  421. package/src/components/status-badge.tsx +28 -0
  422. package/src/components/theme-provider.tsx +8 -0
  423. package/src/components/ui/alert-dialog.tsx +141 -0
  424. package/src/components/ui/badge.tsx +47 -0
  425. package/src/components/ui/banner.tsx +36 -0
  426. package/src/components/ui/button.tsx +64 -0
  427. package/src/components/ui/card.tsx +75 -0
  428. package/src/components/ui/checkbox.tsx +52 -0
  429. package/src/components/ui/collapsible.tsx +31 -0
  430. package/src/components/ui/credit-detailed.tsx +33 -0
  431. package/src/components/ui/dialog.tsx +143 -0
  432. package/src/components/ui/dropdown-menu.tsx +228 -0
  433. package/src/components/ui/form.tsx +151 -0
  434. package/src/components/ui/input.tsx +21 -0
  435. package/src/components/ui/label.tsx +21 -0
  436. package/src/components/ui/popover.tsx +74 -0
  437. package/src/components/ui/progress.tsx +28 -0
  438. package/src/components/ui/radio-group.tsx +45 -0
  439. package/src/components/ui/select.tsx +175 -0
  440. package/src/components/ui/separator.tsx +28 -0
  441. package/src/components/ui/sheet.tsx +125 -0
  442. package/src/components/ui/skeleton.tsx +15 -0
  443. package/src/components/ui/switch.tsx +35 -0
  444. package/src/components/ui/table.tsx +92 -0
  445. package/src/components/ui/tabs.tsx +81 -0
  446. package/src/components/ui/textarea.tsx +18 -0
  447. package/src/components/ui/tooltip.tsx +44 -0
  448. package/src/config/provider-docs.ts +17 -0
  449. package/src/hooks/__tests__/use-async.test.ts +127 -0
  450. package/src/hooks/__tests__/use-count-up.test.ts +129 -0
  451. package/src/hooks/__tests__/use-debounce.test.ts +105 -0
  452. package/src/hooks/__tests__/use-fleet-sse.test.ts +216 -0
  453. package/src/hooks/__tests__/use-local-storage.test.ts +74 -0
  454. package/src/hooks/__tests__/use-mobile.test.ts +86 -0
  455. package/src/hooks/__tests__/use-save-queue.test.ts +159 -0
  456. package/src/hooks/use-async.ts +54 -0
  457. package/src/hooks/use-capability-meta.ts +99 -0
  458. package/src/hooks/use-count-up.ts +23 -0
  459. package/src/hooks/use-debounce.ts +12 -0
  460. package/src/hooks/use-fleet-sse.ts +47 -0
  461. package/src/hooks/use-has-org.ts +18 -0
  462. package/src/hooks/use-image-status.ts +36 -0
  463. package/src/hooks/use-local-storage.ts +36 -0
  464. package/src/hooks/use-mobile.ts +17 -0
  465. package/src/hooks/use-page-context.ts +24 -0
  466. package/src/hooks/use-pagination-params.ts +30 -0
  467. package/src/hooks/use-plugin-registry.ts +247 -0
  468. package/src/hooks/use-plugin-setup-chat.ts +211 -0
  469. package/src/hooks/use-save-queue.ts +54 -0
  470. package/src/hooks/use-webmcp.ts +40 -0
  471. package/src/lib/__tests__/__snapshots__/pricing-data.test.ts.snap +112 -0
  472. package/src/lib/__tests__/admin-api.test.ts +487 -0
  473. package/src/lib/__tests__/api-bot-crud.test.ts +391 -0
  474. package/src/lib/__tests__/api-fetch.test.ts +196 -0
  475. package/src/lib/__tests__/bot-settings-data.test.ts +352 -0
  476. package/src/lib/__tests__/org-api.test.ts +281 -0
  477. package/src/lib/__tests__/org-billing-api.test.ts +242 -0
  478. package/src/lib/__tests__/pricing-data.test.ts +32 -0
  479. package/src/lib/__tests__/settings-api.test.ts +272 -0
  480. package/src/lib/admin-affiliate-api.ts +51 -0
  481. package/src/lib/admin-api.ts +325 -0
  482. package/src/lib/admin-compliance-api.ts +127 -0
  483. package/src/lib/admin-gpu-api.ts +82 -0
  484. package/src/lib/admin-incident-api.ts +121 -0
  485. package/src/lib/admin-inference-api.ts +47 -0
  486. package/src/lib/admin-marketplace-api.ts +97 -0
  487. package/src/lib/api-config.test.ts +111 -0
  488. package/src/lib/api-config.ts +65 -0
  489. package/src/lib/api-errors.test.ts +43 -0
  490. package/src/lib/api.ts +2011 -0
  491. package/src/lib/auth-client.ts +11 -0
  492. package/src/lib/bot-settings-data.ts +342 -0
  493. package/src/lib/brand-config.ts +145 -0
  494. package/src/lib/brand.ts +669 -0
  495. package/src/lib/changeset-api.ts +29 -0
  496. package/src/lib/changeset-types.ts +56 -0
  497. package/src/lib/channel-manifests.ts +50 -0
  498. package/src/lib/chat/chat-context.tsx +70 -0
  499. package/src/lib/chat/chat-store.ts +62 -0
  500. package/src/lib/chat/types.ts +35 -0
  501. package/src/lib/chat/use-chat.ts +255 -0
  502. package/src/lib/cost-comparison-data.test.ts +95 -0
  503. package/src/lib/cost-comparison-data.ts +54 -0
  504. package/src/lib/errors.test.ts +64 -0
  505. package/src/lib/errors.ts +52 -0
  506. package/src/lib/fetch-utils.test.ts +57 -0
  507. package/src/lib/fetch-utils.ts +25 -0
  508. package/src/lib/format-credit.test.ts +66 -0
  509. package/src/lib/format-credit.ts +24 -0
  510. package/src/lib/format.test.ts +62 -0
  511. package/src/lib/format.ts +17 -0
  512. package/src/lib/logger.ts +28 -0
  513. package/src/lib/marketplace-data.ts +346 -0
  514. package/src/lib/oauth-errors.ts +19 -0
  515. package/src/lib/onboarding-data.ts +1265 -0
  516. package/src/lib/onboarding-store.ts +233 -0
  517. package/src/lib/org-api.ts +74 -0
  518. package/src/lib/org-billing-api.ts +81 -0
  519. package/src/lib/page-prompts.test.ts +32 -0
  520. package/src/lib/page-prompts.ts +23 -0
  521. package/src/lib/plugin/index.ts +32 -0
  522. package/src/lib/plugin/tool-definitions.ts +306 -0
  523. package/src/lib/pricing-data.ts +115 -0
  524. package/src/lib/promotions-types.ts +58 -0
  525. package/src/lib/settings-api.ts +63 -0
  526. package/src/lib/status-colors.ts +38 -0
  527. package/src/lib/tenant-context.tsx +134 -0
  528. package/src/lib/trpc-types.ts +173 -0
  529. package/src/lib/trpc.tsx +86 -0
  530. package/src/lib/utils.test.ts +55 -0
  531. package/src/lib/utils.ts +18 -0
  532. package/src/lib/validate-redirect-url.ts +39 -0
  533. package/src/lib/webmcp/feature-detect.ts +13 -0
  534. package/src/lib/webmcp/marketplace-onboarding-tools.ts +202 -0
  535. package/src/lib/webmcp/register.ts +44 -0
  536. package/src/lib/webmcp/tools.ts +422 -0
  537. package/src/proxy.ts +258 -0
  538. package/src/types/missing-deps.d.ts +160 -0
  539. package/src/types/motion-dom.d.ts +162 -0
  540. package/src/types/vitest-matchers.d.ts +40 -0
  541. package/src/types/web-mcp.d.ts +22 -0
  542. package/tsconfig.json +34 -0
  543. package/vitest.config.ts +26 -0
@@ -0,0 +1,414 @@
1
+ import type { Metadata } from "next";
2
+ import Link from "next/link";
3
+ import { LandingNav } from "@/components/landing/landing-nav";
4
+ import { getBrandConfig } from "@/lib/brand-config";
5
+
6
+ const brand = getBrandConfig();
7
+
8
+ export const metadata: Metadata = {
9
+ title: `Terms of Service — ${brand.productName}`,
10
+ description: `Terms of Service for ${brand.productName}`,
11
+ };
12
+
13
+ export default function TermsPage() {
14
+ return (
15
+ <>
16
+ <LandingNav />
17
+ <div className="mx-auto max-w-2xl px-6 py-16">
18
+ <h1 className="text-2xl font-bold tracking-tight">Terms of Service</h1>
19
+ <p className="mt-2 text-sm text-muted-foreground">Last updated: February 2026</p>
20
+
21
+ <nav className="mt-6 rounded-sm border border-border bg-card p-4">
22
+ <p className="mb-3 text-xs font-medium uppercase tracking-[0.15em] text-muted-foreground">
23
+ Contents
24
+ </p>
25
+ <ol className="list-none space-y-1.5 text-sm text-muted-foreground">
26
+ <li>
27
+ <a href="#section-1" className="underline underline-offset-4 hover:text-foreground">
28
+ 1. Acceptance of Terms
29
+ </a>
30
+ </li>
31
+ <li>
32
+ <a href="#section-2" className="underline underline-offset-4 hover:text-foreground">
33
+ 2. Description of Service
34
+ </a>
35
+ </li>
36
+ <li>
37
+ <a href="#section-3" className="underline underline-offset-4 hover:text-foreground">
38
+ 3. Account Terms
39
+ </a>
40
+ </li>
41
+ <li>
42
+ <a href="#section-4" className="underline underline-offset-4 hover:text-foreground">
43
+ 4. Payment, Refunds, and Plan Changes
44
+ </a>
45
+ </li>
46
+ <li>
47
+ <a href="#section-5" className="underline underline-offset-4 hover:text-foreground">
48
+ 5. Cancellation and Termination
49
+ </a>
50
+ </li>
51
+ <li>
52
+ <a href="#section-6" className="underline underline-offset-4 hover:text-foreground">
53
+ 6. Modifications to the Service
54
+ </a>
55
+ </li>
56
+ <li>
57
+ <a href="#section-7" className="underline underline-offset-4 hover:text-foreground">
58
+ 7. Uptime, Security, and Privacy
59
+ </a>
60
+ </li>
61
+ <li>
62
+ <a href="#section-8" className="underline underline-offset-4 hover:text-foreground">
63
+ 8. Copyright and Content Ownership
64
+ </a>
65
+ </li>
66
+ <li>
67
+ <a href="#section-9" className="underline underline-offset-4 hover:text-foreground">
68
+ 9. API Keys and Third-Party Services
69
+ </a>
70
+ </li>
71
+ <li>
72
+ <a href="#section-10" className="underline underline-offset-4 hover:text-foreground">
73
+ 10. Acceptable Use
74
+ </a>
75
+ </li>
76
+ <li>
77
+ <a href="#section-11" className="underline underline-offset-4 hover:text-foreground">
78
+ 11. Liability
79
+ </a>
80
+ </li>
81
+ <li>
82
+ <a href="#section-12" className="underline underline-offset-4 hover:text-foreground">
83
+ 12. Indemnification
84
+ </a>
85
+ </li>
86
+ <li>
87
+ <a href="#section-13" className="underline underline-offset-4 hover:text-foreground">
88
+ 13. Governing Law
89
+ </a>
90
+ </li>
91
+ <li>
92
+ <a href="#section-14" className="underline underline-offset-4 hover:text-foreground">
93
+ 14. Severability
94
+ </a>
95
+ </li>
96
+ <li>
97
+ <a href="#section-15" className="underline underline-offset-4 hover:text-foreground">
98
+ 15. Changes to Terms
99
+ </a>
100
+ </li>
101
+ <li>
102
+ <a href="#section-16" className="underline underline-offset-4 hover:text-foreground">
103
+ 16. Contact
104
+ </a>
105
+ </li>
106
+ </ol>
107
+ </nav>
108
+
109
+ <div className="mt-8 space-y-8 text-sm leading-relaxed text-muted-foreground">
110
+ <section id="section-1" className="scroll-mt-16">
111
+ <h2 className="mb-2 text-base font-semibold text-foreground">1. Acceptance of Terms</h2>
112
+ <p>
113
+ By creating an account or using {brand.productName} at {brand.domain}, you agree to be
114
+ bound by these Terms of Service and our{" "}
115
+ <Link href="/privacy" className="text-foreground underline underline-offset-4">
116
+ Privacy Policy
117
+ </Link>
118
+ . If you do not agree to these terms, do not use the service.
119
+ </p>
120
+ </section>
121
+
122
+ <section id="section-2" className="scroll-mt-16">
123
+ <h2 className="mb-2 text-base font-semibold text-foreground">
124
+ 2. Description of Service
125
+ </h2>
126
+ <p>
127
+ {brand.productName} provides AI bot orchestration services. You bring your own API
128
+ keys for AI providers (the &ldquo;bring your own key&rdquo; model).{" "}
129
+ {brand.productName} manages orchestration, memory, plugins, and channel integrations.
130
+ The service is available at
131
+ {brand.domain}.
132
+ </p>
133
+ <p className="mt-2">
134
+ {brand.productName} does not provide AI models directly. We orchestrate your
135
+ interactions with your chosen AI providers using your API keys. Additionally, we offer
136
+ optional hosted capabilities (such as voice synthesis and image generation) that
137
+ consume credits on a per-use basis.
138
+ </p>
139
+ </section>
140
+
141
+ <section id="section-3" className="scroll-mt-16">
142
+ <h2 className="mb-2 text-base font-semibold text-foreground">3. Account Terms</h2>
143
+ <ul className="ml-4 mt-2 list-disc space-y-1">
144
+ <li>You must be at least 13 years of age to use this service.</li>
145
+ <li>
146
+ You must provide accurate and complete information when creating your account.
147
+ </li>
148
+ <li>
149
+ You are responsible for maintaining the security of your account and password.{" "}
150
+ {brand.productName} will not be liable for any loss or damage from your failure to
151
+ maintain account security.
152
+ </li>
153
+ <li>
154
+ You are responsible for all activity that occurs under your account, including
155
+ actions taken by bots you configure.
156
+ </li>
157
+ <li>
158
+ One person per account. Accounts are not to be shared between multiple individuals.
159
+ </li>
160
+ <li>
161
+ Accounts must be registered by a human. Automated account creation is not permitted.
162
+ </li>
163
+ </ul>
164
+ </section>
165
+
166
+ <section id="section-4" className="scroll-mt-16">
167
+ <h2 className="mb-2 text-base font-semibold text-foreground">
168
+ 4. Payment, Refunds, and Plan Changes
169
+ </h2>
170
+ <p>
171
+ Paid plans are billed monthly via Stripe. AI provider costs are billed separately by
172
+ your chosen provider and are not included in {brand.productName} charges.
173
+ </p>
174
+ <ul className="ml-4 mt-2 list-disc space-y-1">
175
+ <li>
176
+ Hosted capability credits are consumed on a per-use basis and are non-refundable
177
+ once consumed.
178
+ </li>
179
+ <li>
180
+ Upgrades and downgrades take effect immediately. When upgrading, you will be charged
181
+ a prorated amount for the remainder of the billing period.
182
+ </li>
183
+ <li>
184
+ Upon cancellation, you retain access through the end of your current billing period.
185
+ No prorated refunds are issued for partial months.
186
+ </li>
187
+ <li>
188
+ We reserve the right to change pricing with 30 days&apos; advance notice. Price
189
+ changes do not apply retroactively.
190
+ </li>
191
+ </ul>
192
+ </section>
193
+
194
+ <section id="section-5" className="scroll-mt-16">
195
+ <h2 className="mb-2 text-base font-semibold text-foreground">
196
+ 5. Cancellation and Termination
197
+ </h2>
198
+ <p>
199
+ You may cancel your account at any time from your account settings. Upon cancellation:
200
+ </p>
201
+ <ul className="ml-4 mt-2 list-disc space-y-1">
202
+ <li>Your account data will be retained for 30 days, then permanently deleted.</li>
203
+ <li>
204
+ You may request immediate deletion by contacting{" "}
205
+ <a
206
+ href={`mailto:${brand.emails.legal}`}
207
+ className="text-foreground underline underline-offset-4"
208
+ >
209
+ {brand.emails.legal}
210
+ </a>
211
+ .
212
+ </li>
213
+ <li>
214
+ Deleted data cannot be recovered. Export your data before canceling if you need it.
215
+ </li>
216
+ </ul>
217
+ <p className="mt-2">
218
+ We may suspend or terminate your account for violations of these terms. Where
219
+ possible, we will provide notice before suspension. For serious violations (abuse,
220
+ fraud, illegal activity), we reserve the right to terminate immediately without
221
+ notice.
222
+ </p>
223
+ </section>
224
+
225
+ <section id="section-6" className="scroll-mt-16">
226
+ <h2 className="mb-2 text-base font-semibold text-foreground">
227
+ 6. Modifications to the Service
228
+ </h2>
229
+ <p>
230
+ We reserve the right to modify, suspend, or discontinue any part of the service at any
231
+ time. For material changes that significantly affect your use of the service, we will
232
+ provide 30 days&apos; advance notice via email or through the platform. We will not be
233
+ liable to you or any third party for any modification, suspension, or discontinuation.
234
+ </p>
235
+ </section>
236
+
237
+ <section id="section-7" className="scroll-mt-16">
238
+ <h2 className="mb-2 text-base font-semibold text-foreground">
239
+ 7. Uptime, Security, and Privacy
240
+ </h2>
241
+ <p>
242
+ We make best-effort commitments to maintain service availability but do not guarantee
243
+ specific uptime percentages for free or standard-tier plans. Our handling of your
244
+ personal data is governed by our{" "}
245
+ <Link href="/privacy" className="text-foreground underline underline-offset-4">
246
+ Privacy Policy
247
+ </Link>
248
+ . We take security seriously and implement reasonable safeguards, but no service can
249
+ guarantee absolute security.
250
+ </p>
251
+ </section>
252
+
253
+ <section id="section-8" className="scroll-mt-16">
254
+ <h2 className="mb-2 text-base font-semibold text-foreground">
255
+ 8. Copyright and Content Ownership
256
+ </h2>
257
+ <ul className="ml-4 mt-2 list-disc space-y-1">
258
+ <li>
259
+ You retain ownership of your content, including bot configurations, prompts, and
260
+ data you provide to the service.
261
+ </li>
262
+ <li>
263
+ You grant {brand.productName} a limited, non-exclusive license to process your
264
+ content solely for the purpose of providing the service.
265
+ </li>
266
+ <li>
267
+ {brand.companyLegalName} retains ownership of the platform, its code, documentation,
268
+ and all related intellectual property.
269
+ </li>
270
+ <li>
271
+ AI-generated outputs belong to you, subject to the terms of service of your chosen
272
+ AI provider. {brand.productName} makes no claims to AI-generated content.
273
+ </li>
274
+ </ul>
275
+ </section>
276
+
277
+ <section id="section-9" className="scroll-mt-16">
278
+ <h2 className="mb-2 text-base font-semibold text-foreground">
279
+ 9. API Keys and Third-Party Services
280
+ </h2>
281
+ <ul className="ml-4 mt-2 list-disc space-y-1">
282
+ <li>
283
+ You are solely responsible for your API keys and all usage charges incurred through
284
+ them.
285
+ </li>
286
+ <li>
287
+ {brand.productName} is not liable for charges from your AI providers, including
288
+ charges resulting from bot activity you have configured.
289
+ </li>
290
+ <li>
291
+ You must comply with the terms of service of any AI provider whose API keys you use
292
+ with {brand.productName}.
293
+ </li>
294
+ <li>
295
+ If an AI provider revokes or restricts your API key, the corresponding functionality
296
+ in {brand.productName} will be unavailable. This is not a service failure on our
297
+ part.
298
+ </li>
299
+ </ul>
300
+ </section>
301
+
302
+ <section id="section-10" className="scroll-mt-16">
303
+ <h2 className="mb-2 text-base font-semibold text-foreground">10. Acceptable Use</h2>
304
+ <p>You agree not to use {brand.productName} to:</p>
305
+ <ul className="ml-4 mt-2 list-disc space-y-1">
306
+ <li>Engage in any illegal activity or violate applicable laws and regulations</li>
307
+ <li>
308
+ Generate, distribute, or facilitate harassment, abuse, threats, or harmful content
309
+ </li>
310
+ <li>
311
+ Attempt to disrupt the service, degrade performance for other users, or compromise
312
+ system integrity
313
+ </li>
314
+ <li>
315
+ Reverse engineer, decompile, or attempt to extract the source code of the platform
316
+ </li>
317
+ <li>Circumvent rate limits, usage restrictions, or other technical safeguards</li>
318
+ <li>Impersonate other individuals or entities through your bots</li>
319
+ </ul>
320
+ <p className="mt-2">
321
+ We reserve the right to remove content and suspend or terminate accounts that violate
322
+ this policy. Repeated or serious violations may result in permanent bans.
323
+ </p>
324
+ </section>
325
+
326
+ <section id="section-11" className="scroll-mt-16">
327
+ <h2 className="mb-2 text-base font-semibold text-foreground">11. Liability</h2>
328
+ <p>
329
+ The service is provided &ldquo;as is&rdquo; and &ldquo;as available&rdquo; without
330
+ warranties of any kind, whether express or implied, including but not limited to
331
+ implied warranties of merchantability, fitness for a particular purpose, and
332
+ non-infringement.
333
+ </p>
334
+ <p className="mt-2">
335
+ To the maximum extent permitted by law, {brand.companyLegalName} shall not be liable
336
+ for any indirect, incidental, special, consequential, or punitive damages, or any loss
337
+ of profits or revenues, whether incurred directly or indirectly, arising from your use
338
+ of the service.
339
+ </p>
340
+ <p className="mt-2">
341
+ Our total liability for any claim arising from or related to these terms or the
342
+ service shall not exceed the amount you paid to {brand.productName} in the 12 months
343
+ preceding the claim. We are not liable for actions taken by AI providers or for
344
+ AI-generated content.
345
+ </p>
346
+ </section>
347
+
348
+ <section id="section-12" className="scroll-mt-16">
349
+ <h2 className="mb-2 text-base font-semibold text-foreground">12. Indemnification</h2>
350
+ <p>
351
+ You agree to indemnify, defend, and hold harmless {brand.companyLegalName}, its
352
+ officers, directors, employees, and agents from and against any claims, liabilities,
353
+ damages, losses, and expenses (including reasonable attorneys&apos; fees) arising out
354
+ of or in any way connected with your use of the service, your content, or your
355
+ violation of these terms.
356
+ </p>
357
+ </section>
358
+
359
+ <section id="section-13" className="scroll-mt-16">
360
+ <h2 className="mb-2 text-base font-semibold text-foreground">13. Governing Law</h2>
361
+ <p>
362
+ These terms shall be governed by and construed in accordance with the laws of the
363
+ State of Delaware, United States, without regard to its conflict of law provisions.
364
+ Any disputes arising under these terms shall be resolved in the state or federal
365
+ courts located in Delaware.
366
+ </p>
367
+ </section>
368
+
369
+ <section id="section-14" className="scroll-mt-16">
370
+ <h2 className="mb-2 text-base font-semibold text-foreground">14. Severability</h2>
371
+ <p>
372
+ If any provision of these terms is found to be unenforceable or invalid by a court of
373
+ competent jurisdiction, that provision will be limited or eliminated to the minimum
374
+ extent necessary so that these terms shall otherwise remain in full force and effect.
375
+ </p>
376
+ </section>
377
+
378
+ <section id="section-15" className="scroll-mt-16">
379
+ <h2 className="mb-2 text-base font-semibold text-foreground">15. Changes to Terms</h2>
380
+ <p>
381
+ We may update these Terms of Service from time to time. If we make material changes,
382
+ we will notify you at least 30 days in advance via email or through a prominent notice
383
+ on the service. Your continued use of {brand.productName} after the updated terms take
384
+ effect constitutes acceptance of the new terms.
385
+ </p>
386
+ </section>
387
+
388
+ <section id="section-16" className="scroll-mt-16">
389
+ <h2 className="mb-2 text-base font-semibold text-foreground">16. Contact</h2>
390
+ <p>
391
+ Questions about these terms? Email us at{" "}
392
+ <a
393
+ href={`mailto:${brand.emails.legal}`}
394
+ className="text-foreground underline underline-offset-4"
395
+ >
396
+ {brand.emails.legal}
397
+ </a>
398
+ .
399
+ </p>
400
+ </section>
401
+ </div>
402
+
403
+ <div className="mt-12 flex flex-wrap gap-4 text-sm text-muted-foreground">
404
+ <Link href="/privacy" className="underline underline-offset-4 hover:text-foreground">
405
+ Privacy Policy
406
+ </Link>
407
+ <Link href="/" className="underline underline-offset-4 hover:text-foreground">
408
+ Home
409
+ </Link>
410
+ </div>
411
+ </div>
412
+ </>
413
+ );
414
+ }
@@ -0,0 +1,82 @@
1
+ "use client";
2
+
3
+ import { BuildingIcon, CheckIcon, ChevronsUpDownIcon, UserIcon } from "lucide-react";
4
+ import Image from "next/image";
5
+ import {
6
+ DropdownMenu,
7
+ DropdownMenuContent,
8
+ DropdownMenuItem,
9
+ DropdownMenuLabel,
10
+ DropdownMenuSeparator,
11
+ DropdownMenuTrigger,
12
+ } from "@/components/ui/dropdown-menu";
13
+ import type { TenantOption } from "@/lib/tenant-context";
14
+ import { useTenant } from "@/lib/tenant-context";
15
+
16
+ function TenantAvatar({ tenant, size = 20 }: { tenant: TenantOption; size?: number }) {
17
+ if (tenant.image) {
18
+ return (
19
+ <Image
20
+ src={tenant.image}
21
+ alt={tenant.name}
22
+ width={size}
23
+ height={size}
24
+ className="rounded-full object-cover"
25
+ style={{ width: size, height: size }}
26
+ />
27
+ );
28
+ }
29
+ const Icon = tenant.type === "org" ? BuildingIcon : UserIcon;
30
+ return (
31
+ <span
32
+ className="flex items-center justify-center rounded-full bg-sidebar-accent"
33
+ style={{ width: size, height: size }}
34
+ >
35
+ <Icon className="size-3 text-muted-foreground" />
36
+ </span>
37
+ );
38
+ }
39
+
40
+ export function AccountSwitcher() {
41
+ const { activeTenantId, tenants, isLoading, switchTenant } = useTenant();
42
+
43
+ if (isLoading || tenants.length <= 1) return null;
44
+
45
+ const activeTenant = tenants.find((t) => t.id === activeTenantId) ?? tenants[0];
46
+
47
+ return (
48
+ <div className="border-b border-sidebar-border px-3 py-1">
49
+ <DropdownMenu>
50
+ <DropdownMenuTrigger className="flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground outline-none focus-visible:ring-1 focus-visible:ring-sidebar-ring">
51
+ <TenantAvatar tenant={activeTenant} />
52
+ <span className="flex-1 truncate text-left text-sidebar-foreground">
53
+ {activeTenant.name}
54
+ </span>
55
+ <span className="text-[10px] font-medium uppercase tracking-widest text-terminal-dim/60">
56
+ {activeTenant.type === "org" ? "ORG" : "PERSONAL"}
57
+ </span>
58
+ <ChevronsUpDownIcon className="size-4 shrink-0 text-muted-foreground" />
59
+ </DropdownMenuTrigger>
60
+ <DropdownMenuContent align="start" className="w-[var(--radix-dropdown-menu-trigger-width)]">
61
+ <DropdownMenuLabel className="text-xs font-normal uppercase tracking-wider text-muted-foreground">
62
+ Switch account
63
+ </DropdownMenuLabel>
64
+ <DropdownMenuSeparator />
65
+ {tenants.map((tenant) => (
66
+ <DropdownMenuItem
67
+ key={tenant.id}
68
+ onClick={() => switchTenant(tenant.id)}
69
+ className="flex items-center gap-2"
70
+ >
71
+ <TenantAvatar tenant={tenant} />
72
+ <span className="flex-1 truncate text-sm">{tenant.name}</span>
73
+ {tenant.id === activeTenantId && (
74
+ <CheckIcon className="size-4 shrink-0 text-terminal" />
75
+ )}
76
+ </DropdownMenuItem>
77
+ ))}
78
+ </DropdownMenuContent>
79
+ </DropdownMenu>
80
+ </div>
81
+ );
82
+ }
@@ -0,0 +1,190 @@
1
+ "use client";
2
+
3
+ import { useCallback, useEffect, useState } from "react";
4
+ import { Button } from "@/components/ui/button";
5
+ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
6
+ import { Skeleton } from "@/components/ui/skeleton";
7
+ import { type AdminUserSummary, getUsersList } from "@/lib/admin-api";
8
+ import { formatCreditStandard } from "@/lib/format-credit";
9
+ import { cn } from "@/lib/utils";
10
+
11
+ interface AccountingSummary {
12
+ totalUsers: number;
13
+ activeUsers: number;
14
+ suspendedUsers: number;
15
+ bannedUsers: number;
16
+ trialUsers: number;
17
+ totalCreditBalanceCents: number;
18
+ totalAgents: number;
19
+ users: AdminUserSummary[];
20
+ capped: boolean;
21
+ }
22
+
23
+ function MetricCard({
24
+ label,
25
+ value,
26
+ sub,
27
+ className,
28
+ }: {
29
+ label: string;
30
+ value: string;
31
+ sub?: string;
32
+ className?: string;
33
+ }) {
34
+ return (
35
+ <Card className={className}>
36
+ <CardHeader className="pb-2">
37
+ <CardTitle className="text-xs text-muted-foreground font-normal uppercase tracking-wider">
38
+ {label}
39
+ </CardTitle>
40
+ </CardHeader>
41
+ <CardContent>
42
+ <div className="text-2xl font-bold font-mono">{value}</div>
43
+ {sub && <div className="text-xs text-muted-foreground mt-1">{sub}</div>}
44
+ </CardContent>
45
+ </Card>
46
+ );
47
+ }
48
+
49
+ export function AccountingDashboard() {
50
+ const [summary, setSummary] = useState<AccountingSummary | null>(null);
51
+ const [loading, setLoading] = useState(true);
52
+ const [error, setError] = useState(false);
53
+
54
+ const load = useCallback(async () => {
55
+ setLoading(true);
56
+ setError(false);
57
+ try {
58
+ const result = await getUsersList({ limit: 250 });
59
+ const users = result.users;
60
+ const capped = result.total > 250;
61
+ setSummary({
62
+ totalUsers: result.total,
63
+ activeUsers: users.filter((u) => u.status === "active").length,
64
+ suspendedUsers: users.filter((u) => u.status === "suspended").length,
65
+ bannedUsers: users.filter((u) => u.status === "banned").length,
66
+ trialUsers: users.filter((u) => u.status === "trial").length,
67
+ totalCreditBalanceCents: users.reduce((sum, u) => sum + u.credit_balance_cents, 0),
68
+ totalAgents: users.reduce((sum, u) => sum + u.agent_count, 0),
69
+ users,
70
+ capped,
71
+ });
72
+ } catch {
73
+ setError(true);
74
+ } finally {
75
+ setLoading(false);
76
+ }
77
+ }, []);
78
+
79
+ useEffect(() => {
80
+ load();
81
+ }, [load]);
82
+
83
+ if (error) {
84
+ return (
85
+ <div className="flex h-40 flex-col items-center justify-center gap-3">
86
+ <p className="text-sm text-destructive font-mono">Failed to load accounting data.</p>
87
+ <Button variant="outline" size="sm" onClick={load}>
88
+ Retry
89
+ </Button>
90
+ </div>
91
+ );
92
+ }
93
+
94
+ return (
95
+ <div className="space-y-6 p-6">
96
+ <h1 className="text-xl font-bold uppercase tracking-wider text-terminal [text-shadow:0_0_10px_rgba(0,255,65,0.25)]">
97
+ PLATFORM ACCOUNTING
98
+ </h1>
99
+
100
+ {loading ? (
101
+ <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
102
+ {["users", "credits", "agents", "status"].map((k) => (
103
+ <Skeleton key={k} className="h-24" />
104
+ ))}
105
+ </div>
106
+ ) : summary ? (
107
+ <>
108
+ <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
109
+ <MetricCard
110
+ label="Total Users"
111
+ value={String(summary.totalUsers)}
112
+ sub={`${summary.activeUsers} active, ${summary.suspendedUsers} suspended`}
113
+ />
114
+ <MetricCard
115
+ label="Outstanding Credits"
116
+ value={formatCreditStandard(summary.totalCreditBalanceCents / 100)}
117
+ sub={summary.capped ? "top 250 users only" : "total platform liability"}
118
+ />
119
+ <MetricCard
120
+ label="Total Agents"
121
+ value={String(summary.totalAgents)}
122
+ sub={summary.capped ? "top 250 users only" : "across all tenants"}
123
+ />
124
+ <MetricCard
125
+ label="Status Breakdown"
126
+ value={`${summary.activeUsers} active`}
127
+ sub={[
128
+ summary.suspendedUsers > 0 ? `${summary.suspendedUsers} suspended` : null,
129
+ summary.bannedUsers > 0 ? `${summary.bannedUsers} banned` : null,
130
+ summary.trialUsers > 0 ? `${summary.trialUsers} trial` : null,
131
+ summary.capped ? "(top 250 only)" : null,
132
+ ]
133
+ .filter(Boolean)
134
+ .join(", ")}
135
+ />
136
+ </div>
137
+
138
+ <Card>
139
+ <CardHeader>
140
+ <CardTitle className="text-sm uppercase tracking-wider">
141
+ Top Credit Balances{summary.capped ? " (top 250 users)" : ""}
142
+ </CardTitle>
143
+ </CardHeader>
144
+ <CardContent>
145
+ <div className="space-y-0">
146
+ {[...summary.users]
147
+ .sort((a, b) => b.credit_balance_cents - a.credit_balance_cents)
148
+ .slice(0, 10)
149
+ .map((user) => (
150
+ <div
151
+ key={user.id}
152
+ className="flex justify-between items-center text-sm py-2 border-b border-border/50 last:border-0"
153
+ >
154
+ <div className="flex items-center gap-2">
155
+ <span className="font-mono text-xs">{user.email}</span>
156
+ <span
157
+ className={cn(
158
+ "inline-flex items-center rounded-sm px-1.5 py-0.5 text-[10px] font-medium",
159
+ user.status === "active"
160
+ ? "bg-terminal/15 text-terminal border border-terminal/20"
161
+ : user.status === "suspended"
162
+ ? "bg-destructive/15 text-red-400 border border-destructive/20"
163
+ : "bg-secondary text-muted-foreground border border-border",
164
+ )}
165
+ >
166
+ {user.status}
167
+ </span>
168
+ </div>
169
+ <span
170
+ className={cn(
171
+ "font-mono text-sm",
172
+ user.credit_balance_cents === 0
173
+ ? "text-red-500"
174
+ : user.credit_balance_cents < 200
175
+ ? "text-amber-500"
176
+ : "text-terminal",
177
+ )}
178
+ >
179
+ {formatCreditStandard(user.credit_balance_cents / 100)}
180
+ </span>
181
+ </div>
182
+ ))}
183
+ </div>
184
+ </CardContent>
185
+ </Card>
186
+ </>
187
+ ) : null}
188
+ </div>
189
+ );
190
+ }