@pennyfarthing/cyclist 10.4.0 → 11.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 (384) hide show
  1. package/dist/api/agent-load.d.ts +1 -2
  2. package/dist/api/agent-load.d.ts.map +1 -1
  3. package/dist/api/agent-load.js +2 -123
  4. package/dist/api/agent-load.js.map +1 -1
  5. package/dist/api/audit-log.d.ts +1 -17
  6. package/dist/api/audit-log.d.ts.map +1 -1
  7. package/dist/api/audit-log.js +2 -162
  8. package/dist/api/audit-log.js.map +1 -1
  9. package/dist/api/background-tasks.d.ts +1 -26
  10. package/dist/api/background-tasks.d.ts.map +1 -1
  11. package/dist/api/background-tasks.js +2 -55
  12. package/dist/api/background-tasks.js.map +1 -1
  13. package/dist/api/bell.d.ts +1 -18
  14. package/dist/api/bell.d.ts.map +1 -1
  15. package/dist/api/bell.js +2 -33
  16. package/dist/api/bell.js.map +1 -1
  17. package/dist/api/code-markers.d.ts +1 -8
  18. package/dist/api/code-markers.d.ts.map +1 -1
  19. package/dist/api/code-markers.js +2 -61
  20. package/dist/api/code-markers.js.map +1 -1
  21. package/dist/api/complexity.d.ts +1 -2
  22. package/dist/api/complexity.d.ts.map +1 -1
  23. package/dist/api/complexity.js +2 -46
  24. package/dist/api/complexity.js.map +1 -1
  25. package/dist/api/context.d.ts +1 -37
  26. package/dist/api/context.d.ts.map +1 -1
  27. package/dist/api/context.js +2 -143
  28. package/dist/api/context.js.map +1 -1
  29. package/dist/api/dead-code.d.ts +1 -2
  30. package/dist/api/dead-code.d.ts.map +1 -1
  31. package/dist/api/dead-code.js +2 -69
  32. package/dist/api/dead-code.js.map +1 -1
  33. package/dist/api/dependencies.d.ts +1 -2
  34. package/dist/api/dependencies.d.ts.map +1 -1
  35. package/dist/api/dependencies.js +2 -42
  36. package/dist/api/dependencies.js.map +1 -1
  37. package/dist/api/evaluation.d.ts +1 -19
  38. package/dist/api/evaluation.d.ts.map +1 -1
  39. package/dist/api/evaluation.js +2 -127
  40. package/dist/api/evaluation.js.map +1 -1
  41. package/dist/api/file-browser.d.ts +1 -8
  42. package/dist/api/file-browser.d.ts.map +1 -1
  43. package/dist/api/file-browser.js +2 -114
  44. package/dist/api/file-browser.js.map +1 -1
  45. package/dist/api/git.d.ts +1 -46
  46. package/dist/api/git.d.ts.map +1 -1
  47. package/dist/api/git.js +2 -354
  48. package/dist/api/git.js.map +1 -1
  49. package/dist/api/health-score.d.ts +1 -2
  50. package/dist/api/health-score.d.ts.map +1 -1
  51. package/dist/api/health-score.js +2 -46
  52. package/dist/api/health-score.js.map +1 -1
  53. package/dist/api/hook-request.d.ts +1 -40
  54. package/dist/api/hook-request.d.ts.map +1 -1
  55. package/dist/api/hook-request.js +2 -277
  56. package/dist/api/hook-request.js.map +1 -1
  57. package/dist/api/hotspots.d.ts +1 -2
  58. package/dist/api/hotspots.d.ts.map +1 -1
  59. package/dist/api/hotspots.js +2 -61
  60. package/dist/api/hotspots.js.map +1 -1
  61. package/dist/api/identity.d.ts +1 -16
  62. package/dist/api/identity.d.ts.map +1 -1
  63. package/dist/api/identity.js +2 -78
  64. package/dist/api/identity.js.map +1 -1
  65. package/dist/api/index.d.ts +1 -34
  66. package/dist/api/index.d.ts.map +1 -1
  67. package/dist/api/index.js +2 -44
  68. package/dist/api/index.js.map +1 -1
  69. package/dist/api/mode.d.ts +1 -22
  70. package/dist/api/mode.d.ts.map +1 -1
  71. package/dist/api/mode.js +2 -37
  72. package/dist/api/mode.js.map +1 -1
  73. package/dist/api/otlp.d.ts +1 -2
  74. package/dist/api/otlp.d.ts.map +1 -1
  75. package/dist/api/otlp.js +2 -46
  76. package/dist/api/otlp.js.map +1 -1
  77. package/dist/api/permissions.d.ts +1 -15
  78. package/dist/api/permissions.d.ts.map +1 -1
  79. package/dist/api/permissions.js +2 -66
  80. package/dist/api/permissions.js.map +1 -1
  81. package/dist/api/persona.d.ts +1 -8
  82. package/dist/api/persona.d.ts.map +1 -1
  83. package/dist/api/persona.js +2 -67
  84. package/dist/api/persona.js.map +1 -1
  85. package/dist/api/portrait.d.ts +1 -5
  86. package/dist/api/portrait.d.ts.map +1 -1
  87. package/dist/api/portrait.js +2 -27
  88. package/dist/api/portrait.js.map +1 -1
  89. package/dist/api/settings.d.ts +1 -53
  90. package/dist/api/settings.d.ts.map +1 -1
  91. package/dist/api/settings.js +2 -464
  92. package/dist/api/settings.js.map +1 -1
  93. package/dist/api/spans.d.ts +1 -16
  94. package/dist/api/spans.d.ts.map +1 -1
  95. package/dist/api/spans.js +2 -244
  96. package/dist/api/spans.js.map +1 -1
  97. package/dist/api/stats.d.ts +1 -12
  98. package/dist/api/stats.d.ts.map +1 -1
  99. package/dist/api/stats.js +2 -84
  100. package/dist/api/stats.js.map +1 -1
  101. package/dist/api/story.d.ts +1 -2
  102. package/dist/api/story.d.ts.map +1 -1
  103. package/dist/api/story.js +2 -14
  104. package/dist/api/story.js.map +1 -1
  105. package/dist/api/telemetry.d.ts +1 -18
  106. package/dist/api/telemetry.d.ts.map +1 -1
  107. package/dist/api/telemetry.js +2 -164
  108. package/dist/api/telemetry.js.map +1 -1
  109. package/dist/api/theme-agents.d.ts +1 -60
  110. package/dist/api/theme-agents.d.ts.map +1 -1
  111. package/dist/api/theme-agents.js +2 -213
  112. package/dist/api/theme-agents.js.map +1 -1
  113. package/dist/api/todos.d.ts +1 -32
  114. package/dist/api/todos.d.ts.map +1 -1
  115. package/dist/api/todos.js +2 -43
  116. package/dist/api/todos.js.map +1 -1
  117. package/dist/api/token-stats.d.ts +1 -7
  118. package/dist/api/token-stats.d.ts.map +1 -1
  119. package/dist/api/token-stats.js +2 -35
  120. package/dist/api/token-stats.js.map +1 -1
  121. package/dist/api/welcome.d.ts +1 -21
  122. package/dist/api/welcome.d.ts.map +1 -1
  123. package/dist/api/welcome.js +2 -34
  124. package/dist/api/welcome.js.map +1 -1
  125. package/dist/bikerack.js +2 -2
  126. package/dist/bikerack.js.map +1 -1
  127. package/dist/env.d.ts +6 -0
  128. package/dist/env.d.ts.map +1 -0
  129. package/dist/env.js +10 -0
  130. package/dist/env.js.map +1 -0
  131. package/dist/focus.d.ts +53 -0
  132. package/dist/focus.d.ts.map +1 -0
  133. package/dist/focus.js +122 -0
  134. package/dist/focus.js.map +1 -0
  135. package/dist/git-cache.d.ts +1 -0
  136. package/dist/git-cache.d.ts.map +1 -1
  137. package/dist/git-cache.js +3 -1
  138. package/dist/git-cache.js.map +1 -1
  139. package/dist/menu-builder.d.ts.map +1 -1
  140. package/dist/menu-builder.js +0 -1
  141. package/dist/menu-builder.js.map +1 -1
  142. package/dist/prime.d.ts +3 -3
  143. package/dist/prime.d.ts.map +1 -1
  144. package/dist/prime.js +38 -14
  145. package/dist/prime.js.map +1 -1
  146. package/dist/public/css/react.css +1 -1
  147. package/dist/public/js/react/react.js +53 -61
  148. package/dist/server.d.ts +18 -85
  149. package/dist/server.d.ts.map +1 -1
  150. package/dist/server.js +105 -405
  151. package/dist/server.js.map +1 -1
  152. package/dist/sprint-data.d.ts +1 -1
  153. package/dist/sprint-data.d.ts.map +1 -1
  154. package/dist/sprint-data.js +2 -2
  155. package/dist/sprint-data.js.map +1 -1
  156. package/dist/theme-metadata.d.ts +3 -3
  157. package/dist/theme-metadata.d.ts.map +1 -1
  158. package/dist/theme-metadata.js +4 -4
  159. package/dist/theme-metadata.js.map +1 -1
  160. package/dist/websocket.d.ts +2 -0
  161. package/dist/websocket.d.ts.map +1 -1
  162. package/dist/websocket.js +53 -75
  163. package/dist/websocket.js.map +1 -1
  164. package/package.json +2 -6
  165. package/portraits/hogans-heroes/large/burkhalter-35312.png +0 -0
  166. package/portraits/hogans-heroes/large/carter-34352.png +0 -0
  167. package/portraits/hogans-heroes/large/hochstetter-45314.png +0 -0
  168. package/portraits/hogans-heroes/large/hogan-44541.png +0 -0
  169. package/portraits/hogans-heroes/large/kinch-35241.png +0 -0
  170. package/portraits/hogans-heroes/large/klink-23434.png +0 -0
  171. package/portraits/hogans-heroes/large/lebeau-45443.png +0 -0
  172. package/portraits/hogans-heroes/large/marya-53543.png +0 -0
  173. package/portraits/hogans-heroes/large/newkirk-54432.png +0 -0
  174. package/portraits/hogans-heroes/large/schultz-42453.png +0 -0
  175. package/portraits/hogans-heroes/large/underground-55131.png +0 -0
  176. package/portraits/hogans-heroes/medium/burkhalter-35312.png +0 -0
  177. package/portraits/hogans-heroes/medium/carter-34352.png +0 -0
  178. package/portraits/hogans-heroes/medium/hochstetter-45314.png +0 -0
  179. package/portraits/hogans-heroes/medium/hogan-44541.png +0 -0
  180. package/portraits/hogans-heroes/medium/kinch-35241.png +0 -0
  181. package/portraits/hogans-heroes/medium/klink-23434.png +0 -0
  182. package/portraits/hogans-heroes/medium/lebeau-45443.png +0 -0
  183. package/portraits/hogans-heroes/medium/marya-53543.png +0 -0
  184. package/portraits/hogans-heroes/medium/newkirk-54432.png +0 -0
  185. package/portraits/hogans-heroes/medium/schultz-42453.png +0 -0
  186. package/portraits/hogans-heroes/medium/underground-55131.png +0 -0
  187. package/portraits/monty-python/large/announcer-44441.png +0 -0
  188. package/portraits/monty-python/large/arguer-35412.png +0 -0
  189. package/portraits/monty-python/large/bicycle-repair-man-35241.png +0 -0
  190. package/portraits/monty-python/large/colonel-35423.png +0 -0
  191. package/portraits/monty-python/large/counsellor-45341.png +0 -0
  192. package/portraits/monty-python/large/gumbys-23524.png +0 -0
  193. package/portraits/monty-python/large/nudge-43533.png +0 -0
  194. package/portraits/monty-python/large/praline-45413.png +0 -0
  195. package/portraits/monty-python/large/silly-walks-55322.png +0 -0
  196. package/portraits/monty-python/large/wensleydale-54451.png +0 -0
  197. package/portraits/monty-python/large/xim-nez-43534.png +0 -0
  198. package/portraits/monty-python/medium/announcer-44441.png +0 -0
  199. package/portraits/monty-python/medium/arguer-35412.png +0 -0
  200. package/portraits/monty-python/medium/bicycle-repair-man-35241.png +0 -0
  201. package/portraits/monty-python/medium/colonel-35423.png +0 -0
  202. package/portraits/monty-python/medium/counsellor-45341.png +0 -0
  203. package/portraits/monty-python/medium/gumbys-23524.png +0 -0
  204. package/portraits/monty-python/medium/nudge-43533.png +0 -0
  205. package/portraits/monty-python/medium/praline-45413.png +0 -0
  206. package/portraits/monty-python/medium/silly-walks-55322.png +0 -0
  207. package/portraits/monty-python/medium/wensleydale-54451.png +0 -0
  208. package/portraits/monty-python/medium/xim-nez-43534.png +0 -0
  209. package/portraits/stephen-king/large/andy-55231.png +0 -0
  210. package/portraits/stephen-king/large/christine-25112.png +0 -0
  211. package/portraits/stephen-king/large/danny-53243.png +0 -0
  212. package/portraits/stephen-king/large/flagg-55311.png +0 -0
  213. package/portraits/stephen-king/large/gaunt-54421.png +0 -0
  214. package/portraits/stephen-king/large/jack-44224.png +0 -0
  215. package/portraits/stephen-king/large/johnny-44353.png +0 -0
  216. package/portraits/stephen-king/large/margaret-15415.png +0 -0
  217. package/portraits/stephen-king/large/paul-45233.png +0 -0
  218. package/portraits/stephen-king/large/pennywise-54411.png +0 -0
  219. package/portraits/stephen-king/large/roland-35121.png +0 -0
  220. package/portraits/stephen-king/medium/andy-55231.png +0 -0
  221. package/portraits/stephen-king/medium/christine-25112.png +0 -0
  222. package/portraits/stephen-king/medium/danny-53243.png +0 -0
  223. package/portraits/stephen-king/medium/flagg-55311.png +0 -0
  224. package/portraits/stephen-king/medium/gaunt-54421.png +0 -0
  225. package/portraits/stephen-king/medium/jack-44224.png +0 -0
  226. package/portraits/stephen-king/medium/johnny-44353.png +0 -0
  227. package/portraits/stephen-king/medium/margaret-15415.png +0 -0
  228. package/portraits/stephen-king/medium/paul-45233.png +0 -0
  229. package/portraits/stephen-king/medium/pennywise-54411.png +0 -0
  230. package/portraits/stephen-king/medium/roland-35121.png +0 -0
  231. package/portraits/star-trek-tng/large/beverly-44352.png +0 -0
  232. package/portraits/star-trek-tng/large/data-55241.png +0 -0
  233. package/portraits/star-trek-tng/large/deanna-43353.png +0 -0
  234. package/portraits/star-trek-tng/large/geordi-54342.png +0 -0
  235. package/portraits/star-trek-tng/large/jean-luc-45342.png +0 -0
  236. package/portraits/star-trek-tng/large/kathryn-45332.png +0 -0
  237. package/portraits/star-trek-tng/large/miles-35342.png +0 -0
  238. package/portraits/star-trek-tng/large/q-53521.png +0 -0
  239. package/portraits/star-trek-tng/large/spock-45231.png +0 -0
  240. package/portraits/star-trek-tng/large/troi-44352.png +0 -0
  241. package/portraits/star-trek-tng/medium/beverly-44352.png +0 -0
  242. package/portraits/star-trek-tng/medium/data-55241.png +0 -0
  243. package/portraits/star-trek-tng/medium/deanna-43353.png +0 -0
  244. package/portraits/star-trek-tng/medium/geordi-54342.png +0 -0
  245. package/portraits/star-trek-tng/medium/jean-luc-45342.png +0 -0
  246. package/portraits/star-trek-tng/medium/kathryn-45332.png +0 -0
  247. package/portraits/star-trek-tng/medium/miles-35342.png +0 -0
  248. package/portraits/star-trek-tng/medium/q-53521.png +0 -0
  249. package/portraits/star-trek-tng/medium/spock-45231.png +0 -0
  250. package/portraits/star-trek-tng/medium/troi-44352.png +0 -0
  251. package/src/public/App.tsx +0 -340
  252. package/src/public/components/AgentLoadDialog.tsx +0 -202
  253. package/src/public/components/AgentPopup.tsx +0 -308
  254. package/src/public/components/ApprovalModal/ApprovalModal.css +0 -35
  255. package/src/public/components/ApprovalModal/index.tsx +0 -632
  256. package/src/public/components/BikeRackIndex.tsx +0 -54
  257. package/src/public/components/BikeRackWorkspace.tsx +0 -142
  258. package/src/public/components/CommandPalette.tsx +0 -555
  259. package/src/public/components/ConfirmDialog.tsx +0 -168
  260. package/src/public/components/ContextIndicator/ContextIndicator.css +0 -85
  261. package/src/public/components/ContextIndicator/index.tsx +0 -330
  262. package/src/public/components/ContextSparkline.tsx +0 -56
  263. package/src/public/components/ControlBar.tsx +0 -636
  264. package/src/public/components/DeadCodeDialog.tsx +0 -169
  265. package/src/public/components/DiffViewer.tsx +0 -585
  266. package/src/public/components/DockviewWorkspace.tsx +0 -737
  267. package/src/public/components/Editor.tsx +0 -630
  268. package/src/public/components/ErrorBoundary.tsx +0 -67
  269. package/src/public/components/FileTree.tsx +0 -379
  270. package/src/public/components/FontPicker/FontPicker.css +0 -276
  271. package/src/public/components/FontPicker/index.tsx +0 -430
  272. package/src/public/components/FullFileTree.tsx +0 -237
  273. package/src/public/components/HealthGauge.tsx +0 -181
  274. package/src/public/components/Message.tsx +0 -225
  275. package/src/public/components/MessageList.tsx +0 -98
  276. package/src/public/components/MessageView.tsx +0 -400
  277. package/src/public/components/ModeSwitch/ModeSwitch.css +0 -165
  278. package/src/public/components/ModeSwitch/index.tsx +0 -372
  279. package/src/public/components/PersonaHeader.tsx +0 -240
  280. package/src/public/components/QuickActions.tsx +0 -267
  281. package/src/public/components/SpanTimeline.tsx +0 -352
  282. package/src/public/components/StandalonePanel.tsx +0 -84
  283. package/src/public/components/StatsStrip.tsx +0 -162
  284. package/src/public/components/StreamingContent.tsx +0 -77
  285. package/src/public/components/SubagentSpan.tsx +0 -180
  286. package/src/public/components/TandemPortrait.tsx +0 -72
  287. package/src/public/components/ThemePalette/ThemePalette.css +0 -179
  288. package/src/public/components/ThemePalette/index.tsx +0 -326
  289. package/src/public/components/ToolCallBlock.tsx +0 -252
  290. package/src/public/components/ToolStack.tsx +0 -209
  291. package/src/public/components/ToolStatus.tsx +0 -57
  292. package/src/public/components/dialogs/CodeMarkersDialog.tsx +0 -169
  293. package/src/public/components/dialogs/ComplexityDialog.tsx +0 -163
  294. package/src/public/components/dialogs/DependenciesDialog.tsx +0 -120
  295. package/src/public/components/dialogs/HotspotsDialog.tsx +0 -451
  296. package/src/public/components/dialogs/ToolDialog.tsx +0 -43
  297. package/src/public/components/panel-registry.ts +0 -11
  298. package/src/public/components/panels/ACPanel.tsx +0 -93
  299. package/src/public/components/panels/AcceptanceCriteriaPanel.tsx +0 -104
  300. package/src/public/components/panels/AuditLogPanel.tsx +0 -465
  301. package/src/public/components/panels/BackgroundPanel.tsx +0 -115
  302. package/src/public/components/panels/BikeLanePanel.tsx +0 -214
  303. package/src/public/components/panels/ChangedPanel.tsx +0 -65
  304. package/src/public/components/panels/DebugPanel.tsx +0 -344
  305. package/src/public/components/panels/DiffsPanel.tsx +0 -155
  306. package/src/public/components/panels/GitPanel.tsx +0 -216
  307. package/src/public/components/panels/HotspotsPanel.tsx +0 -365
  308. package/src/public/components/panels/MessagePanel.tsx +0 -497
  309. package/src/public/components/panels/SettingsPanel.tsx +0 -453
  310. package/src/public/components/panels/SprintPanel.tsx +0 -670
  311. package/src/public/components/panels/TTYPanel.tsx +0 -299
  312. package/src/public/components/panels/TodoPanel.tsx +0 -142
  313. package/src/public/components/panels/WorkflowPanel.tsx +0 -224
  314. package/src/public/components/panels/index.ts +0 -24
  315. package/src/public/components/ui/alert-dialog.tsx +0 -139
  316. package/src/public/components/ui/badge.tsx +0 -36
  317. package/src/public/components/ui/button.tsx +0 -57
  318. package/src/public/components/ui/checkbox.tsx +0 -28
  319. package/src/public/components/ui/collapsible.tsx +0 -9
  320. package/src/public/components/ui/command.tsx +0 -151
  321. package/src/public/components/ui/dialog.tsx +0 -120
  322. package/src/public/components/ui/popover.tsx +0 -31
  323. package/src/public/components/ui/progress.tsx +0 -28
  324. package/src/public/components/ui/scroll-area.tsx +0 -46
  325. package/src/public/components/ui/select.tsx +0 -157
  326. package/src/public/components/ui/separator.tsx +0 -29
  327. package/src/public/components/ui/skeleton.tsx +0 -15
  328. package/src/public/components/ui/switch.tsx +0 -27
  329. package/src/public/components/ui/toggle-group.tsx +0 -59
  330. package/src/public/components/ui/toggle.tsx +0 -43
  331. package/src/public/components/ui/tooltip.tsx +0 -30
  332. package/src/public/contexts/ClaudeContext.tsx +0 -311
  333. package/src/public/contexts/MessageQueueContext.tsx +0 -143
  334. package/src/public/css/theme-browser.css +0 -550
  335. package/src/public/css/theme-system.css +0 -630
  336. package/src/public/hooks/index.ts +0 -49
  337. package/src/public/hooks/useAgentLoad.ts +0 -105
  338. package/src/public/hooks/useBackgroundTasks.ts +0 -131
  339. package/src/public/hooks/useClaude.ts +0 -234
  340. package/src/public/hooks/useCodeMarkers.ts +0 -101
  341. package/src/public/hooks/useColorScheme.ts +0 -42
  342. package/src/public/hooks/useCommandHistory.ts +0 -99
  343. package/src/public/hooks/useComplexity.ts +0 -80
  344. package/src/public/hooks/useDeadCode.ts +0 -99
  345. package/src/public/hooks/useDependencies.ts +0 -82
  346. package/src/public/hooks/useDiffs.ts +0 -143
  347. package/src/public/hooks/useFileBrowser.ts +0 -71
  348. package/src/public/hooks/useGitStatus.ts +0 -233
  349. package/src/public/hooks/useHealthScore.ts +0 -69
  350. package/src/public/hooks/useHotspots.ts +0 -123
  351. package/src/public/hooks/useLayoutPersistence.ts +0 -138
  352. package/src/public/hooks/useMarkdownParser.ts +0 -36
  353. package/src/public/hooks/useMarkerActions.ts +0 -234
  354. package/src/public/hooks/useMessageQueue.ts +0 -380
  355. package/src/public/hooks/useMessageStream.ts +0 -131
  356. package/src/public/hooks/usePersona.ts +0 -112
  357. package/src/public/hooks/usePlanModeExit.ts +0 -105
  358. package/src/public/hooks/useResponsiveLayout.ts +0 -173
  359. package/src/public/hooks/useSprint.ts +0 -147
  360. package/src/public/hooks/useStatsStrip.ts +0 -204
  361. package/src/public/hooks/useStory.ts +0 -135
  362. package/src/public/hooks/useSubagentHelper.ts +0 -64
  363. package/src/public/hooks/useSyntaxHighlighter.ts +0 -52
  364. package/src/public/hooks/useTabCompletion.ts +0 -124
  365. package/src/public/hooks/useTodos.ts +0 -93
  366. package/src/public/hooks/useUserAvatar.ts +0 -54
  367. package/src/public/index.tsx +0 -10
  368. package/src/public/lib/utils.ts +0 -6
  369. package/src/public/styles/dockview-theme.css +0 -459
  370. package/src/public/styles/tailwind.css +0 -4396
  371. package/src/public/types/electron.d.ts +0 -18
  372. package/src/public/types/message.ts +0 -51
  373. package/src/public/utils/avatar-service.ts +0 -73
  374. package/src/public/utils/color-presets.ts +0 -940
  375. package/src/public/utils/font-presets.ts +0 -362
  376. package/src/public/utils/formatDuration.ts +0 -14
  377. package/src/public/utils/markdown.ts +0 -249
  378. package/src/public/utils/messageFilters.ts +0 -128
  379. package/src/public/utils/slash-commands.ts +0 -353
  380. package/src/public/utils/subagent-display.ts +0 -146
  381. package/src/public/utils/syntax.ts +0 -219
  382. package/src/public/utils/toolIntentSummarizer.ts +0 -199
  383. package/src/public/utils/toolStackGrouper.ts +0 -106
  384. package/src/public/utils/toolTypeColors.ts +0 -45
@@ -1,430 +0,0 @@
1
- /**
2
- * FontPicker Component
3
- *
4
- * Font selection with system font browser via queryLocalFonts() API.
5
- * Story MSSCI-12769 - Font Customization
6
- *
7
- * Features:
8
- * - shadcn Select-based dropdown with system font discovery
9
- * - Live font preview in each option
10
- * - Monospace detection for code font filtering
11
- * - Graceful fallback when queryLocalFonts() unavailable
12
- * - Font size picker (segmented control)
13
- * - ARIA accessibility via Radix Select
14
- */
15
-
16
- import React, { useState, useEffect, useCallback, useMemo } from 'react';
17
- import { Button } from '@/components/ui/button';
18
- import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
19
- import {
20
- Select,
21
- SelectContent,
22
- SelectGroup,
23
- SelectItem,
24
- SelectLabel,
25
- SelectTrigger,
26
- SelectValue,
27
- } from '@/components/ui/select';
28
- import {
29
- UI_FONT_PRESETS,
30
- CODE_FONT_PRESETS,
31
- FONT_SIZE_SCALE,
32
- FontSize,
33
- } from '../../utils/font-presets';
34
- import './FontPicker.css';
35
-
36
- // =============================================================================
37
- // Types
38
- // =============================================================================
39
-
40
- export interface FontPickerProps {
41
- type: 'ui' | 'code';
42
- currentFont: string;
43
- customFont?: string;
44
- onSelect: (presetId: string, customFamily?: string) => void;
45
- onCustomFontChange?: (family: string) => void;
46
- className?: string;
47
- }
48
-
49
- export interface FontSizePickerProps {
50
- currentSize: FontSize;
51
- onSelect: (size: FontSize) => void;
52
- className?: string;
53
- }
54
-
55
- interface SystemFont {
56
- family: string;
57
- isMonospace: boolean;
58
- }
59
-
60
- // =============================================================================
61
- // Monospace Detection via OpenType `post` table
62
- // =============================================================================
63
-
64
- /**
65
- * Parse SFNT table directory to find a table's offset and length.
66
- * SFNT header: version(4) + numTables(2) + searchRange(2) + entrySelector(2) + rangeShift(2) = 12
67
- * Each table record: tag(4) + checksum(4) + offset(4) + length(4) = 16
68
- */
69
- function findSfntTable(view: DataView, tag: string): { offset: number; length: number } | null {
70
- const numTables = view.getUint16(4);
71
- for (let i = 0; i < numTables; i++) {
72
- const recordOffset = 12 + i * 16;
73
- const tableTag = String.fromCharCode(
74
- view.getUint8(recordOffset),
75
- view.getUint8(recordOffset + 1),
76
- view.getUint8(recordOffset + 2),
77
- view.getUint8(recordOffset + 3),
78
- );
79
- if (tableTag === tag) {
80
- return {
81
- offset: view.getUint32(recordOffset + 8),
82
- length: view.getUint32(recordOffset + 12),
83
- };
84
- }
85
- }
86
- return null;
87
- }
88
-
89
- /**
90
- * Read `isFixedPitch` from the `post` table.
91
- * post layout: version(4) + italicAngle(4) + underlinePosition(2) + underlineThickness(2) = offset 12
92
- * isFixedPitch is uint32 at offset 12: 0 = proportional, non-zero = monospace.
93
- */
94
- async function detectMonospaceFromBlob(fontData: { blob: () => Promise<Blob> }): Promise<boolean> {
95
- try {
96
- const blob = await fontData.blob();
97
- const buffer = await blob.arrayBuffer();
98
- const view = new DataView(buffer);
99
-
100
- const post = findSfntTable(view, 'post');
101
- if (post) {
102
- const isFixedPitch = view.getUint32(post.offset + 12);
103
- return isFixedPitch !== 0;
104
- }
105
- return false;
106
- } catch {
107
- return false;
108
- }
109
- }
110
-
111
- // =============================================================================
112
- // System Font Discovery
113
- // =============================================================================
114
-
115
- interface FontDataEntry {
116
- family: string;
117
- fullName: string;
118
- postscriptName: string;
119
- style: string;
120
- blob: () => Promise<Blob>;
121
- }
122
-
123
- const FONT_CACHE_KEY = 'cyclist-system-fonts';
124
-
125
- interface FontCacheData {
126
- fonts: SystemFont[];
127
- count: number; // number of font families — if it changes, fonts were installed/removed
128
- }
129
-
130
- function loadCachedFonts(): SystemFont[] | null {
131
- try {
132
- const raw = localStorage.getItem(FONT_CACHE_KEY);
133
- if (!raw) return null;
134
- const data: FontCacheData = JSON.parse(raw);
135
- if (data.fonts?.length > 0) return data.fonts;
136
- return null;
137
- } catch {
138
- return null;
139
- }
140
- }
141
-
142
- function saveCachedFonts(fonts: SystemFont[], count: number): void {
143
- try {
144
- const data: FontCacheData = { fonts, count };
145
- localStorage.setItem(FONT_CACHE_KEY, JSON.stringify(data));
146
- } catch {
147
- // localStorage full or unavailable — not critical
148
- }
149
- }
150
-
151
- let systemFontsPromise: Promise<SystemFont[]> | null = null;
152
-
153
- async function getSystemFonts(): Promise<SystemFont[]> {
154
- if (systemFontsPromise) return systemFontsPromise;
155
-
156
- systemFontsPromise = (async () => {
157
- if (!('queryLocalFonts' in window)) {
158
- return [];
159
- }
160
-
161
- try {
162
- const fonts: FontDataEntry[] = await (window as unknown as { queryLocalFonts: () => Promise<FontDataEntry[]> }).queryLocalFonts();
163
-
164
- // Deduplicate by family name, keep one FontData per family for mono detection
165
- const familyMap = new Map<string, FontDataEntry>();
166
- for (const font of fonts) {
167
- if (!familyMap.has(font.family)) {
168
- familyMap.set(font.family, font);
169
- }
170
- }
171
-
172
- const familyCount = familyMap.size;
173
-
174
- // Check localStorage cache — reuse if font count hasn't changed
175
- const cached = loadCachedFonts();
176
- if (cached && cached.length > 0) {
177
- // Load raw cached data to check count
178
- try {
179
- const raw = localStorage.getItem(FONT_CACHE_KEY);
180
- if (raw) {
181
- const data: FontCacheData = JSON.parse(raw);
182
- if (data.count === familyCount) {
183
- return cached;
184
- }
185
- }
186
- } catch {
187
- // Fall through to re-detect
188
- }
189
- }
190
-
191
- // Detect monospace via post table in parallel
192
- const entries = Array.from(familyMap.entries());
193
- const monoResults = await Promise.all(
194
- entries.map(([, fontData]) => detectMonospaceFromBlob(fontData))
195
- );
196
-
197
- const result: SystemFont[] = entries.map(([family], i) => ({
198
- family,
199
- isMonospace: monoResults[i],
200
- }));
201
-
202
- result.sort((a, b) => a.family.localeCompare(b.family));
203
- saveCachedFonts(result, familyCount);
204
- return result;
205
- } catch {
206
- // Permission denied or API error
207
- return [];
208
- }
209
- })();
210
-
211
- return systemFontsPromise;
212
- }
213
-
214
- // Prefix for system font values to distinguish from preset IDs
215
- const SYSTEM_FONT_PREFIX = 'system-font:';
216
-
217
- // =============================================================================
218
- // FontPicker Component
219
- // =============================================================================
220
-
221
- export function FontPicker({
222
- type,
223
- currentFont,
224
- customFont,
225
- onSelect,
226
- onCustomFontChange,
227
- className = '',
228
- }: FontPickerProps): React.ReactElement {
229
- const [customValue, setCustomValue] = useState(customFont || '');
230
- const [systemFonts, setSystemFonts] = useState<SystemFont[]>([]);
231
- const [fontsLoaded, setFontsLoaded] = useState(false);
232
-
233
- const presets = type === 'ui' ? UI_FONT_PRESETS : CODE_FONT_PRESETS;
234
- const currentPreset = presets.find(p => p.id === currentFont);
235
-
236
- // Load system fonts eagerly
237
- useEffect(() => {
238
- if (!fontsLoaded) {
239
- getSystemFonts().then(fonts => {
240
- setSystemFonts(fonts);
241
- setFontsLoaded(true);
242
- });
243
- }
244
- }, [fontsLoaded]);
245
-
246
- // Filter system fonts: English-only (Latin names), monospace-only for code
247
- const filteredSystemFonts = useMemo(() => {
248
- let fonts = systemFonts;
249
-
250
- // Filter to fonts with Latin-script names (excludes CJK, Arabic, Devanagari, etc.)
251
- fonts = fonts.filter(f => /^[\x20-\x7E\u00C0-\u024F]+$/.test(f.family));
252
-
253
- // For code fonts, only show monospace
254
- if (type === 'code') {
255
- fonts = fonts.filter(f => f.isMonospace);
256
- }
257
-
258
- return fonts;
259
- }, [systemFonts, type]);
260
-
261
- // Non-custom presets for display
262
- const displayPresets = useMemo(() => {
263
- return presets.filter(p => !p.isCustom);
264
- }, [presets]);
265
-
266
- // Update custom value when prop changes
267
- useEffect(() => {
268
- if (customFont !== undefined) {
269
- setCustomValue(customFont);
270
- }
271
- }, [customFont]);
272
-
273
- // Compute the Select value: for system fonts we encode as "system-font:FamilyName"
274
- const selectValue = useMemo(() => {
275
- if (currentFont === 'custom' && customValue) {
276
- // Check if this matches a system font
277
- const isSystemFont = systemFonts.some(f => f.family === customValue);
278
- if (isSystemFont) {
279
- return `${SYSTEM_FONT_PREFIX}${customValue}`;
280
- }
281
- return 'custom';
282
- }
283
- return currentFont;
284
- }, [currentFont, customValue, systemFonts]);
285
-
286
- const handleValueChange = useCallback(
287
- (value: string) => {
288
- if (value.startsWith(SYSTEM_FONT_PREFIX)) {
289
- const family = value.slice(SYSTEM_FONT_PREFIX.length);
290
- onSelect('custom', family);
291
- } else if (value === 'custom') {
292
- onSelect('custom');
293
- } else {
294
- onSelect(value);
295
- }
296
- },
297
- [onSelect]
298
- );
299
-
300
- const handleCustomChange = useCallback(
301
- (e: React.ChangeEvent<HTMLInputElement>) => {
302
- const value = e.target.value;
303
- setCustomValue(value);
304
- onCustomFontChange?.(value);
305
- if (currentFont === 'custom') {
306
- onSelect('custom', value);
307
- }
308
- },
309
- [currentFont, onSelect, onCustomFontChange]
310
- );
311
-
312
- const hasSystemFonts = systemFonts.length > 0;
313
- const showCustomInput = currentFont === 'custom' && !hasSystemFonts;
314
-
315
- return (
316
- <div className={`font-picker ${className}`}>
317
- <Select value={selectValue} onValueChange={handleValueChange}>
318
- <SelectTrigger
319
- className="font-picker-trigger"
320
- aria-label={`Select ${type} font`}
321
- style={{ fontFamily: currentPreset?.fontFamily || (customValue ? `"${customValue}"` : 'inherit') }}
322
- >
323
- <SelectValue placeholder="Select font..." />
324
- </SelectTrigger>
325
- <SelectContent className="max-h-[300px]">
326
- {/* Presets section */}
327
- {displayPresets.length > 0 && (
328
- <SelectGroup>
329
- <SelectLabel>Presets</SelectLabel>
330
- {displayPresets.map((preset) => (
331
- <SelectItem
332
- key={preset.id}
333
- value={preset.id}
334
- style={{ fontFamily: preset.fontFamily || 'inherit' }}
335
- >
336
- <span className="font-picker-item-content">
337
- <span className="font-name">{preset.name}</span>
338
- <span className="font-preview" style={{ fontFamily: preset.fontFamily }}>
339
- Aa
340
- </span>
341
- </span>
342
- </SelectItem>
343
- ))}
344
- </SelectGroup>
345
- )}
346
-
347
- {/* System fonts section */}
348
- {hasSystemFonts && filteredSystemFonts.length > 0 && (
349
- <SelectGroup>
350
- <SelectLabel>System Fonts ({filteredSystemFonts.length})</SelectLabel>
351
- {filteredSystemFonts.map((font) => (
352
- <SelectItem
353
- key={font.family}
354
- value={`${SYSTEM_FONT_PREFIX}${font.family}`}
355
- style={{ fontFamily: `"${font.family}", inherit` }}
356
- >
357
- <span className="font-picker-item-content">
358
- <span className="font-name">{font.family}</span>
359
- <span className="font-preview" style={{ fontFamily: `"${font.family}"` }}>
360
- Aa
361
- </span>
362
- </span>
363
- </SelectItem>
364
- ))}
365
- </SelectGroup>
366
- )}
367
-
368
- {/* Custom option (fallback when no system fonts) */}
369
- {!hasSystemFonts && fontsLoaded && (
370
- <SelectGroup>
371
- <SelectLabel>Custom</SelectLabel>
372
- <SelectItem value="custom">
373
- Custom...
374
- </SelectItem>
375
- </SelectGroup>
376
- )}
377
- </SelectContent>
378
- </Select>
379
-
380
- {showCustomInput && (
381
- <input
382
- type="text"
383
- className="font-picker-custom-input"
384
- value={customValue}
385
- onChange={handleCustomChange}
386
- placeholder="Enter font family..."
387
- aria-label="Custom font family"
388
- />
389
- )}
390
- </div>
391
- );
392
- }
393
-
394
- // =============================================================================
395
- // FontSizePicker Component
396
- // =============================================================================
397
-
398
- const SIZES: FontSize[] = ['xs', 'sm', 'base', 'lg', 'xl'];
399
-
400
- export function FontSizePicker({
401
- currentSize,
402
- onSelect,
403
- className = '',
404
- }: FontSizePickerProps): React.ReactElement {
405
- return (
406
- <TooltipProvider delayDuration={300}>
407
- <div className={`font-size-picker ${className}`} role="group" aria-label="Font size">
408
- {SIZES.map((size) => (
409
- <Tooltip key={size}>
410
- <TooltipTrigger asChild>
411
- <Button
412
- variant={size === currentSize ? 'secondary' : 'ghost'}
413
- size="sm"
414
- className={`font-size-option ${size === currentSize ? 'active' : ''}`}
415
- data-size={size}
416
- onClick={() => onSelect(size)}
417
- aria-pressed={size === currentSize}
418
- >
419
- {size.toUpperCase()}
420
- </Button>
421
- </TooltipTrigger>
422
- <TooltipContent>{`${FONT_SIZE_SCALE[size]} (${size})`}</TooltipContent>
423
- </Tooltip>
424
- ))}
425
- </div>
426
- </TooltipProvider>
427
- );
428
- }
429
-
430
- export default FontPicker;
@@ -1,237 +0,0 @@
1
- /**
2
- * FullFileTree - Complete directory tree with changed file highlighting
3
- *
4
- * Displays the full project file tree with lazy-loaded directories.
5
- * Changed files are highlighted with git status colors (created/modified/deleted).
6
- * Uses /api/files for directory listing and /ws/git for change status.
7
- */
8
-
9
- import React, { useState, useCallback, useEffect } from 'react';
10
- import { Badge } from '@/components/ui/badge';
11
- import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
12
- import { ScrollArea } from '@/components/ui/scroll-area';
13
- import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
14
- import { useFileBrowser, DirectoryEntry } from '../hooks/useFileBrowser';
15
- import type { FileStatus } from './FileTree';
16
-
17
- // =============================================================================
18
- // Types
19
- // =============================================================================
20
-
21
- export interface FullFileTreeProps {
22
- /** Map of file path → git status for highlighting */
23
- changedFiles: Map<string, FileStatus>;
24
- /** Callback when a file is clicked */
25
- onFileClick?: (entry: DirectoryEntry, status?: FileStatus) => void;
26
- }
27
-
28
- // =============================================================================
29
- // File Item Component
30
- // =============================================================================
31
-
32
- function TreeFileItem({
33
- entry,
34
- status,
35
- depth,
36
- onFileClick,
37
- }: {
38
- entry: DirectoryEntry;
39
- status?: FileStatus;
40
- depth: number;
41
- onFileClick?: (entry: DirectoryEntry, status?: FileStatus) => void;
42
- }): React.ReactElement {
43
- const statusIcon = status === 'created' ? '+' : status === 'modified' ? '~' : status === 'deleted' ? '-' : null;
44
-
45
- return (
46
- <Tooltip>
47
- <TooltipTrigger asChild>
48
- <div
49
- role="treeitem"
50
- className={`file-item${status ? ` file-${status}` : ''}`}
51
- style={{ paddingLeft: `${12 + depth * 16}px` }}
52
- tabIndex={0}
53
- aria-label={`${entry.name}${status ? `, ${status}` : ''}`}
54
- onClick={() => onFileClick?.(entry, status)}
55
- onKeyDown={(e) => {
56
- if (e.key === 'Enter' || e.key === ' ') {
57
- e.preventDefault();
58
- onFileClick?.(entry, status);
59
- }
60
- }}
61
- >
62
- {statusIcon && (
63
- <span className={`status-icon status-${status}`} aria-hidden="true">
64
- {statusIcon}
65
- </span>
66
- )}
67
- <span className={`file-name${status === 'deleted' ? '' : ''}`}>{entry.name}</span>
68
- </div>
69
- </TooltipTrigger>
70
- <TooltipContent>{entry.path}</TooltipContent>
71
- </Tooltip>
72
- );
73
- }
74
-
75
- // =============================================================================
76
- // Directory Node Component (recursive)
77
- // =============================================================================
78
-
79
- function TreeDirectoryNode({
80
- entry,
81
- depth,
82
- changedFiles,
83
- onFileClick,
84
- fetchDirectory,
85
- cache,
86
- loading,
87
- }: {
88
- entry: DirectoryEntry;
89
- depth: number;
90
- changedFiles: Map<string, FileStatus>;
91
- onFileClick?: (entry: DirectoryEntry, status?: FileStatus) => void;
92
- fetchDirectory: (path: string) => Promise<void>;
93
- cache: Record<string, DirectoryEntry[]>;
94
- loading: Set<string>;
95
- }): React.ReactElement {
96
- // Check if this directory contains any changed files
97
- const hasChanges = Array.from(changedFiles.keys()).some(
98
- (filePath) => filePath.startsWith(entry.path + '/')
99
- );
100
-
101
- const [isOpen, setIsOpen] = useState(hasChanges);
102
- const children = cache[entry.path];
103
- const isLoading = loading.has(entry.path);
104
-
105
- // Auto-fetch children when directory has changes and is opened by default
106
- useEffect(() => {
107
- if (hasChanges && !children && !loading.has(entry.path)) {
108
- fetchDirectory(entry.path);
109
- }
110
- }, [hasChanges, children, entry.path, fetchDirectory, loading]);
111
-
112
- // Auto-open when changes appear in this directory
113
- useEffect(() => {
114
- if (hasChanges) {
115
- setIsOpen(true);
116
- }
117
- }, [hasChanges]);
118
-
119
- const handleToggle = useCallback(() => {
120
- const willOpen = !isOpen;
121
- setIsOpen(willOpen);
122
- if (willOpen && !children) {
123
- fetchDirectory(entry.path);
124
- }
125
- }, [isOpen, children, entry.path, fetchDirectory]);
126
-
127
- return (
128
- <Collapsible open={isOpen} onOpenChange={handleToggle}>
129
- <CollapsibleTrigger asChild>
130
- <div
131
- className={`directory-header${hasChanges ? ' has-changes' : ''}`}
132
- style={{ paddingLeft: `${4 + depth * 16}px` }}
133
- >
134
- <span className="directory-toggle">
135
- <span className="toggle-icon">{isOpen ? '▼' : '▶'}</span>
136
- </span>
137
- <span className="directory-name">{entry.name}</span>
138
- </div>
139
- </CollapsibleTrigger>
140
- <CollapsibleContent>
141
- {isLoading && (
142
- <div
143
- className="tree-loading"
144
- style={{ paddingLeft: `${12 + (depth + 1) * 16}px` }}
145
- >
146
- Loading...
147
- </div>
148
- )}
149
- {children?.map((child) =>
150
- child.type === 'directory' ? (
151
- <TreeDirectoryNode
152
- key={child.path}
153
- entry={child}
154
- depth={depth + 1}
155
- changedFiles={changedFiles}
156
- onFileClick={onFileClick}
157
- fetchDirectory={fetchDirectory}
158
- cache={cache}
159
- loading={loading}
160
- />
161
- ) : (
162
- <TreeFileItem
163
- key={child.path}
164
- entry={child}
165
- status={changedFiles.get(child.path)}
166
- depth={depth + 1}
167
- onFileClick={onFileClick}
168
- />
169
- )
170
- )}
171
- </CollapsibleContent>
172
- </Collapsible>
173
- );
174
- }
175
-
176
- // =============================================================================
177
- // FullFileTree Component
178
- // =============================================================================
179
-
180
- export function FullFileTree({ changedFiles, onFileClick }: FullFileTreeProps): React.ReactElement {
181
- const { cache, loading, error, fetchDirectory } = useFileBrowser();
182
-
183
- // Load root directory on mount
184
- useEffect(() => {
185
- fetchDirectory('');
186
- }, []); // eslint-disable-line react-hooks/exhaustive-deps
187
-
188
- const rootEntries = cache['__root__'];
189
- const changedCount = changedFiles.size;
190
-
191
- return (
192
- <TooltipProvider delayDuration={300}>
193
- <div role="tree" aria-label="Project files" className="filetree full-filetree">
194
- {changedCount > 0 && (
195
- <Badge
196
- variant="secondary"
197
- data-testid="file-count-badge"
198
- className="file-count-badge"
199
- aria-label={`${changedCount} files changed`}
200
- >
201
- {changedCount}
202
- </Badge>
203
- )}
204
- <ScrollArea className="filetree-scroll">
205
- {error && <div className="tree-error">{error}</div>}
206
- {!rootEntries && !error && (
207
- <div className="tree-loading">Loading project files...</div>
208
- )}
209
- {rootEntries?.map((entry) =>
210
- entry.type === 'directory' ? (
211
- <TreeDirectoryNode
212
- key={entry.path}
213
- entry={entry}
214
- depth={0}
215
- changedFiles={changedFiles}
216
- onFileClick={onFileClick}
217
- fetchDirectory={fetchDirectory}
218
- cache={cache}
219
- loading={loading}
220
- />
221
- ) : (
222
- <TreeFileItem
223
- key={entry.path}
224
- entry={entry}
225
- status={changedFiles.get(entry.path)}
226
- depth={0}
227
- onFileClick={onFileClick}
228
- />
229
- )
230
- )}
231
- </ScrollArea>
232
- </div>
233
- </TooltipProvider>
234
- );
235
- }
236
-
237
- export default FullFileTree;