@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,116 +0,0 @@
1
- import { useState } from "react";
2
- import { X, RotateCcw, Eye, EyeOff } from "lucide-react";
3
- import type { ClientAttachment } from "../../hooks/useAttachments";
4
-
5
- interface AttachmentChipsProps {
6
- attachments: ClientAttachment[];
7
- onRemove: (id: string) => void;
8
- onRetry: (id: string) => void;
9
- }
10
-
11
- function formatSize(bytes: number): string {
12
- if (bytes < 1024) return bytes + "B";
13
- if (bytes < 1024 * 1024) return Math.round(bytes / 1024) + "KB";
14
- return (bytes / (1024 * 1024)).toFixed(1) + "MB";
15
- }
16
-
17
- function getExtBadge(name: string, type: string): string {
18
- if (type === "paste") return "TXT";
19
- var ext = name.split(".").pop()?.toUpperCase() || "";
20
- return ext.slice(0, 4) || "FILE";
21
- }
22
-
23
- export function AttachmentChips(props: AttachmentChipsProps) {
24
- var [expandedPaste, setExpandedPaste] = useState<string | null>(null);
25
-
26
- if (props.attachments.length === 0) return null;
27
-
28
- return (
29
- <div className="flex flex-wrap gap-1.5 px-3 py-2 border-b border-base-content/8" role="list" aria-label="Attachments">
30
- {props.attachments.map(function (att) {
31
- var isFailed = att.status === "failed";
32
- var isUploading = att.status === "uploading";
33
-
34
- return (
35
- <div key={att.id} role="listitem" className="relative">
36
- <div
37
- className={
38
- "relative flex items-center gap-1.5 rounded-lg px-2 py-1 text-[12px] overflow-hidden transition-colors " +
39
- (isFailed
40
- ? "bg-error/10 border border-error/30 text-error/80"
41
- : "bg-base-content/5 border border-base-content/10 text-base-content/70")
42
- }
43
- >
44
- {isUploading && (
45
- <div
46
- className="absolute left-0 top-0 bottom-0 bg-primary/10 transition-all duration-300"
47
- style={{ width: att.progress + "%" }}
48
- />
49
- )}
50
-
51
- {att.type === "image" && att.previewUrl ? (
52
- <img
53
- src={att.previewUrl}
54
- alt=""
55
- className="relative w-7 h-7 rounded object-cover flex-shrink-0"
56
- />
57
- ) : (
58
- <span className="relative font-mono text-[10px] text-primary/60 flex-shrink-0">
59
- {getExtBadge(att.name, att.type)}
60
- </span>
61
- )}
62
-
63
- <span className="relative truncate max-w-[120px]">{att.name}</span>
64
-
65
- {att.type === "paste" && att.lineCount ? (
66
- <span className="relative text-[10px] text-base-content/30">{att.lineCount} lines</span>
67
- ) : isUploading ? (
68
- <span className="relative text-[10px] text-primary/50">{att.progress}%</span>
69
- ) : (
70
- <span className="relative text-[10px] text-base-content/30">{formatSize(att.size)}</span>
71
- )}
72
-
73
- {att.type === "paste" && att.content && (
74
- <button
75
- onClick={function () {
76
- setExpandedPaste(expandedPaste === att.id ? null : att.id);
77
- }}
78
- className="icon-action relative text-[10px] text-primary/50 hover:text-primary/80 underline"
79
- aria-label={expandedPaste === att.id ? "Hide preview" : "Show preview"}
80
- >
81
- {expandedPaste === att.id ? <EyeOff size={10} /> : <Eye size={10} />}
82
- </button>
83
- )}
84
-
85
- {isFailed && (
86
- <button
87
- onClick={function () { props.onRetry(att.id); }}
88
- className="icon-action relative text-error/60 hover:text-error/90"
89
- aria-label={"Retry " + att.name}
90
- title={att.error}
91
- >
92
- <RotateCcw size={10} />
93
- </button>
94
- )}
95
-
96
- <button
97
- onClick={function () { props.onRemove(att.id); }}
98
- className="icon-action relative text-base-content/30 hover:text-base-content/60"
99
- aria-label={"Remove " + att.name}
100
- >
101
- <X size={12} />
102
- </button>
103
- </div>
104
-
105
- {expandedPaste === att.id && att.content && (
106
- <div className="absolute left-0 bottom-full mb-1 w-[400px] max-w-[calc(100vw-2rem)] max-h-[200px] overflow-auto rounded-lg border border-base-content/10 bg-base-300 shadow-lg z-50 p-2 font-mono text-[11px] text-base-content/50 whitespace-pre">
107
- {att.content.slice(0, 2000)}
108
- {att.content.length > 2000 && "\n... (" + (att.content.length - 2000) + " more characters)"}
109
- </div>
110
- )}
111
- </div>
112
- );
113
- })}
114
- </div>
115
- );
116
- }
@@ -1,533 +0,0 @@
1
- import { useRef, useState, useEffect, useMemo } from "react";
2
- import { useStore } from "@tanstack/react-store";
3
- import { SendHorizontal, Settings, Paperclip } from "lucide-react";
4
- import { useSkills } from "../../hooks/useSkills";
5
- import { CommandPalette, getFilteredItems } from "./CommandPalette";
6
- import { useAttachments } from "../../hooks/useAttachments";
7
- import { useVoiceRecorder } from "../../hooks/useVoiceRecorder";
8
- import { AttachmentChips } from "./AttachmentChips";
9
- import { VoiceRecorder } from "./VoiceRecorder";
10
- import { getSessionStore } from "../../stores/session";
11
-
12
- interface ChatInputProps {
13
- onSend: (text: string, attachmentIds: string[]) => void;
14
- disabled: boolean;
15
- disabledPlaceholder?: string;
16
- toolbarContent?: React.ReactNode;
17
- failedInput?: string | null;
18
- onFailedInputConsumed?: () => void;
19
- prefillText?: string | null;
20
- onPrefillConsumed?: () => void;
21
- sessionId?: string | null;
22
- }
23
-
24
- function getModKey(): string {
25
- if (typeof navigator === "undefined") return "Ctrl";
26
- var platform = navigator.platform || "";
27
- if (platform.indexOf("Mac") !== -1) return "⌘";
28
- return "Ctrl";
29
- }
30
-
31
- var historyBySession = new Map<string, string[]>();
32
- var MAX_HISTORY = 100;
33
-
34
- function extractTypedInput(text: string): string | null {
35
- var firstNewline = text.search(/\r?\n/);
36
- var firstLine = firstNewline !== -1 ? text.slice(0, firstNewline).trim() : text;
37
- if (firstLine.indexOf(":") !== -1 && /\n---[\r\n]/.test(text)) {
38
- return "/" + firstLine;
39
- }
40
- if (text.startsWith("<skill-name>")) {
41
- var endTag = text.indexOf("</skill-name>");
42
- if (endTag !== -1) {
43
- return "/" + text.slice(12, endTag);
44
- }
45
- return null;
46
- }
47
- if (text.startsWith("<skill-content>")) return null;
48
- if (text.length > 500) return null;
49
- return text;
50
- }
51
-
52
- function getHistory(sessionId: string | null | undefined): string[] {
53
- if (!sessionId) return [];
54
- var hist = historyBySession.get(sessionId);
55
- if (!hist) {
56
- hist = [];
57
- historyBySession.set(sessionId, hist);
58
- }
59
- return hist;
60
- }
61
-
62
- export function ChatInput(props: ChatInputProps) {
63
- var textareaRef = useRef<HTMLTextAreaElement>(null);
64
- var popupRef = useRef<HTMLDivElement>(null);
65
- var settingsRef = useRef<HTMLDivElement>(null);
66
- var settingsBtnRef = useRef<HTMLButtonElement>(null);
67
- var skills = useSkills();
68
- var [slashQuery, setSlashQuery] = useState<string | null>(null);
69
- var [selectedIndex, setSelectedIndex] = useState(0);
70
- var [showMobileSettings, setShowMobileSettings] = useState(false);
71
- var modKey = useMemo(getModKey, []);
72
- var [historyIndex, setHistoryIndex] = useState(-1);
73
- var savedCurrentRef = useRef("");
74
- var inputHistory = getHistory(props.sessionId);
75
- var historyLoading = useStore(getSessionStore(), function (s) { return s.historyLoading; });
76
- var messages = useStore(getSessionStore(), function (s) { return s.messages; });
77
-
78
- useEffect(function () {
79
- setHistoryIndex(-1);
80
- savedCurrentRef.current = "";
81
- }, [props.sessionId]);
82
-
83
- useEffect(function () {
84
- if (!props.sessionId || historyLoading) return;
85
- for (var i = 0; i < messages.length; i++) {
86
- if (messages[i].type === "user" && messages[i].text) {
87
- var typed = extractTypedInput(messages[i].text!.trim());
88
- if (typed && inputHistory.indexOf(typed) === -1) {
89
- inputHistory.push(typed);
90
- }
91
- }
92
- }
93
- if (inputHistory.length > MAX_HISTORY) {
94
- inputHistory.splice(0, inputHistory.length - MAX_HISTORY);
95
- }
96
- }, [props.sessionId, historyLoading]);
97
-
98
- var attachmentsHook = useAttachments();
99
- var voice = useVoiceRecorder();
100
- var [isDragging, setIsDragging] = useState(false);
101
- var dragCounter = useRef(0);
102
- var fileInputRef = useRef<HTMLInputElement>(null);
103
- var savedTextRef = useRef("");
104
-
105
- var itemCount = useMemo(function () {
106
- if (slashQuery === null) return 0;
107
- return getFilteredItems(slashQuery, skills).length;
108
- }, [slashQuery, skills]);
109
-
110
- var isOpen = slashQuery !== null && itemCount > 0;
111
-
112
- useEffect(function () {
113
- setSelectedIndex(0);
114
- }, [slashQuery]);
115
-
116
- useEffect(function () {
117
- if (!isOpen || !popupRef.current) return;
118
- var active = popupRef.current.querySelector("[data-active='true']") as HTMLElement | null;
119
- if (active) {
120
- active.scrollIntoView({ block: "nearest" });
121
- }
122
- }, [selectedIndex, isOpen]);
123
-
124
- useEffect(function () {
125
- if (!showMobileSettings) return;
126
- function handleClick(e: MouseEvent) {
127
- var target = e.target as Node;
128
- if (settingsRef.current && settingsRef.current.contains(target)) return;
129
- if (settingsBtnRef.current && settingsBtnRef.current.contains(target)) return;
130
- setShowMobileSettings(false);
131
- }
132
- document.addEventListener("mousedown", handleClick);
133
- return function () { document.removeEventListener("mousedown", handleClick); };
134
- }, [showMobileSettings]);
135
-
136
- useEffect(function () {
137
- if (props.failedInput && textareaRef.current) {
138
- var el = textareaRef.current;
139
- el.value = props.failedInput;
140
- el.style.height = "auto";
141
- el.style.height = Math.min(el.scrollHeight, 160) + "px";
142
- el.focus();
143
- checkSlash();
144
- if (props.onFailedInputConsumed) {
145
- props.onFailedInputConsumed();
146
- }
147
- }
148
- }, [props.failedInput]);
149
-
150
- useEffect(function () {
151
- if (props.prefillText && textareaRef.current) {
152
- var el = textareaRef.current;
153
- el.value = props.prefillText;
154
- el.style.height = "auto";
155
- el.style.height = Math.min(el.scrollHeight, 160) + "px";
156
- el.focus();
157
- checkSlash();
158
- if (props.onPrefillConsumed) {
159
- props.onPrefillConsumed();
160
- }
161
- }
162
- }, [props.prefillText]);
163
-
164
- function checkSlash() {
165
- var el = textareaRef.current;
166
- if (!el) return;
167
- var val = el.value;
168
- if (val.startsWith("/")) {
169
- setSlashQuery(val.slice(1));
170
- } else {
171
- setSlashQuery(null);
172
- }
173
- }
174
-
175
- function selectItem(item: { name: string; args?: string; category: string; handler: string }) {
176
- var el = textareaRef.current;
177
- if (!el) return;
178
-
179
- var hasArgs = !!item.args;
180
- var isSkill = item.category === "skill";
181
-
182
- if (hasArgs || isSkill) {
183
- el.value = "/" + item.name + " ";
184
- el.focus();
185
- setSlashQuery(null);
186
- } else {
187
- props.onSend("/" + item.name, []);
188
- el.value = "";
189
- el.style.height = "auto";
190
- setSlashQuery(null);
191
- }
192
- }
193
-
194
- function handleKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>) {
195
- if (isOpen) {
196
- if (e.key === "ArrowUp") {
197
- e.preventDefault();
198
- setSelectedIndex(function (i) { return i > 0 ? i - 1 : itemCount - 1; });
199
- return;
200
- }
201
- if (e.key === "ArrowDown") {
202
- e.preventDefault();
203
- setSelectedIndex(function (i) { return i < itemCount - 1 ? i + 1 : 0; });
204
- return;
205
- }
206
- if (e.key === "Tab" || (e.key === "Enter" && !e.shiftKey)) {
207
- e.preventDefault();
208
- var items = getFilteredItems(slashQuery!, skills);
209
- if (items[selectedIndex]) {
210
- selectItem(items[selectedIndex]);
211
- }
212
- return;
213
- }
214
- if (e.key === "Escape") {
215
- e.preventDefault();
216
- setSlashQuery(null);
217
- return;
218
- }
219
- }
220
- if (e.key === "Enter" && !e.shiftKey) {
221
- e.preventDefault();
222
- submit();
223
- return;
224
- }
225
-
226
- if (e.key === "ArrowUp" && inputHistory.length > 0) {
227
- var el = textareaRef.current;
228
- if (!el) return;
229
- var val = el.value;
230
- var cursorPos = el.selectionStart;
231
- var isAtTop = cursorPos === 0 || val.indexOf("\n") === -1 || cursorPos <= val.indexOf("\n");
232
- if (isAtTop) {
233
- e.preventDefault();
234
- if (historyIndex === -1) {
235
- savedCurrentRef.current = val;
236
- }
237
- var newIdx = historyIndex === -1 ? inputHistory.length - 1 : Math.max(0, historyIndex - 1);
238
- setHistoryIndex(newIdx);
239
- el.value = inputHistory[newIdx];
240
- el.style.height = "auto";
241
- el.style.height = Math.min(el.scrollHeight, 160) + "px";
242
- el.setSelectionRange(0, 0);
243
- }
244
- return;
245
- }
246
-
247
- if (e.key === "ArrowDown" && historyIndex >= 0) {
248
- var el = textareaRef.current;
249
- if (!el) return;
250
- var val = el.value;
251
- var cursorPos = el.selectionStart;
252
- var lastNewline = val.lastIndexOf("\n");
253
- var isAtBottom = lastNewline === -1 || cursorPos > lastNewline;
254
- if (isAtBottom) {
255
- e.preventDefault();
256
- if (historyIndex >= inputHistory.length - 1) {
257
- setHistoryIndex(-1);
258
- el.value = savedCurrentRef.current;
259
- } else {
260
- var newIdx = historyIndex + 1;
261
- setHistoryIndex(newIdx);
262
- el.value = inputHistory[newIdx];
263
- }
264
- el.style.height = "auto";
265
- el.style.height = Math.min(el.scrollHeight, 160) + "px";
266
- var len = el.value.length;
267
- el.setSelectionRange(len, len);
268
- }
269
- return;
270
- }
271
- }
272
-
273
- function handleInput(e: React.FormEvent<HTMLTextAreaElement>) {
274
- var el = e.currentTarget;
275
- el.style.height = "auto";
276
- el.style.height = Math.min(el.scrollHeight, 160) + "px";
277
- checkSlash();
278
- }
279
-
280
- function handlePaste(e: React.ClipboardEvent<HTMLTextAreaElement>) {
281
- var items = e.clipboardData.items;
282
- for (var i = 0; i < items.length; i++) {
283
- if (items[i].type.startsWith("image/")) {
284
- e.preventDefault();
285
- var file = items[i].getAsFile();
286
- if (file && attachmentsHook.canAttach) {
287
- attachmentsHook.addFile(file);
288
- }
289
- return;
290
- }
291
- }
292
-
293
- var text = e.clipboardData.getData("text/plain");
294
- if (text && text.split("\n").length >= 10) {
295
- e.preventDefault();
296
- if (attachmentsHook.canAttach) {
297
- attachmentsHook.addPaste(text);
298
- }
299
- }
300
- }
301
-
302
- function handleDragEnter(e: React.DragEvent) {
303
- e.preventDefault();
304
- dragCounter.current++;
305
- if (e.dataTransfer.types.indexOf("Files") !== -1) {
306
- setIsDragging(true);
307
- }
308
- }
309
-
310
- function handleDragLeave(e: React.DragEvent) {
311
- e.preventDefault();
312
- dragCounter.current--;
313
- if (dragCounter.current === 0) {
314
- setIsDragging(false);
315
- }
316
- }
317
-
318
- function handleDragOver(e: React.DragEvent) {
319
- e.preventDefault();
320
- }
321
-
322
- function handleDrop(e: React.DragEvent) {
323
- e.preventDefault();
324
- dragCounter.current = 0;
325
- setIsDragging(false);
326
- var files = e.dataTransfer.files;
327
- for (var i = 0; i < files.length; i++) {
328
- if (attachmentsHook.canAttach) {
329
- attachmentsHook.addFile(files[i]);
330
- }
331
- }
332
- }
333
-
334
- function handleVoiceStart() {
335
- savedTextRef.current = textareaRef.current?.value || "";
336
- voice.start();
337
- }
338
-
339
- function handleVoiceStop() {
340
- var transcript = voice.stop();
341
- if (transcript && textareaRef.current) {
342
- var el = textareaRef.current;
343
- var existing = savedTextRef.current;
344
- el.value = existing ? existing + " " + transcript : transcript;
345
- el.style.height = "auto";
346
- el.style.height = Math.min(el.scrollHeight, 160) + "px";
347
- }
348
- }
349
-
350
- function handleVoiceCancel() {
351
- voice.cancel();
352
- if (textareaRef.current) {
353
- textareaRef.current.value = savedTextRef.current;
354
- }
355
- }
356
-
357
- function submit() {
358
- var el = textareaRef.current;
359
- if (!el) return;
360
- var text = el.value.trim();
361
- if ((!text && attachmentsHook.attachments.length === 0) || props.disabled || attachmentsHook.hasUploading) return;
362
- if (text) {
363
- if (inputHistory.length === 0 || inputHistory[inputHistory.length - 1] !== text) {
364
- inputHistory.push(text);
365
- if (inputHistory.length > MAX_HISTORY) inputHistory.shift();
366
- }
367
- }
368
- setHistoryIndex(-1);
369
- savedCurrentRef.current = "";
370
- props.onSend(text, attachmentsHook.readyIds);
371
- el.value = "";
372
- el.style.height = "auto";
373
- setSlashQuery(null);
374
- attachmentsHook.clearAll();
375
- }
376
-
377
- return (
378
- <div
379
- className="relative"
380
- onDragEnter={handleDragEnter}
381
- onDragLeave={handleDragLeave}
382
- onDragOver={handleDragOver}
383
- onDrop={handleDrop}
384
- >
385
- {isOpen && (
386
- <div ref={popupRef}>
387
- <CommandPalette
388
- query={slashQuery!}
389
- skills={skills}
390
- selectedIndex={selectedIndex}
391
- onSelect={selectItem}
392
- onHover={setSelectedIndex}
393
- />
394
- </div>
395
- )}
396
-
397
- {showMobileSettings && (
398
- <div
399
- ref={settingsRef}
400
- className="absolute right-0 bottom-[calc(100%+6px)] rounded-lg border border-base-content/10 bg-base-300 shadow-lg z-50 p-2.5 min-w-[200px] sm:hidden"
401
- >
402
- <div className="flex flex-col gap-2">
403
- {props.toolbarContent}
404
- </div>
405
- </div>
406
- )}
407
-
408
- <input
409
- ref={fileInputRef}
410
- type="file"
411
- multiple
412
- className="hidden"
413
- onChange={function (e) {
414
- var files = e.target.files;
415
- if (files) {
416
- for (var i = 0; i < files.length; i++) {
417
- if (attachmentsHook.canAttach) {
418
- attachmentsHook.addFile(files[i]);
419
- }
420
- }
421
- }
422
- e.target.value = "";
423
- }}
424
- />
425
-
426
- <div
427
- className={
428
- "border rounded-xl bg-base-300/60 overflow-hidden transition-all duration-150 " +
429
- (isDragging
430
- ? "border-primary/40 shadow-[0_0_0_3px_oklch(from_var(--color-primary)_l_c_h/0.1)]"
431
- : props.disabled
432
- ? "border-base-content/10 opacity-60"
433
- : "border-primary/20 focus-within:border-primary/40 focus-within:shadow-[0_0_0_3px_oklch(from_var(--color-primary)_l_c_h/0.1)]")
434
- }
435
- >
436
- <div className="hidden sm:flex items-center gap-1.5 px-3 py-1.5 border-b border-base-content/8 font-mono text-[10px]">
437
- {props.toolbarContent}
438
- <span className="flex-1" />
439
- <span className="text-base-content/20">{modKey}+K commands</span>
440
- </div>
441
-
442
- <AttachmentChips
443
- attachments={attachmentsHook.attachments}
444
- onRemove={attachmentsHook.removeAttachment}
445
- onRetry={attachmentsHook.retryAttachment}
446
- />
447
-
448
- <div className="flex items-center gap-2 px-3.5 py-2.5">
449
- <div className="flex gap-1 flex-shrink-0">
450
- <button
451
- aria-label="Attach file"
452
- disabled={!attachmentsHook.canAttach}
453
- onClick={function () { fileInputRef.current?.click(); }}
454
- className={
455
- "w-7 h-7 rounded-md flex items-center justify-center transition-colors " +
456
- (attachmentsHook.canAttach
457
- ? "text-base-content/30 hover:text-base-content/50 border border-base-content/10 hover:border-base-content/20"
458
- : "text-base-content/15 cursor-not-allowed")
459
- }
460
- title={attachmentsHook.canAttach ? "Attach file" : "Maximum attachments reached"}
461
- >
462
- <Paperclip size={13} />
463
- </button>
464
- <VoiceRecorder
465
- isRecording={voice.isRecording}
466
- isSupported={voice.isSupported}
467
- isSpeaking={voice.isSpeaking}
468
- elapsed={voice.elapsed}
469
- interimTranscript={voice.interimTranscript}
470
- onStart={handleVoiceStart}
471
- onStop={handleVoiceStop}
472
- onCancel={handleVoiceCancel}
473
- />
474
- </div>
475
-
476
- {voice.isRecording ? null : (
477
- <div className="flex-1 min-w-0 relative">
478
- <span className="absolute left-0 top-[1px] text-primary/50 font-mono text-[14px] leading-relaxed select-none pointer-events-none">›</span>
479
- <textarea
480
- ref={textareaRef}
481
- data-allow-context-menu
482
- aria-label="Message input"
483
- placeholder={props.disabled ? (props.disabledPlaceholder || "Claude is responding...") : "Message Claude..."}
484
- disabled={props.disabled}
485
- onKeyDown={handleKeyDown}
486
- onInput={handleInput}
487
- onPaste={handlePaste}
488
- rows={1}
489
- style={{ padding: "1px 0 0 16px", margin: 0, border: "none" }}
490
- className={
491
- "w-full resize-none bg-transparent text-base-content text-[14px] leading-relaxed max-h-[160px] overflow-y-auto outline-none placeholder:text-base-content/30 " +
492
- (props.disabled ? "cursor-not-allowed" : "cursor-text")
493
- }
494
- />
495
- </div>
496
- )}
497
-
498
- <div className="flex items-center gap-1.5 flex-shrink-0">
499
- <button
500
- ref={settingsBtnRef}
501
- aria-label="Chat settings"
502
- onClick={function () { setShowMobileSettings(!showMobileSettings); }}
503
- className={"sm:hidden w-8 h-8 rounded-lg flex items-center justify-center transition-colors " + (showMobileSettings ? "bg-base-content/10 text-base-content/60" : "text-base-content/30 hover:text-base-content/50")}
504
- >
505
- <Settings size={15} />
506
- </button>
507
- <span className="text-[10px] text-base-content/20 font-mono hidden sm:block">⏎ send</span>
508
- <button
509
- aria-label="Send message"
510
- disabled={props.disabled || attachmentsHook.hasUploading}
511
- onClick={submit}
512
- title={attachmentsHook.hasUploading ? "Uploading..." : "Send message"}
513
- className={
514
- "w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0 transition-all duration-150 outline-none " +
515
- (props.disabled || attachmentsHook.hasUploading
516
- ? "bg-base-content/5 text-base-content/20 cursor-not-allowed"
517
- : "bg-primary text-primary-content hover:bg-primary/80 cursor-pointer focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-base-300")
518
- }
519
- >
520
- <SendHorizontal size={14} />
521
- </button>
522
- </div>
523
- </div>
524
- </div>
525
-
526
- {isDragging && (
527
- <div className="absolute inset-0 rounded-xl border-2 border-dashed border-primary/40 bg-primary/5 flex items-center justify-center z-40 pointer-events-none">
528
- <span className="text-[13px] text-primary/60 font-mono">Drop files to attach</span>
529
- </div>
530
- )}
531
- </div>
532
- );
533
- }