@cryptiklemur/lattice 4.0.1 → 5.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 (394) hide show
  1. package/bin/lattice +1 -9
  2. package/dist/client/assets/{angular-html-N8PCEquT.js → angular-html-DKTL-XDO.js} +1 -1
  3. package/dist/client/assets/{angular-ts-CJ8RJIPD.js → angular-ts-tvBzOwQR.js} +1 -1
  4. package/dist/client/assets/{apl-BD6tCLWN.js → apl-CCzl5qFl.js} +1 -1
  5. package/dist/client/assets/{astro-CpIIfBs6.js → astro-DNQTpO2Y.js} +1 -1
  6. package/dist/client/assets/{blade-D3qgnjiV.js → blade-CyJoIMeJ.js} +1 -1
  7. package/dist/client/assets/{c-Dr6ADN_t.js → c-OEwk5KN8.js} +1 -1
  8. package/dist/client/assets/{cobol-BIfDE0Hr.js → cobol-DpHyJzz2.js} +1 -1
  9. package/dist/client/assets/{coffee-DHQ57vfY.js → coffee-BX5dbDzZ.js} +1 -1
  10. package/dist/client/assets/{cpp-CEBY6JOp.js → cpp-BTBjNg2U.js} +1 -1
  11. package/dist/client/assets/{crystal-D125CSmP.js → crystal-CNzZd6DW.js} +1 -1
  12. package/dist/client/assets/{css-CBmrkYSr.js → css-BuKsNmms.js} +1 -1
  13. package/dist/client/assets/{dist-A_mCRD1f.js → dist-CKpDHMy6.js} +2 -2
  14. package/dist/client/assets/{edge-Ccsz7cJW.js → edge-DzhnGgJE.js} +1 -1
  15. package/dist/client/assets/{elixir-Do6gk14X.js → elixir-Dqs0waqF.js} +1 -1
  16. package/dist/client/assets/{elm-Db22zT4C.js → elm-BtWwjxWn.js} +1 -1
  17. package/dist/client/assets/{erb-MXVqAAJD.js → erb-iPD89b4v.js} +1 -1
  18. package/dist/client/assets/{git-rebase-B-LLWBOA.js → git-rebase-BxVNXJL4.js} +1 -1
  19. package/dist/client/assets/{glimmer-js-eWszRU73.js → glimmer-js-BlyCupwF.js} +1 -1
  20. package/dist/client/assets/{glimmer-ts-VQmwGqUp.js → glimmer-ts-DjIxWOS9.js} +1 -1
  21. package/dist/client/assets/{glsl-B8ilOfAl.js → glsl-CGIL-65r.js} +1 -1
  22. package/dist/client/assets/{graphql-DnTqxeOc.js → graphql-DeOn6mNV.js} +1 -1
  23. package/dist/client/assets/{hack-XJsHYSQb.js → hack-DVppeCmS.js} +1 -1
  24. package/dist/client/assets/{haml-CQ7Vqzwp.js → haml-WDhua0Mp.js} +1 -1
  25. package/dist/client/assets/{handlebars-C4szooBf.js → handlebars-i2Fu_9HI.js} +1 -1
  26. package/dist/client/assets/{html-B6EgAiSd.js → html-B1e6oxzK.js} +1 -1
  27. package/dist/client/assets/{html-derivative-DdinogQX.js → html-derivative-MofKXIVd.js} +1 -1
  28. package/dist/client/assets/{http-BSLxCgRq.js → http-Dk6S5pRD.js} +1 -1
  29. package/dist/client/assets/{hurl-pOsTwNfp.js → hurl-CroFYYJG.js} +1 -1
  30. package/dist/client/assets/{index-BHQ_8mvl.js → index-CVu-S6Yk.js} +2 -2
  31. package/dist/client/assets/{java-DRQLiiST.js → java-B89FYjqS.js} +1 -1
  32. package/dist/client/assets/{javascript-DvEK2-47.js → javascript-m6CO1Uiy.js} +1 -1
  33. package/dist/client/assets/{jinja-D2NYJ25y.js → jinja-DC9Wi41X.js} +1 -1
  34. package/dist/client/assets/{jison-DDZaLNAp.js → jison-6xiegwDk.js} +1 -1
  35. package/dist/client/assets/{json-TGR0NIWd.js → json-HA-96-qr.js} +1 -1
  36. package/dist/client/assets/{jsx-BjUoPYga.js → jsx-Wt1a8i8U.js} +1 -1
  37. package/dist/client/assets/{julia-C4gjSpFu.js → julia-7M93VBON.js} +1 -1
  38. package/dist/client/assets/{just-H351x5u_.js → just-CjfDLYLv.js} +1 -1
  39. package/dist/client/assets/{latex-BiTmf6gf.js → latex-CitsJ46x.js} +1 -1
  40. package/dist/client/assets/{liquid-86ufjRy-.js → liquid-C8VIFin8.js} +1 -1
  41. package/dist/client/assets/{lua-BNxR0F_8.js → lua-Ba2N7esc.js} +1 -1
  42. package/dist/client/assets/{marko-CvRxpRjM.js → marko-lTLvb2wu.js} +1 -1
  43. package/dist/client/assets/{mdc-CYbAIy2C.js → mdc-D6IV-8FD.js} +1 -1
  44. package/dist/client/assets/{nginx-egdgMq-F.js → nginx-Ch5AjE6S.js} +1 -1
  45. package/dist/client/assets/{nim-CXBJVz_w.js → nim-WmDDC6LW.js} +1 -1
  46. package/dist/client/assets/{perl-XRfMobzg.js → perl-CQv0gYuq.js} +1 -1
  47. package/dist/client/assets/{php-Br7a8uil.js → php-BJmH0qOB.js} +1 -1
  48. package/dist/client/assets/{pug-BVbbUVvy.js → pug-CsHPkzc9.js} +1 -1
  49. package/dist/client/assets/{qml-ByKvrL1j.js → qml-B36ecArG.js} +1 -1
  50. package/dist/client/assets/{r-mVoV0Ni6.js → r-D5Yi5Z4y.js} +1 -1
  51. package/dist/client/assets/{razor-T5O-9UJL.js → razor-CHAxVq4R.js} +1 -1
  52. package/dist/client/assets/{regexp-CioRuhuN.js → regexp-gfs--3M7.js} +1 -1
  53. package/dist/client/assets/{rst-V__uTudD.js → rst-ugdlp-hl.js} +1 -1
  54. package/dist/client/assets/{ruby-C_PuKPTI.js → ruby-CDRRW37j.js} +1 -1
  55. package/dist/client/assets/{sas-D_DqqQH4.js → sas-DZaNQaIP.js} +1 -1
  56. package/dist/client/assets/{scss-D-TjzZ4c.js → scss-CzWQEplj.js} +1 -1
  57. package/dist/client/assets/{shellscript-E5759VHu.js → shellscript-fgYvpu9N.js} +1 -1
  58. package/dist/client/assets/{shellsession-AESTM-Pv.js → shellsession-BoAohHh7.js} +1 -1
  59. package/dist/client/assets/{soy-QrbrrcDv.js → soy-DBzVgv9x.js} +1 -1
  60. package/dist/client/assets/{sql-0M8VcDHD.js → sql-BYXpAYTs.js} +1 -1
  61. package/dist/client/assets/{stata-CgeIpGtc.js → stata-I71MMY3p.js} +1 -1
  62. package/dist/client/assets/{surrealql-DBGwnZbw.js → surrealql-C9U8_1VO.js} +1 -1
  63. package/dist/client/assets/{svelte-Cv0PvUc_.js → svelte-VOFrPnWT.js} +1 -1
  64. package/dist/client/assets/{templ-B9t7xRE4.js → templ-BIaxAEtC.js} +1 -1
  65. package/dist/client/assets/{tex-DhZZ8dr2.js → tex-D1dwnBE5.js} +1 -1
  66. package/dist/client/assets/{ts-tags-BFv8sbnd.js → ts-tags-C0L2Q0r5.js} +1 -1
  67. package/dist/client/assets/{tsx-CXC9KSbY.js → tsx-BqcycEv1.js} +1 -1
  68. package/dist/client/assets/{twig-CM_OO66r.js → twig-vyWqOhpM.js} +1 -1
  69. package/dist/client/assets/{typescript-BdgOTaoD.js → typescript-B2YbovqG.js} +1 -1
  70. package/dist/client/assets/{vue-BnQhjnCm.js → vue-CbXxGdjo.js} +1 -1
  71. package/dist/client/assets/{vue-html-CNnGecRI.js → vue-html-DDX4KXW7.js} +1 -1
  72. package/dist/client/assets/{vue-vine-DCuMkRhK.js → vue-vine-DsyY1LR5.js} +1 -1
  73. package/dist/client/assets/{xml-CbTD7cB8.js → xml-Ddi0-r0D.js} +1 -1
  74. package/dist/client/assets/{xsl-uOqqo7cf.js → xsl-CsFcZHFS.js} +1 -1
  75. package/dist/client/assets/{yaml-BNrLoH59.js → yaml-tGJWoH6Y.js} +1 -1
  76. package/dist/client/index.html +1 -1
  77. package/dist/client/sw.js +1 -1
  78. package/dist/server/analytics/engine.js +832 -0
  79. package/dist/server/assets.js +39 -0
  80. package/dist/server/auth/passphrase.js +70 -0
  81. package/dist/server/config.js +47 -0
  82. package/dist/server/daemon.js +535 -0
  83. package/dist/server/features/ralph-loop.js +138 -0
  84. package/dist/server/features/scheduler.js +260 -0
  85. package/dist/server/features/sticky-notes.js +99 -0
  86. package/dist/server/handlers/analytics.js +28 -0
  87. package/dist/server/handlers/attachment.js +158 -0
  88. package/dist/server/handlers/bookmarks.js +41 -0
  89. package/dist/server/handlers/chat.js +350 -0
  90. package/dist/server/handlers/editor.js +72 -0
  91. package/dist/server/handlers/fs.js +234 -0
  92. package/dist/server/handlers/loop.js +33 -0
  93. package/dist/server/handlers/memory.js +181 -0
  94. package/dist/server/handlers/mesh.js +322 -0
  95. package/dist/server/handlers/notes.js +36 -0
  96. package/dist/server/handlers/plugins.js +593 -0
  97. package/dist/server/handlers/project-settings.js +166 -0
  98. package/dist/server/handlers/scheduler.js +52 -0
  99. package/dist/server/handlers/session.js +194 -0
  100. package/dist/server/handlers/settings.js +148 -0
  101. package/dist/server/handlers/skills.js +360 -0
  102. package/dist/server/handlers/terminal.js +75 -0
  103. package/dist/server/handlers/themes.js +102 -0
  104. package/dist/server/handlers/update.js +124 -0
  105. package/dist/server/identity.js +45 -0
  106. package/dist/server/index.js +435 -0
  107. package/dist/server/logger.js +20 -0
  108. package/dist/server/mesh/connector.js +355 -0
  109. package/dist/server/mesh/crypto.js +88 -0
  110. package/dist/server/mesh/discovery.js +95 -0
  111. package/dist/server/mesh/pairing.js +104 -0
  112. package/dist/server/mesh/peers.js +54 -0
  113. package/dist/server/mesh/proxy.js +86 -0
  114. package/dist/server/mesh/session-sync.js +85 -0
  115. package/dist/server/project/bookmarks.js +77 -0
  116. package/dist/server/project/context-breakdown.js +279 -0
  117. package/dist/server/project/file-browser.js +97 -0
  118. package/dist/server/project/project-files.js +274 -0
  119. package/dist/server/project/registry.js +51 -0
  120. package/dist/server/project/sdk-bridge.js +960 -0
  121. package/dist/server/project/session.js +696 -0
  122. package/dist/server/project/terminal.js +87 -0
  123. package/dist/server/project/warmup.js +242 -0
  124. package/dist/server/push.js +87 -0
  125. package/dist/server/tls.js +50 -0
  126. package/dist/server/tui.js +83 -0
  127. package/dist/server/update-checker.js +119 -0
  128. package/dist/server/ws/broadcast.js +50 -0
  129. package/dist/server/ws/router.js +105 -0
  130. package/dist/server/ws/server.js +2 -0
  131. package/dist/shared/analytics.js +1 -0
  132. package/dist/shared/messages.js +1 -0
  133. package/dist/shared/models.js +1 -0
  134. package/dist/shared/project-settings.js +1 -0
  135. package/package.json +5 -8
  136. package/themes/alabaster.json +9 -0
  137. package/themes/amoled.json +20 -0
  138. package/themes/ayu-light.json +9 -0
  139. package/themes/catppuccin-latte.json +9 -0
  140. package/themes/catppuccin-mocha.json +9 -0
  141. package/themes/clay-light.json +10 -0
  142. package/themes/clay.json +10 -0
  143. package/themes/dracula.json +9 -0
  144. package/themes/everforest-light.json +9 -0
  145. package/themes/everforest.json +9 -0
  146. package/themes/github-light.json +9 -0
  147. package/themes/gruvbox-dark.json +9 -0
  148. package/themes/gruvbox-light.json +9 -0
  149. package/themes/horizon-light.json +9 -0
  150. package/themes/kanagawa-lotus.json +9 -0
  151. package/themes/kanagawa.json +9 -0
  152. package/themes/modus-operandi.json +9 -0
  153. package/themes/monokai.json +9 -0
  154. package/themes/nightfox.json +9 -0
  155. package/themes/nord-light.json +9 -0
  156. package/themes/nord.json +9 -0
  157. package/themes/one-dark.json +9 -0
  158. package/themes/one-light.json +9 -0
  159. package/themes/palenight.json +9 -0
  160. package/themes/paper.json +9 -0
  161. package/themes/penumbra-light.json +9 -0
  162. package/themes/poimandres.json +9 -0
  163. package/themes/quiet-light.json +9 -0
  164. package/themes/rose-pine-dawn.json +9 -0
  165. package/themes/rose-pine.json +9 -0
  166. package/themes/solarized-dark.json +9 -0
  167. package/themes/solarized-light.json +9 -0
  168. package/themes/synthwave84.json +9 -0
  169. package/themes/tokyo-night-light.json +9 -0
  170. package/themes/tokyo-night.json +9 -0
  171. package/themes/vesper.json +9 -0
  172. package/index.html +0 -20
  173. package/public/icons/icon-192.svg +0 -11
  174. package/public/icons/icon-512.svg +0 -11
  175. package/public/sw-push.js +0 -53
  176. package/src/client/App.tsx +0 -42
  177. package/src/client/commands.ts +0 -36
  178. package/src/client/components/analytics/AnalyticsView.tsx +0 -244
  179. package/src/client/components/analytics/ChartCard.tsx +0 -194
  180. package/src/client/components/analytics/PeriodSelector.tsx +0 -42
  181. package/src/client/components/analytics/QuickStats.tsx +0 -122
  182. package/src/client/components/analytics/chartTokens.ts +0 -188
  183. package/src/client/components/analytics/charts/ActivityCalendar.tsx +0 -204
  184. package/src/client/components/analytics/charts/CacheEfficiencyChart.tsx +0 -56
  185. package/src/client/components/analytics/charts/ContextUtilizationChart.tsx +0 -106
  186. package/src/client/components/analytics/charts/CostAreaChart.tsx +0 -79
  187. package/src/client/components/analytics/charts/CostDistributionChart.tsx +0 -59
  188. package/src/client/components/analytics/charts/CostDonutChart.tsx +0 -84
  189. package/src/client/components/analytics/charts/CumulativeCostChart.tsx +0 -59
  190. package/src/client/components/analytics/charts/DailySummaryCards.tsx +0 -86
  191. package/src/client/components/analytics/charts/HourlyHeatmap.tsx +0 -133
  192. package/src/client/components/analytics/charts/NodeFleetOverview.tsx +0 -89
  193. package/src/client/components/analytics/charts/PermissionBreakdown.tsx +0 -98
  194. package/src/client/components/analytics/charts/ProjectRadar.tsx +0 -126
  195. package/src/client/components/analytics/charts/ResponseTimeScatter.tsx +0 -96
  196. package/src/client/components/analytics/charts/SessionBubbleChart.tsx +0 -114
  197. package/src/client/components/analytics/charts/SessionComplexityList.tsx +0 -65
  198. package/src/client/components/analytics/charts/SessionTimeline.tsx +0 -107
  199. package/src/client/components/analytics/charts/TokenFlowChart.tsx +0 -78
  200. package/src/client/components/analytics/charts/TokenSankeyChart.tsx +0 -93
  201. package/src/client/components/analytics/charts/ToolSunburst.tsx +0 -123
  202. package/src/client/components/analytics/charts/ToolTreemap.tsx +0 -110
  203. package/src/client/components/auth/PassphrasePrompt.tsx +0 -70
  204. package/src/client/components/chat/AttachmentChips.tsx +0 -116
  205. package/src/client/components/chat/ChatInput.tsx +0 -533
  206. package/src/client/components/chat/ChatView.tsx +0 -1076
  207. package/src/client/components/chat/CommandPalette.tsx +0 -162
  208. package/src/client/components/chat/ElicitationCard.tsx +0 -238
  209. package/src/client/components/chat/Message.tsx +0 -825
  210. package/src/client/components/chat/ModelSelector.tsx +0 -108
  211. package/src/client/components/chat/PermissionModeSelector.tsx +0 -41
  212. package/src/client/components/chat/PromptQuestion.tsx +0 -271
  213. package/src/client/components/chat/StatusBar.tsx +0 -50
  214. package/src/client/components/chat/TodoCard.tsx +0 -57
  215. package/src/client/components/chat/ToolGroup.tsx +0 -129
  216. package/src/client/components/chat/ToolResultRenderer.tsx +0 -348
  217. package/src/client/components/chat/VoiceRecorder.tsx +0 -85
  218. package/src/client/components/chat/toolSummary.ts +0 -41
  219. package/src/client/components/dashboard/DashboardView.tsx +0 -200
  220. package/src/client/components/dashboard/ProjectDashboardView.tsx +0 -179
  221. package/src/client/components/mesh/NodeBadge.tsx +0 -24
  222. package/src/client/components/mesh/PairingDialog.tsx +0 -340
  223. package/src/client/components/project-settings/ProjectClaude.tsx +0 -318
  224. package/src/client/components/project-settings/ProjectEnvironment.tsx +0 -235
  225. package/src/client/components/project-settings/ProjectGeneral.tsx +0 -76
  226. package/src/client/components/project-settings/ProjectMcp.tsx +0 -232
  227. package/src/client/components/project-settings/ProjectMemory.tsx +0 -488
  228. package/src/client/components/project-settings/ProjectNotifications.tsx +0 -48
  229. package/src/client/components/project-settings/ProjectPermissions.tsx +0 -209
  230. package/src/client/components/project-settings/ProjectPlugins.tsx +0 -117
  231. package/src/client/components/project-settings/ProjectRules.tsx +0 -286
  232. package/src/client/components/project-settings/ProjectSettingsView.tsx +0 -117
  233. package/src/client/components/project-settings/ProjectSkills.tsx +0 -91
  234. package/src/client/components/settings/Appearance.tsx +0 -275
  235. package/src/client/components/settings/BudgetSettings.tsx +0 -165
  236. package/src/client/components/settings/ClaudeSettings.tsx +0 -175
  237. package/src/client/components/settings/Editor.tsx +0 -123
  238. package/src/client/components/settings/Environment.tsx +0 -185
  239. package/src/client/components/settings/GlobalMcp.tsx +0 -216
  240. package/src/client/components/settings/GlobalMemory.tsx +0 -19
  241. package/src/client/components/settings/GlobalPlugins.tsx +0 -806
  242. package/src/client/components/settings/GlobalRules.tsx +0 -149
  243. package/src/client/components/settings/GlobalSkills.tsx +0 -140
  244. package/src/client/components/settings/MeshStatus.tsx +0 -183
  245. package/src/client/components/settings/Notifications.tsx +0 -123
  246. package/src/client/components/settings/SettingsView.tsx +0 -75
  247. package/src/client/components/settings/SkillMarketplace.tsx +0 -175
  248. package/src/client/components/settings/ThemePreview.tsx +0 -140
  249. package/src/client/components/settings/ThemeWizard.tsx +0 -405
  250. package/src/client/components/settings/mcp-shared.tsx +0 -194
  251. package/src/client/components/settings/skill-shared.tsx +0 -186
  252. package/src/client/components/setup/SetupWizard.tsx +0 -755
  253. package/src/client/components/sidebar/AddProjectModal.tsx +0 -438
  254. package/src/client/components/sidebar/NodeSettingsModal.tsx +0 -206
  255. package/src/client/components/sidebar/ProjectDropdown.tsx +0 -211
  256. package/src/client/components/sidebar/ProjectRail.tsx +0 -353
  257. package/src/client/components/sidebar/SearchFilter.tsx +0 -52
  258. package/src/client/components/sidebar/SessionList.tsx +0 -599
  259. package/src/client/components/sidebar/SettingsSidebar.tsx +0 -139
  260. package/src/client/components/sidebar/Sidebar.tsx +0 -469
  261. package/src/client/components/sidebar/UserIsland.tsx +0 -282
  262. package/src/client/components/sidebar/UserMenu.tsx +0 -107
  263. package/src/client/components/ui/CommandPalette.tsx +0 -321
  264. package/src/client/components/ui/ContextMenu.tsx +0 -153
  265. package/src/client/components/ui/ErrorBoundary.tsx +0 -56
  266. package/src/client/components/ui/IconPicker.tsx +0 -184
  267. package/src/client/components/ui/KeyboardShortcuts.tsx +0 -129
  268. package/src/client/components/ui/LatticeLogomark.tsx +0 -19
  269. package/src/client/components/ui/NodeDisconnectedOverlay.tsx +0 -35
  270. package/src/client/components/ui/PopupMenu.tsx +0 -120
  271. package/src/client/components/ui/SaveFooter.tsx +0 -63
  272. package/src/client/components/ui/Toast.tsx +0 -132
  273. package/src/client/components/ui/UpdateBanner.tsx +0 -110
  274. package/src/client/components/ui/UpdatePrompt.tsx +0 -47
  275. package/src/client/components/workspace/BookmarksView.tsx +0 -156
  276. package/src/client/components/workspace/FileBrowser.tsx +0 -174
  277. package/src/client/components/workspace/FileTree.tsx +0 -129
  278. package/src/client/components/workspace/FileViewer.tsx +0 -211
  279. package/src/client/components/workspace/NoteCard.tsx +0 -120
  280. package/src/client/components/workspace/NotesView.tsx +0 -102
  281. package/src/client/components/workspace/ScheduledTasksView.tsx +0 -117
  282. package/src/client/components/workspace/SplitPane.tsx +0 -81
  283. package/src/client/components/workspace/TabBar.tsx +0 -170
  284. package/src/client/components/workspace/TaskCard.tsx +0 -159
  285. package/src/client/components/workspace/TaskEditModal.tsx +0 -129
  286. package/src/client/components/workspace/TerminalInstance.tsx +0 -171
  287. package/src/client/components/workspace/TerminalView.tsx +0 -110
  288. package/src/client/components/workspace/WorkspaceView.tsx +0 -141
  289. package/src/client/hooks/useAnalytics.ts +0 -84
  290. package/src/client/hooks/useAttachments.ts +0 -313
  291. package/src/client/hooks/useBookmarks.ts +0 -57
  292. package/src/client/hooks/useEditorConfig.ts +0 -28
  293. package/src/client/hooks/useFocusTrap.ts +0 -74
  294. package/src/client/hooks/useIdleDetection.ts +0 -50
  295. package/src/client/hooks/useInstallPrompt.ts +0 -53
  296. package/src/client/hooks/useMesh.ts +0 -89
  297. package/src/client/hooks/useNotifications.ts +0 -54
  298. package/src/client/hooks/useOnline.ts +0 -6
  299. package/src/client/hooks/useProjectSettings.ts +0 -56
  300. package/src/client/hooks/useProjects.ts +0 -98
  301. package/src/client/hooks/usePushNotifications.ts +0 -92
  302. package/src/client/hooks/useSaveState.ts +0 -65
  303. package/src/client/hooks/useSession.ts +0 -580
  304. package/src/client/hooks/useSidebar.ts +0 -90
  305. package/src/client/hooks/useSkills.ts +0 -30
  306. package/src/client/hooks/useSpinnerVerb.ts +0 -36
  307. package/src/client/hooks/useSwipeDrawer.ts +0 -299
  308. package/src/client/hooks/useTheme.ts +0 -114
  309. package/src/client/hooks/useTimeTick.ts +0 -35
  310. package/src/client/hooks/useVoiceRecorder.ts +0 -169
  311. package/src/client/hooks/useWebSocket.ts +0 -27
  312. package/src/client/hooks/useWorkspace.ts +0 -57
  313. package/src/client/lib/theme-derive.ts +0 -196
  314. package/src/client/lib/workspace-url.ts +0 -219
  315. package/src/client/main.tsx +0 -10
  316. package/src/client/providers/WebSocketProvider.tsx +0 -186
  317. package/src/client/router.tsx +0 -578
  318. package/src/client/stores/analytics.ts +0 -68
  319. package/src/client/stores/bookmarks.ts +0 -45
  320. package/src/client/stores/mesh.ts +0 -78
  321. package/src/client/stores/session.ts +0 -569
  322. package/src/client/stores/sidebar.ts +0 -530
  323. package/src/client/stores/theme.ts +0 -44
  324. package/src/client/stores/workspace.ts +0 -518
  325. package/src/client/styles/global.css +0 -391
  326. package/src/client/styles/theme-vars.css +0 -18
  327. package/src/client/themes/index.ts +0 -105
  328. package/src/client/utils/editorUrl.ts +0 -55
  329. package/src/client/utils/findDuplicateKeys.ts +0 -12
  330. package/src/client/utils/formatSessionTitle.ts +0 -17
  331. package/src/client/vite-env.d.ts +0 -6
  332. package/src/server/analytics/engine.ts +0 -920
  333. package/src/server/assets.ts +0 -45
  334. package/src/server/auth/passphrase.ts +0 -78
  335. package/src/server/config.ts +0 -55
  336. package/src/server/daemon.ts +0 -567
  337. package/src/server/features/ralph-loop.ts +0 -173
  338. package/src/server/features/scheduler.ts +0 -304
  339. package/src/server/features/sticky-notes.ts +0 -104
  340. package/src/server/handlers/analytics.ts +0 -39
  341. package/src/server/handlers/attachment.ts +0 -189
  342. package/src/server/handlers/bookmarks.ts +0 -50
  343. package/src/server/handlers/chat.ts +0 -381
  344. package/src/server/handlers/editor.ts +0 -76
  345. package/src/server/handlers/fs.ts +0 -251
  346. package/src/server/handlers/loop.ts +0 -37
  347. package/src/server/handlers/memory.ts +0 -182
  348. package/src/server/handlers/mesh.ts +0 -362
  349. package/src/server/handlers/notes.ts +0 -47
  350. package/src/server/handlers/plugins.ts +0 -655
  351. package/src/server/handlers/project-settings.ts +0 -180
  352. package/src/server/handlers/scheduler.ts +0 -64
  353. package/src/server/handlers/session.ts +0 -226
  354. package/src/server/handlers/settings.ts +0 -157
  355. package/src/server/handlers/skills.ts +0 -378
  356. package/src/server/handlers/terminal.ts +0 -88
  357. package/src/server/handlers/themes.ts +0 -121
  358. package/src/server/handlers/update.ts +0 -133
  359. package/src/server/identity.ts +0 -56
  360. package/src/server/index.ts +0 -454
  361. package/src/server/logger.ts +0 -21
  362. package/src/server/mesh/connector.ts +0 -419
  363. package/src/server/mesh/crypto.ts +0 -106
  364. package/src/server/mesh/discovery.ts +0 -126
  365. package/src/server/mesh/pairing.ts +0 -123
  366. package/src/server/mesh/peers.ts +0 -60
  367. package/src/server/mesh/proxy.ts +0 -106
  368. package/src/server/mesh/session-sync.ts +0 -107
  369. package/src/server/project/bookmarks.ts +0 -83
  370. package/src/server/project/context-breakdown.ts +0 -307
  371. package/src/server/project/file-browser.ts +0 -106
  372. package/src/server/project/project-files.ts +0 -267
  373. package/src/server/project/pty-worker.cjs +0 -83
  374. package/src/server/project/registry.ts +0 -57
  375. package/src/server/project/sdk-bridge.ts +0 -1100
  376. package/src/server/project/session.ts +0 -723
  377. package/src/server/project/terminal.ts +0 -111
  378. package/src/server/project/warmup.ts +0 -285
  379. package/src/server/push.ts +0 -121
  380. package/src/server/tls.ts +0 -65
  381. package/src/server/tui.ts +0 -103
  382. package/src/server/update-checker.ts +0 -147
  383. package/src/server/ws/broadcast.ts +0 -61
  384. package/src/server/ws/router.ts +0 -123
  385. package/src/server/ws/server.ts +0 -2
  386. package/src/shared/analytics.ts +0 -40
  387. package/src/shared/messages.ts +0 -1302
  388. package/src/shared/models.ts +0 -255
  389. package/src/shared/project-settings.ts +0 -45
  390. package/tsconfig.json +0 -25
  391. package/vite.config.ts +0 -71
  392. /package/{src/server/runtime.ts → dist/server/runtime.js} +0 -0
  393. /package/{src/shared/constants.ts → dist/shared/constants.js} +0 -0
  394. /package/{src/shared/index.ts → dist/shared/index.js} +0 -0
@@ -1,179 +0,0 @@
1
- import { useState, useEffect } from "react";
2
- import { useSidebar } from "../../hooks/useSidebar";
3
- import { useProjectSettings } from "../../hooks/useProjectSettings";
4
- import { useProjects } from "../../hooks/useProjects";
5
- import { useWebSocket } from "../../hooks/useWebSocket";
6
- import {
7
- Menu, Settings, FileText, Terminal, Plug, ScrollText, Shield,
8
- MessageSquare, ChevronRight,
9
- } from "lucide-react";
10
- import type { ProjectSettingsSection } from "../../stores/sidebar";
11
- import type { SessionSummary, ServerMessage } from "#shared";
12
- import { openSessionTab } from "../../stores/workspace";
13
-
14
- function StatCard({ label, value, icon }: { label: string; value: string | number; icon: React.ReactNode }) {
15
- return (
16
- <div className="bg-base-300 rounded-xl border border-base-content/15 p-3 px-4">
17
- <div className="flex items-center gap-2 mb-1.5">
18
- {icon}
19
- <span className="text-[11px] font-semibold tracking-wider uppercase text-base-content/40">{label}</span>
20
- </div>
21
- <div className="text-xl font-mono font-bold text-base-content">{value}</div>
22
- </div>
23
- );
24
- }
25
-
26
- function QuickLink({ label, icon, onClick }: { label: string; icon: React.ReactNode; onClick: () => void }) {
27
- return (
28
- <button
29
- onClick={onClick}
30
- className="flex items-center gap-2.5 px-3 py-2 rounded-xl border border-base-content/15 bg-base-300 text-[12px] text-base-content/60 hover:text-base-content hover:border-base-content/30 transition-colors duration-[120ms] cursor-pointer focus-visible:ring-2 focus-visible:ring-primary"
31
- >
32
- {icon}
33
- <span className="flex-1 text-left">{label}</span>
34
- <ChevronRight size={12} className="text-base-content/30" />
35
- </button>
36
- );
37
- }
38
-
39
- export function ProjectDashboardView() {
40
- var sidebar = useSidebar();
41
-
42
- if (sidebar.activeView.type !== "project-dashboard") {
43
- return null;
44
- }
45
-
46
- var { settings, loading } = useProjectSettings(sidebar.activeProjectSlug);
47
- var { projects } = useProjects();
48
- var { send, subscribe, unsubscribe, status: wsStatus } = useWebSocket();
49
- var [sessions, setSessions] = useState<SessionSummary[]>([]);
50
-
51
- var activeProject = projects.find(function (p) { return p.slug === sidebar.activeProjectSlug; });
52
- var projectTitle = activeProject?.title ?? sidebar.activeProjectSlug ?? "Project";
53
-
54
- useEffect(function () {
55
- if (!sidebar.activeProjectSlug) return;
56
-
57
- function handleSessionList(msg: ServerMessage) {
58
- if (msg.type !== "session:list") return;
59
- var data = msg as { type: "session:list"; projectSlug: string; sessions: SessionSummary[] };
60
- if (data.projectSlug === sidebar.activeProjectSlug) {
61
- var sorted = data.sessions.slice().sort(function (a, b) { return b.updatedAt - a.updatedAt; });
62
- setSessions(sorted);
63
- }
64
- }
65
-
66
- subscribe("session:list", handleSessionList);
67
- if (wsStatus === "connected") {
68
- send({ type: "session:list_request", projectSlug: sidebar.activeProjectSlug });
69
- }
70
-
71
- return function () {
72
- unsubscribe("session:list", handleSessionList);
73
- };
74
- }, [sidebar.activeProjectSlug, wsStatus]);
75
-
76
- function goToSection(section: ProjectSettingsSection) {
77
- sidebar.openProjectSettings(section);
78
- }
79
-
80
- function goToSession(s: SessionSummary) {
81
- if (activeProject) {
82
- openSessionTab(s.id, activeProject.slug, s.title);
83
- sidebar.setActiveSessionId(s.id);
84
- }
85
- }
86
-
87
- var sessionCount = sessions.length;
88
- var mcpCount = settings ? Object.keys(settings.mcpServers).length : 0;
89
- var globalMcpCount = settings ? Object.keys(settings.global.mcpServers).length : 0;
90
- var rulesCount = settings ? settings.rules.length : 0;
91
- var globalRulesCount = settings ? settings.global.rules.length : 0;
92
- var envCount = settings ? Object.keys(settings.env).length : 0;
93
-
94
- return (
95
- <div className="flex-1 overflow-auto px-4 sm:px-8 py-4 sm:py-6 max-w-3xl">
96
- <div className="mb-6 flex items-center gap-3">
97
- <button
98
- className="btn btn-ghost btn-sm btn-square lg:hidden"
99
- aria-label="Toggle sidebar"
100
- onClick={sidebar.toggleDrawer}
101
- >
102
- <Menu size={18} />
103
- </button>
104
- <h1 className="text-lg font-mono font-bold text-base-content">{projectTitle}</h1>
105
- </div>
106
-
107
- {loading && (
108
- <div className="space-y-6 animate-pulse">
109
- <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
110
- {[0, 1, 2, 3].map(function (i) {
111
- return <div key={i} className="bg-base-content/[0.03] rounded-xl p-3.5 h-20" />;
112
- })}
113
- </div>
114
- <div className="bg-base-content/[0.03] rounded-xl h-32" />
115
- </div>
116
- )}
117
-
118
- {!loading && settings && (
119
- <div className="space-y-6">
120
- <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
121
- <StatCard label="Sessions" value={sessionCount} icon={<MessageSquare size={14} className="text-primary" />} />
122
- <StatCard label="MCP Servers" value={mcpCount + globalMcpCount} icon={<Plug size={14} className="text-accent" />} />
123
- <StatCard label="Rules" value={rulesCount + globalRulesCount} icon={<ScrollText size={14} className="text-info" />} />
124
- <StatCard label="Env Vars" value={envCount} icon={<Terminal size={14} className="text-success" />} />
125
- </div>
126
-
127
- {settings.claudeMd && (
128
- <div>
129
- <div className="text-[12px] font-semibold text-base-content/40 mb-2">CLAUDE.md</div>
130
- <div className="px-3 py-2.5 bg-base-300 border border-base-content/15 rounded-xl font-mono text-[11px] text-base-content/60 leading-relaxed max-h-48 overflow-y-auto">
131
- <pre className="whitespace-pre-wrap">{settings.claudeMd}</pre>
132
- </div>
133
- </div>
134
- )}
135
-
136
- {sessionCount > 0 && (
137
- <div>
138
- <div className="text-[12px] font-semibold text-base-content/40 mb-2">Recent Sessions</div>
139
- <div className="flex flex-col gap-1.5">
140
- {sessions.slice(0, 5).map(function (s) {
141
- return (
142
- <button
143
- key={s.id}
144
- onClick={function () { goToSession(s); }}
145
- className="flex items-center gap-3 px-3 py-2 rounded-xl border border-base-content/15 bg-base-300 hover:border-base-content/30 transition-colors duration-[120ms] cursor-pointer text-left focus-visible:ring-2 focus-visible:ring-primary"
146
- >
147
- <MessageSquare size={12} className="text-base-content/30 flex-shrink-0" />
148
- <span className="flex-1 text-[12px] text-base-content truncate">{s.title || "Untitled"}</span>
149
- <span className="text-[10px] text-base-content/30 font-mono flex-shrink-0">
150
- {new Date(s.updatedAt).toLocaleDateString()}
151
- </span>
152
- <ChevronRight size={12} className="text-base-content/20 flex-shrink-0" />
153
- </button>
154
- );
155
- })}
156
- </div>
157
- </div>
158
- )}
159
-
160
- <div>
161
- <div className="text-[12px] font-semibold text-base-content/40 mb-2">Settings</div>
162
- <div className="grid grid-cols-2 sm:grid-cols-3 gap-2">
163
- <QuickLink label="General" icon={<Settings size={13} className="text-base-content/40" />} onClick={function () { goToSection("general"); }} />
164
- <QuickLink label="Claude" icon={<FileText size={13} className="text-base-content/40" />} onClick={function () { goToSection("claude"); }} />
165
- <QuickLink label="Environment" icon={<Terminal size={13} className="text-base-content/40" />} onClick={function () { goToSection("environment"); }} />
166
- <QuickLink label="MCP Servers" icon={<Plug size={13} className="text-base-content/40" />} onClick={function () { goToSection("mcp"); }} />
167
- <QuickLink label="Rules" icon={<ScrollText size={13} className="text-base-content/40" />} onClick={function () { goToSection("rules"); }} />
168
- <QuickLink label="Permissions" icon={<Shield size={13} className="text-base-content/40" />} onClick={function () { goToSection("permissions"); }} />
169
- </div>
170
- </div>
171
-
172
- <div className="text-[11px] text-base-content/30 font-mono truncate">
173
- {settings.path}
174
- </div>
175
- </div>
176
- )}
177
- </div>
178
- );
179
- }
@@ -1,24 +0,0 @@
1
- import type { NodeInfo } from "#shared";
2
-
3
- interface NodeBadgeProps {
4
- node: NodeInfo;
5
- }
6
-
7
- export function NodeBadge(props: NodeBadgeProps) {
8
- var initials = props.node.name.slice(0, 2).toUpperCase();
9
-
10
- return (
11
- <span
12
- title={props.node.name + (props.node.online ? " (online)" : " (offline)")}
13
- className="inline-flex items-center gap-[3px] px-[5px] py-[1px] rounded-full bg-base-300 border border-base-content/15 text-[10px] font-semibold text-base-content/40 tracking-[0.03em] flex-shrink-0"
14
- >
15
- <span
16
- className={
17
- "w-[5px] h-[5px] rounded-full flex-shrink-0 inline-block " +
18
- (props.node.online ? "bg-success" : "bg-base-content/30")
19
- }
20
- />
21
- {initials}
22
- </span>
23
- );
24
- }
@@ -1,340 +0,0 @@
1
- import { useState, useEffect, useCallback, useRef, memo } from "react";
2
- import { X, Copy, Check, Loader2 } from "lucide-react";
3
- import { useWebSocket } from "../../hooks/useWebSocket";
4
- import { useMesh } from "../../hooks/useMesh";
5
- import { clearInvite } from "../../stores/mesh";
6
- import type { ServerMessage } from "#shared";
7
-
8
- type Tab = "generate" | "enter";
9
- type PairStatus = "idle" | "connecting" | "paired" | "failed";
10
-
11
- interface PairingDialogProps {
12
- isOpen: boolean;
13
- onClose: () => void;
14
- }
15
-
16
- export var PairingDialog = memo(function PairingDialog(props: PairingDialogProps) {
17
- var ws = useWebSocket();
18
- var mesh = useMesh();
19
- var [tab, setTab] = useState<Tab>("generate");
20
- var [pairCode, setPairCode] = useState("");
21
- var [pairStatus, setPairStatus] = useState<PairStatus>("idle");
22
- var [pairError, setPairError] = useState<string | null>(null);
23
- var [copied, setCopied] = useState(false);
24
- var [generating, setGenerating] = useState(false);
25
- var [addresses, setAddresses] = useState<Array<{ name: string; address: string }>>([]);
26
- var [selectedAddress, setSelectedAddress] = useState("");
27
- var modalRef = useRef<HTMLDivElement>(null);
28
- var inputRef = useRef<HTMLInputElement>(null);
29
- var pairTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
30
-
31
- useEffect(function () {
32
- if (!props.isOpen) {
33
- clearInvite();
34
- setPairCode("");
35
- setPairStatus("idle");
36
- setPairError(null);
37
- setCopied(false);
38
- setGenerating(false);
39
- setAddresses([]);
40
- setSelectedAddress("");
41
- setTab("generate");
42
- if (pairTimeoutRef.current) { clearTimeout(pairTimeoutRef.current); pairTimeoutRef.current = null; }
43
- return;
44
- }
45
-
46
- function handleAddresses(msg: ServerMessage) {
47
- if ((msg as any).type !== "mesh:addresses_result") return;
48
- var data = msg as any as { addresses: Array<{ name: string; address: string }> };
49
- setAddresses(data.addresses);
50
- if (data.addresses.length > 0) {
51
- setSelectedAddress(data.addresses[0].address);
52
- }
53
- }
54
-
55
- ws.subscribe("mesh:addresses_result", handleAddresses);
56
- ws.send({ type: "mesh:addresses" } as any);
57
-
58
- function handleKeyDown(e: KeyboardEvent) {
59
- if (e.key === "Escape") props.onClose();
60
- }
61
- document.addEventListener("keydown", handleKeyDown);
62
- return function () {
63
- document.removeEventListener("keydown", handleKeyDown);
64
- ws.unsubscribe("mesh:addresses_result", handleAddresses);
65
- };
66
- }, [props.isOpen]);
67
-
68
- useEffect(function () {
69
- function handleInvite(msg: ServerMessage) {
70
- if (msg.type === "mesh:invite_code") {
71
- setGenerating(false);
72
- }
73
- }
74
-
75
- function handlePaired(msg: ServerMessage) {
76
- if (msg.type === "mesh:paired") {
77
- setPairStatus("paired");
78
- setPairError(null);
79
- setTimeout(function () { props.onClose(); }, 3000);
80
- }
81
- }
82
-
83
- function handlePairFailed(msg: ServerMessage) {
84
- if (msg.type !== "mesh:pair_failed") return;
85
- var data = msg as { type: string; message: string };
86
- setPairStatus("failed");
87
- setPairError(data.message);
88
- }
89
-
90
- ws.subscribe("mesh:invite_code", handleInvite);
91
- ws.subscribe("mesh:paired", handlePaired);
92
- ws.subscribe("mesh:pair_failed", handlePairFailed);
93
- return function () {
94
- ws.unsubscribe("mesh:invite_code", handleInvite);
95
- ws.unsubscribe("mesh:paired", handlePaired);
96
- ws.unsubscribe("mesh:pair_failed", handlePairFailed);
97
- };
98
- }, []);
99
-
100
- function handleGenerateInvite() {
101
- clearInvite();
102
- setGenerating(true);
103
- ws.send({ type: "mesh:generate_invite", address: selectedAddress } as any);
104
- }
105
-
106
- function handlePair() {
107
- var trimmed = pairCode.trim();
108
- if (!trimmed) {
109
- return;
110
- }
111
- setPairStatus("connecting");
112
- setPairError(null);
113
-
114
- if (pairTimeoutRef.current) clearTimeout(pairTimeoutRef.current);
115
- pairTimeoutRef.current = setTimeout(function () {
116
- setPairStatus(function (prev) {
117
- if (prev === "connecting") {
118
- setPairError("Pairing timed out. Check the code and try again.");
119
- return "failed";
120
- }
121
- return prev;
122
- });
123
- }, 30000);
124
-
125
- ws.send({ type: "mesh:pair", code: trimmed });
126
- }
127
-
128
- function handleCopyCode() {
129
- if (!mesh.inviteCode) {
130
- return;
131
- }
132
- navigator.clipboard.writeText(mesh.inviteCode).then(function () {
133
- setCopied(true);
134
- setTimeout(function () { setCopied(false); }, 2000);
135
- });
136
- }
137
-
138
- if (!props.isOpen) {
139
- return null;
140
- }
141
-
142
- return (
143
- <div
144
- ref={modalRef}
145
- role="dialog"
146
- aria-modal="true"
147
- aria-label="Pair a node"
148
- className="fixed inset-0 z-[10000] flex items-center justify-center bg-base-content/65 backdrop-blur-sm"
149
- onClick={props.onClose}
150
- >
151
- <div
152
- className="w-[440px] max-w-[calc(100vw-24px)] rounded-xl border border-base-300 bg-base-200 overflow-hidden shadow-2xl"
153
- onClick={function (e) { e.stopPropagation(); }}
154
- >
155
- <div className="flex items-center justify-between px-5 py-4 border-b border-base-300">
156
- <div className="text-[14px] font-semibold text-base-content">Pair a Node</div>
157
- <button
158
- onClick={props.onClose}
159
- aria-label="Close"
160
- className="btn btn-ghost btn-xs btn-square text-base-content/40 hover:text-base-content"
161
- >
162
- <X size={14} />
163
- </button>
164
- </div>
165
-
166
- <div className="flex border-b border-base-300">
167
- {(["generate", "enter"] as Tab[]).map(function (t) {
168
- var label = t === "generate" ? "Generate Invite" : "Enter Code";
169
- var isActive = tab === t;
170
- return (
171
- <button
172
- key={t}
173
- onClick={function () { setTab(t); }}
174
- className={
175
- "flex-1 px-4 py-2.5 text-[13px] cursor-pointer transition-colors duration-[120ms] border-b-2 " +
176
- (isActive
177
- ? "font-semibold text-base-content border-primary"
178
- : "font-normal text-base-content/40 border-transparent hover:text-base-content/70")
179
- }
180
- >
181
- {label}
182
- </button>
183
- );
184
- })}
185
- </div>
186
-
187
- <div className="p-5">
188
- {tab === "generate" && (
189
- <div>
190
- <div className="text-[12px] text-base-content/40 mb-4 leading-relaxed">
191
- Generate an invite code on this machine and share it with the other node.
192
- The code encodes this node&apos;s address and a one-time auth token.
193
- </div>
194
-
195
- {!mesh.inviteCode && !generating && addresses.length > 1 && (
196
- <div className="mb-3">
197
- <label className="text-[11px] font-mono text-base-content/35 uppercase tracking-wider mb-1.5 block">
198
- Network interface
199
- </label>
200
- <select
201
- value={selectedAddress}
202
- onChange={function (e) { setSelectedAddress(e.target.value); }}
203
- className="select select-bordered select-sm w-full bg-base-100 text-base-content text-[13px] font-mono"
204
- >
205
- {addresses.map(function (a) {
206
- return (
207
- <option key={a.address} value={a.address}>
208
- {a.address} ({a.name})
209
- </option>
210
- );
211
- })}
212
- </select>
213
- </div>
214
- )}
215
-
216
- {!mesh.inviteCode && !generating && (
217
- <button
218
- onClick={handleGenerateInvite}
219
- disabled={!selectedAddress && addresses.length > 0}
220
- className="btn btn-primary btn-sm"
221
- >
222
- Generate Invite Code
223
- </button>
224
- )}
225
-
226
- {generating && !mesh.inviteCode && (
227
- <div className="flex items-center gap-2 text-[13px] text-base-content/40">
228
- <Loader2 size={14} className="animate-spin text-primary" />
229
- Generating invite code...
230
- </div>
231
- )}
232
-
233
- {mesh.inviteCode && (
234
- <div>
235
- <div className="flex items-center gap-2 px-3.5 py-2.5 rounded bg-base-100 border border-base-300 mb-4">
236
- <code className="flex-1 font-mono text-[14px] font-semibold text-base-content tracking-[0.08em] break-all">
237
- {mesh.inviteCode}
238
- </code>
239
- <button
240
- onClick={handleCopyCode}
241
- title="Copy code"
242
- className={
243
- "btn btn-xs gap-1 flex-shrink-0 " +
244
- (copied ? "btn-success" : "btn-ghost border border-base-300")
245
- }
246
- >
247
- {copied ? <Check size={12} /> : <Copy size={12} />}
248
- {copied ? "Copied!" : "Copy"}
249
- </button>
250
- </div>
251
-
252
- <button
253
- onClick={handleGenerateInvite}
254
- className="text-[12px] text-base-content/40 underline cursor-pointer"
255
- >
256
- Generate new code
257
- </button>
258
- </div>
259
- )}
260
- </div>
261
- )}
262
-
263
- {tab === "enter" && (
264
- <div>
265
- <div className="text-[12px] text-base-content/40 mb-4 leading-relaxed">
266
- Paste the invite code generated on the other node to pair with it.
267
- </div>
268
-
269
- <input
270
- ref={inputRef}
271
- type="text"
272
- value={pairCode}
273
- onChange={function (e) {
274
- var raw = e.target.value.replace(/[^A-Za-z0-9]/g, "");
275
- var upper = raw.toUpperCase();
276
- if (upper.startsWith("LTCE")) raw = raw.slice(4);
277
- if (raw.length > 16) raw = raw.slice(0, 16);
278
- var chunks: string[] = [];
279
- for (var i = 0; i < raw.length; i += 4) {
280
- chunks.push(raw.slice(i, i + 4));
281
- }
282
- var formatted = chunks.length > 0 ? "LTCE-" + chunks.join("-") : "";
283
- setPairCode(formatted);
284
- if (pairStatus !== "idle") {
285
- setPairStatus("idle");
286
- setPairError(null);
287
- }
288
- }}
289
- onKeyDown={function (e) {
290
- if (e.key === "Enter") {
291
- handlePair();
292
- }
293
- }}
294
- placeholder="LTCE-XXXX-XXXX-XXXX-XXXX"
295
- maxLength={24}
296
- autoFocus
297
- disabled={pairStatus === "connecting" || pairStatus === "paired"}
298
- className="input input-bordered w-full bg-base-100 text-base-content font-mono text-[14px] tracking-[0.06em] mb-3 focus:border-primary"
299
- />
300
-
301
- {pairStatus === "idle" && (
302
- <button
303
- onClick={handlePair}
304
- disabled={!pairCode.trim()}
305
- className={
306
- "btn btn-sm " +
307
- (pairCode.trim() ? "btn-primary" : "btn-ghost border border-base-300 cursor-not-allowed")
308
- }
309
- >
310
- Pair
311
- </button>
312
- )}
313
-
314
- {pairStatus === "connecting" && (
315
- <div className="flex items-center gap-2 text-[13px] text-base-content/40">
316
- <span
317
- className="w-3 h-3 rounded-full border-2 border-primary border-t-transparent inline-block"
318
- style={{ animation: "spin 0.6s linear infinite" }}
319
- />
320
- Connecting...
321
- </div>
322
- )}
323
-
324
- {pairStatus === "paired" && (
325
- <div className="flex items-center gap-1.5 text-[13px] font-semibold text-success">
326
- <Check size={14} />
327
- Paired successfully!
328
- </div>
329
- )}
330
-
331
- {pairStatus === "failed" && pairError && (
332
- <div className="text-[12px] text-error mt-2">{pairError}</div>
333
- )}
334
- </div>
335
- )}
336
- </div>
337
- </div>
338
- </div>
339
- );
340
- });