@cryptiklemur/lattice 4.0.2 → 5.0.1

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 +533 -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 -457
  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
@@ -0,0 +1,39 @@
1
+ import { join, dirname } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { existsSync } from "node:fs";
4
+ var __dirname_local = dirname(fileURLToPath(import.meta.url));
5
+ var CONTENT_TYPES = {
6
+ ".html": "text/html; charset=utf-8",
7
+ ".js": "application/javascript",
8
+ ".css": "text/css",
9
+ ".json": "application/json",
10
+ ".svg": "image/svg+xml",
11
+ ".png": "image/png",
12
+ ".ico": "image/x-icon",
13
+ ".webmanifest": "application/manifest+json",
14
+ ".woff": "font/woff",
15
+ ".woff2": "font/woff2",
16
+ ".ttf": "font/ttf",
17
+ ".txt": "text/plain",
18
+ ".map": "application/json",
19
+ ".wasm": "application/wasm",
20
+ };
21
+ export async function initAssets() {
22
+ // No-op in npm mode — static serving is handled by Express
23
+ }
24
+ export function serveStaticAsset(_pathname) {
25
+ return null;
26
+ }
27
+ export function hasEmbeddedAssets() {
28
+ return false;
29
+ }
30
+ export function getClientDir() {
31
+ var distPath = join(__dirname_local, "../../dist/client");
32
+ if (existsSync(distPath))
33
+ return distPath;
34
+ return join(__dirname_local, "../../dist/client");
35
+ }
36
+ export function guessContentType(path) {
37
+ var ext = path.slice(path.lastIndexOf("."));
38
+ return CONTENT_TYPES[ext] || "application/octet-stream";
39
+ }
@@ -0,0 +1,70 @@
1
+ import { scrypt, randomBytes, timingSafeEqual } from "node:crypto";
2
+ function scryptAsync(password, salt, keylen) {
3
+ return new Promise(function (resolve, reject) {
4
+ scrypt(password, salt, keylen, function (err, derivedKey) {
5
+ if (err)
6
+ reject(err);
7
+ else
8
+ resolve(derivedKey);
9
+ });
10
+ });
11
+ }
12
+ var TOKEN_TTL = 86400000;
13
+ var CLEANUP_INTERVAL = 600000;
14
+ var activeSessions = new Map();
15
+ export async function hashPassphrase(passphrase) {
16
+ var salt = randomBytes(16).toString("hex");
17
+ var hash = (await scryptAsync(passphrase, salt, 64)).toString("hex");
18
+ return salt + ":" + hash;
19
+ }
20
+ export async function verifyPassphrase(passphrase, storedHash) {
21
+ var parts = storedHash.split(":");
22
+ if (parts.length !== 2) {
23
+ return false;
24
+ }
25
+ var salt = parts[0];
26
+ var hash = parts[1];
27
+ try {
28
+ var derived = await scryptAsync(passphrase, salt, 64);
29
+ var expected = Buffer.from(hash, "hex");
30
+ if (derived.length !== expected.length) {
31
+ return false;
32
+ }
33
+ return timingSafeEqual(derived, expected);
34
+ }
35
+ catch {
36
+ return false;
37
+ }
38
+ }
39
+ export function generateSessionToken() {
40
+ return randomBytes(32).toString("hex");
41
+ }
42
+ export function addSession(token) {
43
+ activeSessions.set(token, Date.now());
44
+ }
45
+ export function removeSession(token) {
46
+ activeSessions.delete(token);
47
+ }
48
+ export function isValidSession(token) {
49
+ var createdAt = activeSessions.get(token);
50
+ if (createdAt === undefined) {
51
+ return false;
52
+ }
53
+ if (Date.now() - createdAt > TOKEN_TTL) {
54
+ activeSessions.delete(token);
55
+ return false;
56
+ }
57
+ return true;
58
+ }
59
+ export function clearSessions() {
60
+ activeSessions.clear();
61
+ }
62
+ var cleanupInterval = setInterval(function () {
63
+ var now = Date.now();
64
+ activeSessions.forEach(function (createdAt, token) {
65
+ if (now - createdAt > TOKEN_TTL) {
66
+ activeSessions.delete(token);
67
+ }
68
+ });
69
+ }, CLEANUP_INTERVAL);
70
+ cleanupInterval.unref();
@@ -0,0 +1,47 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { homedir, hostname } from "node:os";
3
+ import { join } from "node:path";
4
+ import { DEFAULT_PORT, LATTICE_HOME_DIR } from "#shared";
5
+ var home = process.env.LATTICE_HOME || join(homedir(), LATTICE_HOME_DIR);
6
+ var cachedConfig = null;
7
+ export function getLatticeHome() {
8
+ if (!existsSync(home)) {
9
+ mkdirSync(home, { recursive: true });
10
+ }
11
+ return home;
12
+ }
13
+ export function getConfigPath() {
14
+ return join(getLatticeHome(), "config.json");
15
+ }
16
+ export function loadConfig() {
17
+ if (cachedConfig) {
18
+ return cachedConfig;
19
+ }
20
+ var configPath = getConfigPath();
21
+ if (!existsSync(configPath)) {
22
+ return createDefaultConfig();
23
+ }
24
+ var raw = readFileSync(configPath, "utf-8");
25
+ cachedConfig = JSON.parse(raw);
26
+ return cachedConfig;
27
+ }
28
+ export function saveConfig(config) {
29
+ var configPath = getConfigPath();
30
+ writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
31
+ cachedConfig = config;
32
+ }
33
+ export function invalidateConfigCache() {
34
+ cachedConfig = null;
35
+ }
36
+ function createDefaultConfig() {
37
+ var config = {
38
+ port: DEFAULT_PORT,
39
+ name: hostname(),
40
+ tls: false,
41
+ debug: false,
42
+ globalEnv: {},
43
+ projects: [],
44
+ };
45
+ saveConfig(config);
46
+ return config;
47
+ }
@@ -0,0 +1,533 @@
1
+ import { join, resolve } from "node:path";
2
+ import { createServer as createHttpServer } from "node:http";
3
+ import { createServer as createHttpsServer } from "node:https";
4
+ import { readFileSync, existsSync, createReadStream, statSync } from "node:fs";
5
+ import express from "express";
6
+ import { WebSocketServer } from "ws";
7
+ import { getClientDir } from "./assets.js";
8
+ import { getLatticeHome, loadConfig } from "./config.js";
9
+ import { loadOrCreateIdentity } from "./identity.js";
10
+ import { addClient, removeClient, routeMessage } from "./ws/server.js";
11
+ import { broadcast, sendTo } from "./ws/broadcast.js";
12
+ import { buildNodesMessage } from "./handlers/mesh.js";
13
+ import { startDiscovery } from "./mesh/discovery.js";
14
+ import { startMeshConnections, onPeerConnected, onPeerDisconnected, onPeerMessage, getAllRemoteProjects } from "./mesh/connector.js";
15
+ import { handleProxyRequest, handleProxyResponse } from "./mesh/proxy.js";
16
+ import { verifyPassphrase, generateSessionToken, addSession, isValidSession } from "./auth/passphrase.js";
17
+ import { ensureCerts } from "./tls.js";
18
+ import { log } from "./logger.js";
19
+ import { detectIdeProjectName } from "./handlers/settings.js";
20
+ import "./handlers/session";
21
+ import "./handlers/chat";
22
+ import "./handlers/attachment";
23
+ import { loadInterruptedSessions, cleanupClientPermissions, cleanupClientElicitations, getActiveStreamCountForProject } from "./project/sdk-bridge.js";
24
+ import { runWarmup, isWarmupComplete, getWarmupModels, getWarmupAccountInfo, getWarmupRateLimits } from "./project/warmup.js";
25
+ import { clearActiveSession } from "./handlers/chat.js";
26
+ import { clearActiveProject } from "./handlers/fs.js";
27
+ import { clearClientRemoteNode } from "./ws/router.js";
28
+ import "./handlers/fs";
29
+ import "./handlers/terminal";
30
+ import "./handlers/settings";
31
+ import "./handlers/project-settings";
32
+ import "./handlers/mesh";
33
+ import "./handlers/loop";
34
+ import "./handlers/scheduler";
35
+ import "./handlers/notes";
36
+ import "./handlers/skills";
37
+ import "./handlers/memory";
38
+ import "./handlers/editor";
39
+ import "./handlers/analytics";
40
+ import "./handlers/bookmarks";
41
+ import "./handlers/plugins";
42
+ import "./handlers/update";
43
+ import "./handlers/themes";
44
+ import { startScheduler } from "./features/scheduler.js";
45
+ import { loadNotes } from "./features/sticky-notes.js";
46
+ import { startPeriodicUpdateCheck, getCachedUpdateInfo } from "./update-checker.js";
47
+ import { loadBookmarks } from "./project/bookmarks.js";
48
+ import { cleanupClientTerminals } from "./handlers/terminal.js";
49
+ import { cleanupClient as cleanupClientAttachments } from "./handlers/attachment.js";
50
+ import { initPush, getVapidPublicKey, addPushSubscription } from "./push.js";
51
+ var RATE_LIMIT_WINDOW = 10000;
52
+ var RATE_LIMIT_MAX = 100;
53
+ var clientRateLimits = new Map();
54
+ var wsClientIds = new WeakMap();
55
+ function parseCookies(cookieHeader) {
56
+ var map = new Map();
57
+ var parts = cookieHeader.split(";");
58
+ for (var i = 0; i < parts.length; i++) {
59
+ var part = parts[i].trim();
60
+ var eqIdx = part.indexOf("=");
61
+ if (eqIdx === -1) {
62
+ continue;
63
+ }
64
+ var key = part.slice(0, eqIdx).trim();
65
+ var value = part.slice(eqIdx + 1).trim();
66
+ map.set(key, value);
67
+ }
68
+ return map;
69
+ }
70
+ function isAuthenticatedReq(req, passphraseHash) {
71
+ if (!passphraseHash) {
72
+ return true;
73
+ }
74
+ var cookieHeader = req.headers.cookie || "";
75
+ var cookies = parseCookies(cookieHeader);
76
+ var token = cookies.get("lattice_auth");
77
+ if (!token) {
78
+ return false;
79
+ }
80
+ return isValidSession(token);
81
+ }
82
+ function buildLoginPage() {
83
+ return `<!DOCTYPE html>
84
+ <html lang="en">
85
+ <head>
86
+ <meta charset="UTF-8" />
87
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
88
+ <title>Lattice — Authenticate</title>
89
+ <style>
90
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
91
+ body {
92
+ font-family: 'Courier New', monospace;
93
+ background: #0d0d0d;
94
+ color: #e0e0e0;
95
+ min-height: 100vh;
96
+ display: flex;
97
+ align-items: center;
98
+ justify-content: center;
99
+ }
100
+ .card {
101
+ background: #161616;
102
+ border: 1px solid #2a2a2a;
103
+ border-radius: 6px;
104
+ padding: 2.5rem;
105
+ width: 100%;
106
+ max-width: 360px;
107
+ }
108
+ h1 {
109
+ font-size: 1.1rem;
110
+ font-weight: 600;
111
+ letter-spacing: 0.08em;
112
+ text-transform: uppercase;
113
+ color: #a0a0a0;
114
+ margin-bottom: 1.75rem;
115
+ }
116
+ label {
117
+ display: block;
118
+ font-size: 0.72rem;
119
+ text-transform: uppercase;
120
+ letter-spacing: 0.1em;
121
+ color: #606060;
122
+ margin-bottom: 0.4rem;
123
+ }
124
+ input[type="password"] {
125
+ width: 100%;
126
+ background: #0d0d0d;
127
+ border: 1px solid #2a2a2a;
128
+ border-radius: 4px;
129
+ color: #e0e0e0;
130
+ font-family: inherit;
131
+ font-size: 0.9rem;
132
+ padding: 0.6rem 0.75rem;
133
+ outline: none;
134
+ transition: border-color 0.15s;
135
+ }
136
+ input[type="password"]:focus { border-color: #4a4a4a; }
137
+ button {
138
+ width: 100%;
139
+ margin-top: 1.25rem;
140
+ background: #e0e0e0;
141
+ color: #0d0d0d;
142
+ border: none;
143
+ border-radius: 4px;
144
+ font-family: inherit;
145
+ font-size: 0.85rem;
146
+ font-weight: 700;
147
+ letter-spacing: 0.06em;
148
+ text-transform: uppercase;
149
+ padding: 0.65rem;
150
+ cursor: pointer;
151
+ transition: background 0.15s;
152
+ }
153
+ button:hover { background: #c0c0c0; }
154
+ .error {
155
+ margin-top: 0.85rem;
156
+ font-size: 0.78rem;
157
+ color: #c07070;
158
+ text-align: center;
159
+ }
160
+ </style>
161
+ </head>
162
+ <body>
163
+ <div class="card">
164
+ <h1>Lattice</h1>
165
+ <form id="form">
166
+ <label for="passphrase">Passphrase</label>
167
+ <input type="password" id="passphrase" name="passphrase" autofocus autocomplete="current-password" />
168
+ <button type="submit">Authenticate</button>
169
+ <div class="error" id="error"></div>
170
+ </form>
171
+ </div>
172
+ <script>
173
+ document.getElementById('form').addEventListener('submit', async function(e) {
174
+ e.preventDefault();
175
+ var passphrase = document.getElementById('passphrase').value;
176
+ try {
177
+ var res = await fetch('/auth', {
178
+ method: 'POST',
179
+ headers: { 'Content-Type': 'application/json' },
180
+ body: JSON.stringify({ passphrase: passphrase })
181
+ });
182
+ if (res.ok) {
183
+ window.location.reload();
184
+ } else {
185
+ document.getElementById('error').textContent = 'Invalid passphrase.';
186
+ }
187
+ } catch {
188
+ document.getElementById('error').textContent = 'Connection error.';
189
+ }
190
+ });
191
+ </script>
192
+ </body>
193
+ </html>`;
194
+ }
195
+ function getMimeType(filePath) {
196
+ var ext = filePath.split(".").pop() || "";
197
+ var mimeTypes = {
198
+ html: "text/html; charset=utf-8",
199
+ js: "application/javascript",
200
+ css: "text/css",
201
+ json: "application/json",
202
+ svg: "image/svg+xml",
203
+ png: "image/png",
204
+ ico: "image/x-icon",
205
+ webmanifest: "application/manifest+json",
206
+ woff: "font/woff",
207
+ woff2: "font/woff2",
208
+ ttf: "font/ttf",
209
+ txt: "text/plain",
210
+ map: "application/json",
211
+ };
212
+ return mimeTypes[ext] || "application/octet-stream";
213
+ }
214
+ function handleWsOpen(ws, clientId) {
215
+ wsClientIds.set(ws, clientId);
216
+ addClient(clientId, ws);
217
+ log.ws("Client connected: %s", clientId);
218
+ sendTo(clientId, { type: "mesh:nodes", nodes: buildNodesMessage() });
219
+ var connectConfig = loadConfig();
220
+ var connectIdentity = loadOrCreateIdentity();
221
+ var localProjects = connectConfig.projects.map(function (p) {
222
+ return { slug: p.slug, path: p.path, title: p.title, nodeId: connectIdentity.id, nodeName: connectConfig.name, isRemote: false, ideProjectName: detectIdeProjectName(p.path), activeSessions: getActiveStreamCountForProject(p.slug) };
223
+ });
224
+ var connectRemoteProjects = getAllRemoteProjects(connectIdentity.id);
225
+ sendTo(clientId, {
226
+ type: "projects:list",
227
+ projects: localProjects.concat(connectRemoteProjects),
228
+ });
229
+ if (isWarmupComplete()) {
230
+ sendTo(clientId, { type: "warmup:models", models: getWarmupModels() });
231
+ var accountInfo = getWarmupAccountInfo();
232
+ if (accountInfo) {
233
+ sendTo(clientId, {
234
+ type: "warmup:account",
235
+ email: accountInfo.email,
236
+ organization: accountInfo.organization,
237
+ subscriptionType: accountInfo.subscriptionType,
238
+ apiKeySource: accountInfo.apiKeySource,
239
+ apiProvider: accountInfo.apiProvider,
240
+ });
241
+ }
242
+ var cachedRateLimits = getWarmupRateLimits();
243
+ for (var rli = 0; rli < cachedRateLimits.length; rli++) {
244
+ var rl = cachedRateLimits[rli];
245
+ sendTo(clientId, {
246
+ type: "chat:rate_limit",
247
+ status: rl.status,
248
+ utilization: rl.utilization,
249
+ resetsAt: rl.resetsAt,
250
+ rateLimitType: rl.rateLimitType,
251
+ overageStatus: rl.overageStatus,
252
+ overageResetsAt: rl.overageResetsAt,
253
+ isUsingOverage: rl.isUsingOverage,
254
+ });
255
+ }
256
+ }
257
+ void (async function () {
258
+ var { listSessions } = await import("./project/session.js");
259
+ for (var pi = 0; pi < connectConfig.projects.length; pi++) {
260
+ try {
261
+ var result = await listSessions(connectConfig.projects[pi].slug, { limit: 40 });
262
+ sendTo(clientId, {
263
+ type: "session:list",
264
+ projectSlug: connectConfig.projects[pi].slug,
265
+ sessions: result.sessions,
266
+ totalCount: result.totalCount,
267
+ });
268
+ }
269
+ catch { }
270
+ }
271
+ })();
272
+ }
273
+ function handleWsMessage(ws, data) {
274
+ var clientId = wsClientIds.get(ws);
275
+ if (!clientId)
276
+ return;
277
+ var now = Date.now();
278
+ var limit = clientRateLimits.get(clientId);
279
+ if (!limit || now - limit.windowStart > RATE_LIMIT_WINDOW) {
280
+ limit = { count: 0, windowStart: now };
281
+ clientRateLimits.set(clientId, limit);
282
+ }
283
+ limit.count++;
284
+ if (limit.count > RATE_LIMIT_MAX) {
285
+ sendTo(clientId, { type: "chat:error", message: "Rate limit exceeded, please slow down" });
286
+ return;
287
+ }
288
+ var text = typeof data === "string" ? data : Buffer.isBuffer(data) ? data.toString() : Buffer.from(data).toString();
289
+ try {
290
+ var msg = JSON.parse(text);
291
+ routeMessage(clientId, msg);
292
+ }
293
+ catch (err) {
294
+ log.ws("Invalid JSON message: %O", err);
295
+ }
296
+ }
297
+ function handleWsClose(ws) {
298
+ var clientId = wsClientIds.get(ws);
299
+ if (!clientId)
300
+ return;
301
+ clearActiveSession(clientId);
302
+ clearActiveProject(clientId);
303
+ clearClientRemoteNode(clientId);
304
+ removeClient(clientId);
305
+ cleanupClientTerminals(clientId);
306
+ cleanupClientAttachments(clientId);
307
+ cleanupClientPermissions(clientId);
308
+ cleanupClientElicitations(clientId);
309
+ clientRateLimits.delete(clientId);
310
+ wsClientIds.delete(ws);
311
+ log.ws("Client disconnected: %s", clientId);
312
+ }
313
+ export async function startDaemon(portOverride) {
314
+ var config = loadConfig();
315
+ var effectivePort = (portOverride && !isNaN(portOverride)) ? portOverride : config.port;
316
+ var identity = loadOrCreateIdentity();
317
+ log.server("Node: %s (%s)", config.name, identity.id);
318
+ log.server("Home: %s", getLatticeHome());
319
+ var clientDir = getClientDir();
320
+ var app = express();
321
+ app.use(express.json());
322
+ var authAttempts = new Map();
323
+ var AUTH_RATE_LIMIT = 5;
324
+ var AUTH_RATE_WINDOW = 60000;
325
+ app.post("/auth", async function (req, res) {
326
+ var ip = req.ip || req.socket.remoteAddress || "unknown";
327
+ var now = Date.now();
328
+ var attempts = authAttempts.get(ip) || [];
329
+ attempts = attempts.filter(function (t) { return now - t < AUTH_RATE_WINDOW; });
330
+ if (attempts.length >= AUTH_RATE_LIMIT) {
331
+ res.status(429).json({ ok: false, error: "Too many attempts. Try again later." });
332
+ return;
333
+ }
334
+ attempts.push(now);
335
+ authAttempts.set(ip, attempts);
336
+ var passphrase = req.body.passphrase || "";
337
+ if (!config.passphraseHash || await verifyPassphrase(passphrase, config.passphraseHash)) {
338
+ var token = generateSessionToken();
339
+ addSession(token);
340
+ res.setHeader("Set-Cookie", "lattice_auth=" + token + "; HttpOnly; Path=/; SameSite=Strict");
341
+ res.json({ ok: true });
342
+ }
343
+ else {
344
+ res.status(401).json({ ok: false });
345
+ }
346
+ });
347
+ app.use(function (req, res, next) {
348
+ if (req.path === "/ws" || req.path === "/auth") {
349
+ next();
350
+ return;
351
+ }
352
+ if (!isAuthenticatedReq(req, config.passphraseHash)) {
353
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
354
+ res.send(buildLoginPage());
355
+ return;
356
+ }
357
+ next();
358
+ });
359
+ app.get("/api/vapid-public-key", function (_req, res) {
360
+ res.json({ publicKey: getVapidPublicKey() });
361
+ });
362
+ app.post("/api/push-subscribe", function (req, res) {
363
+ try {
364
+ var pushBody = req.body;
365
+ addPushSubscription(pushBody);
366
+ res.json({ ok: true });
367
+ }
368
+ catch {
369
+ res.status(400).json({ ok: false });
370
+ }
371
+ });
372
+ app.get("/api/file", function (req, res) {
373
+ var reqFilePath = req.query.path;
374
+ if (!reqFilePath) {
375
+ res.status(400).send("Missing path parameter");
376
+ return;
377
+ }
378
+ var resolved = null;
379
+ for (var pi = 0; pi < config.projects.length; pi++) {
380
+ var projectPath = resolve(config.projects[pi].path);
381
+ var candidate = resolve(projectPath, reqFilePath);
382
+ if (candidate.startsWith(projectPath + "/") && existsSync(candidate)) {
383
+ resolved = candidate;
384
+ break;
385
+ }
386
+ }
387
+ if (!resolved) {
388
+ res.status(404).send("File not found");
389
+ return;
390
+ }
391
+ var stat = statSync(resolved);
392
+ res.setHeader("Content-Type", getMimeType(resolved));
393
+ res.setHeader("Content-Length", stat.size);
394
+ createReadStream(resolved).pipe(res);
395
+ });
396
+ var tlsOptions;
397
+ if (config.tls) {
398
+ try {
399
+ var certs = ensureCerts();
400
+ tlsOptions = {
401
+ cert: readFileSync(certs.cert),
402
+ key: readFileSync(certs.key),
403
+ };
404
+ log.server("TLS enabled");
405
+ }
406
+ catch (err) {
407
+ console.error("[lattice] Failed to load TLS certs, falling back to HTTP:", err);
408
+ }
409
+ }
410
+ var protocol = tlsOptions ? "https" : "http";
411
+ var httpServer = tlsOptions
412
+ ? createHttpsServer(tlsOptions, app)
413
+ : createHttpServer(app);
414
+ var isDev = process.env.NODE_ENV !== "production";
415
+ if (isDev) {
416
+ var { createServer: createViteServer } = await import("vite");
417
+ var vite = await createViteServer({
418
+ server: {
419
+ middlewareMode: true,
420
+ hmr: { server: httpServer },
421
+ },
422
+ appType: "spa",
423
+ });
424
+ app.use(vite.middlewares);
425
+ log.server("Vite dev server attached (middleware mode, HMR on same port)");
426
+ }
427
+ else if (clientDir && existsSync(clientDir)) {
428
+ app.use(express.static(clientDir));
429
+ app.get("/{*path}", function (_req, res) {
430
+ var indexPath = join(clientDir, "index.html");
431
+ if (existsSync(indexPath)) {
432
+ res.sendFile(indexPath);
433
+ }
434
+ else {
435
+ res.status(404).send("Not found");
436
+ }
437
+ });
438
+ }
439
+ var wss = new WebSocketServer({ noServer: true });
440
+ httpServer.on("upgrade", function (req, socket, head) {
441
+ var url = new URL(req.url || "/", "http://localhost");
442
+ if (url.pathname !== "/ws") {
443
+ return;
444
+ }
445
+ if (!isAuthenticatedReq(req, config.passphraseHash)) {
446
+ socket.destroy();
447
+ return;
448
+ }
449
+ wss.handleUpgrade(req, socket, head, function (ws) {
450
+ var clientId = crypto.randomUUID();
451
+ handleWsOpen(ws, clientId);
452
+ ws.on("message", function (data) { handleWsMessage(ws, data); });
453
+ ws.on("close", function () { handleWsClose(ws); });
454
+ });
455
+ });
456
+ var maxRetries = 10;
457
+ for (var attempt = 0; attempt < maxRetries; attempt++) {
458
+ try {
459
+ await new Promise(function (resolveP, reject) {
460
+ httpServer.once("error", function (err) {
461
+ if (err.code === "EADDRINUSE" && attempt < maxRetries - 1) {
462
+ log.server("Port %d in use, retrying in 1s (%d/%d)...", effectivePort, attempt + 1, maxRetries);
463
+ setTimeout(function () { resolveP(); }, 1000);
464
+ }
465
+ else {
466
+ reject(err);
467
+ }
468
+ });
469
+ httpServer.listen(effectivePort, "0.0.0.0", function () {
470
+ resolveP();
471
+ });
472
+ });
473
+ if (httpServer.listening)
474
+ break;
475
+ }
476
+ catch (err) {
477
+ throw err;
478
+ }
479
+ }
480
+ log.server("Listening on %s://0.0.0.0:%d", protocol, effectivePort);
481
+ startDiscovery(identity.id, config.name, effectivePort);
482
+ startMeshConnections();
483
+ startScheduler();
484
+ loadNotes();
485
+ loadBookmarks();
486
+ startPeriodicUpdateCheck();
487
+ loadInterruptedSessions();
488
+ initPush();
489
+ var firstProject = config.projects[0];
490
+ if (firstProject) {
491
+ void runWarmup(firstProject.path);
492
+ }
493
+ onPeerConnected(function (nodeId) {
494
+ broadcast({ type: "mesh:node_online", nodeId: nodeId });
495
+ });
496
+ onPeerDisconnected(function (nodeId) {
497
+ broadcast({ type: "mesh:node_offline", nodeId: nodeId });
498
+ });
499
+ onPeerMessage(function (nodeId, msg) {
500
+ if (msg.type === "mesh:proxy_request") {
501
+ handleProxyRequest(nodeId, msg);
502
+ return;
503
+ }
504
+ if (msg.type === "mesh:proxy_response") {
505
+ handleProxyResponse(msg);
506
+ return;
507
+ }
508
+ });
509
+ setInterval(function () {
510
+ var currentConfig = loadConfig();
511
+ var currentIdentity = loadOrCreateIdentity();
512
+ broadcast({ type: "mesh:nodes", nodes: buildNodesMessage() });
513
+ var localProjects = currentConfig.projects.map(function (p) {
514
+ return { slug: p.slug, path: p.path, title: p.title, nodeId: currentIdentity.id, nodeName: currentConfig.name, isRemote: false, ideProjectName: detectIdeProjectName(p.path), activeSessions: getActiveStreamCountForProject(p.slug) };
515
+ });
516
+ var remoteProjects = getAllRemoteProjects(currentIdentity.id);
517
+ broadcast({
518
+ type: "projects:list",
519
+ projects: localProjects.concat(remoteProjects),
520
+ });
521
+ var updateInfo = getCachedUpdateInfo();
522
+ if (updateInfo && updateInfo.updateAvailable) {
523
+ broadcast({
524
+ type: "update:status",
525
+ currentVersion: updateInfo.currentVersion,
526
+ latestVersion: updateInfo.latestVersion,
527
+ updateAvailable: updateInfo.updateAvailable,
528
+ releaseUrl: updateInfo.releaseUrl,
529
+ installMode: updateInfo.installMode,
530
+ });
531
+ }
532
+ }, 10000);
533
+ }