@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,920 +0,0 @@
1
- import { readdirSync, existsSync, readFileSync, statSync } from "node:fs";
2
- import { readFile } from "node:fs/promises";
3
- import { homedir } from "node:os";
4
- import { join } from "node:path";
5
- import type { AnalyticsPayload, AnalyticsPeriod, AnalyticsScope, AnalyticsSectionName } from "#shared";
6
- import { estimateCost, projectPathToHash } from "../project/session";
7
- import { loadConfig } from "../config";
8
-
9
- interface ResponseTimeDatum {
10
- tokens: number;
11
- duration: number;
12
- model: string;
13
- }
14
-
15
- interface ContextMessage {
16
- messageIndex: number;
17
- inputTokens: number;
18
- model: string;
19
- }
20
-
21
- interface SessionData {
22
- id: string;
23
- title: string;
24
- project: string;
25
- cost: number;
26
- inputTokens: number;
27
- outputTokens: number;
28
- cacheReadTokens: number;
29
- cacheCreationTokens: number;
30
- models: Map<string, { cost: number; tokens: number }>;
31
- tools: Map<string, number>;
32
- startTime: number;
33
- endTime: number;
34
- responseTimePoints: ResponseTimeDatum[];
35
- contextMessages: ContextMessage[];
36
- }
37
-
38
- interface CacheEntry {
39
- data: AnalyticsPayload;
40
- timestamp: number;
41
- }
42
-
43
- var cache = new Map<string, CacheEntry>();
44
- var CACHE_TTL = 5 * 60 * 1000;
45
- var inflight = new Map<string, Promise<AnalyticsPayload>>();
46
-
47
- export var SECTION_KEYS: Record<AnalyticsSectionName, Array<keyof AnalyticsPayload>> = {
48
- summary: ["totalCost", "totalSessions", "totalTokens", "cacheHitRate", "avgSessionCost", "avgSessionDuration", "costOverTime", "cumulativeCost", "sessionsOverTime", "tokensOverTime", "cacheHitRateOverTime"],
49
- spending: ["costDistribution", "sessionBubbles", "modelUsage", "projectBreakdown"],
50
- usage: ["toolUsage", "responseTimeData", "contextUtilization", "tokenFlowSankey"],
51
- activity: ["activityCalendar", "hourlyHeatmap", "sessionTimeline", "dailySummaries"],
52
- projects: ["toolTreemap", "toolSunburst", "permissionStats", "projectRadar", "sessionComplexity"],
53
- };
54
-
55
- function bucketModel(model: string): "opus" | "sonnet" | "haiku" | "other" {
56
- if (model.includes("opus")) return "opus";
57
- if (model.includes("haiku")) return "haiku";
58
- if (model.includes("sonnet")) return "sonnet";
59
- return "other";
60
- }
61
-
62
- function getPeriodCutoff(period: AnalyticsPeriod): number {
63
- if (period === "all") return 0;
64
- var now = Date.now();
65
- var hours: Record<string, number> = { "24h": 24, "7d": 168, "30d": 720, "90d": 2160 };
66
- return now - (hours[period] || 0) * 60 * 60 * 1000;
67
- }
68
-
69
- function formatDate(ts: number): string {
70
- var d = new Date(ts);
71
- var year = d.getFullYear();
72
- var month = String(d.getMonth() + 1).padStart(2, "0");
73
- var day = String(d.getDate()).padStart(2, "0");
74
- return year + "-" + month + "-" + day;
75
- }
76
-
77
- function getCostBucket(cost: number): string | null {
78
- if (cost <= 0) return null;
79
- if (cost < 0.01) return "<$0.01";
80
- if (cost < 0.05) return "$0.01-0.05";
81
- if (cost < 0.10) return "$0.05-0.10";
82
- if (cost < 0.50) return "$0.10-0.50";
83
- if (cost < 1.00) return "$0.50-1.00";
84
- if (cost < 5.00) return "$1.00-5.00";
85
- return "$5.00+";
86
- }
87
-
88
- function parseSessionText(text: string, sessionId: string, projectSlug: string): SessionData | null {
89
- try {
90
- var lines = text.split("\n");
91
- var data: SessionData = {
92
- id: sessionId,
93
- title: "",
94
- project: projectSlug,
95
- cost: 0,
96
- inputTokens: 0,
97
- outputTokens: 0,
98
- cacheReadTokens: 0,
99
- cacheCreationTokens: 0,
100
- models: new Map(),
101
- tools: new Map(),
102
- startTime: 0,
103
- endTime: 0,
104
- responseTimePoints: [],
105
- contextMessages: [],
106
- };
107
-
108
- var lastUserTimestamp = 0;
109
- var assistantIndex = 0;
110
-
111
- for (var i = 0; i < lines.length; i++) {
112
- var line = lines[i].trim();
113
- if (!line) continue;
114
-
115
- var parsed: Record<string, unknown>;
116
- try {
117
- parsed = JSON.parse(line);
118
- } catch {
119
- continue;
120
- }
121
-
122
- var timestamp = 0;
123
- if (typeof parsed.timestamp === "string") {
124
- var ts = new Date(parsed.timestamp as string).getTime();
125
- if (!isNaN(ts)) timestamp = ts;
126
- }
127
-
128
- if (timestamp > 0) {
129
- if (data.startTime === 0 || timestamp < data.startTime) data.startTime = timestamp;
130
- if (timestamp > data.endTime) data.endTime = timestamp;
131
- }
132
-
133
- if (parsed.type === "assistant") {
134
- var message = parsed.message as Record<string, unknown> | undefined;
135
- if (!message) continue;
136
-
137
- var usage = message.usage as Record<string, number> | undefined;
138
- var model = (message.model as string) || "";
139
-
140
- if (usage) {
141
- var inTok = usage.input_tokens || 0;
142
- var outTok = usage.output_tokens || 0;
143
- var cacheRead = usage.cache_read_input_tokens || 0;
144
- var cacheCreation = usage.cache_creation_input_tokens || 0;
145
-
146
- data.inputTokens += inTok;
147
- data.outputTokens += outTok;
148
- data.cacheReadTokens += cacheRead;
149
- data.cacheCreationTokens += cacheCreation;
150
-
151
- var cost = estimateCost(model, inTok, outTok, cacheRead, cacheCreation);
152
- data.cost += cost;
153
-
154
- var bucket = bucketModel(model);
155
- var existing = data.models.get(bucket);
156
- if (existing) {
157
- existing.cost += cost;
158
- existing.tokens += inTok + outTok;
159
- } else {
160
- data.models.set(bucket, { cost: cost, tokens: inTok + outTok });
161
- }
162
-
163
- if (outTok > 0 && timestamp > 0 && lastUserTimestamp > 0) {
164
- var dur = timestamp - lastUserTimestamp;
165
- if (dur > 0 && dur < 600000) {
166
- data.responseTimePoints.push({ tokens: outTok, duration: dur, model: bucket });
167
- }
168
- }
169
-
170
- data.contextMessages.push({ messageIndex: assistantIndex, inputTokens: inTok + cacheRead + cacheCreation, model: bucket });
171
- assistantIndex++;
172
- }
173
-
174
- if (!data.title && message.content) {
175
- if (typeof message.content === "string" && message.content.length > 0) {
176
- data.title = message.content.slice(0, 80);
177
- }
178
- }
179
- } else if (parsed.type === "user") {
180
- if (timestamp > 0) lastUserTimestamp = timestamp;
181
- var userMsg = parsed.message as Record<string, unknown> | undefined;
182
- if (!userMsg || !Array.isArray(userMsg.content)) continue;
183
-
184
- var contentArr = userMsg.content as Array<Record<string, unknown>>;
185
- for (var j = 0; j < contentArr.length; j++) {
186
- var block = contentArr[j];
187
- if (block.type === "tool_result" && typeof block.tool_use_id === "string") {
188
- var toolName = (block.name as string) || "unknown";
189
- data.tools.set(toolName, (data.tools.get(toolName) || 0) + 1);
190
- }
191
- }
192
-
193
- if (!data.title && Array.isArray(userMsg.content)) {
194
- for (var k = 0; k < contentArr.length; k++) {
195
- if (contentArr[k].type === "text" && typeof contentArr[k].text === "string") {
196
- data.title = (contentArr[k].text as string).slice(0, 80);
197
- break;
198
- }
199
- }
200
- }
201
- }
202
- }
203
-
204
- if (!data.title) data.title = "Session " + sessionId.slice(0, 8);
205
-
206
- return data;
207
- } catch {
208
- return null;
209
- }
210
- }
211
-
212
- function parseSessionFile(filePath: string, sessionId: string, projectSlug: string): SessionData | null {
213
- try {
214
- var text = readFileSync(filePath, "utf-8");
215
- return parseSessionText(text, sessionId, projectSlug);
216
- } catch {
217
- return null;
218
- }
219
- }
220
-
221
- async function parseSessionFileAsync(filePath: string, sessionId: string, projectSlug: string): Promise<SessionData | null> {
222
- try {
223
- var text = await readFile(filePath, "utf-8");
224
- return parseSessionText(text, sessionId, projectSlug);
225
- } catch {
226
- return null;
227
- }
228
- }
229
-
230
- function getSessionFilesForProject(projectPath: string, cutoff?: number): Array<{ path: string; id: string }> {
231
- var hash = projectPathToHash(projectPath);
232
- var dir = join(homedir(), ".claude", "projects", hash);
233
- if (!existsSync(dir)) return [];
234
-
235
- var files: Array<{ path: string; id: string }> = [];
236
- try {
237
- var entries = readdirSync(dir);
238
- for (var i = 0; i < entries.length; i++) {
239
- if (!entries[i].endsWith(".jsonl")) continue;
240
- var filePath = join(dir, entries[i]);
241
- if (cutoff && cutoff > 0) {
242
- try {
243
- var mtime = statSync(filePath).mtimeMs;
244
- if (mtime < cutoff) continue;
245
- } catch {
246
- // include if stat fails
247
- }
248
- }
249
- files.push({ path: filePath, id: entries[i].replace(".jsonl", "") });
250
- }
251
- } catch {
252
- return [];
253
- }
254
- return files;
255
- }
256
-
257
- function aggregate(sessions: SessionData[], period: AnalyticsPeriod): AnalyticsPayload {
258
- var cutoff = getPeriodCutoff(period);
259
- var filtered: SessionData[] = [];
260
- for (var i = 0; i < sessions.length; i++) {
261
- var s = sessions[i];
262
- var sessionTime = s.endTime > 0 ? s.endTime : s.startTime;
263
- if (sessionTime >= cutoff) filtered.push(s);
264
- }
265
-
266
- var totalCost = 0;
267
- var totalInput = 0;
268
- var totalOutput = 0;
269
- var totalCacheRead = 0;
270
- var totalCacheCreation = 0;
271
- var totalDuration = 0;
272
- var durationCount = 0;
273
-
274
- var dailyCost = new Map<string, { total: number; opus: number; sonnet: number; haiku: number; other: number }>();
275
- var dailySessions = new Map<string, number>();
276
- var dailyTokens = new Map<string, { input: number; output: number; cacheRead: number }>();
277
- var dailyCacheHit = new Map<string, { cacheRead: number; totalInput: number }>();
278
-
279
- var modelStats = new Map<string, { sessions: number; cost: number; tokens: number }>();
280
- var projectStats = new Map<string, { cost: number; sessions: number; tokens: number }>();
281
- var toolStats = new Map<string, { count: number; totalCost: number; sessions: number }>();
282
-
283
- var costBuckets = new Map<string, number>();
284
- var bucketOrder = ["<$0.01", "$0.01-0.05", "$0.05-0.10", "$0.10-0.50", "$0.50-1.00", "$1.00-5.00", "$5.00+"];
285
- for (var b = 0; b < bucketOrder.length; b++) {
286
- costBuckets.set(bucketOrder[b], 0);
287
- }
288
-
289
- for (var si = 0; si < filtered.length; si++) {
290
- var sess = filtered[si];
291
- totalCost += sess.cost;
292
- totalInput += sess.inputTokens;
293
- totalOutput += sess.outputTokens;
294
- totalCacheRead += sess.cacheReadTokens;
295
- totalCacheCreation += sess.cacheCreationTokens;
296
-
297
- if (sess.startTime > 0 && sess.endTime > 0 && sess.endTime > sess.startTime) {
298
- totalDuration += sess.endTime - sess.startTime;
299
- durationCount++;
300
- }
301
-
302
- var date = formatDate(sess.endTime > 0 ? sess.endTime : sess.startTime);
303
-
304
- var dc = dailyCost.get(date);
305
- if (!dc) {
306
- dc = { total: 0, opus: 0, sonnet: 0, haiku: 0, other: 0 };
307
- dailyCost.set(date, dc);
308
- }
309
- dc.total += sess.cost;
310
- sess.models.forEach(function (val, key) {
311
- dc![key as "opus" | "sonnet" | "haiku" | "other"] += val.cost;
312
- });
313
-
314
- dailySessions.set(date, (dailySessions.get(date) || 0) + 1);
315
-
316
- var dt = dailyTokens.get(date);
317
- if (!dt) {
318
- dt = { input: 0, output: 0, cacheRead: 0 };
319
- dailyTokens.set(date, dt);
320
- }
321
- dt.input += sess.inputTokens;
322
- dt.output += sess.outputTokens;
323
- dt.cacheRead += sess.cacheReadTokens;
324
-
325
- var dch = dailyCacheHit.get(date);
326
- if (!dch) {
327
- dch = { cacheRead: 0, totalInput: 0 };
328
- dailyCacheHit.set(date, dch);
329
- }
330
- dch.cacheRead += sess.cacheReadTokens;
331
- dch.totalInput += sess.inputTokens;
332
-
333
- sess.models.forEach(function (val, key) {
334
- var ms = modelStats.get(key);
335
- if (!ms) {
336
- ms = { sessions: 0, cost: 0, tokens: 0 };
337
- modelStats.set(key, ms);
338
- }
339
- ms.sessions++;
340
- ms.cost += val.cost;
341
- ms.tokens += val.tokens;
342
- });
343
-
344
- var ps = projectStats.get(sess.project);
345
- if (!ps) {
346
- ps = { cost: 0, sessions: 0, tokens: 0 };
347
- projectStats.set(sess.project, ps);
348
- }
349
- ps.cost += sess.cost;
350
- ps.sessions++;
351
- ps.tokens += sess.inputTokens + sess.outputTokens;
352
-
353
- sess.tools.forEach(function (count, tool) {
354
- var ts = toolStats.get(tool);
355
- if (!ts) {
356
- ts = { count: 0, totalCost: 0, sessions: 0 };
357
- toolStats.set(tool, ts);
358
- }
359
- ts.count += count;
360
- ts.totalCost += sess.cost;
361
- ts.sessions++;
362
- });
363
-
364
- var bucket = getCostBucket(sess.cost);
365
- if (bucket) {
366
- costBuckets.set(bucket, (costBuckets.get(bucket) || 0) + 1);
367
- }
368
- }
369
-
370
- var totalTokensAll = totalInput + totalOutput + totalCacheRead + totalCacheCreation;
371
- var cacheHitRate = (totalInput + totalCacheRead) > 0 ? totalCacheRead / (totalInput + totalCacheRead) : 0;
372
-
373
- var dates = Array.from(dailyCost.keys()).sort();
374
-
375
- var costOverTime: AnalyticsPayload["costOverTime"] = [];
376
- var cumulativeCost: AnalyticsPayload["cumulativeCost"] = [];
377
- var sessionsOverTime: AnalyticsPayload["sessionsOverTime"] = [];
378
- var tokensOverTime: AnalyticsPayload["tokensOverTime"] = [];
379
- var cacheHitRateOverTime: AnalyticsPayload["cacheHitRateOverTime"] = [];
380
-
381
- var cumTotal = 0;
382
- for (var di = 0; di < dates.length; di++) {
383
- var d = dates[di];
384
- var dcEntry = dailyCost.get(d)!;
385
- cumTotal += dcEntry.total;
386
-
387
- costOverTime.push({
388
- date: d,
389
- total: dcEntry.total,
390
- opus: dcEntry.opus,
391
- sonnet: dcEntry.sonnet,
392
- haiku: dcEntry.haiku,
393
- other: dcEntry.other,
394
- });
395
- cumulativeCost.push({ date: d, total: cumTotal });
396
- sessionsOverTime.push({ date: d, count: dailySessions.get(d) || 0 });
397
-
398
- var dtEntry = dailyTokens.get(d);
399
- tokensOverTime.push({
400
- date: d,
401
- input: dtEntry ? dtEntry.input : 0,
402
- output: dtEntry ? dtEntry.output : 0,
403
- cacheRead: dtEntry ? dtEntry.cacheRead : 0,
404
- });
405
-
406
- var dchEntry = dailyCacheHit.get(d);
407
- var rate = dchEntry && (dchEntry.totalInput + dchEntry.cacheRead) > 0 ? dchEntry.cacheRead / (dchEntry.totalInput + dchEntry.cacheRead) : 0;
408
- cacheHitRateOverTime.push({ date: d, rate: rate });
409
- }
410
-
411
- var costDistribution: AnalyticsPayload["costDistribution"] = [];
412
- for (var bi = 0; bi < bucketOrder.length; bi++) {
413
- costDistribution.push({
414
- bucket: bucketOrder[bi],
415
- count: costBuckets.get(bucketOrder[bi]) || 0,
416
- });
417
- }
418
-
419
- var sessionBubbles: AnalyticsPayload["sessionBubbles"] = [];
420
- var nonZeroCost = filtered.filter(function (s) { return s.cost > 0; });
421
- var sorted = nonZeroCost.slice().sort(function (a, b) {
422
- return (b.endTime || b.startTime) - (a.endTime || a.startTime);
423
- });
424
- var bubbleCap = Math.min(sorted.length, 200);
425
- for (var sbi = 0; sbi < bubbleCap; sbi++) {
426
- var sb = sorted[sbi];
427
- sessionBubbles.push({
428
- id: sb.id,
429
- title: sb.title,
430
- cost: sb.cost,
431
- tokens: sb.inputTokens + sb.outputTokens,
432
- timestamp: sb.endTime > 0 ? sb.endTime : sb.startTime,
433
- project: sb.project,
434
- });
435
- }
436
-
437
- var modelUsage: AnalyticsPayload["modelUsage"] = [];
438
- var totalModelCost = totalCost || 1;
439
- modelStats.forEach(function (val, key) {
440
- modelUsage.push({
441
- model: key,
442
- sessions: val.sessions,
443
- cost: val.cost,
444
- tokens: val.tokens,
445
- percentage: (val.cost / totalModelCost) * 100,
446
- });
447
- });
448
- modelUsage.sort(function (a: typeof modelUsage[number], b: typeof modelUsage[number]) { return b.cost - a.cost; });
449
-
450
- var projectBreakdown: AnalyticsPayload["projectBreakdown"] = [];
451
- projectStats.forEach(function (val, key) {
452
- projectBreakdown.push({
453
- project: key,
454
- cost: val.cost,
455
- sessions: val.sessions,
456
- tokens: val.tokens,
457
- });
458
- });
459
- projectBreakdown.sort(function (a: typeof projectBreakdown[number], b: typeof projectBreakdown[number]) { return b.cost - a.cost; });
460
-
461
- var toolUsage: AnalyticsPayload["toolUsage"] = [];
462
- toolStats.forEach(function (val, key) {
463
- toolUsage.push({
464
- tool: key,
465
- count: val.count,
466
- avgCost: val.sessions > 0 ? val.totalCost / val.sessions : 0,
467
- });
468
- });
469
- toolUsage.sort(function (a: typeof toolUsage[number], b: typeof toolUsage[number]) { return b.count - a.count; });
470
-
471
- var responseTimeData: AnalyticsPayload["responseTimeData"] = [];
472
- for (var rti = 0; rti < filtered.length; rti++) {
473
- var rtSess = filtered[rti];
474
- for (var rtj = 0; rtj < rtSess.responseTimePoints.length; rtj++) {
475
- var rtp = rtSess.responseTimePoints[rtj];
476
- responseTimeData.push({ tokens: rtp.tokens, duration: rtp.duration, model: rtp.model, sessionId: rtSess.id });
477
- }
478
- if (responseTimeData.length >= 200) break;
479
- }
480
- if (responseTimeData.length > 200) responseTimeData.length = 200;
481
-
482
- var contextWindowSizes: Record<string, number> = { opus: 200000, sonnet: 200000, haiku: 200000, other: 200000 };
483
- var contextUtilization: AnalyticsPayload["contextUtilization"] = [];
484
- var recentSessions = sorted.slice(0, 5);
485
- for (var cui = 0; cui < recentSessions.length; cui++) {
486
- var cuSess = recentSessions[cui];
487
- var runningTokens = 0;
488
- var primaryModel = "other";
489
- var maxModelTokens = 0;
490
- cuSess.models.forEach(function (val, key) {
491
- if (val.tokens > maxModelTokens) {
492
- maxModelTokens = val.tokens;
493
- primaryModel = key;
494
- }
495
- });
496
- var windowSize = contextWindowSizes[primaryModel] || 200000;
497
- for (var cmj = 0; cmj < cuSess.contextMessages.length; cmj++) {
498
- var cm = cuSess.contextMessages[cmj];
499
- runningTokens += cm.inputTokens;
500
- contextUtilization.push({
501
- messageIndex: cm.messageIndex,
502
- contextPercent: Math.min((runningTokens / windowSize) * 100, 100),
503
- sessionId: cuSess.id,
504
- title: cuSess.title,
505
- });
506
- }
507
- }
508
-
509
- var sankeyNodes = [
510
- { name: "Input Tokens" },
511
- { name: "Cache Read" },
512
- { name: "Cache Creation" },
513
- { name: "Opus" },
514
- { name: "Sonnet" },
515
- { name: "Haiku" },
516
- { name: "Other" },
517
- { name: "Output Tokens" },
518
- ];
519
- var modelNodeMap: Record<string, number> = { opus: 3, sonnet: 4, haiku: 5, other: 6 };
520
- var sankeyLinks: Array<{ source: number; target: number; value: number }> = [];
521
- var modelInputTotals = new Map<string, number>();
522
- var modelCacheTotals = new Map<string, number>();
523
- var modelCacheCreationTotals = new Map<string, number>();
524
- var modelOutputTotals = new Map<string, number>();
525
-
526
- for (var ski = 0; ski < filtered.length; ski++) {
527
- var skSess = filtered[ski];
528
- var skTotal = skSess.inputTokens + skSess.cacheReadTokens + skSess.cacheCreationTokens;
529
- if (skTotal === 0) continue;
530
- skSess.models.forEach(function (val, key) {
531
- var proportion = val.tokens / (skTotal + skSess.outputTokens || 1);
532
- modelInputTotals.set(key, (modelInputTotals.get(key) || 0) + skSess.inputTokens * proportion);
533
- modelCacheTotals.set(key, (modelCacheTotals.get(key) || 0) + skSess.cacheReadTokens * proportion);
534
- modelCacheCreationTotals.set(key, (modelCacheCreationTotals.get(key) || 0) + skSess.cacheCreationTokens * proportion);
535
- modelOutputTotals.set(key, (modelOutputTotals.get(key) || 0) + skSess.outputTokens * proportion);
536
- });
537
- }
538
-
539
- ["opus", "sonnet", "haiku", "other"].forEach(function (model) {
540
- var nodeIdx = modelNodeMap[model];
541
- var inputVal = Math.round(modelInputTotals.get(model) || 0);
542
- var cacheVal = Math.round(modelCacheTotals.get(model) || 0);
543
- var cacheCreationVal = Math.round(modelCacheCreationTotals.get(model) || 0);
544
- var outputVal = Math.round(modelOutputTotals.get(model) || 0);
545
- if (inputVal > 0) sankeyLinks.push({ source: 0, target: nodeIdx, value: inputVal });
546
- if (cacheVal > 0) sankeyLinks.push({ source: 1, target: nodeIdx, value: cacheVal });
547
- if (cacheCreationVal > 0) sankeyLinks.push({ source: 2, target: nodeIdx, value: cacheCreationVal });
548
- if (outputVal > 0) sankeyLinks.push({ source: nodeIdx, target: 7, value: outputVal });
549
- });
550
-
551
- var tokenFlowSankey: AnalyticsPayload["tokenFlowSankey"] = { nodes: sankeyNodes, links: sankeyLinks };
552
-
553
- var activityCalendarMap = new Map<string, { count: number; tokens: number; cost: number }>();
554
- for (var aci = 0; aci < filtered.length; aci++) {
555
- var acSess = filtered[aci];
556
- var acDate = formatDate(acSess.endTime > 0 ? acSess.endTime : acSess.startTime);
557
- var acEntry = activityCalendarMap.get(acDate);
558
- if (!acEntry) {
559
- acEntry = { count: 0, tokens: 0, cost: 0 };
560
- activityCalendarMap.set(acDate, acEntry);
561
- }
562
- acEntry.count++;
563
- acEntry.tokens += acSess.inputTokens + acSess.outputTokens;
564
- acEntry.cost += acSess.cost;
565
- }
566
-
567
- var activityCalendar: AnalyticsPayload["activityCalendar"] = [];
568
- if (dates.length > 0) {
569
- var calStart = new Date(dates[0]);
570
- var calEnd = new Date(dates[dates.length - 1]);
571
- var calCursor = new Date(calStart);
572
- while (calCursor <= calEnd) {
573
- var calKey = formatDate(calCursor.getTime());
574
- var calData = activityCalendarMap.get(calKey);
575
- activityCalendar.push({
576
- date: calKey,
577
- count: calData ? calData.count : 0,
578
- tokens: calData ? calData.tokens : 0,
579
- cost: calData ? calData.cost : 0,
580
- });
581
- calCursor.setDate(calCursor.getDate() + 1);
582
- }
583
- }
584
-
585
- var hourlyHeatmap: AnalyticsPayload["hourlyHeatmap"] = [];
586
- var heatmapGrid = new Map<string, number>();
587
- for (var hmi = 0; hmi < filtered.length; hmi++) {
588
- var hmSess = filtered[hmi];
589
- if (hmSess.startTime <= 0) continue;
590
- var hmDate = new Date(hmSess.startTime);
591
- var hmDay = hmDate.getDay();
592
- var hmHour = hmDate.getHours();
593
- var hmKey = hmDay + ":" + hmHour;
594
- heatmapGrid.set(hmKey, (heatmapGrid.get(hmKey) || 0) + 1);
595
- }
596
- for (var hd = 0; hd < 7; hd++) {
597
- for (var hh = 0; hh < 24; hh++) {
598
- var hhKey = hd + ":" + hh;
599
- hourlyHeatmap.push({ day: hd, hour: hh, count: heatmapGrid.get(hhKey) || 0 });
600
- }
601
- }
602
-
603
- var sessionTimeline: AnalyticsPayload["sessionTimeline"] = [];
604
- var tlSorted = filtered
605
- .filter(function (s) { return s.startTime > 0 && s.endTime > 0 && s.cost > 0; })
606
- .sort(function (a, b) { return b.startTime - a.startTime; });
607
- var tlCap = Math.min(tlSorted.length, 50);
608
- for (var tli = 0; tli < tlCap; tli++) {
609
- var tlSess = tlSorted[tli];
610
- sessionTimeline.push({
611
- id: tlSess.id,
612
- title: tlSess.title,
613
- project: tlSess.project,
614
- start: tlSess.startTime,
615
- end: tlSess.endTime,
616
- cost: tlSess.cost,
617
- });
618
- }
619
-
620
- var dailySummaryMap = new Map<string, { sessions: number; cost: number; tokens: number; tools: Map<string, number>; models: Map<string, number> }>();
621
- for (var dsi = 0; dsi < filtered.length; dsi++) {
622
- var dsSess = filtered[dsi];
623
- var dsDate = formatDate(dsSess.endTime > 0 ? dsSess.endTime : dsSess.startTime);
624
- var dsEntry = dailySummaryMap.get(dsDate);
625
- if (!dsEntry) {
626
- dsEntry = { sessions: 0, cost: 0, tokens: 0, tools: new Map(), models: new Map() };
627
- dailySummaryMap.set(dsDate, dsEntry);
628
- }
629
- dsEntry.sessions++;
630
- dsEntry.cost += dsSess.cost;
631
- dsEntry.tokens += dsSess.inputTokens + dsSess.outputTokens;
632
- dsSess.tools.forEach(function (count, tool) {
633
- dsEntry!.tools.set(tool, (dsEntry!.tools.get(tool) || 0) + count);
634
- });
635
- dsSess.models.forEach(function (val, key) {
636
- dsEntry!.models.set(key, (dsEntry!.models.get(key) || 0) + val.cost);
637
- });
638
- }
639
-
640
- var dailySummaries: AnalyticsPayload["dailySummaries"] = [];
641
- var dsSortedDates = Array.from(dailySummaryMap.keys()).sort();
642
- for (var dsdi = 0; dsdi < dsSortedDates.length; dsdi++) {
643
- var dsd = dsSortedDates[dsdi];
644
- var dsData = dailySummaryMap.get(dsd)!;
645
- var topTool = "";
646
- var topToolCount = 0;
647
- dsData.tools.forEach(function (count, tool) {
648
- if (count > topToolCount) {
649
- topToolCount = count;
650
- topTool = tool;
651
- }
652
- });
653
- var modelMix: Record<string, number> = {};
654
- var modelTotal = 0;
655
- dsData.models.forEach(function (cost) { modelTotal += cost; });
656
- if (modelTotal > 0) {
657
- dsData.models.forEach(function (cost, model) {
658
- modelMix[model] = Math.round((cost / modelTotal) * 100) / 100;
659
- });
660
- }
661
- dailySummaries.push({
662
- date: dsd,
663
- sessions: dsData.sessions,
664
- cost: dsData.cost,
665
- tokens: dsData.tokens,
666
- topTool: topTool,
667
- modelMix: modelMix,
668
- });
669
- }
670
-
671
- var toolTreemap: AnalyticsPayload["toolTreemap"] = [];
672
- toolStats.forEach(function (val, key) {
673
- toolTreemap.push({
674
- name: key,
675
- count: val.count,
676
- avgCost: val.sessions > 0 ? val.totalCost / val.sessions : 0,
677
- });
678
- });
679
- toolTreemap.sort(function (a: typeof toolTreemap[number], b: typeof toolTreemap[number]) { return b.count - a.count; });
680
-
681
- var toolCategoryMap: Record<string, string> = {
682
- Read: "Read", Glob: "Read", Grep: "Read", LS: "Read",
683
- Edit: "Write", Write: "Write", MultiEdit: "Write",
684
- Bash: "Execute",
685
- Agent: "AI", Skill: "AI",
686
- };
687
- var toolSunburst: AnalyticsPayload["toolSunburst"] = [];
688
- toolStats.forEach(function (val, key) {
689
- var category = toolCategoryMap[key] || "Other";
690
- toolSunburst.push({ name: key, category: category, count: val.count });
691
- });
692
- toolSunburst.sort(function (a: typeof toolSunburst[number], b: typeof toolSunburst[number]) { return b.count - a.count; });
693
-
694
- var totalToolCalls = 0;
695
- toolStats.forEach(function (val) { totalToolCalls += val.count; });
696
- var permissionStats: AnalyticsPayload["permissionStats"] = {
697
- allowed: totalToolCalls,
698
- denied: 0,
699
- alwaysAllowed: 0,
700
- };
701
-
702
- var projectRadarMap = new Map<string, { cost: number; sessions: number; totalDuration: number; durationCount: number; tools: Set<string>; totalTokens: number }>();
703
- for (var pri = 0; pri < filtered.length; pri++) {
704
- var prSess = filtered[pri];
705
- var prEntry = projectRadarMap.get(prSess.project);
706
- if (!prEntry) {
707
- prEntry = { cost: 0, sessions: 0, totalDuration: 0, durationCount: 0, tools: new Set(), totalTokens: 0 };
708
- projectRadarMap.set(prSess.project, prEntry);
709
- }
710
- prEntry.cost += prSess.cost;
711
- prEntry.sessions++;
712
- prEntry.totalTokens += prSess.inputTokens + prSess.outputTokens;
713
- if (prSess.startTime > 0 && prSess.endTime > prSess.startTime) {
714
- prEntry.totalDuration += prSess.endTime - prSess.startTime;
715
- prEntry.durationCount++;
716
- }
717
- prSess.tools.forEach(function (_count, tool) { prEntry!.tools.add(tool); });
718
- }
719
- var projectRadar: AnalyticsPayload["projectRadar"] = [];
720
- projectRadarMap.forEach(function (val, key) {
721
- projectRadar.push({
722
- project: key,
723
- cost: val.cost,
724
- sessions: val.sessions,
725
- avgDuration: val.durationCount > 0 ? val.totalDuration / val.durationCount : 0,
726
- toolDiversity: val.tools.size,
727
- tokensPerSession: val.sessions > 0 ? val.totalTokens / val.sessions : 0,
728
- });
729
- });
730
- projectRadar.sort(function (a: typeof projectRadar[number], b: typeof projectRadar[number]) { return b.cost - a.cost; });
731
- if (projectRadar.length > 5) projectRadar.length = 5;
732
-
733
- var contextWindowSizesForComplexity: Record<string, number> = { opus: 200000, sonnet: 200000, haiku: 200000, other: 200000 };
734
- var sessionComplexity: AnalyticsPayload["sessionComplexity"] = [];
735
- for (var sci = 0; sci < filtered.length; sci++) {
736
- var scSess = filtered[sci];
737
- var scUniqueTools = scSess.tools.size;
738
- var scMessages = scSess.contextMessages.length;
739
- var scRunning = 0;
740
- var scPrimaryModel = "other";
741
- var scMaxTokens = 0;
742
- scSess.models.forEach(function (val, key) {
743
- if (val.tokens > scMaxTokens) { scMaxTokens = val.tokens; scPrimaryModel = key; }
744
- });
745
- var scWindowSize = contextWindowSizesForComplexity[scPrimaryModel] || 200000;
746
- for (var scmi = 0; scmi < scSess.contextMessages.length; scmi++) {
747
- scRunning += scSess.contextMessages[scmi].inputTokens;
748
- }
749
- var scContextPercent = Math.min((scRunning / scWindowSize) * 100, 100);
750
- var scScore = (scMessages * 1) + (scUniqueTools * 5) + (scContextPercent * 0.5);
751
- sessionComplexity.push({
752
- id: scSess.id,
753
- title: scSess.title,
754
- score: Math.round(scScore * 10) / 10,
755
- messages: scMessages,
756
- tools: scUniqueTools,
757
- contextPercent: Math.round(scContextPercent * 10) / 10,
758
- });
759
- }
760
- sessionComplexity.sort(function (a: typeof sessionComplexity[number], b: typeof sessionComplexity[number]) { return b.score - a.score; });
761
- if (sessionComplexity.length > 20) sessionComplexity.length = 20;
762
-
763
- return {
764
- totalCost: totalCost,
765
- totalSessions: filtered.length,
766
- totalTokens: {
767
- input: totalInput,
768
- output: totalOutput,
769
- cacheRead: totalCacheRead,
770
- cacheCreation: totalCacheCreation,
771
- },
772
- cacheHitRate: cacheHitRate,
773
- avgSessionCost: filtered.length > 0 ? totalCost / filtered.length : 0,
774
- avgSessionDuration: durationCount > 0 ? totalDuration / durationCount : 0,
775
- costOverTime: costOverTime,
776
- cumulativeCost: cumulativeCost,
777
- sessionsOverTime: sessionsOverTime,
778
- tokensOverTime: tokensOverTime,
779
- cacheHitRateOverTime: cacheHitRateOverTime,
780
- costDistribution: costDistribution,
781
- sessionBubbles: sessionBubbles,
782
- modelUsage: modelUsage,
783
- projectBreakdown: projectBreakdown,
784
- toolUsage: toolUsage,
785
- responseTimeData: responseTimeData,
786
- contextUtilization: contextUtilization,
787
- tokenFlowSankey: tokenFlowSankey,
788
- activityCalendar: activityCalendar,
789
- hourlyHeatmap: hourlyHeatmap,
790
- sessionTimeline: sessionTimeline,
791
- dailySummaries: dailySummaries,
792
- toolTreemap: toolTreemap,
793
- toolSunburst: toolSunburst,
794
- permissionStats: permissionStats,
795
- projectRadar: projectRadar,
796
- sessionComplexity: sessionComplexity,
797
- };
798
- }
799
-
800
- export async function getAnalytics(
801
- scope: AnalyticsScope,
802
- period: AnalyticsPeriod,
803
- projectSlug?: string,
804
- sessionId?: string,
805
- forceRefresh?: boolean,
806
- ): Promise<AnalyticsPayload> {
807
- var cacheKey = scope + ":" + period + ":" + (projectSlug || "all");
808
- if (sessionId) cacheKey += ":" + sessionId;
809
-
810
- if (!forceRefresh) {
811
- var cached = cache.get(cacheKey);
812
- if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
813
- return Promise.resolve(cached.data);
814
- }
815
- var existing = inflight.get(cacheKey);
816
- if (existing) return existing;
817
- }
818
-
819
- var config = loadConfig();
820
- var cutoff = getPeriodCutoff(period);
821
- var fileRefs: Array<{ path: string; id: string; slug: string }> = [];
822
-
823
- if (scope === "global") {
824
- for (var i = 0; i < config.projects.length; i++) {
825
- var proj = config.projects[i];
826
- var files = getSessionFilesForProject(proj.path, cutoff);
827
- for (var j = 0; j < files.length; j++) {
828
- fileRefs.push({ path: files[j].path, id: files[j].id, slug: proj.slug });
829
- }
830
- }
831
- } else if (scope === "project" && projectSlug) {
832
- var project = config.projects.find(function (p: typeof config.projects[number]) { return p.slug === projectSlug; });
833
- if (project) {
834
- var projFiles = getSessionFilesForProject(project.path, cutoff);
835
- for (var pf = 0; pf < projFiles.length; pf++) {
836
- fileRefs.push({ path: projFiles[pf].path, id: projFiles[pf].id, slug: projectSlug });
837
- }
838
- }
839
- } else if (scope === "session" && projectSlug && sessionId) {
840
- var sessProject = config.projects.find(function (p: typeof config.projects[number]) { return p.slug === projectSlug; });
841
- if (sessProject) {
842
- var hash = projectPathToHash(sessProject.path);
843
- var filePath = join(homedir(), ".claude", "projects", hash, sessionId + ".jsonl");
844
- if (existsSync(filePath)) {
845
- fileRefs.push({ path: filePath, id: sessionId, slug: projectSlug });
846
- }
847
- }
848
- }
849
-
850
- var promise = Promise.all(fileRefs.map(function (ref) {
851
- return parseSessionFileAsync(ref.path, ref.id, ref.slug);
852
- })).then(function (results) {
853
- var sessions = results.filter(function (s): s is SessionData { return s !== null; });
854
- var result = aggregate(sessions, period);
855
- cache.set(cacheKey, { data: result, timestamp: Date.now() });
856
- inflight.delete(cacheKey);
857
- return result;
858
- });
859
-
860
- inflight.set(cacheKey, promise);
861
- return promise;
862
- }
863
-
864
- var dailySpendCache: { value: number; timestamp: number } | null = null;
865
- var DAILY_SPEND_CACHE_TTL = 30 * 1000;
866
-
867
- export function getDailySpend(): number {
868
- if (dailySpendCache && Date.now() - dailySpendCache.timestamp < DAILY_SPEND_CACHE_TTL) {
869
- return dailySpendCache.value;
870
- }
871
-
872
- var config = loadConfig();
873
- var now = new Date();
874
- var todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
875
- var totalCost = 0;
876
-
877
- for (var i = 0; i < config.projects.length; i++) {
878
- var proj = config.projects[i];
879
- var files = getSessionFilesForProject(proj.path);
880
- for (var j = 0; j < files.length; j++) {
881
- var data = parseSessionFile(files[j].path, files[j].id, proj.slug);
882
- if (!data) continue;
883
- var sessionTime = data.endTime > 0 ? data.endTime : data.startTime;
884
- if (sessionTime >= todayStart) {
885
- totalCost += data.cost;
886
- }
887
- }
888
- }
889
-
890
- dailySpendCache = { value: totalCost, timestamp: Date.now() };
891
- return totalCost;
892
- }
893
-
894
- export function invalidateDailySpendCache(): void {
895
- dailySpendCache = null;
896
- }
897
-
898
- export async function streamAnalyticsSections(
899
- scope: AnalyticsScope,
900
- period: AnalyticsPeriod,
901
- projectSlug: string | undefined,
902
- sessionId: string | undefined,
903
- forceRefresh: boolean | undefined,
904
- onSection: (name: AnalyticsSectionName, data: Partial<AnalyticsPayload>) => void,
905
- ): Promise<void> {
906
- var payload = await getAnalytics(scope, period, projectSlug, sessionId, forceRefresh);
907
- var sectionNames: AnalyticsSectionName[] = ["summary", "spending", "usage", "activity", "projects"];
908
-
909
- for (var si = 0; si < sectionNames.length; si++) {
910
- var name = sectionNames[si];
911
- var keys = SECTION_KEYS[name];
912
- var sectionData: Partial<AnalyticsPayload> = {};
913
- for (var ki = 0; ki < keys.length; ki++) {
914
- var key = keys[ki];
915
- (sectionData as Record<string, unknown>)[key] = payload[key];
916
- }
917
- onSection(name, sectionData);
918
- await new Promise<void>(function (resolve) { setImmediate(resolve); });
919
- }
920
- }