gloomberb 0.9.9 → 0.10.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 (519) hide show
  1. package/README.md +41 -3
  2. package/README.zh-CN.md +294 -0
  3. package/package.json +10 -4
  4. package/patches/@opentui%2Fcore@0.3.2.patch +26 -69
  5. package/src/api-client/auth.ts +2 -0
  6. package/src/api-client/index.test.ts +4 -0
  7. package/src/api-client/types.ts +3 -0
  8. package/src/app/pane-runtime/pane-settings-runtime.tsx +1 -0
  9. package/src/app/pane-template-dialog-wizard.test.tsx +36 -0
  10. package/src/app/pane-template-dialog-wizard.tsx +10 -3
  11. package/src/app/runtime/desktop-deeplink.test.ts +15 -0
  12. package/src/app/runtime/desktop-deeplink.ts +21 -6
  13. package/src/app.tsx +40 -33
  14. package/src/capabilities/service-capabilities.ts +7 -2
  15. package/src/cli/commands/automation.test.ts +202 -0
  16. package/src/cli/commands/automation.ts +153 -36
  17. package/src/cli/commands/market.ts +1 -14
  18. package/src/cli/commands/system.ts +4 -1
  19. package/src/cli/context.ts +1 -1
  20. package/src/cli/desktop-pane-shot.ts +65 -4
  21. package/src/cli/entry.ts +1 -1
  22. package/src/cli/pane-functions/capabilities.ts +532 -0
  23. package/src/cli/pane-functions/catalog.ts +39 -4
  24. package/src/cli/pane-functions/data.test.ts +17 -0
  25. package/src/cli/pane-functions/data.ts +55 -13
  26. package/src/cli/pane-functions/discovery.ts +36 -9
  27. package/src/cli/pane-functions/index.test.ts +104 -1
  28. package/src/cli/pane-functions/index.ts +64 -5
  29. package/src/cli/pane-functions/options.ts +21 -6
  30. package/src/cli/pane-functions/report.ts +735 -72
  31. package/src/cli/pane-functions/resolver.ts +70 -6
  32. package/src/cli/pane-functions/screenshot.test.ts +431 -0
  33. package/src/cli/pane-functions/screenshot.ts +952 -8
  34. package/src/components/chart/composite/column-layout.ts +215 -0
  35. package/src/components/chart/composite/composite-chart.test.tsx +630 -0
  36. package/src/components/chart/composite/composite-chart.tsx +1148 -0
  37. package/src/components/chart/composite/format.test.ts +137 -0
  38. package/src/components/chart/composite/format.ts +135 -0
  39. package/src/components/chart/composite/index.ts +38 -0
  40. package/src/components/chart/composite/interactions.test.ts +109 -0
  41. package/src/components/chart/composite/interactions.ts +247 -0
  42. package/src/components/chart/composite/price-series.test.ts +39 -0
  43. package/src/components/chart/composite/price-series.ts +78 -0
  44. package/src/components/chart/composite/rasterizer.ts +359 -0
  45. package/src/components/chart/composite/renderers.test.ts +610 -0
  46. package/src/components/chart/composite/scene.test.ts +464 -0
  47. package/src/components/chart/composite/scene.ts +553 -0
  48. package/src/components/chart/composite/text-renderer.ts +285 -0
  49. package/src/components/chart/composite/time-scale.test.ts +88 -0
  50. package/src/components/chart/composite/time-scale.ts +217 -0
  51. package/src/components/chart/composite/types.ts +141 -0
  52. package/src/components/chart/core/data.ts +81 -5
  53. package/src/components/chart/core/index.test.ts +128 -43
  54. package/src/components/chart/core/resolution.ts +0 -6
  55. package/src/components/chart/native/chart-rasterizer.ts +1 -3
  56. package/src/components/chart/native/kitty/index.test.ts +99 -120
  57. package/src/components/chart/native/kitty/manager.ts +3 -0
  58. package/src/components/chart/native/kitty/protocol.ts +4 -1
  59. package/src/components/chart/native/raster/crosshair.ts +79 -46
  60. package/src/components/chart/native/raster/types.ts +2 -11
  61. package/src/components/chart/native/surface/manager.ts +48 -3
  62. package/src/components/chart/price-axis-labels.tsx +18 -4
  63. package/src/components/command-bar/commands/direct/index.ts +25 -0
  64. package/src/components/command-bar/commands/registry.ts +9 -0
  65. package/src/components/command-bar/helpers.test.ts +4 -1
  66. package/src/components/command-bar/list/view.tsx +18 -6
  67. package/src/components/command-bar/multi-select-picker.tsx +6 -5
  68. package/src/components/command-bar/pane-settings.test.ts +141 -0
  69. package/src/components/command-bar/pane-settings.ts +61 -1
  70. package/src/components/command-bar/panel/body.tsx +7 -6
  71. package/src/components/command-bar/routes/root/command-items.ts +4 -4
  72. package/src/components/command-bar/routes/root/results.ts +10 -1
  73. package/src/components/command-bar/routes/root/selection.test.ts +54 -0
  74. package/src/components/command-bar/routes/root/selection.ts +13 -0
  75. package/src/components/command-bar/routing/actions.ts +18 -2
  76. package/src/components/command-bar/routing/list-state.ts +2 -1
  77. package/src/components/command-bar/surface/index.test.tsx +36 -4
  78. package/src/components/command-bar/surface/pane.test.tsx +93 -0
  79. package/src/components/command-bar/theme-picker.tsx +2 -1
  80. package/src/components/command-bar/view-model.ts +19 -20
  81. package/src/components/command-bar/workflow/body.tsx +2 -1
  82. package/src/components/command-bar/workflow/field-row.tsx +3 -2
  83. package/src/components/command-bar/workflow/fields.ts +4 -2
  84. package/src/components/command-bar/workflow/ops.test.ts +161 -0
  85. package/src/components/command-bar/workflow/ops.ts +20 -50
  86. package/src/components/command-bar/workflow/route-actions.test.ts +34 -0
  87. package/src/components/command-bar/workflow/route-actions.ts +4 -0
  88. package/src/components/command-bar/workflow/types.ts +1 -0
  89. package/src/components/feed-data-table/stack-view.tsx +6 -5
  90. package/src/components/index.ts +13 -1
  91. package/src/components/layout/detached-pane-shell.tsx +2 -1
  92. package/src/components/layout/floating-pane.tsx +3 -0
  93. package/src/components/layout/header.tsx +15 -8
  94. package/src/components/layout/pane/footer/index.test.tsx +22 -3
  95. package/src/components/layout/pane/footer/index.tsx +3 -1
  96. package/src/components/layout/pane/footer/model.ts +9 -2
  97. package/src/components/layout/pane/header.tsx +4 -6
  98. package/src/components/layout/pane/index.tsx +3 -0
  99. package/src/components/layout/pane/sidebar.test.tsx +100 -0
  100. package/src/components/layout/pane/sidebar.tsx +239 -0
  101. package/src/components/layout/pane/title.ts +4 -3
  102. package/src/components/layout/shell/action-menu-overlay.tsx +5 -3
  103. package/src/components/layout/shell/drag/runtime.ts +2 -0
  104. package/src/components/layout/shell/menu.test.ts +19 -0
  105. package/src/components/layout/shell/menu.ts +8 -5
  106. package/src/components/layout/shell/native/pointer-runtime.ts +4 -1
  107. package/src/components/layout/shell/pane/layers.tsx +2 -2
  108. package/src/components/layout/status-bar.tsx +8 -7
  109. package/src/components/layout/window-controls.tsx +4 -3
  110. package/src/components/metric-treemap/index.tsx +3 -2
  111. package/src/components/onboarding/onboarding-steps.tsx +30 -29
  112. package/src/components/onboarding/onboarding-wizard.tsx +5 -4
  113. package/src/components/onboarding/portfolio-step/broker-fields-panel.tsx +15 -12
  114. package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +17 -16
  115. package/src/components/onboarding/portfolio-step/broker-sync-panel.tsx +6 -5
  116. package/src/components/onboarding/portfolio-step/choose-panel.tsx +5 -4
  117. package/src/components/pane-settings-dialog/desktop.tsx +25 -3
  118. package/src/components/pane-settings-dialog/field-dialogs.tsx +5 -4
  119. package/src/components/pane-settings-dialog/tui.tsx +11 -9
  120. package/src/components/pane-settings-dialog/value.ts +8 -5
  121. package/src/components/pane-settings-dialog.test.tsx +235 -0
  122. package/src/components/pane-settings-dialog.tsx +24 -0
  123. package/src/components/pane-template-wizard.tsx +6 -2
  124. package/src/components/ticker/list-table-view.tsx +3 -2
  125. package/src/components/ui/button.tsx +3 -1
  126. package/src/components/ui/choice-dialog.tsx +6 -1
  127. package/src/components/ui/confirm-dialog.tsx +3 -2
  128. package/src/components/ui/fields.tsx +10 -1
  129. package/src/components/ui/frame.tsx +4 -1
  130. package/src/components/ui/index.ts +5 -0
  131. package/src/components/ui/inline-quick-add.tsx +104 -0
  132. package/src/components/ui/list-view.tsx +5 -4
  133. package/src/components/ui/loading.tsx +2 -1
  134. package/src/components/ui/multi-select/dialog.tsx +188 -44
  135. package/src/components/ui/popover.tsx +10 -0
  136. package/src/components/ui/shortcut-hint.tsx +2 -0
  137. package/src/components/ui/status.tsx +4 -3
  138. package/src/components/ui/tabs.tsx +19 -8
  139. package/src/components/ui/toggle.tsx +44 -3
  140. package/src/components/ui/ui.test.tsx +67 -5
  141. package/src/core/app-services.ts +4 -6
  142. package/src/core/state/session-persistence.ts +3 -2
  143. package/src/data/config/chart-settings.ts +712 -0
  144. package/src/data/config/layout.ts +24 -5
  145. package/src/data/config/store/index.test.ts +377 -14
  146. package/src/data/config/store/normalize.ts +79 -65
  147. package/src/data/fred-series.ts +137 -0
  148. package/src/i18n/index.test.ts +114 -0
  149. package/src/i18n/index.ts +147 -0
  150. package/src/i18n/ja.ts +1013 -0
  151. package/src/i18n/ko.ts +1011 -0
  152. package/src/i18n/languages.test.ts +31 -0
  153. package/src/i18n/languages.ts +72 -0
  154. package/src/i18n/zh-cn.ts +1013 -0
  155. package/src/i18n/zh-tw.ts +1013 -0
  156. package/src/plugins/builtin/account-management/footer.ts +3 -2
  157. package/src/plugins/builtin/account-management/form-components.tsx +3 -2
  158. package/src/plugins/builtin/account-management/keyboard.ts +6 -0
  159. package/src/plugins/builtin/account-management/model.ts +25 -21
  160. package/src/plugins/builtin/account-management/navigation.test.ts +27 -0
  161. package/src/plugins/builtin/account-management/navigation.ts +24 -0
  162. package/src/plugins/builtin/account-management/pane.tsx +120 -85
  163. package/src/plugins/builtin/account-management/password-dialog.tsx +10 -9
  164. package/src/plugins/builtin/ai/agent-history.ts +139 -0
  165. package/src/plugins/builtin/ai/ask-ai-detail-tab.tsx +133 -51
  166. package/src/plugins/builtin/ai/ask-ai.test.tsx +83 -22
  167. package/src/plugins/builtin/ai/index.test.ts +302 -0
  168. package/src/plugins/builtin/ai/index.tsx +374 -40
  169. package/src/plugins/builtin/ai/pane-settings.test.ts +155 -0
  170. package/src/plugins/builtin/ai/pane-settings.ts +319 -0
  171. package/src/plugins/builtin/ai/pi/credential-store.test.ts +80 -0
  172. package/src/plugins/builtin/ai/pi/credential-store.ts +138 -0
  173. package/src/plugins/builtin/ai/pi/file-store.ts +138 -0
  174. package/src/plugins/builtin/ai/pi/host.test.ts +500 -0
  175. package/src/plugins/builtin/ai/pi/host.ts +564 -0
  176. package/src/plugins/builtin/ai/pi/index.ts +5 -0
  177. package/src/plugins/builtin/ai/pi/models-store.test.ts +44 -0
  178. package/src/plugins/builtin/ai/pi/models-store.ts +141 -0
  179. package/src/plugins/builtin/ai/pi/providers.ts +68 -0
  180. package/src/plugins/builtin/ai/pi/runtime.test.ts +240 -0
  181. package/src/plugins/builtin/ai/pi/runtime.ts +635 -0
  182. package/src/plugins/builtin/ai/providers.test.ts +68 -0
  183. package/src/plugins/builtin/ai/providers.ts +163 -38
  184. package/src/plugins/builtin/ai/runner-selection.test.ts +174 -0
  185. package/src/plugins/builtin/ai/runner-selection.ts +193 -0
  186. package/src/plugins/builtin/ai/runner-selector.tsx +153 -0
  187. package/src/plugins/builtin/ai/runner.test.ts +198 -0
  188. package/src/plugins/builtin/ai/runner.ts +276 -73
  189. package/src/plugins/builtin/ai/screener/contract.test.ts +26 -73
  190. package/src/plugins/builtin/ai/screener/contract.ts +14 -52
  191. package/src/plugins/builtin/ai/screener/editor-runtime.ts +55 -5
  192. package/src/plugins/builtin/ai/screener/editor.tsx +42 -36
  193. package/src/plugins/builtin/ai/screener/footer.ts +82 -67
  194. package/src/plugins/builtin/ai/screener/keyboard.ts +27 -11
  195. package/src/plugins/builtin/ai/screener/model.test.ts +24 -0
  196. package/src/plugins/builtin/ai/screener/model.ts +9 -3
  197. package/src/plugins/builtin/ai/screener/pane.test.tsx +142 -55
  198. package/src/plugins/builtin/ai/screener/pane.tsx +95 -97
  199. package/src/plugins/builtin/ai/screener/results-view.tsx +8 -41
  200. package/src/plugins/builtin/ai/screener/runner.ts +41 -25
  201. package/src/plugins/builtin/ai/screener/tabs-bar.tsx +2 -2
  202. package/src/plugins/builtin/ai/use-runtime-providers.ts +28 -0
  203. package/src/plugins/builtin/ai/workspace/model.test.ts +227 -0
  204. package/src/plugins/builtin/ai/workspace/model.ts +308 -0
  205. package/src/plugins/builtin/ai/workspace/pane.test.tsx +197 -0
  206. package/src/plugins/builtin/ai/workspace/pane.tsx +896 -0
  207. package/src/plugins/builtin/analytics/index.test.tsx +3 -3
  208. package/src/plugins/builtin/analytics/index.tsx +3 -8
  209. package/src/plugins/builtin/broker-manager/detail.tsx +25 -24
  210. package/src/plugins/builtin/broker-manager/index.test.tsx +1 -1
  211. package/src/plugins/builtin/broker-manager/index.tsx +9 -11
  212. package/src/plugins/builtin/broker-manager/model.ts +11 -10
  213. package/src/plugins/builtin/broker-manager/pane-actions.tsx +22 -21
  214. package/src/plugins/builtin/broker-manager/table.ts +9 -8
  215. package/src/plugins/builtin/changelog/index.tsx +3 -8
  216. package/src/plugins/builtin/chart-composer/chart-spec.ts +89 -0
  217. package/src/plugins/builtin/chart-composer/cli-options.ts +98 -0
  218. package/src/plugins/builtin/chart-composer/date-window-dialog.tsx +120 -0
  219. package/src/plugins/builtin/chart-composer/editor.test.tsx +332 -0
  220. package/src/plugins/builtin/chart-composer/editor.tsx +1107 -0
  221. package/src/plugins/builtin/chart-composer/index.tsx +228 -0
  222. package/src/plugins/builtin/chart-composer/pane.tsx +645 -0
  223. package/src/plugins/builtin/chart-composer/presets.test.ts +561 -0
  224. package/src/plugins/builtin/chart-composer/presets.ts +759 -0
  225. package/src/plugins/builtin/chart-composer/quick-add.test.tsx +245 -0
  226. package/src/plugins/builtin/chart-composer/quick-add.tsx +409 -0
  227. package/src/plugins/builtin/chart-composer/semantic.ts +86 -0
  228. package/src/plugins/builtin/chart-composer/series-catalog.test.ts +65 -0
  229. package/src/plugins/builtin/chart-composer/series-catalog.ts +295 -0
  230. package/src/plugins/builtin/chart-composer/settings.test.ts +163 -0
  231. package/src/plugins/builtin/chart-composer/settings.ts +397 -0
  232. package/src/plugins/builtin/chart-composer/shortcuts.test.ts +44 -0
  233. package/src/plugins/builtin/chart-composer/shortcuts.ts +35 -0
  234. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +103 -0
  235. package/src/plugins/builtin/chat/channel-labels.ts +5 -4
  236. package/src/plugins/builtin/chat/channels.ts +12 -11
  237. package/src/plugins/builtin/chat/chat.test.tsx +32 -0
  238. package/src/plugins/builtin/chat/content/composer-runtime.ts +6 -1
  239. package/src/plugins/builtin/chat/content/composer.tsx +9 -8
  240. package/src/plugins/builtin/chat/content/index.tsx +36 -1
  241. package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +8 -7
  242. package/src/plugins/builtin/chat/content/transcript.tsx +9 -3
  243. package/src/plugins/builtin/chat/controller/utils.ts +10 -9
  244. package/src/plugins/builtin/chat/message/desktop.tsx +17 -10
  245. package/src/plugins/builtin/chat/message/profile-popover.test.tsx +122 -3
  246. package/src/plugins/builtin/chat/message/profile-popover.tsx +38 -1
  247. package/src/plugins/builtin/chat/message/terminal.tsx +19 -10
  248. package/src/plugins/builtin/chat/pane-state.test.ts +31 -0
  249. package/src/plugins/builtin/chat/pane-state.ts +30 -0
  250. package/src/plugins/builtin/chat/pane.tsx +27 -4
  251. package/src/plugins/builtin/chat/profile-popover.ts +62 -5
  252. package/src/plugins/builtin/chat/sidebar.test.tsx +4 -7
  253. package/src/plugins/builtin/chat/sidebar.tsx +107 -168
  254. package/src/plugins/builtin/chat/test-harness.tsx +6 -0
  255. package/src/plugins/builtin/cloud/auth-actions.tsx +5 -4
  256. package/src/plugins/builtin/cloud/plugin.tsx +150 -127
  257. package/src/plugins/builtin/composite-plugins.ts +71 -0
  258. package/src/plugins/builtin/correlation/index.test.tsx +4 -4
  259. package/src/plugins/builtin/correlation/index.tsx +3 -8
  260. package/src/plugins/builtin/earnings/index.tsx +37 -21
  261. package/src/plugins/builtin/earnings/model.test.ts +52 -0
  262. package/src/plugins/builtin/earnings/model.ts +32 -0
  263. package/src/plugins/builtin/econ/detail-view.tsx +17 -4
  264. package/src/plugins/builtin/econ/fred-cache.test.ts +57 -11
  265. package/src/plugins/builtin/econ/index.tsx +16 -20
  266. package/src/plugins/builtin/fear-greed/index.tsx +2 -8
  267. package/src/plugins/builtin/fx-matrix/index.tsx +3 -8
  268. package/src/plugins/builtin/help/components.tsx +5 -4
  269. package/src/plugins/builtin/help/index.tsx +14 -17
  270. package/src/plugins/builtin/holders/index.tsx +2 -8
  271. package/src/plugins/builtin/insider/index.tsx +2 -7
  272. package/src/plugins/builtin/kelly-sizer/index.test.tsx +2 -2
  273. package/src/plugins/builtin/kelly-sizer/index.tsx +3 -7
  274. package/src/plugins/builtin/kelly-sizer/test-support.tsx +3 -3
  275. package/src/plugins/builtin/layout-manager/index.tsx +3 -7
  276. package/src/plugins/builtin/market-heatmap/index.tsx +3 -8
  277. package/src/plugins/builtin/market-movers/index.tsx +3 -8
  278. package/src/plugins/builtin/news/index.tsx +12 -16
  279. package/src/plugins/builtin/news/wire/breaking/pane.test.tsx +3 -3
  280. package/src/plugins/builtin/news/wire/index.tsx +83 -73
  281. package/src/plugins/builtin/options/index.tsx +2 -8
  282. package/src/plugins/builtin/plugin-module.test.ts +89 -0
  283. package/src/plugins/builtin/plugin-module.ts +116 -0
  284. package/src/plugins/builtin/portfolio-list/header.tsx +4 -3
  285. package/src/plugins/builtin/portfolio-list/index.test.ts +17 -0
  286. package/src/plugins/builtin/portfolio-list/index.tsx +3 -5
  287. package/src/plugins/builtin/portfolio-list/pane/index.test.tsx +3 -3
  288. package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +53 -53
  289. package/src/plugins/builtin/portfolio-list/settings.ts +5 -3
  290. package/src/plugins/builtin/portfolio-list/summary/index.tsx +4 -3
  291. package/src/plugins/builtin/research/index.tsx +2 -8
  292. package/src/plugins/builtin/sec/index.tsx +2 -8
  293. package/src/plugins/builtin/sectors/index.tsx +3 -8
  294. package/src/plugins/builtin/thirteenf/index.tsx +3 -8
  295. package/src/plugins/builtin/thirteenf/pane.test.tsx +1 -1
  296. package/src/plugins/builtin/ticker-detail/chart-tab-switch.test.tsx +49 -23
  297. package/src/plugins/builtin/ticker-detail/index.test.tsx +15 -136
  298. package/src/plugins/builtin/ticker-detail/index.tsx +2 -93
  299. package/src/plugins/builtin/ticker-detail/overview/components.tsx +6 -5
  300. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +41 -17
  301. package/src/plugins/builtin/ticker-detail/pane.tsx +4 -3
  302. package/src/plugins/builtin/ticker-detail/quote-monitor/index.test.tsx +1 -1
  303. package/src/plugins/builtin/ticker-detail/settings.ts +3 -50
  304. package/src/plugins/builtin/ticker-research-backend-plugin.ts +17 -0
  305. package/src/plugins/builtin/ticker-research-plugin.ts +27 -0
  306. package/src/plugins/builtin/tv/channels.ts +27 -0
  307. package/src/plugins/builtin/tv/index.tsx +40 -0
  308. package/src/plugins/builtin/tv/pane.tsx +286 -0
  309. package/src/plugins/builtin/tv/youtube-stream.ts +100 -0
  310. package/src/plugins/builtin/world-indices/index.tsx +3 -8
  311. package/src/plugins/builtin/yield-curve/index.tsx +8 -8
  312. package/src/plugins/catalog-backend.test.ts +21 -0
  313. package/src/plugins/catalog-backend.ts +42 -0
  314. package/src/plugins/catalog-ui.ts +6 -14
  315. package/src/plugins/ibkr/instance-selection.test.ts +0 -1
  316. package/src/plugins/ownership.ts +143 -0
  317. package/src/plugins/prediction-markets/backend-plugin.ts +19 -0
  318. package/src/plugins/prediction-markets/chart.test.tsx +7 -5
  319. package/src/plugins/prediction-markets/chart.tsx +25 -7
  320. package/src/plugins/registry/index.test.ts +51 -0
  321. package/src/plugins/registry/index.ts +8 -0
  322. package/src/plugins/registry/pane-settings.ts +1 -1
  323. package/src/plugins/runtime/index.test.tsx +2 -2
  324. package/src/remote/app-host.tsx +16 -3
  325. package/src/remote/controller.test.ts +102 -1
  326. package/src/remote/controller.ts +122 -0
  327. package/src/remote/types.ts +11 -0
  328. package/src/renderers/electrobun/bun/core-capabilities.ts +123 -27
  329. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +5 -1
  330. package/src/renderers/electrobun/bun/desktop/initialization.ts +5 -1
  331. package/src/renderers/electrobun/bun/desktop/media.ts +15 -0
  332. package/src/renderers/electrobun/bun/desktop/window-style.ts +4 -1
  333. package/src/renderers/electrobun/bun/desktop/workspace/index.test.ts +32 -1
  334. package/src/renderers/electrobun/bun/desktop/workspace/index.ts +10 -0
  335. package/src/renderers/electrobun/bun/index.ts +5 -0
  336. package/src/renderers/electrobun/bun/tui-entry.ts +1 -6
  337. package/src/renderers/electrobun/view/ai-host.ts +124 -19
  338. package/src/renderers/electrobun/view/backend-rpc.ts +4 -0
  339. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +151 -39
  340. package/src/renderers/electrobun/view/desktop/popover.tsx +166 -0
  341. package/src/renderers/electrobun/view/dialog-host.test.ts +25 -0
  342. package/src/renderers/electrobun/view/dialog-host.tsx +75 -12
  343. package/src/renderers/electrobun/view/host/box.tsx +5 -0
  344. package/src/renderers/electrobun/view/host/chart-surface.tsx +10 -9
  345. package/src/renderers/electrobun/view/host/input.tsx +9 -19
  346. package/src/renderers/electrobun/view/host/media-surface.tsx +170 -0
  347. package/src/renderers/electrobun/view/host/mouse.ts +1 -0
  348. package/src/renderers/electrobun/view/host/style.ts +1 -1
  349. package/src/renderers/electrobun/view/host/tabs.tsx +4 -3
  350. package/src/renderers/electrobun/view/main.tsx +10 -3
  351. package/src/renderers/electrobun/view/styles.css +17 -0
  352. package/src/renderers/electrobun/view/ui-host.tsx +7 -0
  353. package/src/renderers/opentui/chart-surface.test.tsx +52 -6
  354. package/src/renderers/opentui/chart-surface.tsx +95 -11
  355. package/src/renderers/opentui/dialog-host.tsx +36 -5
  356. package/src/renderers/opentui/host.tsx +39 -0
  357. package/src/renderers/opentui/start.tsx +30 -0
  358. package/src/renderers/opentui/ui-host.tsx +2 -0
  359. package/src/sources/provider-router/index.test.ts +43 -0
  360. package/src/sources/provider-router/index.ts +4 -0
  361. package/src/sources/provider-router/supplemental.ts +46 -0
  362. package/src/sources/sec-edgar.test.ts +203 -2
  363. package/src/sources/sec-edgar.ts +70 -15
  364. package/src/state/app/context/index.tsx +13 -1
  365. package/src/state/app/context/selector.test.tsx +62 -1
  366. package/src/state/session-persistence.test.ts +13 -2
  367. package/src/sync/controller.test.ts +190 -3
  368. package/src/sync/controller.ts +76 -45
  369. package/src/sync/core-contributors.test.ts +121 -0
  370. package/src/sync/core-contributors.ts +104 -27
  371. package/src/sync/react.ts +6 -8
  372. package/src/sync/types.ts +3 -0
  373. package/src/time-series/alignment.ts +158 -0
  374. package/src/time-series/economic.ts +49 -0
  375. package/src/time-series/field-catalog.ts +306 -0
  376. package/src/time-series/fundamentals.test.ts +505 -0
  377. package/src/time-series/fundamentals.ts +842 -0
  378. package/src/time-series/hooks.ts +45 -0
  379. package/src/time-series/index.ts +14 -0
  380. package/src/time-series/live-quotes.test.ts +219 -0
  381. package/src/time-series/live-quotes.ts +203 -0
  382. package/src/time-series/market-resolution.ts +53 -0
  383. package/src/time-series/market.ts +125 -0
  384. package/src/time-series/reporting.ts +98 -0
  385. package/src/time-series/resolve.test.ts +1281 -0
  386. package/src/time-series/resolve.ts +783 -0
  387. package/src/time-series/spec-studies.test.ts +400 -0
  388. package/src/time-series/spec.ts +487 -0
  389. package/src/time-series/studies.ts +563 -0
  390. package/src/time-series/transforms.test.ts +105 -0
  391. package/src/time-series/transforms.ts +152 -0
  392. package/src/time-series/types.ts +162 -0
  393. package/src/time-series/use-chart-resolution.ts +166 -0
  394. package/src/types/config.ts +9 -11
  395. package/src/types/desktop-window.ts +1 -0
  396. package/src/types/financials.ts +4 -0
  397. package/src/types/media.ts +17 -0
  398. package/src/types/plugin.ts +32 -1
  399. package/src/ui/context-menu.tsx +15 -3
  400. package/src/ui/dialog.tsx +14 -2
  401. package/src/ui/host.tsx +40 -1
  402. package/src/ui/index.tsx +9 -0
  403. package/src/utils/exchanges.test.ts +13 -1
  404. package/src/utils/exchanges.ts +10 -0
  405. package/src/utils/financial-statements.test.ts +138 -0
  406. package/src/utils/financial-statements.ts +115 -8
  407. package/src/utils/format.test.ts +11 -1
  408. package/src/utils/format.ts +7 -0
  409. package/src/version.ts +1 -1
  410. package/src/components/chart/bar-chart-renderer.test.ts +0 -233
  411. package/src/components/chart/bar-chart-renderer.ts +0 -445
  412. package/src/components/chart/comparison/data.test.ts +0 -159
  413. package/src/components/chart/comparison/data.ts +0 -302
  414. package/src/components/chart/comparison/renderer.test.ts +0 -187
  415. package/src/components/chart/comparison/renderer.ts +0 -282
  416. package/src/components/chart/comparison/scene.ts +0 -178
  417. package/src/components/chart/comparison-stock-chart/axis-width.ts +0 -99
  418. package/src/components/chart/comparison-stock-chart/canvas.ts +0 -148
  419. package/src/components/chart/comparison-stock-chart/controls.ts +0 -252
  420. package/src/components/chart/comparison-stock-chart/helpers.ts +0 -101
  421. package/src/components/chart/comparison-stock-chart/interactions.ts +0 -208
  422. package/src/components/chart/comparison-stock-chart/layout-metrics.ts +0 -62
  423. package/src/components/chart/comparison-stock-chart/layout.tsx +0 -155
  424. package/src/components/chart/comparison-stock-chart/legend.tsx +0 -74
  425. package/src/components/chart/comparison-stock-chart/native-surfaces.ts +0 -89
  426. package/src/components/chart/comparison-stock-chart/render-data.ts +0 -227
  427. package/src/components/chart/comparison-stock-chart/render-output.ts +0 -140
  428. package/src/components/chart/comparison-stock-chart/selection-runtime.ts +0 -128
  429. package/src/components/chart/comparison-stock-chart/sources.ts +0 -51
  430. package/src/components/chart/comparison-stock-chart/surface-runtime.ts +0 -159
  431. package/src/components/chart/comparison-stock-chart/toolbar.tsx +0 -117
  432. package/src/components/chart/comparison-stock-chart/types.ts +0 -22
  433. package/src/components/chart/comparison-stock-chart/view.tsx +0 -572
  434. package/src/components/chart/comparison-stock-chart/viewport-runtime.ts +0 -239
  435. package/src/components/chart/comparison-stock-chart.tsx +0 -24
  436. package/src/components/chart/core/axis-measure.ts +0 -33
  437. package/src/components/chart/core/controller.test.ts +0 -157
  438. package/src/components/chart/core/controller.ts +0 -349
  439. package/src/components/chart/core/indicator-selector.tsx +0 -75
  440. package/src/components/chart/core/keyboard.ts +0 -24
  441. package/src/components/chart/core/pane-settings.test.ts +0 -52
  442. package/src/components/chart/core/pane-settings.ts +0 -141
  443. package/src/components/chart/core/scroll.test.ts +0 -64
  444. package/src/components/chart/core/scroll.ts +0 -82
  445. package/src/components/chart/core/window-viewport.test.ts +0 -69
  446. package/src/components/chart/core/window-viewport.ts +0 -162
  447. package/src/components/chart/display-cursor.ts +0 -153
  448. package/src/components/chart/indicators/bands.test.ts +0 -36
  449. package/src/components/chart/indicators/bands.ts +0 -29
  450. package/src/components/chart/indicators/moving-averages.test.ts +0 -39
  451. package/src/components/chart/indicators/moving-averages.ts +0 -42
  452. package/src/components/chart/indicators/options.test.ts +0 -32
  453. package/src/components/chart/indicators/options.ts +0 -107
  454. package/src/components/chart/indicators/oscillators.test.ts +0 -58
  455. package/src/components/chart/indicators/oscillators.ts +0 -92
  456. package/src/components/chart/native/canvas-bitmaps.ts +0 -140
  457. package/src/components/chart/native/raster/comparison-chart.ts +0 -162
  458. package/src/components/chart/native/surface/hooks.ts +0 -144
  459. package/src/components/chart/native/surface/rendering.ts +0 -211
  460. package/src/components/chart/static/bar-chart-surface.test.tsx +0 -101
  461. package/src/components/chart/static/bar-chart-surface.tsx +0 -292
  462. package/src/components/chart/stock-chart/auto.ts +0 -216
  463. package/src/components/chart/stock-chart/axis-width.ts +0 -146
  464. package/src/components/chart/stock-chart/bitmaps.ts +0 -22
  465. package/src/components/chart/stock-chart/canvas.ts +0 -202
  466. package/src/components/chart/stock-chart/controls.tsx +0 -149
  467. package/src/components/chart/stock-chart/cursor.ts +0 -60
  468. package/src/components/chart/stock-chart/data-runtime.ts +0 -128
  469. package/src/components/chart/stock-chart/footer.test.ts +0 -65
  470. package/src/components/chart/stock-chart/footer.ts +0 -303
  471. package/src/components/chart/stock-chart/geometry.ts +0 -160
  472. package/src/components/chart/stock-chart/index.test.ts +0 -532
  473. package/src/components/chart/stock-chart/index.tsx +0 -29
  474. package/src/components/chart/stock-chart/indicators.ts +0 -226
  475. package/src/components/chart/stock-chart/interaction-runtime.ts +0 -44
  476. package/src/components/chart/stock-chart/interactions.ts +0 -300
  477. package/src/components/chart/stock-chart/keyboard.ts +0 -373
  478. package/src/components/chart/stock-chart/layout-metrics.ts +0 -62
  479. package/src/components/chart/stock-chart/layout.tsx +0 -177
  480. package/src/components/chart/stock-chart/native-surfaces.ts +0 -121
  481. package/src/components/chart/stock-chart/presentation.ts +0 -67
  482. package/src/components/chart/stock-chart/renderer-switch.test.tsx +0 -263
  483. package/src/components/chart/stock-chart/rendering/bounds.ts +0 -116
  484. package/src/components/chart/stock-chart/rendering/candidates.ts +0 -145
  485. package/src/components/chart/stock-chart/rendering/data.ts +0 -370
  486. package/src/components/chart/stock-chart/rendering/invalidation.ts +0 -68
  487. package/src/components/chart/stock-chart/rendering/output.ts +0 -304
  488. package/src/components/chart/stock-chart/rendering/planning.ts +0 -122
  489. package/src/components/chart/stock-chart/rendering/projection.test.tsx +0 -98
  490. package/src/components/chart/stock-chart/rendering/projection.ts +0 -112
  491. package/src/components/chart/stock-chart/rendering/state.test.ts +0 -70
  492. package/src/components/chart/stock-chart/rendering/state.ts +0 -283
  493. package/src/components/chart/stock-chart/requests.ts +0 -337
  494. package/src/components/chart/stock-chart/resolution-support.ts +0 -96
  495. package/src/components/chart/stock-chart/resolved/runtime.ts +0 -289
  496. package/src/components/chart/stock-chart/resolved.tsx +0 -359
  497. package/src/components/chart/stock-chart/settings.ts +0 -81
  498. package/src/components/chart/stock-chart/surface-runtime.ts +0 -62
  499. package/src/components/chart/stock-chart/types.ts +0 -25
  500. package/src/components/chart/stock-chart/view.tsx +0 -155
  501. package/src/components/chart/stock-chart/viewport/effects.ts +0 -293
  502. package/src/components/chart/stock-chart/viewport/index.ts +0 -144
  503. package/src/components/chart/stock-chart/viewport/runtime.ts +0 -375
  504. package/src/components/chart/time-axis-label.tsx +0 -175
  505. package/src/plugins/builtin/ai/gloomberb-cli.ts +0 -71
  506. package/src/plugins/builtin/ai/screener/action-bar.tsx +0 -58
  507. package/src/plugins/builtin/comparison-chart/index.test.tsx +0 -848
  508. package/src/plugins/builtin/comparison-chart/index.tsx +0 -194
  509. package/src/plugins/builtin/econ/fred-cache.ts +0 -106
  510. package/src/plugins/builtin/plugin-groups.ts +0 -130
  511. package/src/plugins/builtin/ticker-detail/chart-pane.tsx +0 -91
  512. package/src/plugins/builtin/ticker-detail/chart-tab.tsx +0 -100
  513. package/src/plugins/builtin/ticker-detail/data-panes/fundamental-graph/content.tsx +0 -296
  514. package/src/plugins/builtin/ticker-detail/data-panes/fundamental-graph/data.ts +0 -62
  515. package/src/plugins/builtin/ticker-detail/data-panes/fundamental-graph/model.ts +0 -608
  516. package/src/plugins/builtin/ticker-detail/data-panes/fundamental-graph/settings.ts +0 -65
  517. package/src/plugins/builtin/ticker-detail/data-panes/fundamental-graph/types.ts +0 -58
  518. package/src/plugins/builtin/ticker-detail/data-panes/fundamental-graph.tsx +0 -138
  519. package/src/plugins/builtin/ticker-detail/data-panes.test.ts +0 -220
@@ -0,0 +1,42 @@
1
+ import type { GloomPlugin } from "../types/plugin";
2
+ import { aiPlugin } from "./builtin/ai";
3
+ import { alertsPlugin } from "./builtin/alerts";
4
+ import { gloomberbCloudPlugin } from "./builtin/cloud";
5
+ import {
6
+ applicationPlugin,
7
+ brokerPlugin,
8
+ macroPlugin,
9
+ marketOverviewPlugin,
10
+ portfolioPlugin,
11
+ } from "./builtin/composite-plugins";
12
+ import { debugPlugin } from "./builtin/debug";
13
+ import { newsPlugin } from "./builtin/news";
14
+ import { notesPlugin } from "./builtin/notes";
15
+ import { substackPlugin } from "./builtin/substack";
16
+ import { tickerResearchBackendPlugin } from "./builtin/ticker-research-backend-plugin";
17
+ import { yahooPlugin } from "./builtin/yahoo";
18
+ import { ibkrPlugin } from "./ibkr";
19
+ import { predictionMarketsBackendPlugin } from "./prediction-markets/backend-plugin";
20
+
21
+ const desktopBackendPlugins: GloomPlugin[] = [
22
+ yahooPlugin,
23
+ gloomberbCloudPlugin,
24
+ portfolioPlugin,
25
+ tickerResearchBackendPlugin,
26
+ brokerPlugin,
27
+ ibkrPlugin,
28
+ applicationPlugin,
29
+ newsPlugin,
30
+ substackPlugin,
31
+ notesPlugin,
32
+ aiPlugin,
33
+ predictionMarketsBackendPlugin,
34
+ marketOverviewPlugin,
35
+ macroPlugin,
36
+ alertsPlugin,
37
+ debugPlugin,
38
+ ];
39
+
40
+ export function getDesktopBackendPlugins(): GloomPlugin[] {
41
+ return desktopBackendPlugins;
42
+ }
@@ -1,43 +1,35 @@
1
1
  import type { GloomPlugin } from "../types/plugin";
2
- import { portfolioListPlugin } from "./builtin/portfolio-list";
3
2
  import { newsPlugin } from "./builtin/news";
4
3
  import { notesPlugin } from "./builtin/notes";
5
4
  import { substackPlugin } from "./builtin/substack";
6
5
  import { aiPlugin } from "./builtin/ai";
7
6
  import { gloomberbCloudPlugin } from "./builtin/cloud";
8
- import { changelogPlugin } from "./builtin/changelog";
9
- import { helpPlugin } from "./builtin/help";
10
7
  import { ibkrPlugin } from "./ibkr";
11
- import { layoutManagerPlugin } from "./builtin/layout-manager";
12
8
  import { predictionMarketsPlugin } from "./prediction-markets";
13
- import { analyticsPlugin } from "./builtin/analytics";
14
9
  import { alertsPlugin } from "./builtin/alerts";
15
- import { kellySizerPlugin } from "./builtin/kelly-sizer";
16
10
  import {
11
+ applicationPlugin,
17
12
  brokerPlugin,
18
13
  macroPlugin,
19
14
  marketOverviewPlugin,
20
- tickerResearchPlugin,
21
- } from "./builtin/plugin-groups";
15
+ portfolioPlugin,
16
+ } from "./builtin/composite-plugins";
17
+ import { tickerResearchPlugin } from "./builtin/ticker-research-plugin";
22
18
 
23
19
  export const uiBuiltinPlugins: GloomPlugin[] = [
24
20
  gloomberbCloudPlugin,
25
- portfolioListPlugin,
21
+ portfolioPlugin,
26
22
  tickerResearchPlugin,
27
23
  brokerPlugin,
28
24
  ibkrPlugin,
29
- layoutManagerPlugin,
25
+ applicationPlugin,
30
26
  newsPlugin,
31
27
  substackPlugin,
32
28
  notesPlugin,
33
29
  aiPlugin,
34
- changelogPlugin,
35
- helpPlugin,
36
30
  predictionMarketsPlugin,
37
31
  marketOverviewPlugin,
38
32
  macroPlugin,
39
- analyticsPlugin,
40
- kellySizerPlugin,
41
33
  alertsPlugin,
42
34
  ];
43
35
 
@@ -35,7 +35,6 @@ function createConfig(overrides: Partial<AppConfig> = {}): AppConfig {
35
35
  pluginConfig: {},
36
36
  theme: "amber",
37
37
  chartPreferences: {
38
- defaultRenderMode: "area",
39
38
  renderer: "auto",
40
39
  },
41
40
  recentTickers: [],
@@ -0,0 +1,143 @@
1
+ const BUILTIN_PLUGIN_OWNER_ALIASES: Record<string, string> = {
2
+ analytics: "portfolio",
3
+ "broker-manager": "broker",
4
+ changelog: "application",
5
+ "company-research": "ticker-research",
6
+ "chart-composer": "ticker-research",
7
+ "comparison-chart": "ticker-research",
8
+ correlation: "market-overview",
9
+ "earnings-calendar": "macro",
10
+ "fear-greed": "market-overview",
11
+ "fx-matrix": "market-overview",
12
+ help: "application",
13
+ holders: "ticker-research",
14
+ insider: "ticker-research",
15
+ "kelly-sizer": "portfolio",
16
+ "layout-manager": "application",
17
+ "macro-tv": "macro",
18
+ "market-heatmap": "market-overview",
19
+ "market-movers": "market-overview",
20
+ options: "ticker-research",
21
+ "portfolio-list": "portfolio",
22
+ research: "ticker-research",
23
+ sectors: "market-overview",
24
+ sec: "ticker-research",
25
+ thirteenf: "ticker-research",
26
+ "ticker-detail": "ticker-research",
27
+ "world-indices": "market-overview",
28
+ };
29
+
30
+ const NON_TOGGLEABLE_BUILTIN_PLUGIN_IDS = new Set([
31
+ "application",
32
+ "changelog",
33
+ "help",
34
+ "layout-manager",
35
+ ]);
36
+
37
+ const LEGACY_MODULE_IDS_BY_OWNER: Record<string, readonly string[]> = {
38
+ application: ["layout-manager", "help", "changelog"],
39
+ portfolio: ["portfolio-list", "analytics", "kelly-sizer"],
40
+ };
41
+
42
+ export function normalizeBuiltinPluginOwnerId(pluginId: string): string {
43
+ return BUILTIN_PLUGIN_OWNER_ALIASES[pluginId] ?? pluginId;
44
+ }
45
+
46
+ export function isReservedBuiltinPluginId(pluginId: string): boolean {
47
+ return Object.prototype.hasOwnProperty.call(BUILTIN_PLUGIN_OWNER_ALIASES, pluginId);
48
+ }
49
+
50
+ export function isNonToggleableBuiltinPluginId(pluginId: string): boolean {
51
+ return NON_TOGGLEABLE_BUILTIN_PLUGIN_IDS.has(pluginId);
52
+ }
53
+
54
+ export function normalizeBuiltinDisabledPluginIds(pluginIds: readonly string[]): string[] {
55
+ return [...new Set(
56
+ pluginIds
57
+ .filter((pluginId) => !isNonToggleableBuiltinPluginId(pluginId))
58
+ .map(normalizeBuiltinPluginOwnerId)
59
+ .filter((pluginId) => !isNonToggleableBuiltinPluginId(pluginId)),
60
+ )];
61
+ }
62
+
63
+ export function normalizeBuiltinPluginStateMap(
64
+ value: Record<string, Record<string, unknown>>,
65
+ ): Record<string, Record<string, unknown>> {
66
+ return Object.fromEntries(
67
+ Object.entries(value).reduce<Array<[string, Record<string, unknown>]>>((entries, [pluginId, state]) => {
68
+ const normalizedPluginId = normalizeBuiltinPluginOwnerId(pluginId);
69
+ const existing = entries.find(([entryPluginId]) => entryPluginId === normalizedPluginId);
70
+ if (existing) {
71
+ existing[1] = pluginId === normalizedPluginId
72
+ ? { ...existing[1], ...state }
73
+ : { ...state, ...existing[1] };
74
+ } else {
75
+ entries.push([normalizedPluginId, { ...state }]);
76
+ }
77
+ return entries;
78
+ }, []),
79
+ );
80
+ }
81
+
82
+ /**
83
+ * Keeps config snapshots readable by clients from before built-in modules were
84
+ * consolidated. Current clients normalize these aliases back to their owner.
85
+ */
86
+ export function addLegacyBuiltinPluginOwnerAliases(
87
+ value: Record<string, Record<string, unknown>>,
88
+ ): Record<string, Record<string, unknown>> {
89
+ const output = Object.fromEntries(
90
+ Object.entries(value).map(([pluginId, state]) => [pluginId, { ...state }]),
91
+ );
92
+ for (const [ownerId, legacyIds] of Object.entries(LEGACY_MODULE_IDS_BY_OWNER)) {
93
+ const ownerState = value[ownerId];
94
+ if (!ownerState) continue;
95
+ for (const legacyId of legacyIds) {
96
+ output[legacyId] ??= { ...ownerState };
97
+ }
98
+ }
99
+ return output;
100
+ }
101
+
102
+ export function addLegacyBuiltinDisabledPluginAliases(pluginIds: readonly string[]): string[] {
103
+ const output = new Set(pluginIds);
104
+ for (const pluginId of pluginIds) {
105
+ for (const legacyId of LEGACY_MODULE_IDS_BY_OWNER[pluginId] ?? []) {
106
+ output.add(legacyId);
107
+ }
108
+ }
109
+ return [...output];
110
+ }
111
+
112
+ function isPluginStateMap(value: unknown): value is Record<string, Record<string, unknown>> {
113
+ return !!value
114
+ && typeof value === "object"
115
+ && !Array.isArray(value)
116
+ && Object.values(value).every((entry) => !!entry && typeof entry === "object" && !Array.isArray(entry));
117
+ }
118
+
119
+ export function normalizeBuiltinPaneStatePluginOwners(
120
+ paneState: Record<string, Record<string, unknown>>,
121
+ ): Record<string, Record<string, unknown>> {
122
+ return Object.fromEntries(
123
+ Object.entries(paneState).map(([paneId, state]) => [
124
+ paneId,
125
+ isPluginStateMap(state.pluginState)
126
+ ? { ...state, pluginState: normalizeBuiltinPluginStateMap(state.pluginState) }
127
+ : state,
128
+ ]),
129
+ );
130
+ }
131
+
132
+ export function addLegacyBuiltinPaneStatePluginAliases(
133
+ paneState: Record<string, Record<string, unknown>>,
134
+ ): Record<string, Record<string, unknown>> {
135
+ return Object.fromEntries(
136
+ Object.entries(paneState).map(([paneId, state]) => [
137
+ paneId,
138
+ isPluginStateMap(state.pluginState)
139
+ ? { ...state, pluginState: addLegacyBuiltinPluginOwnerAliases(state.pluginState) }
140
+ : state,
141
+ ]),
142
+ );
143
+ }
@@ -0,0 +1,19 @@
1
+ import type { GloomPlugin } from "../../types/plugin";
2
+ import {
3
+ attachPredictionMarketsPersistence,
4
+ resetPredictionMarketsPersistence,
5
+ } from "./services/fetch";
6
+
7
+ export const predictionMarketsBackendPlugin: GloomPlugin = {
8
+ id: "prediction-markets",
9
+ name: "Prediction Markets",
10
+ version: "1.0.0",
11
+ description: "Browse prediction markets (Polymarket and Kalshi).",
12
+ toggleable: true,
13
+ setup(ctx) {
14
+ attachPredictionMarketsPersistence(ctx.persistence);
15
+ },
16
+ dispose() {
17
+ resetPredictionMarketsPersistence();
18
+ },
19
+ };
@@ -14,7 +14,6 @@ import { getNativeSurfaceManager } from "../../components/chart/native/surface/m
14
14
  import { PredictionMarketChart } from "./chart";
15
15
 
16
16
  const TEST_PANE_ID = "prediction-scroll:test";
17
- const SURFACE_ID = `chart-surface:${TEST_PANE_ID}:compact:base`;
18
17
 
19
18
  let testSetup: Awaited<ReturnType<typeof createTestRenderer>> | undefined;
20
19
  let root: ReturnType<typeof createRoot> | undefined;
@@ -96,10 +95,10 @@ describe("PredictionMarketChart kitty scrolling", () => {
96
95
  test("creates a native chart surface when scrolled into view", async () => {
97
96
  actEnvironment.IS_REACT_ACT_ENVIRONMENT = true;
98
97
  testSetup = await createTestRenderer({ width: 100, height: 24 });
99
- (testSetup.renderer as { _capabilities: unknown })._capabilities = {
98
+ (testSetup.renderer as unknown as { _capabilities: unknown })._capabilities = {
100
99
  kitty_graphics: true,
101
100
  };
102
- (testSetup.renderer as { _resolution: unknown })._resolution = {
101
+ (testSetup.renderer as unknown as { _resolution: unknown })._resolution = {
103
102
  width: 1000,
104
103
  height: 720,
105
104
  };
@@ -116,13 +115,16 @@ describe("PredictionMarketChart kitty scrolling", () => {
116
115
  string,
117
116
  {
118
117
  snapshot: {
118
+ paneId: string;
119
119
  visibleRect: { x: number; y: number; width: number; height: number } | null;
120
120
  };
121
121
  }
122
122
  >;
123
123
  };
124
124
 
125
- const hiddenSurface = manager.surfaces.get(SURFACE_ID);
125
+ const findPredictionSurface = () => [...manager.surfaces.values()]
126
+ .find((surface) => surface.snapshot.paneId === TEST_PANE_ID);
127
+ const hiddenSurface = findPredictionSurface();
126
128
  expect(hiddenSurface).toBeUndefined();
127
129
 
128
130
  act(() => {
@@ -131,7 +133,7 @@ describe("PredictionMarketChart kitty scrolling", () => {
131
133
 
132
134
  await flushFrames();
133
135
 
134
- const visibleSurface = manager.surfaces.get(SURFACE_ID);
136
+ const visibleSurface = findPredictionSurface();
135
137
  expect(visibleSurface).toBeDefined();
136
138
  expect(visibleSurface?.snapshot.visibleRect).not.toBeNull();
137
139
  expect(testSetup.captureCharFrame()).toContain("1M");
@@ -1,7 +1,11 @@
1
1
  import { Box, Text } from "../../ui";
2
2
  import { useMemo } from "react";
3
3
  import { TextAttributes } from "../../ui";
4
- import { StockChart } from "../../components/chart/stock-chart";
4
+ import {
5
+ CompositeChart,
6
+ pricePointsToResolvedSeries,
7
+ } from "../../components/chart/composite";
8
+ import type { ChartMouseEvent } from "../../components/chart/core/pointer";
5
9
  import { EmptyState } from "../../components/ui/status";
6
10
  import { colors } from "../../theme/colors";
7
11
  import { formatNumber, formatPercentRaw } from "../../utils/format";
@@ -50,10 +54,13 @@ function PredictionRangeTabs({
50
54
  return (
51
55
  <Box
52
56
  key={entry}
53
- onMouseDown={(event) => {
54
- event.preventDefault();
57
+ onMouseDown={(event: ChartMouseEvent) => {
58
+ event.preventDefault?.();
55
59
  onRangeSelect(entry);
56
60
  }}
61
+ cursor="pointer"
62
+ data-gloom-interactive="true"
63
+ data-gloom-label={`${entry} prediction history`}
57
64
  >
58
65
  <Text
59
66
  fg={active ? colors.textBright : colors.textDim}
@@ -113,6 +120,15 @@ export function PredictionMarketChart({
113
120
  const delta = first && last ? last.close - first.close : 0;
114
121
  const deltaPct = first?.close ? (delta / first.close) * 100 : 0;
115
122
  const chartHeight = Math.max(height - 1, 2);
123
+ const priceSeries = pricePointsToResolvedSeries(pricePoints, {
124
+ id: "prediction-price",
125
+ label: "YES price",
126
+ color: delta > 0 ? colors.positive : delta < 0 ? colors.negative : colors.text,
127
+ unit: "USD",
128
+ style: "area",
129
+ axis: "right",
130
+ panelId: "price",
131
+ });
116
132
 
117
133
  return (
118
134
  <Box flexDirection="column" height={height}>
@@ -135,13 +151,15 @@ export function PredictionMarketChart({
135
151
  </Text>
136
152
  </Box>
137
153
 
138
- <StockChart
154
+ <CompositeChart
139
155
  width={width}
140
156
  height={chartHeight}
141
157
  focused={false}
142
- compact
143
- historyOverride={pricePoints}
144
- currencyOverride="USD"
158
+ interactive={false}
159
+ series={[priceSeries]}
160
+ panels={[{ id: "price" }]}
161
+ axisWidth={8}
162
+ showLegend={false}
145
163
  />
146
164
  </Box>
147
165
  );
@@ -5,6 +5,11 @@ import { createDefaultConfig } from "../../types/config";
5
5
  import type { DataProvider } from "../../types/data-provider";
6
6
  import type { GloomPlugin, GloomPluginContext } from "../../types/plugin";
7
7
  import { assetDataProvider } from "../../capabilities";
8
+ import {
9
+ applicationPlugin,
10
+ macroPlugin,
11
+ portfolioPlugin,
12
+ } from "../builtin/composite-plugins";
8
13
  import { PluginRegistry } from "./index";
9
14
 
10
15
  const dataProvider: DataProvider = {
@@ -71,6 +76,18 @@ afterEach(() => {
71
76
  });
72
77
 
73
78
  describe("PluginRegistry lifecycle", () => {
79
+ test("rejects retired built-in module ids", async () => {
80
+ const registry = createRegistry();
81
+
82
+ await expect(registry.register({
83
+ id: "analytics",
84
+ name: "Conflicting Analytics",
85
+ version: "1.0.0",
86
+ })).rejects.toThrow("Plugin id is reserved by a built-in module: analytics");
87
+
88
+ expect(registry.allPlugins.has("analytics")).toBe(false);
89
+ });
90
+
74
91
  test("rolls back rejected registrations and always removes owned contributions", async () => {
75
92
  const registry = createRegistry();
76
93
  const pane = {
@@ -113,6 +130,40 @@ describe("PluginRegistry lifecycle", () => {
113
130
  });
114
131
  });
115
132
 
133
+ describe("built-in composite plugin ownership", () => {
134
+ test("registers modules through their one top-level owner", async () => {
135
+ const registry = createRegistry();
136
+ await registry.register(portfolioPlugin);
137
+ await registry.register(applicationPlugin);
138
+ await registry.register(macroPlugin);
139
+
140
+ expect(registry.getPluginPaneIds("portfolio")).toEqual(expect.arrayContaining([
141
+ "portfolio-list",
142
+ "analytics",
143
+ "kelly-sizer",
144
+ ]));
145
+ expect(registry.getPluginPaneIds("application")).toEqual(expect.arrayContaining([
146
+ "help",
147
+ "changelog",
148
+ ]));
149
+ expect(registry.getPluginPaneIds("macro")).toEqual(expect.arrayContaining([
150
+ "econ-calendar",
151
+ "yield-curve",
152
+ "earnings-calendar",
153
+ "macro-tv",
154
+ ]));
155
+ expect(registry.getPaneTemplatePluginId("macro-tv-pane")).toBe("macro");
156
+ expect(registry.getPanePluginId("analytics")).toBe("portfolio");
157
+ expect(registry.getPanePluginId("help")).toBe("application");
158
+ expect(registry.getPanePluginId("macro-tv")).toBe("macro");
159
+ expect(registry.getCommandPluginId("earnings-monitor-shortcut")).toBe("macro");
160
+ expect(registry.getCommandPluginId("gridlock-all")).toBe("application");
161
+ expect(registry.allPlugins.has("analytics")).toBe(false);
162
+ expect(registry.allPlugins.has("kelly-sizer")).toBe(false);
163
+ expect(registry.allPlugins.has("changelog")).toBe(false);
164
+ });
165
+ });
166
+
116
167
  describe("PluginRegistry context menu providers", () => {
117
168
  test("registers and unregisters context menu providers", async () => {
118
169
  const registry = createRegistry();
@@ -56,6 +56,7 @@ import {
56
56
  } from "./shared";
57
57
  import { RegistryResumeStateListeners } from "./plugin-state";
58
58
  import { cloudSyncController } from "../../sync/controller";
59
+ import { isReservedBuiltinPluginId } from "../ownership";
59
60
 
60
61
  interface PluginRegistryOptions {
61
62
  enableCapabilityHandlers?: boolean;
@@ -367,6 +368,10 @@ export class PluginRegistry implements PluginRuntimeAccess {
367
368
  return this.contributions.commandOwners.get(commandId);
368
369
  }
369
370
 
371
+ getPanePluginId(paneId: string): string | undefined {
372
+ return this.contributions.paneOwners.get(paneId);
373
+ }
374
+
370
375
  getPaneTemplatePluginId(templateId: string): string | undefined {
371
376
  return this.contributions.paneTemplateOwners.get(templateId);
372
377
  }
@@ -441,6 +446,9 @@ export class PluginRegistry implements PluginRuntimeAccess {
441
446
 
442
447
  async register(plugin: GloomPlugin): Promise<void> {
443
448
  this.registryLog.info(`Registering plugin: ${plugin.id} v${plugin.version ?? "?"}`);
449
+ if (isReservedBuiltinPluginId(plugin.id)) {
450
+ throw new Error(`Plugin id is reserved by a built-in module: ${plugin.id}`);
451
+ }
444
452
  if (this.plugins.has(plugin.id)) throw new Error(`Plugin already registered: ${plugin.id}`);
445
453
  this.plugins.set(plugin.id, plugin);
446
454
  try {
@@ -82,7 +82,7 @@ export function resolveRegistryPaneSettings({
82
82
  };
83
83
  if (pluginId) {
84
84
  for (const field of settingsDef.fields) {
85
- if (field.storage !== "plugin") continue;
85
+ if (field.type === "action" || field.storage !== "plugin") continue;
86
86
  const configValue = getConfigState(pluginId, field.key);
87
87
  if (configValue === null) {
88
88
  delete resolvedSettings[field.key];
@@ -223,7 +223,7 @@ describe("plugin runtime hooks", () => {
223
223
  }
224
224
 
225
225
  testSetup = await testRender(
226
- <PluginRenderProvider pluginId="help" runtime={runtime}>
226
+ <PluginRenderProvider pluginId="application" runtime={runtime}>
227
227
  <HookProbe />
228
228
  </PluginRenderProvider>,
229
229
  { width: 40, height: 5 },
@@ -267,7 +267,7 @@ describe("plugin runtime hooks", () => {
267
267
 
268
268
  testSetup = await testRender(
269
269
  <PaneInstanceProvider paneId="comparison-chart:main">
270
- <PluginRenderProvider pluginId="comparison-chart" runtime={runtime}>
270
+ <PluginRenderProvider pluginId="market-overview" runtime={runtime}>
271
271
  <HookProbe />
272
272
  </PluginRenderProvider>
273
273
  </PaneInstanceProvider>,
@@ -1,5 +1,5 @@
1
- import { useEffect, useMemo } from "react";
2
- import type { Dispatch } from "react";
1
+ import { createContext, useContext, useEffect, useMemo } from "react";
2
+ import type { Dispatch, ReactNode } from "react";
3
3
  import type { PluginRegistry } from "../plugins/registry";
4
4
  import type { AppAction, AppState } from "../state/app/context";
5
5
  import type { DesktopWindowBridge } from "../types/desktop-window";
@@ -9,13 +9,21 @@ import type { RemoteControlRequest, RemoteControlResponse } from "./types";
9
9
 
10
10
  export type RemoteControlHandler = (request: RemoteControlRequest) => Promise<RemoteControlResponse>;
11
11
 
12
+ const RemoteControlHandlerContext = createContext<RemoteControlHandler | null>(null);
13
+
14
+ export function useRemoteControlHandler(): RemoteControlHandler | null {
15
+ return useContext(RemoteControlHandlerContext);
16
+ }
17
+
12
18
  export interface RemoteControlAdapter {
19
+ handleRequest?: RemoteControlHandler;
13
20
  startServer?(options: { dataDir: string; handle: RemoteControlHandler }): void | (() => void | Promise<void>);
14
21
  registerHandler?(handler: RemoteControlHandler | null): void | (() => void);
15
22
  }
16
23
 
17
24
  interface RemoteControlHostProps {
18
25
  adapter?: RemoteControlAdapter;
26
+ children: ReactNode;
19
27
  dispatch: Dispatch<AppAction>;
20
28
  getState: () => AppState;
21
29
  pluginRegistry: PluginRegistry;
@@ -24,6 +32,7 @@ interface RemoteControlHostProps {
24
32
 
25
33
  export function RemoteControlHost({
26
34
  adapter,
35
+ children,
27
36
  dispatch,
28
37
  getState,
29
38
  pluginRegistry,
@@ -73,5 +82,9 @@ export function RemoteControlHost({
73
82
  };
74
83
  }, [adapter, controller]);
75
84
 
76
- return null;
85
+ return (
86
+ <RemoteControlHandlerContext value={adapter?.handleRequest ?? (adapter ? controller.handle : null)}>
87
+ {children}
88
+ </RemoteControlHandlerContext>
89
+ );
77
90
  }