gloomberb 0.16.2 → 0.16.4

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 (527) hide show
  1. package/package.json +4 -1
  2. package/src/api-client/askg.ts +43 -0
  3. package/src/api-client/auth.ts +15 -0
  4. package/src/api-client/beneficial-owners.ts +4 -0
  5. package/src/api-client/chat.ts +19 -0
  6. package/src/api-client/company-kpis.ts +14 -2
  7. package/src/api-client/data.ts +34 -16
  8. package/src/api-client/index.ts +12 -0
  9. package/src/api-client/normalizers.ts +27 -0
  10. package/src/api-client/paths.ts +88 -23
  11. package/src/api-client/request.ts +2 -1
  12. package/src/api-client/research-activity.ts +31 -0
  13. package/src/api-client/socket.ts +39 -8
  14. package/src/api-client/types.ts +57 -1
  15. package/src/api-client/upgrade-experiment.ts +90 -0
  16. package/src/app/global-shortcuts.ts +11 -1
  17. package/src/app/keybindings/actions.ts +10 -0
  18. package/src/app/pane-runtime/index.tsx +8 -0
  19. package/src/app/pane-runtime/pane-template-runtime.ts +5 -0
  20. package/src/app/pane-runtime/plugin-bindings.ts +65 -25
  21. package/src/app/pane-runtime/ticker-inspector-runtime.ts +12 -0
  22. package/src/app/pane-runtime/ticker-open-runtime.ts +18 -1
  23. package/src/app/runtime/desktop-deeplink.ts +5 -0
  24. package/src/app/star-prompt/model.ts +98 -0
  25. package/src/app/star-prompt/runtime.ts +41 -0
  26. package/src/app/star-prompt/status-line.tsx +190 -0
  27. package/src/app.tsx +13 -7
  28. package/src/architecture/core-builtin-allowlist.json +70 -0
  29. package/src/brokers/account-cache.ts +45 -0
  30. package/src/brokers/signed-in/adapter.ts +33 -2
  31. package/src/brokers/signed-in/client.ts +10 -0
  32. package/src/brokers/signed-in/sign-in-dialog.tsx +23 -9
  33. package/src/brokers/signed-in/sign-in.ts +62 -5
  34. package/src/capabilities/registry.ts +8 -1
  35. package/src/capabilities/types.ts +2 -0
  36. package/src/cli/command-options.ts +74 -0
  37. package/src/cli/commands/command-utils.ts +29 -0
  38. package/src/cli/commands/crypto-hints.ts +12 -4
  39. package/src/cli/commands/market.ts +524 -148
  40. package/src/cli/commands/options-chain.ts +172 -0
  41. package/src/cli/commands/options-leaps.ts +422 -0
  42. package/src/cli/commands/overview.ts +223 -42
  43. package/src/cli/commands/search.ts +29 -8
  44. package/src/cli/commands/system.ts +99 -19
  45. package/src/cli/commands/themes.ts +64 -0
  46. package/src/cli/commands/ticker.ts +200 -73
  47. package/src/cli/desktop-pane-shot.ts +100 -16
  48. package/src/cli/errors.ts +25 -2
  49. package/src/cli/freshness.ts +7 -4
  50. package/src/cli/fx-pair.ts +57 -0
  51. package/src/cli/help.ts +40 -7
  52. package/src/cli/history-rows.ts +187 -15
  53. package/src/cli/index-roots.ts +51 -0
  54. package/src/cli/index.ts +21 -13
  55. package/src/cli/listing-arg.ts +211 -3
  56. package/src/cli/not-a-ticker.ts +37 -0
  57. package/src/cli/options.ts +55 -7
  58. package/src/cli/pane-functions/capabilities.ts +13 -2
  59. package/src/cli/pane-functions/catalog.ts +13 -2
  60. package/src/cli/pane-functions/data.ts +36 -5
  61. package/src/cli/pane-functions/dom.ts +89 -28
  62. package/src/cli/pane-functions/freshness.ts +205 -26
  63. package/src/cli/pane-functions/function-help.ts +71 -24
  64. package/src/cli/pane-functions/headless.ts +168 -35
  65. package/src/cli/pane-functions/index.ts +12 -2
  66. package/src/cli/pane-functions/market-session.ts +133 -0
  67. package/src/cli/pane-functions/options.ts +15 -4
  68. package/src/cli/pane-functions/report-notices.ts +63 -0
  69. package/src/cli/pane-functions/report.ts +12 -1
  70. package/src/cli/pane-functions/resolver.ts +32 -8
  71. package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
  72. package/src/cli/pane-functions/screenshot.ts +109 -23
  73. package/src/cli/registry.ts +8 -4
  74. package/src/cli/report-tables.ts +460 -0
  75. package/src/cli/result.ts +63 -16
  76. package/src/cli/row-window.ts +76 -0
  77. package/src/cli/scroll-truncation.ts +34 -0
  78. package/src/components/chart/composite/composite-chart.tsx +43 -4
  79. package/src/components/chart/composite/legend.tsx +39 -6
  80. package/src/components/chart/composite/rasterizer.ts +64 -4
  81. package/src/components/chart/composite/series-cues.ts +71 -0
  82. package/src/components/chart/composite/text-renderer.ts +16 -8
  83. package/src/components/chart/composite/types.ts +3 -0
  84. package/src/components/command-bar/commands/direct/index.ts +9 -1
  85. package/src/components/command-bar/commands/plugin/items.ts +3 -1
  86. package/src/components/command-bar/commands/registry.ts +7 -0
  87. package/src/components/command-bar/layout-items/focused-pane.ts +38 -0
  88. package/src/components/command-bar/pane-templates/workflow.ts +5 -0
  89. package/src/components/command-bar/routes/root/command-items.ts +2 -0
  90. package/src/components/command-bar/routes/root/plugin-turn-on.ts +92 -0
  91. package/src/components/command-bar/routes/root/results.ts +40 -10
  92. package/src/components/command-bar/routes/root/runtime.ts +8 -0
  93. package/src/components/command-bar/routes/root/search-providers.ts +97 -14
  94. package/src/components/command-bar/surface/index.tsx +18 -4
  95. package/src/components/command-bar/theme-picker.tsx +48 -13
  96. package/src/components/command-bar/workflow/ops.ts +5 -3
  97. package/src/components/data-table/export.ts +6 -51
  98. package/src/components/data-table/view.tsx +31 -10
  99. package/src/components/layout/floating-pane.tsx +6 -2
  100. package/src/components/layout/market-summary.ts +23 -9
  101. package/src/components/layout/pane/content.tsx +46 -29
  102. package/src/components/layout/pane/cycle-order.ts +2 -11
  103. package/src/components/layout/pane/header.tsx +2 -1
  104. package/src/components/layout/pane/title.ts +1 -1
  105. package/src/components/layout/presentation.ts +22 -0
  106. package/src/components/layout/shell/active-drag.ts +67 -35
  107. package/src/components/layout/shell/cursor-occlusion.ts +6 -5
  108. package/src/components/layout/shell/drag/index.ts +16 -7
  109. package/src/components/layout/shell/drag/live.ts +193 -0
  110. package/src/components/layout/shell/drag/overlays.tsx +179 -35
  111. package/src/components/layout/shell/drag/runtime.ts +62 -50
  112. package/src/components/layout/shell/drag/slide.ts +10 -0
  113. package/src/components/layout/shell/index.tsx +84 -57
  114. package/src/components/layout/shell/layout-state.ts +5 -11
  115. package/src/components/layout/shell/menu.ts +28 -1
  116. package/src/components/layout/shell/native/pointer-runtime.ts +13 -13
  117. package/src/components/layout/shell/native/surfaces.ts +30 -14
  118. package/src/components/layout/shell/pane/actions.ts +2 -1
  119. package/src/components/layout/shell/pane/layers.tsx +461 -180
  120. package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
  121. package/src/components/layout/shell/pane/new-layout.ts +116 -0
  122. package/src/components/layout/shell/shortcuts.ts +5 -2
  123. package/src/components/layout/shell/terminal-pointer-runtime.ts +18 -18
  124. package/src/components/layout/shell/visible-layout.ts +44 -1
  125. package/src/components/layout/shell/window-mode/overlays.tsx +12 -4
  126. package/src/components/layout/status-bar.tsx +4 -1
  127. package/src/components/markdown-text.tsx +9 -5
  128. package/src/components/metric-treemap/heat-surface.tsx +27 -8
  129. package/src/components/metric-treemap/heat-tiles.ts +48 -17
  130. package/src/components/onboarding/onboarding-frame.tsx +33 -10
  131. package/src/components/onboarding/onboarding-wizard.tsx +49 -40
  132. package/src/components/onboarding/portfolio-step/positions-panel.tsx +5 -2
  133. package/src/components/onboarding/pro-step-layout.ts +86 -0
  134. package/src/components/onboarding/use-onboarding-upgrade.ts +6 -2
  135. package/src/components/ui/button.tsx +10 -0
  136. package/src/components/ui/data-table/index.tsx +38 -0
  137. package/src/components/ui/data-table/types.ts +8 -1
  138. package/src/components/ui/data-table/visible-range.ts +2 -0
  139. package/src/components/ui/icon.tsx +11 -2
  140. package/src/components/ui/index.ts +1 -1
  141. package/src/core/connection-health.ts +1 -1
  142. package/src/core/state/app/layout-reducer.ts +89 -3
  143. package/src/core/state/app/state.ts +8 -5
  144. package/src/core/state/app/types.ts +13 -2
  145. package/src/data/config/layout.ts +55 -21
  146. package/src/data/config/store/fold-panes.ts +149 -0
  147. package/src/data/config/store/migrations.ts +7 -0
  148. package/src/data/config/store/node.ts +27 -6
  149. package/src/data/config/store/normalize.ts +37 -3
  150. package/src/data/json-persistence.ts +17 -3
  151. package/src/data/json-storage.ts +2 -0
  152. package/src/data/memory-resource-store.ts +46 -0
  153. package/src/i18n/es.ts +14 -1
  154. package/src/i18n/ja.ts +14 -1
  155. package/src/i18n/ko.ts +14 -1
  156. package/src/i18n/zh-cn.ts +14 -1
  157. package/src/i18n/zh-tw.ts +14 -1
  158. package/src/layout/desks.ts +1 -2
  159. package/src/layout/pane-layout-move.ts +264 -0
  160. package/src/layout/pane-manager/hidden-panes.ts +160 -0
  161. package/src/layout/pane-manager/index.ts +1 -0
  162. package/src/market-data/coordinator/entries.ts +7 -1
  163. package/src/market-data/coordinator/quotes.ts +2 -2
  164. package/src/market-data/market/freshness.ts +156 -11
  165. package/src/market-data/market/status.ts +40 -0
  166. package/src/market-data/options-alternatives.ts +69 -0
  167. package/src/market-data/quotes/contributions.ts +19 -2
  168. package/src/market-data/quotes/freshness.ts +5 -0
  169. package/src/market-data/quotes/metadata.ts +16 -0
  170. package/src/market-data/quotes/screener-live-quotes.ts +56 -5
  171. package/src/plugins/builtin/account-management/keyboard.ts +3 -0
  172. package/src/plugins/builtin/account-management/model.ts +1 -0
  173. package/src/plugins/builtin/account-management/navigation.ts +1 -1
  174. package/src/plugins/builtin/account-management/pane.tsx +31 -4
  175. package/src/plugins/builtin/alerts/quotes.ts +3 -0
  176. package/src/plugins/builtin/analytics/pane-model.ts +10 -6
  177. package/src/plugins/builtin/analytics/risk-headless.ts +3 -1
  178. package/src/plugins/builtin/analytics/risk-model.ts +37 -8
  179. package/src/plugins/builtin/analytics/risk-pane.tsx +8 -4
  180. package/src/plugins/builtin/attention/pane.tsx +1 -1
  181. package/src/plugins/builtin/backtest/pane.tsx +1 -1
  182. package/src/plugins/builtin/broker-manager/detail.tsx +4 -0
  183. package/src/plugins/builtin/broker-manager/index.tsx +7 -3
  184. package/src/plugins/builtin/broker-manager/model.ts +8 -0
  185. package/src/plugins/builtin/broker-manager/pane-actions.tsx +8 -2
  186. package/src/plugins/builtin/broker-manager/sign-in-end.ts +82 -0
  187. package/src/plugins/builtin/broker-manager/table.ts +5 -0
  188. package/src/plugins/builtin/builtin-plugin-meta.ts +121 -11
  189. package/src/plugins/builtin/catalysts/detail.tsx +1 -1
  190. package/src/plugins/builtin/chart-composer/pane.tsx +1 -1
  191. package/src/plugins/builtin/chat/channels.ts +34 -36
  192. package/src/plugins/builtin/chat/command-bar.ts +138 -0
  193. package/src/plugins/builtin/chat/composer-commands.ts +21 -1
  194. package/src/plugins/builtin/chat/content/composer-runtime.ts +11 -1
  195. package/src/plugins/builtin/chat/content/footer.tsx +5 -3
  196. package/src/plugins/builtin/chat/content/index.tsx +21 -1
  197. package/src/plugins/builtin/chat/content/mentions.ts +2 -1
  198. package/src/plugins/builtin/chat/content/user-map.ts +3 -1
  199. package/src/plugins/builtin/chat/controller/index.ts +48 -0
  200. package/src/plugins/builtin/chat/conversations.ts +256 -0
  201. package/src/plugins/builtin/chat/discord-command.ts +91 -0
  202. package/src/plugins/builtin/chat/edit-window.ts +12 -6
  203. package/src/plugins/builtin/chat/ghost-user.ts +14 -0
  204. package/src/plugins/builtin/chat/index.tsx +40 -2
  205. package/src/plugins/builtin/chat/layout.ts +2 -0
  206. package/src/plugins/builtin/chat/message/desktop.tsx +2 -1
  207. package/src/plugins/builtin/chat/message/header.tsx +24 -15
  208. package/src/plugins/builtin/chat/message/profile-popover.tsx +2 -1
  209. package/src/plugins/builtin/chat/message/render-state.ts +3 -0
  210. package/src/plugins/builtin/chat/pane-requests.ts +60 -0
  211. package/src/plugins/builtin/chat/pane-state.ts +32 -2
  212. package/src/plugins/builtin/chat/pane.tsx +8 -0
  213. package/src/plugins/builtin/cloud/askg/controller.ts +112 -4
  214. package/src/plugins/builtin/cloud/askg/conversation-store.ts +21 -0
  215. package/src/plugins/builtin/cloud/askg/manifest.ts +1 -0
  216. package/src/plugins/builtin/cloud/askg/model.ts +129 -70
  217. package/src/plugins/builtin/cloud/askg/pane.tsx +772 -377
  218. package/src/plugins/builtin/cloud/askg/protocol.ts +40 -2
  219. package/src/plugins/builtin/cloud/askg/tool-display.ts +437 -0
  220. package/src/plugins/builtin/cloud/askg/tool-timeline.tsx +403 -0
  221. package/src/plugins/builtin/cloud/company-picker.tsx +1 -9
  222. package/src/plugins/builtin/cloud/mcp-connect/command.ts +24 -0
  223. package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +360 -0
  224. package/src/plugins/builtin/cloud/mcp-connect/model.ts +135 -0
  225. package/src/plugins/builtin/cloud/mcp-connect/sections.ts +62 -0
  226. package/src/plugins/builtin/cloud/plugin.tsx +36 -1
  227. package/src/plugins/builtin/cloud/starter-symbols.ts +8 -0
  228. package/src/plugins/builtin/cloud/terminal-relay/acm-tab.tsx +89 -0
  229. package/src/plugins/builtin/cloud/terminal-relay/client.ts +97 -0
  230. package/src/plugins/builtin/cloud/terminal-relay/connect-section.tsx +57 -0
  231. package/src/plugins/builtin/cloud/terminal-relay/engine.ts +666 -0
  232. package/src/plugins/builtin/cloud/terminal-relay/grants.ts +137 -0
  233. package/src/plugins/builtin/cloud/terminal-relay/host.tsx +81 -0
  234. package/src/plugins/builtin/cloud/terminal-relay/indicator.tsx +82 -0
  235. package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +234 -0
  236. package/src/plugins/builtin/cloud/terminal-relay/policy.ts +153 -0
  237. package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +168 -0
  238. package/src/plugins/builtin/cloud/terminal-relay/redact.ts +73 -0
  239. package/src/plugins/builtin/cloud/terminal-relay/summary.ts +62 -0
  240. package/src/plugins/builtin/cloud/upgrade-dialog.tsx +26 -2
  241. package/src/plugins/builtin/cloud/upgrade-personalization.ts +57 -0
  242. package/src/plugins/builtin/cloud/upgrade-tickers.ts +124 -0
  243. package/src/plugins/builtin/comment-letters/client.ts +1 -3
  244. package/src/plugins/builtin/company-attention/pane.tsx +1 -1
  245. package/src/plugins/builtin/company-kpis/client.ts +23 -8
  246. package/src/plugins/builtin/company-kpis/headless.ts +3 -1
  247. package/src/plugins/builtin/company-kpis/pane.tsx +15 -7
  248. package/src/plugins/builtin/company-kpis/screenshot-evidence.ts +10 -3
  249. package/src/plugins/builtin/composite-plugins.ts +107 -64
  250. package/src/plugins/builtin/credit-boards/cdx-pane.tsx +4 -4
  251. package/src/plugins/builtin/credit-boards/index.tsx +21 -21
  252. package/src/plugins/builtin/credit-boards/model.ts +0 -1
  253. package/src/plugins/builtin/credit-boards/pane.tsx +30 -0
  254. package/src/plugins/builtin/credit-boards/sovr-pane.tsx +4 -4
  255. package/src/plugins/builtin/debt-maturities/client.ts +37 -9
  256. package/src/plugins/builtin/debt-maturities/headless.ts +3 -1
  257. package/src/plugins/builtin/debt-maturities/pane.tsx +5 -4
  258. package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
  259. package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
  260. package/src/plugins/builtin/earnings-calls/data.ts +28 -7
  261. package/src/plugins/builtin/earnings-calls/headless.ts +3 -2
  262. package/src/plugins/builtin/earnings-calls/pane.tsx +10 -5
  263. package/src/plugins/builtin/econ/calendar-model.ts +42 -17
  264. package/src/plugins/builtin/econ/detail-view.tsx +2 -2
  265. package/src/plugins/builtin/econ/index.tsx +68 -22
  266. package/src/plugins/builtin/econ-statistics/headless.ts +12 -2
  267. package/src/plugins/builtin/econ-statistics/pane.tsx +1 -1
  268. package/src/plugins/builtin/econ-statistics/view.ts +17 -0
  269. package/src/plugins/builtin/executives/data.ts +17 -6
  270. package/src/plugins/builtin/executives/pane.tsx +16 -7
  271. package/src/plugins/builtin/filing-events/pane.tsx +22 -5
  272. package/src/plugins/builtin/fx-matrix/freshness.ts +65 -0
  273. package/src/plugins/builtin/fx-matrix/index.tsx +22 -1
  274. package/src/plugins/builtin/fx-matrix/pairs.ts +1 -1
  275. package/src/plugins/builtin/fx-matrix/settings.ts +42 -2
  276. package/src/plugins/builtin/gpu/headless.ts +9 -3
  277. package/src/plugins/builtin/gpu/model.ts +14 -5
  278. package/src/plugins/builtin/help/index.tsx +1 -0
  279. package/src/plugins/builtin/holders/beneficial-client.ts +29 -7
  280. package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
  281. package/src/plugins/builtin/holders/client.ts +3 -6
  282. package/src/plugins/builtin/holders/format.ts +31 -1
  283. package/src/plugins/builtin/holders/headless.ts +32 -6
  284. package/src/plugins/builtin/holders/pane.tsx +25 -13
  285. package/src/plugins/builtin/holders/report-header.ts +46 -5
  286. package/src/plugins/builtin/insider/index.tsx +4 -4
  287. package/src/plugins/builtin/iv-history/charts.tsx +21 -7
  288. package/src/plugins/builtin/iv-history/client.ts +12 -2
  289. package/src/plugins/builtin/iv-history/format.ts +33 -2
  290. package/src/plugins/builtin/iv-history/headless.ts +22 -10
  291. package/src/plugins/builtin/iv-history/index.tsx +3 -3
  292. package/src/plugins/builtin/iv-history/model.ts +61 -13
  293. package/src/plugins/builtin/iv-history/pane.tsx +11 -3
  294. package/src/plugins/builtin/iv-history/screen-pane.tsx +42 -18
  295. package/src/plugins/builtin/jobs/pane.tsx +1 -1
  296. package/src/plugins/builtin/kelly-sizer/headless.ts +149 -0
  297. package/src/plugins/builtin/kelly-sizer/history.ts +80 -0
  298. package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
  299. package/src/plugins/builtin/kelly-sizer/pane.tsx +121 -45
  300. package/src/plugins/builtin/kelly-sizer/portfolio.ts +25 -0
  301. package/src/plugins/builtin/kelly-sizer/sections.tsx +14 -0
  302. package/src/plugins/builtin/kelly-sizer/types.ts +9 -1
  303. package/src/plugins/builtin/layout-manager/index.tsx +9 -1
  304. package/src/plugins/builtin/macro-day/client.ts +24 -0
  305. package/src/plugins/builtin/macro-day/headless.ts +11 -8
  306. package/src/plugins/builtin/macro-day/index.tsx +3 -0
  307. package/src/plugins/builtin/macro-day/model.ts +11 -6
  308. package/src/plugins/builtin/macro-day/pane.tsx +12 -8
  309. package/src/plugins/builtin/macro-day/release-table.ts +40 -0
  310. package/src/plugins/builtin/macro-day/releases.ts +62 -44
  311. package/src/plugins/builtin/market-heatmap/data.ts +25 -5
  312. package/src/plugins/builtin/market-heatmap/evidence.ts +90 -0
  313. package/src/plugins/builtin/market-heatmap/index.tsx +144 -63
  314. package/src/plugins/builtin/market-heatmap/model.ts +94 -3
  315. package/src/plugins/builtin/market-heatmap/portfolio.ts +12 -2
  316. package/src/plugins/builtin/market-movers/headless.ts +31 -4
  317. package/src/plugins/builtin/market-movers/index.tsx +8 -1
  318. package/src/plugins/builtin/market-movers/model.ts +71 -17
  319. package/src/plugins/builtin/market-movers/table.ts +50 -23
  320. package/src/plugins/builtin/members/pane.tsx +10 -0
  321. package/src/plugins/builtin/news/headless.ts +9 -2
  322. package/src/plugins/builtin/news/wire/news/footer.ts +10 -0
  323. package/src/plugins/builtin/openfda/client.ts +1 -1
  324. package/src/plugins/builtin/options/carry.ts +95 -0
  325. package/src/plugins/builtin/options/index.tsx +58 -5
  326. package/src/plugins/builtin/options/strike-window.ts +183 -0
  327. package/src/plugins/builtin/options/table.ts +55 -3
  328. package/src/plugins/builtin/options/types.ts +8 -1
  329. package/src/plugins/builtin/options/view.tsx +161 -12
  330. package/src/plugins/builtin/options-positioning/headless.ts +4 -2
  331. package/src/plugins/builtin/options-scenario/charts.tsx +2 -2
  332. package/src/plugins/builtin/options-scenario/client.ts +73 -17
  333. package/src/plugins/builtin/options-scenario/headless.ts +71 -24
  334. package/src/plugins/builtin/options-scenario/hedge.ts +284 -0
  335. package/src/plugins/builtin/options-scenario/index.tsx +9 -2
  336. package/src/plugins/builtin/options-scenario/model.ts +33 -0
  337. package/src/plugins/builtin/options-scenario/pane.tsx +40 -16
  338. package/src/plugins/builtin/pe-band/model.ts +2 -2
  339. package/src/plugins/builtin/pe-band/report-dates.ts +11 -7
  340. package/src/plugins/builtin/perps/equity-row.tsx +8 -5
  341. package/src/plugins/builtin/perps/model.ts +16 -5
  342. package/src/plugins/builtin/perps/pane.tsx +1 -1
  343. package/src/plugins/builtin/plugin-marketplace/model.ts +64 -21
  344. package/src/plugins/builtin/plugin-marketplace/packs.ts +118 -0
  345. package/src/plugins/builtin/plugin-marketplace/pane.tsx +344 -32
  346. package/src/plugins/builtin/plugin-marketplace/store.ts +7 -1
  347. package/src/plugins/builtin/plugin-module.ts +87 -4
  348. package/src/plugins/builtin/portfolio-list/account-metrics.ts +16 -1
  349. package/src/plugins/builtin/portfolio-list/allocation.ts +3 -0
  350. package/src/plugins/builtin/portfolio-list/cached-account.ts +18 -9
  351. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +71 -36
  352. package/src/plugins/builtin/portfolio-list/cli/render.ts +89 -18
  353. package/src/plugins/builtin/portfolio-list/cli/shared.ts +2 -16
  354. package/src/plugins/builtin/portfolio-list/headless.ts +40 -7
  355. package/src/plugins/builtin/portfolio-list/pane/index.tsx +7 -4
  356. package/src/plugins/builtin/portfolio-list/summary/index.tsx +22 -4
  357. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +11 -1
  358. package/src/plugins/builtin/realized-vol/headless.ts +3 -0
  359. package/src/plugins/builtin/realized-vol/pane.tsx +1 -1
  360. package/src/plugins/builtin/research/corporate-actions-pane.tsx +2 -2
  361. package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +1 -1
  362. package/src/plugins/builtin/research/relative-valuation-model.ts +7 -3
  363. package/src/plugins/builtin/revenue-breakdown/client.ts +13 -6
  364. package/src/plugins/builtin/revenue-breakdown/headless.ts +4 -1
  365. package/src/plugins/builtin/revenue-breakdown/pane.tsx +7 -4
  366. package/src/plugins/builtin/reverse-dcf/headless.ts +5 -1
  367. package/src/plugins/builtin/reverse-dcf/model.ts +2 -1
  368. package/src/plugins/builtin/reverse-dcf/pane.tsx +1 -1
  369. package/src/plugins/builtin/risk-factors/data.ts +23 -9
  370. package/src/plugins/builtin/risk-factors/headless.ts +5 -2
  371. package/src/plugins/builtin/risk-factors/pane.tsx +6 -5
  372. package/src/plugins/builtin/seasonality/pane.tsx +1 -1
  373. package/src/plugins/builtin/sec/index.tsx +5 -5
  374. package/src/plugins/builtin/sectors/client.ts +10 -2
  375. package/src/plugins/builtin/sectors/headless.ts +35 -6
  376. package/src/plugins/builtin/sectors/index.tsx +18 -1
  377. package/src/plugins/builtin/sectors/sector-model.ts +150 -41
  378. package/src/plugins/builtin/shared/command-tab.ts +51 -0
  379. package/src/plugins/builtin/shared/headless-market-data.ts +33 -1
  380. package/src/plugins/builtin/shared/members-menu.tsx +260 -0
  381. package/src/plugins/builtin/shared/report-freshness.ts +50 -2
  382. package/src/plugins/builtin/shared/ticker-request.ts +25 -1
  383. package/src/plugins/builtin/shared/use-quote-board.ts +25 -5
  384. package/src/plugins/builtin/shared/volatility/options.ts +1 -46
  385. package/src/plugins/builtin/short-interest/index.tsx +19 -4
  386. package/src/plugins/builtin/short-interest/surface.tsx +4 -4
  387. package/src/plugins/builtin/short-volume/index.tsx +1 -10
  388. package/src/plugins/builtin/short-volume/pane.tsx +1 -1
  389. package/src/plugins/builtin/social-mentions/pane.tsx +1 -1
  390. package/src/plugins/builtin/supply-chain/model.ts +1 -1
  391. package/src/plugins/builtin/themes/pane.tsx +3 -0
  392. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +4 -0
  393. package/src/plugins/builtin/ticker-detail/financials/model.ts +25 -2
  394. package/src/plugins/builtin/ticker-detail/headless.ts +63 -25
  395. package/src/plugins/builtin/ticker-detail/overview/model.ts +9 -4
  396. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +3 -2
  397. package/src/plugins/builtin/ticker-detail/pane.tsx +4 -5
  398. package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +94 -6
  399. package/src/plugins/builtin/treasury-auctions/cache.ts +5 -2
  400. package/src/plugins/builtin/treasury-auctions/client.ts +22 -8
  401. package/src/plugins/builtin/treasury-auctions/headless.ts +40 -4
  402. package/src/plugins/builtin/treasury-auctions/index.tsx +11 -9
  403. package/src/plugins/builtin/treasury-auctions/model.ts +197 -30
  404. package/src/plugins/builtin/treasury-auctions/pane.tsx +35 -11
  405. package/src/plugins/builtin/treasury-auctions/types.ts +11 -1
  406. package/src/plugins/builtin/vol-surface/charts.tsx +1 -3
  407. package/src/plugins/builtin/vol-surface/client.ts +6 -2
  408. package/src/plugins/builtin/vol-surface/evidence.ts +11 -6
  409. package/src/plugins/builtin/vol-surface/headless.ts +124 -20
  410. package/src/plugins/builtin/vol-surface/model.ts +23 -11
  411. package/src/plugins/builtin/vol-surface/pane.tsx +38 -27
  412. package/src/plugins/builtin/vol-surface/tables.ts +124 -0
  413. package/src/plugins/builtin/world-indices/client.ts +22 -4
  414. package/src/plugins/builtin/world-indices/headless.ts +54 -27
  415. package/src/plugins/builtin/world-indices/model.ts +4 -2
  416. package/src/plugins/builtin/world-indices/table.tsx +13 -2
  417. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +2 -0
  418. package/src/plugins/builtin/world-venue-map/basemap.ts +18 -0
  419. package/src/plugins/builtin/world-venue-map/country-labels.ts +78 -0
  420. package/src/plugins/builtin/world-venue-map/geo-series.ts +1 -1
  421. package/src/plugins/builtin/world-venue-map/geo-svg.tsx +2 -1
  422. package/src/plugins/builtin/world-venue-map/index.ts +6 -6
  423. package/src/plugins/builtin/world-venue-map/layered-pane.tsx +27 -14
  424. package/src/plugins/builtin/world-venue-map/layers.ts +68 -10
  425. package/src/plugins/builtin/world-venue-map/map.tsx +198 -62
  426. package/src/plugins/builtin/world-venue-map/model.ts +16 -0
  427. package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +3 -0
  428. package/src/plugins/builtin/world-venue-map/natural-earth/labels.chunk.ts +244 -0
  429. package/src/plugins/builtin/world-venue-map/pane.tsx +16 -10
  430. package/src/plugins/builtin/yield-curve/index.tsx +1 -1
  431. package/src/plugins/builtin-editorial.ts +126 -0
  432. package/src/plugins/catalog-backend.ts +16 -9
  433. package/src/plugins/catalog-browser.ts +127 -63
  434. package/src/plugins/catalog-manifest.ts +73 -40
  435. package/src/plugins/catalog-ui.ts +26 -6
  436. package/src/plugins/extracted-plugins.ts +7 -1
  437. package/src/plugins/ownership.ts +150 -7
  438. package/src/plugins/plugin-functions.ts +54 -0
  439. package/src/plugins/plugin-off.ts +36 -0
  440. package/src/plugins/registry/host-actions.ts +16 -0
  441. package/src/plugins/registry/index.ts +84 -24
  442. package/src/plugins/registry/plugin-state.ts +25 -1
  443. package/src/plugins/runtime/context.tsx +29 -0
  444. package/src/react/input.ts +48 -1
  445. package/src/remote/app-host.tsx +5 -0
  446. package/src/remote/controller.ts +3 -53
  447. package/src/remote/matching.ts +69 -0
  448. package/src/remote/schema.ts +1 -1
  449. package/src/remote/semantic-tree.tsx +14 -0
  450. package/src/remote/types.ts +2 -0
  451. package/src/renderers/browser/app-services.ts +3 -1
  452. package/src/renderers/dom/data-table/dom.ts +31 -0
  453. package/src/renderers/dom/data-table/index.tsx +5 -0
  454. package/src/renderers/dom/desktop/icons.tsx +14 -0
  455. package/src/renderers/dom/desktop/query-bar.tsx +59 -32
  456. package/src/renderers/dom/host/box.tsx +113 -17
  457. package/src/renderers/dom/host/drag-shield.ts +35 -0
  458. package/src/renderers/dom/host/live-frame.ts +62 -0
  459. package/src/renderers/dom/host/mouse.ts +8 -1
  460. package/src/renderers/dom/host/scroll-box.tsx +6 -5
  461. package/src/renderers/dom/host/tabs.tsx +3 -2
  462. package/src/renderers/dom/input-host.tsx +6 -1
  463. package/src/renderers/dom/styles.css +26 -5
  464. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +7 -0
  465. package/src/renderers/electrobun/bun/desktop/backend.ts +7 -1
  466. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +12 -1
  467. package/src/renderers/electrobun/bun/desktop/initialization.ts +15 -1
  468. package/src/renderers/electrobun/shared/protocol.ts +12 -1
  469. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +4 -1
  470. package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +101 -5
  471. package/src/renderers/electrobun/view/host/native.ts +0 -10
  472. package/src/renderers/electrobun/view/host/window-move.ts +28 -0
  473. package/src/renderers/electrobun/view/main.tsx +4 -1
  474. package/src/renderers/electrobun/view/remote/persistence.ts +15 -2
  475. package/src/renderers/electrobun/view/ui-host.tsx +2 -5
  476. package/src/renderers/opentui/input-host.tsx +6 -1
  477. package/src/renderers/opentui/start.tsx +9 -0
  478. package/src/renderers/opentui/ui-host.tsx +7 -1
  479. package/src/shares/portable-layout.ts +16 -6
  480. package/src/sources/gloomberb-cloud/index.ts +19 -10
  481. package/src/sources/gloomberb-cloud/normalizers.ts +20 -21
  482. package/src/sources/listing-symbols.ts +11 -5
  483. package/src/sources/provider-errors.ts +88 -3
  484. package/src/sources/provider-router/batches.ts +3 -3
  485. package/src/sources/provider-router/cached-routes.ts +8 -4
  486. package/src/sources/provider-router/financial-routes.ts +13 -7
  487. package/src/sources/provider-router/financials.ts +106 -16
  488. package/src/sources/provider-router/history.ts +27 -11
  489. package/src/sources/provider-router/index.ts +1 -1
  490. package/src/sources/provider-router/primary.ts +24 -6
  491. package/src/sources/sec-edgar.ts +68 -8
  492. package/src/state/pane-scroll-registry.tsx +67 -35
  493. package/src/sync/core-contributors.ts +4 -3
  494. package/src/test-support/cli-context.ts +2 -1
  495. package/src/test-support/data-provider.ts +34 -0
  496. package/src/test-support/margin-account.ts +108 -0
  497. package/src/test-support/shell-pane-keys.tsx +1 -0
  498. package/src/theme/series-colors.ts +46 -0
  499. package/src/theme/themes.ts +149 -0
  500. package/src/tickers/search/index.ts +22 -2
  501. package/src/tickers/search/ranking.ts +45 -1
  502. package/src/tickers/search/types.ts +3 -1
  503. package/src/time-series/resolution.ts +15 -0
  504. package/src/time-series/resolve.ts +1 -14
  505. package/src/types/config.ts +61 -1
  506. package/src/types/financials.ts +32 -3
  507. package/src/types/headless.ts +11 -0
  508. package/src/types/instrument.ts +8 -0
  509. package/src/types/plugin.ts +49 -3
  510. package/src/ui/host.tsx +16 -0
  511. package/src/ui/index.tsx +10 -3
  512. package/src/ui/scroll-box-axis.ts +26 -0
  513. package/src/utils/cli-output.ts +14 -1
  514. package/src/utils/currency-units.ts +8 -3
  515. package/src/utils/depositary-receipt.ts +54 -10
  516. package/src/utils/display-number.ts +63 -0
  517. package/src/utils/exchanges.ts +13 -0
  518. package/src/utils/format.ts +2 -1
  519. package/src/utils/fundamentals.ts +17 -1
  520. package/src/utils/fx-market-hours.ts +34 -0
  521. package/src/utils/option-expiry.ts +126 -0
  522. package/src/utils/price-history-integrity.ts +19 -6
  523. package/src/utils/price-history.ts +39 -6
  524. package/src/utils/rpc-timeout-error.ts +6 -2
  525. package/src/utils/sec-eps-basis.ts +159 -30
  526. package/src/utils/sec.ts +38 -34
  527. package/src/utils/throttled-fetch.ts +51 -22
@@ -633,6 +633,81 @@ const rawThemes: Record<string, Theme> = {
633
633
  commandBg: "#000033",
634
634
  commandBorder: "#ff6600",
635
635
  },
636
+
637
+ // Gains, losses, warnings and chart series stay apart for deuteranopia,
638
+ // protanopia and tritanopia: up is blue, down is vermillion (the Okabe-Ito
639
+ // set), never red against green. The chrome is grey so hue only ever means
640
+ // data. themes.test.ts simulates the three deficiencies on these palettes.
641
+ colorblind: {
642
+ name: "Colorblind",
643
+ description: "Blue gains and vermillion losses, safe for color-blind eyes",
644
+ bg: "#0e1013",
645
+ panel: "#15181c",
646
+ border: "#3b4149",
647
+ borderFocused: "#d7dade",
648
+ text: "#e4e6e9",
649
+ textDim: "#a3a9b2",
650
+ textBright: "#ffffff",
651
+ textMuted: "#858c96",
652
+ positive: "#56b4e9",
653
+ negative: "#e66a1f",
654
+ neutral: "#9aa0a8",
655
+ warning: "#f0e442",
656
+ header: "#1c2026",
657
+ headerText: "#ffffff",
658
+ selected: "#2b3540",
659
+ selectedText: "#ffffff",
660
+ commandBg: "#15181c",
661
+ commandBorder: "#a3a9b2",
662
+ },
663
+
664
+ "colorblind-light": {
665
+ name: "Colorblind Light",
666
+ description: "Light, blue gains and vermillion losses, safe for color-blind eyes",
667
+ bg: "#ffffff",
668
+ panel: "#f5f6f8",
669
+ border: "#c8cdd4",
670
+ borderFocused: "#1f2328",
671
+ text: "#1f2328",
672
+ textDim: "#4d545e",
673
+ textBright: "#000000",
674
+ textMuted: "#646b75",
675
+ positive: "#0072b2",
676
+ negative: "#a84100",
677
+ neutral: "#5f6670",
678
+ warning: "#a27409",
679
+ header: "#e9ecef",
680
+ headerText: "#1f2328",
681
+ selected: "#d3e3f0",
682
+ selectedText: "#000000",
683
+ commandBg: "#f5f6f8",
684
+ commandBorder: "#1f2328",
685
+ },
686
+
687
+ // Every text role clears 7:1 (WCAG AAA) on the page, and the up, down and
688
+ // warning colours are the colour-blind safe ones.
689
+ "high-contrast": {
690
+ name: "High Contrast",
691
+ description: "White on black at AAA contrast, color-blind safe",
692
+ bg: "#000000",
693
+ panel: "#000000",
694
+ border: "#9a9a9a",
695
+ borderFocused: "#ffffff",
696
+ text: "#ffffff",
697
+ textDim: "#e0e0e0",
698
+ textBright: "#ffffff",
699
+ textMuted: "#c8c8c8",
700
+ positive: "#56b4e9",
701
+ negative: "#ff8c42",
702
+ neutral: "#c8c8c8",
703
+ warning: "#f0e442",
704
+ header: "#1a1a1a",
705
+ headerText: "#ffffff",
706
+ selected: "#3d3d3d",
707
+ selectedText: "#ffffff",
708
+ commandBg: "#000000",
709
+ commandBorder: "#ffffff",
710
+ },
636
711
  };
637
712
 
638
713
  export const themes: Record<string, Theme> = Object.fromEntries(
@@ -661,3 +736,77 @@ export function isDarkTheme(themeId: string): boolean {
661
736
  export function getTheme(id: string): Theme {
662
737
  return themes[id] ?? themes[DEFAULT_THEME]!;
663
738
  }
739
+
740
+ type ThemeTrait = "colorblind-safe" | "high-contrast";
741
+
742
+ const THEME_TRAITS: Readonly<Record<string, readonly ThemeTrait[]>> = {
743
+ colorblind: ["colorblind-safe"],
744
+ "colorblind-light": ["colorblind-safe"],
745
+ "high-contrast": ["high-contrast", "colorblind-safe"],
746
+ };
747
+
748
+ export interface ThemeSummary {
749
+ id: string;
750
+ name: string;
751
+ appearance: "dark" | "light";
752
+ traits: readonly ThemeTrait[];
753
+ }
754
+
755
+ /** Every theme in registry order: what `config themes`, help and the docs list. */
756
+ export function listThemes(): ThemeSummary[] {
757
+ return getThemeIds().map((id) => ({
758
+ id,
759
+ name: themes[id]!.name,
760
+ appearance: isDarkTheme(id) ? "dark" : "light",
761
+ traits: THEME_TRAITS[id] ?? [],
762
+ }));
763
+ }
764
+
765
+ export type ThemeLookup =
766
+ | { ok: true; id: string }
767
+ | { ok: false; suggestion: string | null };
768
+
769
+ /** `White Phosphor`, `white_phosphor` and `WHITE` all read as `white-phosphor` / `white`. */
770
+ function themeKey(value: string): string {
771
+ return value.trim().toLowerCase().replace(/[\s_]+/g, "-");
772
+ }
773
+
774
+ function editDistance(left: string, right: string): number {
775
+ let previous = Array.from({ length: right.length + 1 }, (_, index) => index);
776
+ for (let row = 1; row <= left.length; row += 1) {
777
+ const current = [row];
778
+ for (let column = 1; column <= right.length; column += 1) {
779
+ const substitution = previous[column - 1]! + (left[row - 1] === right[column - 1] ? 0 : 1);
780
+ current.push(Math.min(previous[column]! + 1, current[column - 1]! + 1, substitution));
781
+ }
782
+ previous = current;
783
+ }
784
+ return previous[right.length]!;
785
+ }
786
+
787
+ /**
788
+ * The theme id a person meant. An id or a display name, in any case, is that
789
+ * theme; anything else is unknown, with the closest id when the input is a
790
+ * typo of one (or of a name), or names part of exactly one theme.
791
+ */
792
+ export function resolveThemeId(input: string): ThemeLookup {
793
+ const key = themeKey(input);
794
+ const ids = getThemeIds();
795
+ const exact = ids.find((id) => id === key) ?? ids.find((id) => themeKey(themes[id]!.name) === key);
796
+ if (exact) return { ok: true, id: exact };
797
+ if (!key) return { ok: false, suggestion: null };
798
+
799
+ let best: { id: string; distance: number } | null = null;
800
+ for (const id of ids) {
801
+ for (const candidate of [id, themeKey(themes[id]!.name)]) {
802
+ const distance = editDistance(key, candidate);
803
+ if (!best || distance < best.distance) best = { id, distance };
804
+ }
805
+ }
806
+ const tolerance = Math.max(2, Math.floor(key.length / 3));
807
+ if (best && best.distance <= tolerance) return { ok: false, suggestion: best.id };
808
+ const partial = key.length >= 3
809
+ ? ids.filter((id) => id.includes(key) || themeKey(themes[id]!.name).includes(key))
810
+ : [];
811
+ return { ok: false, suggestion: partial.length === 1 ? partial[0]! : null };
812
+ }
@@ -9,6 +9,7 @@ import { assetClassMarketSymbol, parseAssetClassQuery } from "./asset-classes";
9
9
  import { searchContractKey, searchInstrumentKey } from "./identity";
10
10
  import { tickerInstrumentLabel } from "../instrument-label";
11
11
  import {
12
+ answersOnlyByKeyword,
12
13
  buildSymbolAliases,
13
14
  classifyInstrumentKind,
14
15
  findExactTickerSearchMatch,
@@ -178,6 +179,7 @@ function createProviderTickerSearchCandidates(
178
179
  instrumentClass: classifyInstrumentKind(result.brokerContract?.secType || result.type),
179
180
  instrumentType: result.brokerContract?.secType || result.type,
180
181
  searchAliases: buildSearchResultAliases(result),
182
+ ...(searchResultKeywords(result) ? { searchKeywords: searchResultKeywords(result) } : {}),
181
183
  result,
182
184
  }];
183
185
  });
@@ -251,7 +253,7 @@ export function buildTickerSearchCandidates({
251
253
  );
252
254
  const providerItems = createProviderTickerSearchCandidates(filteredProviderResults, tickers, candidateOptions);
253
255
  const ranked = rankTickerSearchItems([...localItems, ...providerItems], query);
254
- return limitTickerSearchCandidates(assignTickerSearchCategories(ranked), totalLimit, localLimit);
256
+ return limitTickerSearchCandidates(assignTickerSearchCategories(ranked, query), totalLimit, localLimit);
255
257
  }
256
258
 
257
259
  interface ResolveTickerSearchOptions {
@@ -589,10 +591,22 @@ function getProviderHintScore(result: InstrumentSearchResult, preferredExchange?
589
591
  return getProviderHintRichness(result) + (matchesPreferredExchange ? 10_000 : 0);
590
592
  }
591
593
 
592
- function assignTickerSearchCategories<T extends TickerSearchCandidate>(items: T[]): T[] {
594
+ /** Older servers send none; anything malformed is ignored. */
595
+ function searchResultKeywords(result: InstrumentSearchResult): string[] | undefined {
596
+ const keywords = Array.isArray(result.searchKeywords)
597
+ ? result.searchKeywords.filter((keyword): keyword is string => typeof keyword === "string" && !!keyword.trim())
598
+ : [];
599
+ return keywords.length > 0 ? keywords : undefined;
600
+ }
601
+
602
+ function assignTickerSearchCategories<T extends TickerSearchCandidate>(items: T[], query: string): T[] {
593
603
  let assignedPrimaryListing = false;
594
604
 
595
605
  return items.map((item) => {
606
+ // A company the theme's funds hold is not another listing of the one searched for.
607
+ if (!item.saved && item.kind === "search" && item.instrumentClass === "equity" && answersOnlyByKeyword(item, query)) {
608
+ return { ...item, category: "Related" };
609
+ }
596
610
  if (item.saved || item.kind === "ticker") {
597
611
  if (item.instrumentClass !== "fund" && item.instrumentClass !== "derivative") {
598
612
  assignedPrimaryListing = true;
@@ -669,5 +683,11 @@ function buildSearchResultAliases(result: InstrumentSearchResult): string[] {
669
683
  if (result.brokerContract?.symbol) {
670
684
  for (const alias of buildSymbolAliases(result.brokerContract.symbol)) aliases.add(alias);
671
685
  }
686
+ // Older servers send none. Anything else malformed is ignored.
687
+ if (Array.isArray(result.searchAliases)) {
688
+ for (const alias of result.searchAliases) {
689
+ if (typeof alias === "string" && alias.trim()) aliases.add(alias.trim());
690
+ }
691
+ }
672
692
  return [...aliases];
673
693
  }
@@ -216,7 +216,12 @@ export function rankTickerSearchItems<T extends Pick<TickerSearchRankableItem, "
216
216
  const aliases = getItemSearchAliases(item);
217
217
  const aliasScore = (exactListingSymbol ? [...aliases, exactListingSymbol] : aliases)
218
218
  .reduce((best, alias) => Math.max(best, scoreSearchAlias(intent, alias)), 0);
219
- const textScore = labelScore + detailScore + aliasScore
219
+ // Several words match on all of them, in any order, across the name, type,
220
+ // venue and the themes the row answers to; a theme alone ranks after a name.
221
+ const keywordScore = scoreAllWords(intent, [...(item.searchKeywords ?? [])]) > 0 ? KEYWORD_MATCH_SCORE : 0;
222
+ const wordsScore = labelScore + detailScore + aliasScore > 0 ? 0
223
+ : scoreAllWords(intent, [item.label, item.detail, item.right ?? "", ...(item.searchKeywords ?? [])]);
224
+ const textScore = labelScore + detailScore + aliasScore + Math.max(keywordScore, wordsScore)
220
225
  + (isQualifiedTickerQuery(query) && matchesQualifiedTicker(item, query) ? 100_000 : 0);
221
226
  const saved = isSavedSearchItem(item);
222
227
  const explicitIntentScore = scoreAssetPreference(intent, item.instrumentClass)
@@ -285,6 +290,13 @@ export function rankTickerSearchItems<T extends Pick<TickerSearchRankableItem, "
285
290
  const aSaved = isSavedSearchItem(a.item);
286
291
  const bSaved = isSavedSearchItem(b.item);
287
292
  if (aSaved !== bSaved) return aSaved ? -1 : 1;
293
+ // Rows that answer to the same typed name (GOOGL and GOOG for "Google")
294
+ // keep the order the server gave them rather than the shorter symbol first.
295
+ if (a.symbolMatchRank === 2) {
296
+ const aProviderRank = a.item.providerRank ?? Number.POSITIVE_INFINITY;
297
+ const bProviderRank = b.item.providerRank ?? Number.POSITIVE_INFINITY;
298
+ if (aProviderRank !== bProviderRank) return aProviderRank - bProviderRank;
299
+ }
288
300
  if (a.item.label.length !== b.item.label.length) return a.item.label.length - b.item.label.length;
289
301
  return a.index - b.index;
290
302
  };
@@ -487,6 +499,38 @@ function getItemSearchAliases(item: Pick<TickerSearchRankableItem, "label"> & Pa
487
499
  return aliases.length > 0 ? aliases : [item.label];
488
500
  }
489
501
 
502
+ /** A row that answers only to a theme it was sent with (`searchKeywords`), below any name match. */
503
+ const KEYWORD_MATCH_SCORE = 500;
504
+ /** Every query word found somewhere in the row, in any order. */
505
+ const ALL_WORDS_SCORE = 2_200;
506
+
507
+ /**
508
+ * ALL_WORDS_SCORE when every word of the query (exchange and asset words
509
+ * aside) starts a word of some field: "miners copper" finds "Copper Miners
510
+ * ETF", "lithium" finds a row sent with the lithium theme. Zero otherwise.
511
+ */
512
+ function scoreAllWords(intent: SearchQueryIntent, fields: readonly string[]): number {
513
+ const terms = intent.companyQuery.split(" ").filter(Boolean);
514
+ if (terms.length === 0) return 0;
515
+ const words = fields.flatMap((field) => normalizeSearchText(field).split(" ").filter(Boolean));
516
+ return terms.every((term) => words.some((word) => word.startsWith(term))) ? ALL_WORDS_SCORE : 0;
517
+ }
518
+
519
+ /**
520
+ * Whether a row is in an answer for a theme it was sent with, not for its
521
+ * name: the name lacks some of the query's words (Albemarle for "lithium",
522
+ * Southern Copper for "copper miners").
523
+ */
524
+ export function answersOnlyByKeyword(
525
+ item: Pick<TickerSearchRankableItem, "label" | "detail"> & Partial<TickerSearchRankableItem>,
526
+ query: string,
527
+ ): boolean {
528
+ if (!item.searchKeywords?.length) return false;
529
+ const terms = analyzeSearchQuery(query).companyQuery.split(" ").filter(Boolean);
530
+ const words = [item.label, item.detail].flatMap((field) => normalizeSearchText(field).split(" ").filter(Boolean));
531
+ return terms.length > 0 && !terms.every((term) => words.some((word) => word.startsWith(term)));
532
+ }
533
+
490
534
  function maxScoreForQueries(
491
535
  queries: string[],
492
536
  value: string,
@@ -2,7 +2,7 @@ import type { BrokerContractRef, InstrumentSearchResult, TickerListingRef } from
2
2
  import type { TickerRecord } from "../../types/ticker";
3
3
 
4
4
  export type TickerSearchInstrumentClass = "equity" | "fund" | "derivative" | "other";
5
- type TickerSearchCategory = "Saved" | "Primary Listing" | "Other Listings" | "Funds & Derivatives";
5
+ type TickerSearchCategory = "Saved" | "Primary Listing" | "Other Listings" | "Funds & Derivatives" | "Related";
6
6
 
7
7
  export interface TickerSearchRankableItem {
8
8
  id: string;
@@ -21,6 +21,8 @@ export interface TickerSearchRankableItem {
21
21
  providerRank?: number;
22
22
  popularity?: number;
23
23
  searchAliases?: string[];
24
+ /** Themes the row answers to that its name does not say (`InstrumentSearchResult.searchKeywords`). */
25
+ searchKeywords?: string[];
24
26
  }
25
27
 
26
28
  export interface TickerSearchCandidate extends TickerSearchRankableItem {
@@ -37,6 +37,21 @@ const RANGE_PRESET_RESOLUTION: Record<TimeRange, ManualChartResolution> = {
37
37
  "ALL": "1mo",
38
38
  };
39
39
 
40
+ /**
41
+ * The bar size a price history for a range is served in, unlike the chart
42
+ * presets above: what `gloomberb history` and the historical prices pane get.
43
+ */
44
+ export const RANGE_HISTORY_RESOLUTION: Readonly<Record<TimeRange, ManualChartResolution>> = {
45
+ "1D": "5m",
46
+ "1W": "1h",
47
+ "1M": "1d",
48
+ "3M": "1d",
49
+ "6M": "1d",
50
+ "1Y": "1d",
51
+ "5Y": "1wk",
52
+ "ALL": "1mo",
53
+ };
54
+
40
55
  const RANGE_PRELOAD_BUFFER: Record<TimeRange, TimeRange> = {
41
56
  "1D": "1W",
42
57
  "1W": "1M",
@@ -80,6 +80,7 @@ import { getPricePointTimestamp, isPriceHistoryStaleForCurrentWindow } from "../
80
80
  import { latestSessionStart, latestTradingSessionOpen, listingTimeZone, priorSessionClose } from "../market-data/market/trading-sessions";
81
81
  import { futuresGenericCaption, futuresGenericListing, futuresGenericPriceBasis } from "../utils/futures-generic";
82
82
  import { isOhlcSeriesStyle } from "./spec";
83
+ import { SERIES_COLORS } from "../theme/series-colors";
83
84
  import type {
84
85
  ChartResolutionResult,
85
86
  ChartSeriesSpec,
@@ -88,20 +89,6 @@ import type {
88
89
  TimeSeriesPoint,
89
90
  } from "./types";
90
91
 
91
- /** Colours for series told apart by name (compared tickers, markets). */
92
- export const SERIES_COLORS = [
93
- "#4dabf7",
94
- "#63e6be",
95
- "#f6c85f",
96
- "#b197fc",
97
- "#ff8787",
98
- "#ffa94d",
99
- "#74c0fc",
100
- "#e599f7",
101
- "#8ce99a",
102
- "#ffd43b",
103
- ] as const;
104
-
105
92
  export interface ChartResolveSources {
106
93
  dataProvider: DataProvider | null;
107
94
  loadFredSeries: (request: FredSeriesRequest) => Promise<FredSeriesLoadResult>;
@@ -2,7 +2,7 @@ import type { Portfolio, Watchlist } from "./ticker";
2
2
  import type { BrokerContractRef, TickerListingRef } from "./instrument";
3
3
  import type { LanguagePreference } from "../i18n/languages";
4
4
 
5
- export const CURRENT_CONFIG_VERSION = 24;
5
+ export const CURRENT_CONFIG_VERSION = 25;
6
6
 
7
7
  type ChartRendererPreference = "auto" | "kitty" | "braille";
8
8
 
@@ -59,6 +59,30 @@ export interface PanePlacementMemory {
59
59
  detached?: DetachedPlacementMemory;
60
60
  }
61
61
 
62
+ /**
63
+ * A ticker link Move to New Layout had to cut: the pane followed another one
64
+ * that stayed behind (or left with the moved pane) and was pinned on `symbol`.
65
+ * Move Back links it again while it is still pinned there.
66
+ */
67
+ export interface PaneMovedLink {
68
+ instanceId: string;
69
+ sourceInstanceId: string;
70
+ symbol: string;
71
+ /** The title before the pin renamed it ("OPX" for "OPX NVDA"), when it did. */
72
+ title?: string;
73
+ }
74
+
75
+ /** Where Move to New Layout took a pane from, so Move Back can return it. */
76
+ export interface PaneMovedFrom {
77
+ /** `SavedLayout.id` of the layout it left. */
78
+ layoutId: string;
79
+ /** Set when it was docked there: its place in the tree and its share of the split. */
80
+ docked?: DockedPlacementMemory & { ratio?: number };
81
+ /** Set when it was floating there. */
82
+ floating?: FloatingPlacementMemory;
83
+ links?: PaneMovedLink[];
84
+ }
85
+
62
86
  export interface PaneInstanceConfig {
63
87
  instanceId: string;
64
88
  paneId: string;
@@ -69,6 +93,8 @@ export interface PaneInstanceConfig {
69
93
  placementMemory?: PanePlacementMemory;
70
94
  /** Pinned by the user: the keyboard close shortcuts leave this pane alone. */
71
95
  locked?: boolean;
96
+ /** Set by Move to New Layout and cleared by Move Back; never published. */
97
+ movedFrom?: PaneMovedFrom;
72
98
  }
73
99
 
74
100
  interface DockPaneNode {
@@ -203,6 +229,21 @@ export interface TelemetryConfig {
203
229
  attention?: boolean;
204
230
  }
205
231
 
232
+ /**
233
+ * The one-time line in the terminal's status bar asking to star Gloomberb on
234
+ * GitHub. Absent means on and not shown yet. Kept on this machine only.
235
+ */
236
+ export interface StarPromptConfig {
237
+ /** `false` turns the line off; absent means on. */
238
+ enabled?: boolean;
239
+ /** Local days (`YYYY-MM-DD`) the terminal app was opened on, oldest first, until the line shows. */
240
+ days?: string[];
241
+ /** When the line showed. Once set it never shows again. */
242
+ shownAt?: string;
243
+ /** How it ended: the repository was opened, the line was dismissed, or it timed out. */
244
+ outcome?: "opened" | "dismissed" | "expired";
245
+ }
246
+
206
247
  /**
207
248
  * One recent command-bar run: `id` is `pane-template:<templateId>`, `label`
208
249
  * its name when it ran, and `arg` a ticker it ran with (never free text).
@@ -255,6 +296,12 @@ export interface AppConfig {
255
296
  /** Key overrides for this machine. Absent means every default applies. */
256
297
  keybindings?: KeybindingsConfig;
257
298
  telemetry?: TelemetryConfig;
299
+ starPrompt?: StarPromptConfig;
300
+ /**
301
+ * Presentation mode: the panes fill the window, without the header or the
302
+ * status bar, for a screen that is shown rather than worked at. Absent is off.
303
+ */
304
+ presentationMode?: boolean;
258
305
  }
259
306
 
260
307
  export const TICKER_RESEARCH_PANE_ID = "ticker-research";
@@ -582,6 +629,17 @@ export function clonePlacementMemory(memory: PanePlacementMemory | undefined): P
582
629
  };
583
630
  }
584
631
 
632
+ function clonePaneMovedFrom(movedFrom: PaneMovedFrom): PaneMovedFrom {
633
+ return {
634
+ layoutId: movedFrom.layoutId,
635
+ ...(movedFrom.docked ? {
636
+ docked: { ...movedFrom.docked, ...(movedFrom.docked.path ? { path: [...movedFrom.docked.path] } : {}) },
637
+ } : {}),
638
+ ...(movedFrom.floating ? { floating: { ...movedFrom.floating } } : {}),
639
+ ...(movedFrom.links ? { links: movedFrom.links.map((link) => ({ ...link })) } : {}),
640
+ };
641
+ }
642
+
585
643
  function cloneUnknownValue<T>(value: T): T {
586
644
  if (Array.isArray(value)) {
587
645
  return value.map((entry) => cloneUnknownValue(entry)) as T;
@@ -816,6 +874,7 @@ export function normalizePaneLayout(
816
874
  params: instance.params ? { ...instance.params } : undefined,
817
875
  settings: clonePaneSettings(instance.settings),
818
876
  placementMemory: clonePlacementMemory(instance.placementMemory),
877
+ ...(instance.movedFrom ? { movedFrom: clonePaneMovedFrom(instance.movedFrom) } : {}),
819
878
  })),
820
879
  floating: nextLayout.floating
821
880
  .filter((entry) => (
@@ -838,6 +897,7 @@ export function cloneLayout(layout: LayoutConfig): LayoutConfig {
838
897
  params: instance.params ? { ...instance.params } : undefined,
839
898
  settings: clonePaneSettings(instance.settings),
840
899
  placementMemory: clonePlacementMemory(instance.placementMemory),
900
+ ...(instance.movedFrom ? { movedFrom: clonePaneMovedFrom(instance.movedFrom) } : {}),
841
901
  })),
842
902
  floating: layout.floating.map((entry) => ({ ...entry })),
843
903
  detached: detached.map((entry) => ({ ...entry })),
@@ -38,7 +38,21 @@ export interface QuoteMetadata {
38
38
  fieldSources?: Partial<Record<"currency" | "instrumentType", QuoteMetadataSource>>;
39
39
  }
40
40
 
41
- export interface Quote {
41
+ /**
42
+ * What a record's share counts count: depositary receipts or the ordinary
43
+ * shares behind them. Gloom Cloud states it only when it established it.
44
+ */
45
+ export type ShareBasis = "depositary_receipt" | "ordinary";
46
+
47
+ /** How a depositary receipt relates to the ordinary shares, as Gloom Cloud states it. */
48
+ interface DepositaryReceiptFacts {
49
+ /** Whether the listing is a depositary receipt; absent when unknown. */
50
+ isDepositaryReceipt?: boolean;
51
+ /** Ordinary shares per receipt, on a receipt's own records. */
52
+ adrRatio?: number;
53
+ }
54
+
55
+ export interface Quote extends DepositaryReceiptFacts {
42
56
  /** Applies to this price observation; a stored position cannot supply it. */
43
57
  priceBasis?: PriceBasis;
44
58
  /** Daily fund net asset value; independent of the units used to format its price. */
@@ -109,7 +123,11 @@ export interface QuoteContribution extends Quote {
109
123
 
110
124
  export type QuoteContributionMap = Record<string, QuoteContribution>;
111
125
 
112
- export interface Fundamentals {
126
+ export interface Fundamentals extends DepositaryReceiptFacts {
127
+ /** Every share count here is on this basis, the basis of the listing's price and market cap; absent when unproven. */
128
+ shareBasis?: ShareBasis;
129
+ /** On a receipt, the ordinary shares behind `sharesOutstanding`. */
130
+ underlyingOrdinaryShares?: number;
113
131
  source?: "gloom";
114
132
  fetchedAt?: string;
115
133
  stale?: boolean;
@@ -180,6 +198,8 @@ export interface HolderRecord {
180
198
  percentHeld?: number;
181
199
  changeShares?: number;
182
200
  changePercent?: number;
201
+ /** Set when the position's filing ties it to the receipts or to the ordinary shares. */
202
+ shareBasis?: ShareBasis;
183
203
  }
184
204
 
185
205
  interface HolderSummary {
@@ -189,11 +209,18 @@ interface HolderSummary {
189
209
  institutionsCount?: number;
190
210
  }
191
211
 
192
- export interface HolderData {
212
+ export interface HolderData extends DepositaryReceiptFacts {
193
213
  providerId?: string;
194
214
  symbol: string;
195
215
  name?: string;
216
+ /** The listing's price currency. */
196
217
  currency?: string;
218
+ /** The currency of `value`, which can differ from the listing's (USD on a London line priced from 13F filings). */
219
+ valueCurrency?: string;
220
+ /** Reported shares times the latest price, or times the price at the report date. */
221
+ valueBasis?: "latest_price" | "period_end_price";
222
+ /** Set when every row is on one basis. */
223
+ shareBasis?: ShareBasis;
197
224
  exchange?: string;
198
225
  asOf?: string;
199
226
  summary?: HolderSummary;
@@ -430,6 +457,8 @@ export interface ReportedEarningsCohort {
430
457
  export interface EarningsResultProvenance { version: 1; reported: ReportedEarningsCohort }
431
458
 
432
459
  export interface FinancialStatement {
460
+ /** The basis of this row's share counts and per-share earnings; absent when unproven. */
461
+ shareBasis?: ShareBasis;
433
462
  /** @deprecated No longer populated. */
434
463
  earningsResult?: EarningsResultProvenance;
435
464
  /** EPS lines unavailable for this period, for example because they disagree with the row's own income and shares. */
@@ -51,6 +51,15 @@ export interface HeadlessPaneOptionDef {
51
51
  pluginId: string;
52
52
  key?: string;
53
53
  };
54
+ /** The value's name in the catalog's flag, `--expiration <YYYY-MM-DD|unix>`; the type when absent. */
55
+ placeholder?: string;
56
+ /** The option in use as typed after the function, such as `--expiration 2028-01-21`; the catalog shows it as an example. */
57
+ example?: string;
58
+ /**
59
+ * Checks a typed value and returns it as the pane reads it, in place of the
60
+ * type's own check; throws an Error that names what is wrong.
61
+ */
62
+ normalize?(value: string): string | number | boolean;
54
63
  }
55
64
 
56
65
  export interface HeadlessPaneLoadArgs {
@@ -90,6 +99,8 @@ export interface HeadlessPaneColumn {
90
99
  header: string;
91
100
  align?: "left" | "right" | "center";
92
101
  width?: number;
102
+ /** False keeps the column whole when the text table is fitted to a narrow width, so a time or an id is never cut. */
103
+ shrink?: boolean;
93
104
  description?: string;
94
105
  format?: (value: unknown, row: HeadlessPaneRow) => string;
95
106
  }
@@ -59,4 +59,12 @@ export interface InstrumentSearchResult {
59
59
  /** How often the listing is searched, higher is more (the search service score,
60
60
  * sent by newer cloud servers). Only comparable within one response. */
61
61
  popularity?: number;
62
+ /** Trade names the row answers to ("Aramco" for Saudi Arabian Oil Co.), sent by
63
+ * newer cloud servers on a row a trade-name query added. The legal name does not
64
+ * contain them, so search matches the query against them too. */
65
+ searchAliases?: string[];
66
+ /** A theme the row answers to without its name saying so ("lithium" on
67
+ * Albemarle, which the lithium funds hold), sent by newer cloud servers on a
68
+ * row a theme query added. Matched like the name, ranked after name matches. */
69
+ searchKeywords?: string[];
62
70
  }