gloomberb 0.16.0 → 0.16.2

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 (691) hide show
  1. package/README.md +2 -1
  2. package/package.json +2 -1
  3. package/src/api-client/beneficial-owners.ts +92 -0
  4. package/src/api-client/data.ts +44 -11
  5. package/src/api-client/errors.ts +12 -0
  6. package/src/api-client/geo.ts +363 -0
  7. package/src/api-client/index.ts +5 -0
  8. package/src/api-client/market-discovery.ts +10 -0
  9. package/src/api-client/members.ts +26 -0
  10. package/src/api-client/paths.ts +30 -1
  11. package/src/api-client/perps.ts +41 -0
  12. package/src/api-client/request.ts +5 -2
  13. package/src/api-client/types.ts +9 -1
  14. package/src/app/global-shortcuts.ts +14 -6
  15. package/src/app/keybindings/actions.ts +1 -1
  16. package/src/app/runtime/update.ts +38 -2
  17. package/src/app.tsx +10 -6
  18. package/src/brokers/account-cache.ts +24 -0
  19. package/src/cli/commands/command-utils.ts +8 -0
  20. package/src/cli/commands/crypto-hints.ts +75 -0
  21. package/src/cli/commands/market.ts +414 -106
  22. package/src/cli/commands/overview.ts +77 -32
  23. package/src/cli/commands/ticker.ts +101 -43
  24. package/src/cli/desktop-pane-shot.ts +34 -4
  25. package/src/cli/freshness.ts +61 -0
  26. package/src/cli/help.ts +1 -0
  27. package/src/cli/helpers.ts +4 -8
  28. package/src/cli/index.ts +12 -2
  29. package/src/cli/listing-arg.ts +321 -0
  30. package/src/cli/pane-functions/access-gate.ts +42 -0
  31. package/src/cli/pane-functions/catalog.ts +28 -1
  32. package/src/cli/pane-functions/data.ts +3 -1
  33. package/src/cli/pane-functions/dom.ts +20 -2
  34. package/src/cli/pane-functions/freshness.ts +400 -0
  35. package/src/cli/pane-functions/function-help.ts +36 -22
  36. package/src/cli/pane-functions/headless.ts +39 -11
  37. package/src/cli/pane-functions/index.ts +15 -4
  38. package/src/cli/pane-functions/options.ts +3 -0
  39. package/src/cli/pane-functions/report.ts +4 -0
  40. package/src/cli/pane-functions/resolver.ts +35 -7
  41. package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
  42. package/src/cli/pane-functions/screenshot.ts +7 -3
  43. package/src/cli/result.ts +41 -27
  44. package/src/cli/ticker-resolution.ts +7 -5
  45. package/src/components/chart/composite/composite-chart.tsx +88 -2536
  46. package/src/components/chart/composite/drawing-store.ts +59 -0
  47. package/src/components/chart/composite/legend.tsx +319 -0
  48. package/src/components/chart/composite/panel-bitmap.ts +139 -0
  49. package/src/components/chart/composite/panel-gestures.ts +59 -0
  50. package/src/components/chart/composite/panel-labels.ts +107 -0
  51. package/src/components/chart/composite/panel-surface.tsx +876 -0
  52. package/src/components/chart/composite/tool-catalog.ts +98 -0
  53. package/src/components/chart/composite/toolbar.tsx +186 -0
  54. package/src/components/chart/composite/tools.ts +8 -0
  55. package/src/components/chart/composite/use-composite-chart-keyboard.ts +703 -0
  56. package/src/components/chart/composite/use-composite-viewport.ts +143 -0
  57. package/src/components/command-bar/commands/collection.ts +5 -1
  58. package/src/components/command-bar/list/model.ts +5 -0
  59. package/src/components/command-bar/list/view.tsx +16 -3
  60. package/src/components/command-bar/pane-templates/workflow.ts +1 -0
  61. package/src/components/command-bar/routes/root/command-items.ts +9 -2
  62. package/src/components/command-bar/routes/root/plugin-install.ts +2 -2
  63. package/src/components/command-bar/routes/root/provider-search.ts +19 -5
  64. package/src/components/command-bar/routes/root/runtime.ts +14 -5
  65. package/src/components/command-bar/routes/ticker-search/actions.ts +5 -0
  66. package/src/components/command-bar/routes/ticker-search/results.ts +31 -5
  67. package/src/components/command-bar/routes/ticker-search/route.ts +2 -2
  68. package/src/components/command-bar/routing/actions.ts +2 -0
  69. package/src/components/command-bar/selection-runtime.ts +38 -0
  70. package/src/components/command-bar/surface/index.tsx +7 -2
  71. package/src/components/command-bar/workflow/ops.ts +1 -1
  72. package/src/components/command-bar/workflow/tickers.ts +6 -0
  73. package/src/components/data-table/view.tsx +29 -10
  74. package/src/components/feedback-dialog.tsx +2 -1
  75. package/src/components/form-modal/field-row.tsx +2 -2
  76. package/src/components/index.ts +2 -2
  77. package/src/components/layout/detached-pane-shell.tsx +6 -3
  78. package/src/components/layout/floating-pane.tsx +6 -0
  79. package/src/components/layout/header.tsx +24 -7
  80. package/src/components/layout/missing-pane.tsx +2 -2
  81. package/src/components/layout/pane/content.tsx +23 -10
  82. package/src/components/layout/pane/error-boundary.tsx +103 -0
  83. package/src/components/layout/pane/footer/registration.tsx +68 -23
  84. package/src/components/layout/pane/header.tsx +61 -28
  85. package/src/components/layout/pane/index.tsx +6 -0
  86. package/src/components/layout/pane/title.ts +31 -7
  87. package/src/components/layout/shell/drag/index.ts +6 -5
  88. package/src/components/layout/shell/drag/runtime.ts +3 -0
  89. package/src/components/layout/shell/index.tsx +6 -0
  90. package/src/components/layout/shell/menu.ts +2 -1
  91. package/src/components/layout/shell/pane/actions.ts +2 -1
  92. package/src/components/layout/shell/pane/layers.tsx +29 -10
  93. package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -3
  94. package/src/components/layout/shell/ticker-link-menu.ts +23 -9
  95. package/src/components/metric-treemap/heat-surface.tsx +745 -0
  96. package/src/components/metric-treemap/heat-tiles.ts +228 -0
  97. package/src/components/metric-treemap/index.tsx +2 -0
  98. package/src/components/metric-treemap/layout.ts +8 -0
  99. package/src/components/metric-treemap/scene.ts +432 -0
  100. package/src/components/onboarding/onboarding-keyboard.ts +311 -0
  101. package/src/components/onboarding/onboarding-wizard.tsx +101 -788
  102. package/src/components/onboarding/use-onboarding-broker-form.ts +263 -0
  103. package/src/components/onboarding/use-onboarding-progress.ts +298 -0
  104. package/src/components/onboarding/use-onboarding-upgrade.ts +83 -0
  105. package/src/components/pane-settings-dialog/field-dialogs.tsx +1 -0
  106. package/src/components/ticker/list-table-view.tsx +13 -1
  107. package/src/components/toggle-list.tsx +38 -12
  108. package/src/components/ui/country-flag-art.tsx +449 -0
  109. package/src/components/ui/country-flag.tsx +41 -0
  110. package/src/components/ui/data-table/types.ts +13 -0
  111. package/src/components/ui/fields.tsx +8 -0
  112. package/src/components/ui/icon.tsx +2 -0
  113. package/src/components/ui/index.ts +4 -0
  114. package/src/components/ui/multi-select/dialog.tsx +108 -22
  115. package/src/components/ui/range-track.tsx +53 -0
  116. package/src/components/ui/status.tsx +8 -2
  117. package/src/components/ui/tabs.tsx +11 -4
  118. package/src/components/ui/text-prompt-dialog.tsx +4 -2
  119. package/src/core/state/app/types.ts +10 -1
  120. package/src/data/config/store/normalize.ts +17 -1
  121. package/src/i18n/es.ts +24 -4
  122. package/src/i18n/ja.ts +24 -4
  123. package/src/i18n/ko.ts +24 -4
  124. package/src/i18n/zh-cn.ts +24 -4
  125. package/src/i18n/zh-tw.ts +24 -4
  126. package/src/layout/ticker-navigation.ts +28 -2
  127. package/src/market-data/coordinator/chart.ts +1 -1
  128. package/src/market-data/coordinator/quotes.ts +23 -4
  129. package/src/market-data/fx-closes.ts +72 -0
  130. package/src/market-data/market/freshness.ts +78 -6
  131. package/src/market-data/market/session-close-note.ts +57 -0
  132. package/src/market-data/market/status.ts +151 -0
  133. package/src/market-data/published-apac-sessions.ts +66 -0
  134. package/src/market-data/quotes/contributions.ts +8 -0
  135. package/src/market-data/quotes/freshness.ts +36 -0
  136. package/src/market-data/quotes/resolution.ts +24 -8
  137. package/src/market-data/quotes/screener-live-quotes.ts +49 -4
  138. package/src/market-data/quotes/time.ts +16 -0
  139. package/src/plugins/builtin/account-management/pane.tsx +4 -0
  140. package/src/plugins/builtin/alerts/cli.ts +10 -5
  141. package/src/plugins/builtin/alerts/index.tsx +1 -0
  142. package/src/plugins/builtin/analytics/metrics.ts +8 -3
  143. package/src/plugins/builtin/analytics/risk-client.ts +330 -79
  144. package/src/plugins/builtin/analytics/risk-fx.ts +102 -0
  145. package/src/plugins/builtin/analytics/risk-headless.ts +61 -49
  146. package/src/plugins/builtin/analytics/risk-math.ts +33 -13
  147. package/src/plugins/builtin/analytics/risk-model.ts +282 -64
  148. package/src/plugins/builtin/analytics/risk-pane.tsx +62 -30
  149. package/src/plugins/builtin/analytics/risk-test-data.ts +206 -0
  150. package/src/plugins/builtin/attention/headless.ts +6 -4
  151. package/src/plugins/builtin/attention/index.tsx +1 -1
  152. package/src/plugins/builtin/attention/pane.tsx +1 -1
  153. package/src/plugins/builtin/awards/headless.ts +1 -0
  154. package/src/plugins/builtin/awards/pane.tsx +1 -1
  155. package/src/plugins/builtin/backtest/headless.ts +1 -0
  156. package/src/plugins/builtin/bond-calculator/headless.ts +1 -0
  157. package/src/plugins/builtin/buildout/cells.tsx +15 -12
  158. package/src/plugins/builtin/buildout/detail/company.tsx +3 -3
  159. package/src/plugins/builtin/buildout/detail/index.tsx +0 -1
  160. package/src/plugins/builtin/buildout/detail/intel.tsx +6 -6
  161. package/src/plugins/builtin/buildout/detail/site.tsx +4 -7
  162. package/src/plugins/builtin/buildout/detail/ui.tsx +0 -19
  163. package/src/plugins/builtin/buildout/index.tsx +1 -0
  164. package/src/plugins/builtin/catalysts/headless.ts +3 -1
  165. package/src/plugins/builtin/catalysts/index.tsx +2 -2
  166. package/src/plugins/builtin/catalysts/pane.tsx +3 -1
  167. package/src/plugins/builtin/cds/headless.ts +2 -0
  168. package/src/plugins/builtin/cds/index.tsx +1 -0
  169. package/src/plugins/builtin/central-bank-rates/headless.ts +1 -0
  170. package/src/plugins/builtin/chart-composer/headless.ts +38 -3
  171. package/src/plugins/builtin/chart-composer/index.tsx +3 -1
  172. package/src/plugins/builtin/chart-composer/series-expression.ts +18 -2
  173. package/src/plugins/builtin/chat/channels.ts +19 -3
  174. package/src/plugins/builtin/chat/content/composer-runtime.ts +28 -13
  175. package/src/plugins/builtin/chat/content/footer.tsx +15 -6
  176. package/src/plugins/builtin/chat/content/index.tsx +120 -21
  177. package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +261 -113
  178. package/src/plugins/builtin/chat/content/transcript.tsx +20 -2
  179. package/src/plugins/builtin/chat/direct-messages.ts +200 -0
  180. package/src/plugins/builtin/chat/index.tsx +1 -0
  181. package/src/plugins/builtin/chat/message/desktop.tsx +3 -0
  182. package/src/plugins/builtin/chat/message/header.tsx +16 -6
  183. package/src/plugins/builtin/chat/message/inline-tokens.tsx +72 -32
  184. package/src/plugins/builtin/chat/message/profile-popover.tsx +96 -12
  185. package/src/plugins/builtin/chat/message/terminal.tsx +3 -0
  186. package/src/plugins/builtin/chat/message/types.ts +14 -2
  187. package/src/plugins/builtin/chat/profile-popover.ts +18 -13
  188. package/src/plugins/builtin/clinical-trials/index.tsx +1 -0
  189. package/src/plugins/builtin/cloud/askg/executor.ts +2 -1
  190. package/src/plugins/builtin/cloud/plugin.tsx +1 -0
  191. package/src/plugins/builtin/cloud/team/module.tsx +1 -0
  192. package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
  193. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  194. package/src/plugins/builtin/comment-letters/index.tsx +1 -0
  195. package/src/plugins/builtin/company-attention/headless.ts +5 -1
  196. package/src/plugins/builtin/company-attention/pane.tsx +1 -1
  197. package/src/plugins/builtin/company-kpis/headless.ts +1 -0
  198. package/src/plugins/builtin/congress-trades/headless.ts +1 -0
  199. package/src/plugins/builtin/correlation/compute.ts +59 -16
  200. package/src/plugins/builtin/correlation/geo.ts +34 -0
  201. package/src/plugins/builtin/correlation/headless-schema.ts +4 -1
  202. package/src/plugins/builtin/correlation/headless.ts +42 -8
  203. package/src/plugins/builtin/correlation/history.ts +2 -0
  204. package/src/plugins/builtin/correlation/index.tsx +68 -14
  205. package/src/plugins/builtin/correlation/matrix/model.ts +17 -2
  206. package/src/plugins/builtin/correlation/matrix/selection.ts +5 -3
  207. package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
  208. package/src/plugins/builtin/correlation/relationship/pane.tsx +4 -2
  209. package/src/plugins/builtin/correlation/relationship/view-model.ts +16 -1
  210. package/src/plugins/builtin/correlation/settings.ts +1 -1
  211. package/src/plugins/builtin/cot/headless.ts +6 -3
  212. package/src/plugins/builtin/cot/index.tsx +3 -3
  213. package/src/plugins/builtin/cot/model.ts +36 -3
  214. package/src/plugins/builtin/cpi/headless.ts +4 -0
  215. package/src/plugins/builtin/credit-boards/headless.ts +2 -0
  216. package/src/plugins/builtin/credit-conditions/headless.ts +1 -0
  217. package/src/plugins/builtin/credit-documents/gauge.tsx +5 -8
  218. package/src/plugins/builtin/credit-documents/headless.ts +2 -0
  219. package/src/plugins/builtin/crypto-board/headless.ts +3 -0
  220. package/src/plugins/builtin/custom-view/loader.ts +1 -1
  221. package/src/plugins/builtin/debt-maturities/headless.ts +4 -0
  222. package/src/plugins/builtin/debt-maturities/wall-bar.tsx +14 -41
  223. package/src/plugins/builtin/dividend-yield/client.ts +4 -2
  224. package/src/plugins/builtin/dividend-yield/headless.ts +1 -0
  225. package/src/plugins/builtin/doe/headless.ts +7 -0
  226. package/src/plugins/builtin/doe/range-bar.tsx +7 -37
  227. package/src/plugins/builtin/earnings/client.ts +2 -2
  228. package/src/plugins/builtin/earnings/headless.ts +5 -0
  229. package/src/plugins/builtin/earnings-calls/headless.ts +1 -0
  230. package/src/plugins/builtin/earnings-calls/index.tsx +1 -0
  231. package/src/plugins/builtin/earnings-ripple/client.ts +91 -18
  232. package/src/plugins/builtin/earnings-ripple/headless.ts +28 -8
  233. package/src/plugins/builtin/earnings-ripple/index.tsx +2 -2
  234. package/src/plugins/builtin/earnings-ripple/model.ts +97 -7
  235. package/src/plugins/builtin/earnings-ripple/pane.tsx +148 -23
  236. package/src/plugins/builtin/econ/index.tsx +1 -0
  237. package/src/plugins/builtin/econ-statistics/headless.ts +2 -0
  238. package/src/plugins/builtin/equity-screener/headless.ts +2 -0
  239. package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
  240. package/src/plugins/builtin/executives/index.tsx +1 -0
  241. package/src/plugins/builtin/exposure/headless.ts +3 -1
  242. package/src/plugins/builtin/fear-greed/headless.ts +2 -0
  243. package/src/plugins/builtin/filing-events/index.tsx +1 -0
  244. package/src/plugins/builtin/futures-curve/client.ts +12 -3
  245. package/src/plugins/builtin/futures-curve/headless.ts +39 -10
  246. package/src/plugins/builtin/futures-curve/index.tsx +3 -3
  247. package/src/plugins/builtin/futures-curve/model.ts +188 -4
  248. package/src/plugins/builtin/futures-curve/pane.tsx +51 -9
  249. package/src/plugins/builtin/fx-matrix/direction.ts +81 -0
  250. package/src/plugins/builtin/fx-matrix/index.tsx +71 -33
  251. package/src/plugins/builtin/fx-matrix/live-legs.ts +17 -0
  252. package/src/plugins/builtin/fx-matrix/pairs.ts +68 -14
  253. package/src/plugins/builtin/fx-matrix/settings.ts +62 -0
  254. package/src/plugins/builtin/gpu/headless.ts +7 -3
  255. package/src/plugins/builtin/gpu/ladder.tsx +26 -30
  256. package/src/plugins/builtin/gpu/model.ts +27 -1
  257. package/src/plugins/builtin/holders/beneficial-client.ts +209 -0
  258. package/src/plugins/builtin/holders/beneficial-model.ts +279 -0
  259. package/src/plugins/builtin/holders/beneficial-report.ts +126 -0
  260. package/src/plugins/builtin/holders/beneficial-view.tsx +241 -0
  261. package/src/plugins/builtin/holders/headless.ts +139 -5
  262. package/src/plugins/builtin/holders/index.tsx +10 -3
  263. package/src/plugins/builtin/holders/pane.tsx +20 -3
  264. package/src/plugins/builtin/holders/report-header.ts +95 -0
  265. package/src/plugins/builtin/holders/table-model.ts +20 -5
  266. package/src/plugins/builtin/holders/thirteenf-match.ts +29 -1
  267. package/src/plugins/builtin/holders/types.ts +2 -1
  268. package/src/plugins/builtin/insider/headless.ts +2 -0
  269. package/src/plugins/builtin/ipo-calendar/headless.ts +1 -0
  270. package/src/plugins/builtin/iv-history/headless.ts +4 -1
  271. package/src/plugins/builtin/jobs/headless.ts +1 -0
  272. package/src/plugins/builtin/jobs/index.tsx +1 -0
  273. package/src/plugins/builtin/jobs/share-bars.tsx +5 -28
  274. package/src/plugins/builtin/kelly-sizer/index.tsx +1 -0
  275. package/src/plugins/builtin/macro-day/headless.ts +2 -0
  276. package/src/plugins/builtin/market-halts/index.tsx +1 -0
  277. package/src/plugins/builtin/market-heatmap/data.ts +30 -2
  278. package/src/plugins/builtin/market-heatmap/headless.ts +135 -0
  279. package/src/plugins/builtin/market-heatmap/index.tsx +245 -81
  280. package/src/plugins/builtin/market-heatmap/live.ts +88 -0
  281. package/src/plugins/builtin/market-heatmap/model.ts +146 -0
  282. package/src/plugins/builtin/market-heatmap/portfolio.ts +50 -11
  283. package/src/plugins/builtin/market-movers/client.ts +3 -2
  284. package/src/plugins/builtin/market-movers/headless.ts +10 -1
  285. package/src/plugins/builtin/market-movers/screener.ts +18 -5
  286. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  287. package/src/plugins/builtin/members/client.ts +53 -0
  288. package/src/plugins/builtin/members/headless.ts +35 -0
  289. package/src/plugins/builtin/members/index.tsx +20 -0
  290. package/src/plugins/builtin/members/model.ts +68 -0
  291. package/src/plugins/builtin/members/pane.tsx +175 -0
  292. package/src/plugins/builtin/mna/distress/headless.ts +1 -0
  293. package/src/plugins/builtin/mna/headless.ts +1 -0
  294. package/src/plugins/builtin/mna/index.tsx +2 -1
  295. package/src/plugins/builtin/mna/pane.tsx +5 -2
  296. package/src/plugins/builtin/money-markets/headless.ts +1 -0
  297. package/src/plugins/builtin/news/headless.ts +2 -0
  298. package/src/plugins/builtin/news/wire/index.tsx +8 -1
  299. package/src/plugins/builtin/notes/cli.ts +14 -6
  300. package/src/plugins/builtin/notes/index.tsx +1 -0
  301. package/src/plugins/builtin/openfda/index.tsx +1 -0
  302. package/src/plugins/builtin/options/index.tsx +2 -1
  303. package/src/plugins/builtin/options-calculator/headless.ts +2 -0
  304. package/src/plugins/builtin/options-positioning/headless.ts +3 -0
  305. package/src/plugins/builtin/options-scenario/headless.ts +5 -0
  306. package/src/plugins/builtin/pe-band/client.ts +74 -2
  307. package/src/plugins/builtin/pe-band/headless.ts +26 -8
  308. package/src/plugins/builtin/pe-band/model.ts +102 -22
  309. package/src/plugins/builtin/pe-band/pane.tsx +34 -16
  310. package/src/plugins/builtin/pe-band/report-dates.ts +78 -0
  311. package/src/plugins/builtin/perps/client.ts +66 -5
  312. package/src/plugins/builtin/perps/equity-identity.ts +16 -0
  313. package/src/plugins/builtin/perps/equity-row.tsx +6 -4
  314. package/src/plugins/builtin/perps/headless.ts +144 -16
  315. package/src/plugins/builtin/perps/index.tsx +6 -6
  316. package/src/plugins/builtin/perps/model.ts +189 -12
  317. package/src/plugins/builtin/perps/pane.tsx +248 -47
  318. package/src/plugins/builtin/plugin-marketplace/activation.ts +19 -0
  319. package/src/plugins/builtin/plugin-marketplace/pane.tsx +2 -2
  320. package/src/plugins/builtin/plugin-marketplace/store.ts +2 -0
  321. package/src/plugins/builtin/portfolio-list/allocation.ts +245 -0
  322. package/src/plugins/builtin/portfolio-list/cached-account.ts +33 -0
  323. package/src/plugins/builtin/portfolio-list/cell-version.ts +19 -1
  324. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +328 -29
  325. package/src/plugins/builtin/portfolio-list/cli/render.ts +230 -39
  326. package/src/plugins/builtin/portfolio-list/cli/shared.ts +67 -2
  327. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +35 -31
  328. package/src/plugins/builtin/portfolio-list/column-values.ts +124 -47
  329. package/src/plugins/builtin/portfolio-list/headless.ts +98 -16
  330. package/src/plugins/builtin/portfolio-list/index.tsx +14 -3
  331. package/src/plugins/builtin/portfolio-list/live-valuation.ts +7 -5
  332. package/src/plugins/builtin/portfolio-list/mutations.ts +55 -1
  333. package/src/plugins/builtin/portfolio-list/pane/data.ts +6 -0
  334. package/src/plugins/builtin/portfolio-list/pane/index.tsx +47 -13
  335. package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +43 -2
  336. package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +48 -5
  337. package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
  338. package/src/plugins/builtin/portfolio-list/summary/index.tsx +24 -1
  339. package/src/plugins/builtin/portfolio-list/summary/totals.ts +26 -7
  340. package/src/plugins/builtin/power/headless.ts +3 -1
  341. package/src/plugins/builtin/rate-path/headless.ts +2 -0
  342. package/src/plugins/builtin/realized-vol/headless.ts +2 -0
  343. package/src/plugins/builtin/relative-rotation/headless.ts +2 -0
  344. package/src/plugins/builtin/research/analyst-headless.ts +3 -0
  345. package/src/plugins/builtin/research/events-headless.ts +2 -0
  346. package/src/plugins/builtin/research/headless.ts +2 -0
  347. package/src/plugins/builtin/research/index.tsx +1 -0
  348. package/src/plugins/builtin/research/relative-valuation-headless.ts +10 -5
  349. package/src/plugins/builtin/research/relative-valuation-model.ts +11 -3
  350. package/src/plugins/builtin/research/relative-valuation-pane.tsx +3 -3
  351. package/src/plugins/builtin/research-search/index.tsx +1 -0
  352. package/src/plugins/builtin/revenue-breakdown/headless.ts +2 -0
  353. package/src/plugins/builtin/reverse-dcf/headless.ts +2 -0
  354. package/src/plugins/builtin/risk-factors/headless.ts +2 -0
  355. package/src/plugins/builtin/scanner/flow-history.ts +2 -13
  356. package/src/plugins/builtin/scanner/headless.ts +14 -0
  357. package/src/plugins/builtin/scanner/hilo-bars.tsx +12 -70
  358. package/src/plugins/builtin/scanner/hilo-model.ts +0 -18
  359. package/src/plugins/builtin/seasonality/headless.ts +2 -0
  360. package/src/plugins/builtin/sec/command-bar-search.ts +14 -4
  361. package/src/plugins/builtin/sec/filing-content.ts +42 -17
  362. package/src/plugins/builtin/sec/forms.ts +12 -0
  363. package/src/plugins/builtin/sec/headless.ts +2 -0
  364. package/src/plugins/builtin/sectors/client.ts +1 -0
  365. package/src/plugins/builtin/sectors/headless.ts +9 -1
  366. package/src/plugins/builtin/sectors/move-bar.tsx +10 -32
  367. package/src/plugins/builtin/sectors/sector-model.ts +2 -0
  368. package/src/plugins/builtin/shared/crypto-pair.ts +14 -0
  369. package/src/plugins/builtin/shared/locked-rows.tsx +1 -1
  370. package/src/plugins/builtin/shared/report-freshness.ts +57 -0
  371. package/src/plugins/builtin/shared/research-cells.tsx +4 -9
  372. package/src/plugins/builtin/short-interest/headless.ts +2 -0
  373. package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
  374. package/src/plugins/builtin/short-volume/headless.ts +1 -0
  375. package/src/plugins/builtin/social-mentions/headless.ts +1 -0
  376. package/src/plugins/builtin/social-mentions/index.tsx +1 -1
  377. package/src/plugins/builtin/supply-chain/headless.ts +7 -1
  378. package/src/plugins/builtin/supply-chain/index.tsx +10 -1
  379. package/src/plugins/builtin/supply-chain/model.ts +27 -2
  380. package/src/plugins/builtin/supply-chain/pane.tsx +71 -32
  381. package/src/plugins/builtin/themes/headless.ts +3 -0
  382. package/src/plugins/builtin/thirteenf/headless.ts +110 -25
  383. package/src/plugins/builtin/thirteenf/index.tsx +2 -1
  384. package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
  385. package/src/plugins/builtin/ticker-detail/headless.ts +7 -1
  386. package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
  387. package/src/plugins/builtin/ticker-detail/overview/components.tsx +5 -60
  388. package/src/plugins/builtin/ticker-detail/overview/model.ts +9 -2
  389. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +1 -1
  390. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +26 -26
  391. package/src/plugins/builtin/ticker-detail/pane.tsx +1 -1
  392. package/src/plugins/builtin/ticker-detail/quote-footer.ts +7 -1
  393. package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +20 -4
  394. package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +2 -2
  395. package/src/plugins/builtin/time-sales/headless.ts +5 -1
  396. package/src/plugins/builtin/treasury-auctions/headless.ts +1 -0
  397. package/src/plugins/builtin/vol-surface/index.tsx +1 -1
  398. package/src/plugins/builtin/volatility/headless.ts +6 -1
  399. package/src/plugins/builtin/world-indices/headless.ts +2 -0
  400. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +157 -0
  401. package/src/plugins/builtin/world-venue-map/basemap.ts +214 -0
  402. package/src/plugins/builtin/world-venue-map/client.ts +45 -0
  403. package/src/plugins/builtin/world-venue-map/entity-detail.tsx +147 -0
  404. package/src/plugins/builtin/world-venue-map/entity-table.ts +59 -0
  405. package/src/plugins/builtin/world-venue-map/evidence.ts +77 -0
  406. package/src/plugins/builtin/world-venue-map/feed.ts +293 -0
  407. package/src/plugins/builtin/world-venue-map/geo-draw.tsx +248 -0
  408. package/src/plugins/builtin/world-venue-map/geo-series.ts +142 -0
  409. package/src/plugins/builtin/world-venue-map/geo-svg.tsx +447 -0
  410. package/src/plugins/builtin/world-venue-map/headless.ts +146 -0
  411. package/src/plugins/builtin/world-venue-map/ids.ts +1 -0
  412. package/src/plugins/builtin/world-venue-map/index.ts +67 -4
  413. package/src/plugins/builtin/world-venue-map/layered-pane.tsx +552 -0
  414. package/src/plugins/builtin/world-venue-map/layers.ts +348 -0
  415. package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
  416. package/src/plugins/builtin/world-venue-map/map.tsx +381 -45
  417. package/src/plugins/builtin/world-venue-map/model.ts +7 -4
  418. package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +199 -0
  419. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n00.chunk.ts +4 -0
  420. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n15.chunk.ts +4 -0
  421. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n30.chunk.ts +4 -0
  422. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n45.chunk.ts +4 -0
  423. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n60.chunk.ts +4 -0
  424. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n75.chunk.ts +4 -0
  425. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s15.chunk.ts +4 -0
  426. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s30.chunk.ts +4 -0
  427. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s60.chunk.ts +4 -0
  428. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n00.chunk.ts +4 -0
  429. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n15.chunk.ts +4 -0
  430. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n30.chunk.ts +4 -0
  431. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n45.chunk.ts +4 -0
  432. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n60.chunk.ts +4 -0
  433. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n75.chunk.ts +4 -0
  434. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s15.chunk.ts +4 -0
  435. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s30.chunk.ts +4 -0
  436. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s45.chunk.ts +4 -0
  437. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n00.chunk.ts +4 -0
  438. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n15.chunk.ts +4 -0
  439. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n30.chunk.ts +4 -0
  440. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n45.chunk.ts +4 -0
  441. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n60.chunk.ts +4 -0
  442. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n75.chunk.ts +4 -0
  443. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s15.chunk.ts +4 -0
  444. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s30.chunk.ts +4 -0
  445. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s45.chunk.ts +4 -0
  446. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s60.chunk.ts +4 -0
  447. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n00.chunk.ts +4 -0
  448. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n15.chunk.ts +4 -0
  449. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n30.chunk.ts +4 -0
  450. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n45.chunk.ts +4 -0
  451. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n60.chunk.ts +4 -0
  452. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n75.chunk.ts +4 -0
  453. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s15.chunk.ts +4 -0
  454. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s30.chunk.ts +4 -0
  455. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s60.chunk.ts +4 -0
  456. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n00.chunk.ts +4 -0
  457. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n15.chunk.ts +4 -0
  458. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n30.chunk.ts +4 -0
  459. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n45.chunk.ts +4 -0
  460. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n60.chunk.ts +4 -0
  461. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n75.chunk.ts +4 -0
  462. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s15.chunk.ts +4 -0
  463. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s30.chunk.ts +4 -0
  464. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s60.chunk.ts +4 -0
  465. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n00.chunk.ts +4 -0
  466. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n15.chunk.ts +4 -0
  467. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n30.chunk.ts +4 -0
  468. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n45.chunk.ts +4 -0
  469. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n60.chunk.ts +4 -0
  470. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n75.chunk.ts +4 -0
  471. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075s45.chunk.ts +4 -0
  472. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n00.chunk.ts +4 -0
  473. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n15.chunk.ts +4 -0
  474. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n30.chunk.ts +4 -0
  475. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n45.chunk.ts +4 -0
  476. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n60.chunk.ts +4 -0
  477. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n75.chunk.ts +4 -0
  478. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090s15.chunk.ts +4 -0
  479. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n00.chunk.ts +4 -0
  480. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n15.chunk.ts +4 -0
  481. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n30.chunk.ts +4 -0
  482. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n45.chunk.ts +4 -0
  483. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n60.chunk.ts +4 -0
  484. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n75.chunk.ts +4 -0
  485. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s15.chunk.ts +4 -0
  486. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s30.chunk.ts +4 -0
  487. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s45.chunk.ts +4 -0
  488. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n00.chunk.ts +4 -0
  489. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n15.chunk.ts +4 -0
  490. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n30.chunk.ts +4 -0
  491. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n45.chunk.ts +4 -0
  492. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n60.chunk.ts +4 -0
  493. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s15.chunk.ts +4 -0
  494. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s30.chunk.ts +4 -0
  495. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s45.chunk.ts +4 -0
  496. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n00.chunk.ts +4 -0
  497. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n15.chunk.ts +4 -0
  498. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n30.chunk.ts +4 -0
  499. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n45.chunk.ts +4 -0
  500. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n60.chunk.ts +4 -0
  501. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n75.chunk.ts +4 -0
  502. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s15.chunk.ts +4 -0
  503. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s30.chunk.ts +4 -0
  504. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s45.chunk.ts +4 -0
  505. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n00.chunk.ts +4 -0
  506. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n15.chunk.ts +4 -0
  507. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n45.chunk.ts +4 -0
  508. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n60.chunk.ts +4 -0
  509. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n75.chunk.ts +4 -0
  510. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s15.chunk.ts +4 -0
  511. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s30.chunk.ts +4 -0
  512. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s45.chunk.ts +4 -0
  513. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s60.chunk.ts +4 -0
  514. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n00.chunk.ts +4 -0
  515. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n15.chunk.ts +4 -0
  516. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n45.chunk.ts +4 -0
  517. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n60.chunk.ts +4 -0
  518. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s15.chunk.ts +4 -0
  519. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s30.chunk.ts +4 -0
  520. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s45.chunk.ts +4 -0
  521. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s60.chunk.ts +4 -0
  522. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n00.chunk.ts +4 -0
  523. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n15.chunk.ts +4 -0
  524. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n30.chunk.ts +4 -0
  525. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n45.chunk.ts +4 -0
  526. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n60.chunk.ts +4 -0
  527. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n75.chunk.ts +4 -0
  528. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s15.chunk.ts +4 -0
  529. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s30.chunk.ts +4 -0
  530. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s45.chunk.ts +4 -0
  531. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n00.chunk.ts +4 -0
  532. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n15.chunk.ts +4 -0
  533. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n30.chunk.ts +4 -0
  534. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n60.chunk.ts +4 -0
  535. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n75.chunk.ts +4 -0
  536. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s30.chunk.ts +4 -0
  537. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s60.chunk.ts +4 -0
  538. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n30.chunk.ts +4 -0
  539. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n45.chunk.ts +4 -0
  540. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n60.chunk.ts +4 -0
  541. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n75.chunk.ts +4 -0
  542. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s15.chunk.ts +4 -0
  543. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s30.chunk.ts +4 -0
  544. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s60.chunk.ts +4 -0
  545. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n00.chunk.ts +4 -0
  546. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n30.chunk.ts +4 -0
  547. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n45.chunk.ts +4 -0
  548. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n60.chunk.ts +4 -0
  549. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n75.chunk.ts +4 -0
  550. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s15.chunk.ts +4 -0
  551. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s30.chunk.ts +4 -0
  552. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s45.chunk.ts +4 -0
  553. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s60.chunk.ts +4 -0
  554. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n00.chunk.ts +4 -0
  555. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n15.chunk.ts +4 -0
  556. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n30.chunk.ts +4 -0
  557. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n45.chunk.ts +4 -0
  558. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n60.chunk.ts +4 -0
  559. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n75.chunk.ts +4 -0
  560. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s15.chunk.ts +4 -0
  561. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s30.chunk.ts +4 -0
  562. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s45.chunk.ts +4 -0
  563. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s60.chunk.ts +4 -0
  564. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n00.chunk.ts +4 -0
  565. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n15.chunk.ts +4 -0
  566. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n30.chunk.ts +4 -0
  567. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n45.chunk.ts +4 -0
  568. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n60.chunk.ts +4 -0
  569. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n75.chunk.ts +4 -0
  570. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s15.chunk.ts +4 -0
  571. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s30.chunk.ts +4 -0
  572. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s45.chunk.ts +4 -0
  573. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s60.chunk.ts +4 -0
  574. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n00.chunk.ts +4 -0
  575. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n15.chunk.ts +4 -0
  576. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n30.chunk.ts +4 -0
  577. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n45.chunk.ts +4 -0
  578. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n60.chunk.ts +4 -0
  579. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n75.chunk.ts +4 -0
  580. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105s15.chunk.ts +4 -0
  581. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n00.chunk.ts +4 -0
  582. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n15.chunk.ts +4 -0
  583. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n30.chunk.ts +4 -0
  584. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n45.chunk.ts +4 -0
  585. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n60.chunk.ts +4 -0
  586. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n75.chunk.ts +4 -0
  587. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120s30.chunk.ts +4 -0
  588. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n30.chunk.ts +4 -0
  589. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n45.chunk.ts +4 -0
  590. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n60.chunk.ts +4 -0
  591. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n75.chunk.ts +4 -0
  592. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135s30.chunk.ts +4 -0
  593. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n45.chunk.ts +4 -0
  594. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n60.chunk.ts +4 -0
  595. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s15.chunk.ts +4 -0
  596. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s30.chunk.ts +4 -0
  597. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n00.chunk.ts +4 -0
  598. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n15.chunk.ts +4 -0
  599. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n45.chunk.ts +4 -0
  600. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n60.chunk.ts +4 -0
  601. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s15.chunk.ts +4 -0
  602. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s30.chunk.ts +4 -0
  603. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n00.chunk.ts +4 -0
  604. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n15.chunk.ts +4 -0
  605. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n45.chunk.ts +4 -0
  606. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n60.chunk.ts +4 -0
  607. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s15.chunk.ts +4 -0
  608. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s30.chunk.ts +4 -0
  609. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s45.chunk.ts +4 -0
  610. package/src/plugins/builtin/world-venue-map/natural-earth/world-50m.chunk.ts +4 -0
  611. package/src/plugins/builtin/world-venue-map/pane.tsx +28 -43
  612. package/src/plugins/builtin/world-venue-map/use-geo.ts +55 -0
  613. package/src/plugins/builtin/world-venue-map/venue-header.tsx +32 -0
  614. package/src/plugins/builtin/yield-curve/headless.ts +16 -0
  615. package/src/plugins/catalog-browser.ts +2 -0
  616. package/src/plugins/catalog-manifest.ts +1 -0
  617. package/src/plugins/catalog-ui.ts +3 -1
  618. package/src/plugins/catalog.ts +1 -1
  619. package/src/plugins/host-link.ts +33 -1
  620. package/src/plugins/installer.ts +48 -12
  621. package/src/plugins/loader.ts +30 -3
  622. package/src/plugins/manager-node.ts +15 -5
  623. package/src/plugins/registry/index.ts +1 -1
  624. package/src/plugins/registry/pane-settings.ts +26 -7
  625. package/src/public/__snapshots__/public-api.test.ts.snap +2 -0
  626. package/src/renderers/dom/build-assets.ts +81 -3
  627. package/src/renderers/dom/data-table/row.tsx +52 -16
  628. package/src/renderers/dom/desktop/controls.tsx +7 -3
  629. package/src/renderers/dom/desktop/icons.tsx +1 -0
  630. package/src/renderers/dom/desktop/list-view.tsx +35 -10
  631. package/src/renderers/dom/desktop/popover.tsx +73 -14
  632. package/src/renderers/dom/host/box.tsx +69 -26
  633. package/src/renderers/dom/host/input.tsx +14 -3
  634. package/src/renderers/dom/host/tabs.tsx +37 -1
  635. package/src/renderers/dom/styles.css +41 -7
  636. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +11 -6
  637. package/src/renderers/electrobun/bun/desktop/backend.ts +1 -0
  638. package/src/renderers/electrobun/bun/desktop/update.ts +181 -87
  639. package/src/renderers/electrobun/bun/index.ts +73 -6
  640. package/src/renderers/electrobun/bun/window/remembered-frame.ts +122 -0
  641. package/src/renderers/electrobun/shared/protocol.ts +3 -0
  642. package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
  643. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +3 -1
  644. package/src/renderers/electrobun/view/main.tsx +7 -1
  645. package/src/renderers/electrobun/view/renderer-window-error.ts +18 -0
  646. package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
  647. package/src/renderers/electrobun/view/update-host.ts +45 -21
  648. package/src/renderers/opentui/host.tsx +5 -0
  649. package/src/sources/gloomberb-cloud/index.ts +25 -4
  650. package/src/sources/gloomberb-cloud/normalizers.ts +36 -5
  651. package/src/sources/provider-router/cached-routes.ts +4 -1
  652. package/src/sources/provider-router/financials.ts +11 -8
  653. package/src/sources/provider-router/history.ts +15 -10
  654. package/src/sources/sec-registrant.ts +75 -0
  655. package/src/state/app/context/index.tsx +24 -8
  656. package/src/state/hooks/quote-streaming.ts +41 -26
  657. package/src/sync/core-contributors.ts +4 -0
  658. package/src/telemetry/benign-window-error.ts +7 -0
  659. package/src/telemetry/crash-reports-dom.ts +2 -0
  660. package/src/telemetry/crash-reports.ts +4 -1
  661. package/src/test-support/cli-context.ts +10 -2
  662. package/src/test-support/daily-nav.ts +25 -0
  663. package/src/theme/heat-colors.ts +357 -2
  664. package/src/tickers/instrument-kind.ts +34 -7
  665. package/src/tickers/search/asset-classes.ts +24 -9
  666. package/src/tickers/search/index.ts +44 -11
  667. package/src/tickers/search/ranking.ts +23 -3
  668. package/src/time-series/resolve.ts +1 -1
  669. package/src/time-series/use-chart-resolution.ts +1 -1
  670. package/src/types/context-menu.ts +6 -0
  671. package/src/types/data-provider.ts +2 -0
  672. package/src/types/financials.ts +5 -0
  673. package/src/types/headless.ts +79 -2
  674. package/src/types/plugin.ts +38 -6
  675. package/src/types/ticker.ts +15 -0
  676. package/src/ui/context-menu.tsx +1 -0
  677. package/src/ui/host.tsx +16 -0
  678. package/src/updater/index.ts +38 -13
  679. package/src/utils/async-deadline.ts +21 -0
  680. package/src/utils/cli-output.ts +5 -1
  681. package/src/utils/crypto-pair.ts +41 -0
  682. package/src/utils/currency-units.ts +14 -0
  683. package/src/utils/depositary-receipt.ts +26 -0
  684. package/src/utils/exchanges.ts +72 -0
  685. package/src/utils/fire-and-forget.ts +24 -0
  686. package/src/utils/format.ts +13 -0
  687. package/src/utils/price-earnings.ts +70 -3
  688. package/src/utils/price-history.ts +58 -13
  689. package/src/utils/rpc-timeout-error.ts +27 -0
  690. package/src/utils/sec.ts +13 -1
  691. package/src/utils/utc-time.ts +79 -0
@@ -15,6 +15,7 @@ import type { RemoteUiNodeSnapshot } from "../remote/types";
15
15
  import type { DatedObservation } from "../plugins/builtin/market-valuation/series";
16
16
  import type { DesktopExternalPluginBundle } from "../renderers/electrobun/shared/protocol";
17
17
  import type { HttpProxyRequestEnvelope, HttpProxyResponseEnvelope } from "../utils/http-proxy-response";
18
+ import type { PaneAccessGate } from "./pane-functions/access-gate";
18
19
  import { readVisibleKeyValues } from "./visible-key-values";
19
20
  import { SHOT_API_PROXY_PREFIX, SHOT_HTTP_BRIDGE_PATH, SHOT_MARKET_BRIDGE_PATH } from "./desktop-pane-shot-routes";
20
21
  import { SESSION_COOKIE_NAMES } from "../api-client/session-cookie";
@@ -93,6 +94,8 @@ interface DesktopPaneShotRenderedCell {
93
94
  columnId?: string;
94
95
  columnLabel: string;
95
96
  text: string;
97
+ /** The ISO instant behind a cell whose text shortens a time ("Wed 11:27"), from the table cell's export value. */
98
+ instant?: string;
96
99
  }
97
100
 
98
101
  export interface DesktopPaneShotRenderedRow {
@@ -105,6 +108,8 @@ export interface DesktopPaneShotRenderedRow {
105
108
 
106
109
  export interface DesktopPaneShotRenderResult {
107
110
  visibleText: string;
111
+ /** Text of the pane footers, where a pane says whether its data is live, delayed or stale. */
112
+ footerText?: string;
108
113
  visibleKeyValues?: Array<{ label: string; text: string }>;
109
114
  rows: DesktopPaneShotRenderedRow[];
110
115
  truncated: boolean;
@@ -114,6 +119,8 @@ export interface DesktopPaneShotRenderResult {
114
119
  errorStateMarkers: string[];
115
120
  emptyStateDetected: boolean;
116
121
  emptyStateMarkers: string[];
122
+ /** A wall that needs an account, or a Pro lock on part of the pane. */
123
+ accessGate?: PaneAccessGate | null;
117
124
  semanticUi: RemoteUiNodeSnapshot[];
118
125
  }
119
126
 
@@ -472,14 +479,22 @@ const LOADING_STATE_PATTERNS = [
472
479
  /\bRendering pane\.{3}/gi,
473
480
  ];
474
481
 
475
- const ERROR_STATE_PATTERNS = [
476
- /\b[^.]{1,100} unavailable\./gi,
477
- /\bFailed to fetch\b/gi,
478
- /\bCould not load\b/gi,
482
+ const SIGN_IN_WALL_PATTERNS = [
479
483
  /\bSign in to\b/gi,
480
484
  /\bVerify your email\b/gi,
481
485
  /\brequires signup and email verification\b/gi,
486
+ ];
487
+
488
+ const PRO_WALL_PATTERNS = [
482
489
  /\bpart of Gloom Cloud Pro\b/gi,
490
+ ];
491
+
492
+ const ERROR_STATE_PATTERNS = [
493
+ /\b[^.]{1,100} unavailable\./gi,
494
+ /\bFailed to fetch\b/gi,
495
+ /\bCould not load\b/gi,
496
+ ...SIGN_IN_WALL_PATTERNS,
497
+ ...PRO_WALL_PATTERNS,
483
498
  /\bCloud API request failed\b/gi,
484
499
  ];
485
500
 
@@ -569,12 +584,14 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
569
584
  ) {
570
585
  truncationReasons.add("one or more cells are visibly clipped");
571
586
  }
587
+ const instant = cell.getAttribute("data-gloom-cell-instant");
572
588
  return {
573
589
  ...(typeof semanticColumn.id === "string" ? { columnId: semanticColumn.id } : {}),
574
590
  columnLabel: typeof semanticColumn.label === "string"
575
591
  ? semanticColumn.label
576
592
  : headers[cellIndex] || (values.length === 1 ? "Row" : String(cellIndex + 1)),
577
593
  text,
594
+ ...(instant ? { instant } : {}),
578
595
  };
579
596
  }).filter((cell) => cell.text.length > 0);
580
597
  if (cells.length === 0) return;
@@ -605,6 +622,10 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
605
622
  }
606
623
  return {
607
624
  visibleText: root.innerText || root.textContent || "",
625
+ footerText: [...root.querySelectorAll('[data-gloom-role="pane-footer"]')]
626
+ .map((footer) => normalize(footer.innerText || footer.textContent))
627
+ .filter(Boolean)
628
+ .join(" "),
608
629
  visibleKeyValues: (${readVisibleKeyValues.toString()})(root),
609
630
  error: window.__GLOOM_CLI_SHOT_ERROR__ || "",
610
631
  loadingStateDetected: root.querySelector('[data-gloom-status="loading"]') !== null,
@@ -612,6 +633,9 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
612
633
  // An empty sub-section off screen, such as a ticker's news list below
613
634
  // the fold, does not make the captured view empty.
614
635
  emptyStateDetected: [...root.querySelectorAll('[data-gloom-status="empty"]')].some(isVisible),
636
+ // The shared sign-in wall and the Pro lock prompt every gated pane draws.
637
+ accessGate: [...root.querySelectorAll('[data-gloom-ui="sign-in-wall"]')].some(isVisible) ? "sign-in"
638
+ : [...root.querySelectorAll('[data-gloom-ui="pro-lock"]')].some(isVisible) ? "pro" : "",
615
639
  rows,
616
640
  truncated: truncationReasons.size > 0,
617
641
  truncationReasons: [...truncationReasons],
@@ -623,11 +647,13 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
623
647
  result?: {
624
648
  value?: {
625
649
  visibleText?: string;
650
+ footerText?: string;
626
651
  visibleKeyValues?: Array<{ label: string; text: string }>;
627
652
  error?: string;
628
653
  loadingStateDetected?: boolean;
629
654
  errorStateDetected?: boolean;
630
655
  emptyStateDetected?: boolean;
656
+ accessGate?: string;
631
657
  rows?: DesktopPaneShotRenderedRow[];
632
658
  truncated?: boolean;
633
659
  truncationReasons?: string[];
@@ -641,6 +667,8 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
641
667
  const loadingStateMarkers = stateMarkers(visibleText, LOADING_STATE_PATTERNS);
642
668
  const errorStateMarkers = stateMarkers(visibleText, ERROR_STATE_PATTERNS);
643
669
  const emptyStateMarkers = stateMarkers(visibleText, EMPTY_STATE_PATTERNS);
670
+ const accessGate: PaneAccessGate | null = value?.accessGate === "sign-in" || stateMarkers(visibleText, SIGN_IN_WALL_PATTERNS).length > 0 ? "sign-in"
671
+ : value?.accessGate === "pro" || stateMarkers(visibleText, PRO_WALL_PATTERNS).length > 0 ? "pro" : null;
644
672
  const rows = Array.isArray(value?.rows) ? value.rows : [];
645
673
  const textShowsEllipsis = rows.some((row) => row.cells.some((cell) => /\u2026|\.\.\./.test(cell.text)));
646
674
  const truncationReasons = Array.isArray(value?.truncationReasons)
@@ -651,6 +679,7 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
651
679
  }
652
680
  return {
653
681
  visibleText,
682
+ footerText: typeof value?.footerText === "string" ? value.footerText : "",
654
683
  visibleKeyValues: Array.isArray(value?.visibleKeyValues) ? value.visibleKeyValues : [],
655
684
  rows,
656
685
  truncated: value?.truncated === true || textShowsEllipsis,
@@ -660,6 +689,7 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
660
689
  errorStateMarkers,
661
690
  emptyStateDetected: value?.emptyStateDetected === true || emptyStateMarkers.length > 0,
662
691
  emptyStateMarkers,
692
+ accessGate,
663
693
  semanticUi: Array.isArray(value?.semanticUi) ? value.semanticUi : [],
664
694
  };
665
695
  }
@@ -0,0 +1,61 @@
1
+ import type { FinancialStatement, Quote, TickerFinancials } from "../types/financials";
2
+ import type { HeadlessPaneFreshness, HeadlessPaneRow } from "../types/headless";
3
+ import { deriveHeadlessFreshness, type ReportFreshness } from "./pane-functions/freshness";
4
+ import { quoteFreshnessFields, REPORTED_DATA } from "../plugins/builtin/shared/report-freshness";
5
+ import { latestFinancialPeriod } from "../utils/latest-financial-period";
6
+
7
+ /**
8
+ * The source, as-of and status line of a plain CLI command, derived exactly as
9
+ * an `fn` report derives it: rows read like a headless report's rows (quote
10
+ * `dataSource`, `delayMinutes`, `stale` flags, observation times, worst of
11
+ * across rows) under what the command declares about them. Nothing to cite, no line.
12
+ */
13
+ export function rowsFreshness(
14
+ rows: readonly object[],
15
+ declared?: HeadlessPaneFreshness,
16
+ metadata?: Record<string, unknown>,
17
+ now = Date.now(),
18
+ ): ReportFreshness | undefined {
19
+ if (rows.length === 0 && !metadata && !declared) return undefined;
20
+ return deriveHeadlessFreshness(
21
+ { shape: "rows", freshness: declared },
22
+ { rows: rows as HeadlessPaneRow[], ...(metadata ? { metadata } : {}) },
23
+ now,
24
+ );
25
+ }
26
+
27
+ /** One row per quote shown, as `fn` quote reports carry them: live, delayed or stale for its session. */
28
+ function quoteFreshnessRow(quote: Quote): HeadlessPaneRow {
29
+ return { ...quoteFreshnessFields(quote), updatedAt: quote.lastUpdated };
30
+ }
31
+
32
+ /** Worst of across the quotes shown, dated by the newest. Quotes that failed to load say nothing. */
33
+ export function quotesFreshness(
34
+ quotes: Iterable<Quote | null | undefined>,
35
+ declared?: HeadlessPaneFreshness,
36
+ now = Date.now(),
37
+ ): ReportFreshness | undefined {
38
+ const rows = [...quotes].filter((quote): quote is Quote => quote != null).map(quoteFreshnessRow);
39
+ return rows.length > 0 ? rowsFreshness(rows, declared, undefined, now) : undefined;
40
+ }
41
+
42
+ /** The newest reported period end in the statements, the period the trailing figures run through. */
43
+ function latestReportedPeriod(financials: Pick<TickerFinancials, "annualStatements" | "quarterlyStatements">): string | null {
44
+ const rows: FinancialStatement[] = [...financials.annualStatements, ...financials.quarterlyStatements];
45
+ return latestFinancialPeriod(rows, (row) => row.date)?.date ?? null;
46
+ }
47
+
48
+ /**
49
+ * Fundamentals and valuation: reported figures, not a feed. Dated by when the
50
+ * statistics block was observed, with the newest statement period they run
51
+ * through named in the status; stale only when the block says so.
52
+ */
53
+ export function fundamentalsFreshness(financials: TickerFinancials, now = Date.now()): ReportFreshness {
54
+ const fundamentals = financials.fundamentals;
55
+ const period = latestReportedPeriod(financials);
56
+ return rowsFreshness([], {
57
+ ...REPORTED_DATA,
58
+ basis: period ? `reported through ${period}` : REPORTED_DATA.basis,
59
+ asOf: fundamentals?.fetchedAt ?? null,
60
+ }, { stale: fundamentals?.stale === true }, now)!;
61
+ }
package/src/cli/help.ts CHANGED
@@ -95,6 +95,7 @@ export function renderCliHelp(entries: CliHelpEntry[], version: string, descript
95
95
  ["gloomberb", "Open the terminal UI"],
96
96
  ["gloomberb <command> [args]", "Run a command and print the result"],
97
97
  ["gloomberb help <command>", "Show a command's usage, options, and examples"],
98
+ ["gloomberb ticker SAN:EPA", "Name the listing of a symbol that trades in several places (or --exchange EPA)"],
98
99
  ], { width }),
99
100
  ];
100
101
 
@@ -9,6 +9,7 @@ import { cliStyles, colorBySign } from "../utils/cli-output";
9
9
  import type { AppConfig } from "../types/config";
10
10
  import type { Watchlist, TickerRecord } from "../types/ticker";
11
11
  import { isFiniteNumber } from "../utils/guards";
12
+ import { formatUtcTime } from "../utils/utc-time";
12
13
 
13
14
  export function formatSignedCurrency(value: number, currency: string): string {
14
15
  return value > 0 ? `+${formatCurrency(value, currency)}` : formatCurrency(value, currency);
@@ -87,15 +88,10 @@ export function formatPriceRange(
87
88
  return `${format(low, { fixedFractionDigits: digits })}${separator}${format(high, { fixedFractionDigits: digits })}`;
88
89
  }
89
90
 
91
+ /** A timestamp in CLI text: UTC with the zone named, the same on every machine. */
90
92
  export function formatTimestamp(timestamp: number | undefined): string {
91
- if (!timestamp) return "—";
92
- return new Date(timestamp).toLocaleString("en-US", {
93
- month: "short",
94
- day: "numeric",
95
- year: "numeric",
96
- hour: "numeric",
97
- minute: "2-digit",
98
- });
93
+ if (!timestamp || !Number.isFinite(timestamp)) return "—";
94
+ return formatUtcTime(new Date(timestamp)) || "—";
99
95
  }
100
96
 
101
97
  export function formatBidAsk(
package/src/cli/index.ts CHANGED
@@ -23,6 +23,8 @@ import { fail, inferCliErrorOptions, printCliError } from "./errors";
23
23
  import { setCliColorEnabledOverride } from "../utils/cli-output";
24
24
  import { search, searchCandidatesForCli, buildSearchReport } from "./commands/search";
25
25
  import { ticker } from "./commands/ticker";
26
+ import { takeOption } from "./commands/command-utils";
27
+ import { EXCHANGE_OPTION } from "./listing-arg";
26
28
  import { apiCliCommand } from "./commands/api";
27
29
  import { marketDataCliCommands } from "./commands/market";
28
30
  import { overviewCliCommands } from "./commands/overview";
@@ -99,14 +101,18 @@ function createCoreCliCommands(
99
101
  help: {
100
102
  group: CLI_COMMAND_GROUPS.research,
101
103
  usage: ["ticker <symbol>"],
102
- examples: ["ticker AAPL", "ticker 7203.T", "ticker AAPL --json"],
104
+ options: [EXCHANGE_OPTION],
105
+ examples: ["ticker AAPL", "ticker SAN:EPA", "ticker 7203.T", "ticker AAPL --json"],
103
106
  },
104
- execute: async (args, ctx) => {
107
+ execute: async (rawArgs, ctx) => {
108
+ const args = [...rawArgs];
109
+ const exchange = takeOption(args, "--exchange");
105
110
  const symbol = args[0];
106
111
  if (!symbol) {
107
112
  ctx.fail("Usage: gloomberb ticker <symbol>");
108
113
  }
109
114
  await ticker(symbol!, {
115
+ exchange,
110
116
  initMarketData: ctx.initMarketData,
111
117
  fail: ctx.fail,
112
118
  ...(ctx.cliOptions.format === "text" ? {} : { printResult: ctx.printResult }),
@@ -140,9 +146,11 @@ function createCoreCliCommands(
140
146
  options: [
141
147
  { flags: "--<option> <value>", description: "A function setting; gloomberb catalog <function> lists them" },
142
148
  { flags: "--require-bot-safe", description: "Fail unless the function has a verified, complete report" },
149
+ EXCHANGE_OPTION,
143
150
  ],
144
151
  examples: [
145
152
  "fn HP AAPL",
153
+ "fn ANR SAN:EPA",
146
154
  "fn CBR --json",
147
155
  "fn 13F AAPL --view=ticker-holdings",
148
156
  "fn OVME --spot 100 --strike 100 --days 30 --volatility 25",
@@ -168,9 +176,11 @@ function createCoreCliCommands(
168
176
  { flags: "--scale <n>", description: "Text scale from 0.5 to 4 (default 1)" },
169
177
  { flags: "--watermark <label>", description: "Label drawn in the pane title bar" },
170
178
  { flags: "--<option> <value>", description: "A function setting; gloomberb catalog <function> lists them" },
179
+ EXCHANGE_OPTION,
171
180
  ],
172
181
  examples: [
173
182
  "shot TAS AAPL --output tape.png",
183
+ "shot HP BHP:ASX",
174
184
  "shot DDIS MSFT --tab history",
175
185
  "shot HP NVDA --width 1600 --theme green",
176
186
  ],
@@ -0,0 +1,321 @@
1
+ import type { DataProvider } from "../types/data-provider";
2
+ import type { Quote } from "../types/financials";
3
+ import type { CliCommandContext } from "../types/plugin";
4
+ import type { TickerRecord } from "../types/ticker";
5
+ import { AmbiguousContractError, AmbiguousTickerError, listingChoiceQuery, resolveTickerSearch } from "../tickers/search";
6
+ import { cliStyles } from "../utils/cli-output";
7
+ import {
8
+ canonicalExchange,
9
+ exchangeLabel,
10
+ isKnownExchangeCode,
11
+ parsePublicTickerKey,
12
+ publicTickerKey,
13
+ } from "../utils/exchanges";
14
+ import { withMarketData } from "./scoped-context";
15
+
16
+ /** The `--exchange` option of every command that takes a ticker. */
17
+ export const EXCHANGE_OPTION = {
18
+ flags: "--exchange <code>",
19
+ description: "Listing exchange, for a symbol that trades in several places (same as SYMBOL:CODE)",
20
+ };
21
+
22
+ export class ListingArgError extends Error {
23
+ constructor(message: string, readonly details?: string) {
24
+ super(message);
25
+ this.name = "ListingArgError";
26
+ }
27
+ }
28
+
29
+ export interface ListingArg {
30
+ /** The symbol without a venue: SAN. */
31
+ symbol: string;
32
+ /** The canonical code of the exchange the user named, or "" when none was. */
33
+ exchange: string;
34
+ /** SAN:EPA, or SAN when no exchange was named. */
35
+ key: string;
36
+ }
37
+
38
+ /**
39
+ * `SAN:EPA` and `SAN --exchange EPA` name the same listing. Both spellings of
40
+ * an exchange go through the app's alias table, so `SAN:XPAR` is `SAN:EPA`.
41
+ * A symbol's own exchange and `--exchange` that disagree are an error, unless
42
+ * the command takes several symbols and `--exchange` only fills in the ones
43
+ * without an exchange of their own.
44
+ */
45
+ export function parseListingArg(
46
+ raw: string,
47
+ exchangeOption?: string | null,
48
+ { ownExchangeWins = false }: { ownExchangeWins?: boolean } = {},
49
+ ): ListingArg {
50
+ const option = canonicalExchange(exchangeOption ?? "");
51
+ let typed = raw.trim().replace(/^\$/, "").toUpperCase();
52
+ // `SAN:` asks which listing; with --exchange it has its answer.
53
+ if (option && typed.endsWith(":")) typed = typed.slice(0, -1);
54
+ const parsed = parsePublicTickerKey(typed);
55
+ if (parsed.exchange && option && parsed.exchange !== option && !ownExchangeWins) {
56
+ throw new ListingArgError(
57
+ `${typed} names exchange ${parsed.exchange}, but --exchange names ${option}.`,
58
+ `Name the exchange once, as ${parsed.symbol}:${parsed.exchange} or ${parsed.symbol} --exchange ${option}.`,
59
+ );
60
+ }
61
+ const exchange = parsed.exchange ?? option;
62
+ return { symbol: parsed.symbol, exchange, key: exchange ? `${parsed.symbol}:${exchange}` : parsed.symbol };
63
+ }
64
+
65
+ interface ListingStore {
66
+ loadTicker(symbol: string): Promise<TickerRecord | null>;
67
+ loadAllTickers(): Promise<TickerRecord[]>;
68
+ }
69
+
70
+ export interface ListingDeps {
71
+ store: ListingStore;
72
+ dataProvider: DataProvider;
73
+ }
74
+
75
+ export interface ListingVenue {
76
+ /** Canonical code. */
77
+ exchange: string;
78
+ name: string;
79
+ }
80
+
81
+ /**
82
+ * The venues a symbol trades on and the company on each, from the same
83
+ * listing picker the command bar opens for `SAN:`.
84
+ */
85
+ export async function listingVenues(symbol: string, { store, dataProvider }: ListingDeps): Promise<ListingVenue[]> {
86
+ const query = `${symbol}:`;
87
+ if (!listingChoiceQuery(query)) return [];
88
+ const tickers = new Map((await store.loadAllTickers()).map((ticker) => [ticker.metadata.ticker.toUpperCase(), ticker] as const));
89
+ let venues: ListingVenue[];
90
+ try {
91
+ const resolved = await resolveTickerSearch({ query, activeTicker: null, tickers, dataProvider });
92
+ const only = !resolved ? null
93
+ : resolved.kind === "local" ? { exchange: resolved.ticker.metadata.exchange, name: resolved.ticker.metadata.name }
94
+ : {
95
+ exchange: resolved.result.exchange === "SMART" ? resolved.result.primaryExchange ?? "" : resolved.result.exchange || resolved.result.primaryExchange || "",
96
+ name: resolved.result.name,
97
+ };
98
+ venues = only?.exchange ? [{ exchange: canonicalExchange(only.exchange), name: only.name }] : [];
99
+ } catch (error) {
100
+ // One listing settles the picker; several are its choices.
101
+ if (!(error instanceof AmbiguousTickerError) || error instanceof AmbiguousContractError) return [];
102
+ venues = error.listings.flatMap((listing) => {
103
+ const exchange = parsePublicTickerKey(listing).exchange;
104
+ return exchange ? [{ exchange, name: error.listingNames[listing] ?? "" }] : [];
105
+ });
106
+ }
107
+ return venues.filter((venue, index) => venues.findIndex((other) => other.exchange === venue.exchange) === index);
108
+ }
109
+
110
+ function tradesOn(symbol: string, venues: readonly ListingVenue[]): string {
111
+ return venues.length > 0 ? ` ${symbol} trades on: ${venues.map((venue) => venue.exchange).join(", ")}.` : "";
112
+ }
113
+
114
+ /**
115
+ * An exchange code the app does not know is accepted only when the symbol is
116
+ * listed there, so a typo never falls back to another venue's line.
117
+ */
118
+ async function checkListingExchange(listing: ListingArg, deps: ListingDeps): Promise<void> {
119
+ if (listing.symbol.endsWith(":")) {
120
+ const symbol = listing.symbol.slice(0, -1);
121
+ throw new ListingArgError(`Choose an exchange for ${symbol}.${tradesOn(symbol, await listingVenues(symbol, deps))}`);
122
+ }
123
+ if (!listing.exchange || isKnownExchangeCode(listing.exchange)) return;
124
+ const venues = await listingVenues(listing.symbol, deps);
125
+ if (venues.some((venue) => venue.exchange === listing.exchange)) return;
126
+ throw new ListingArgError(
127
+ `Unknown exchange ${listing.exchange} for ${listing.symbol}.${tradesOn(listing.symbol, venues)}`,
128
+ venues.length > 0 ? undefined : `No listings of ${listing.symbol} were found.`,
129
+ );
130
+ }
131
+
132
+ /**
133
+ * "SAN does not trade on TSX. SAN trades on: NYSE, EPA." for a listing whose
134
+ * exchange the symbol is not listed on, from the same picker `SAN:` opens.
135
+ * Null when no exchange was named, when the symbol is listed there, or when its
136
+ * venues cannot be found, so the request's own failure stands. It searches, so
137
+ * ask only after a request came back empty.
138
+ */
139
+ export async function notTradedMessage(
140
+ listing: Pick<ListingArg, "symbol" | "exchange">,
141
+ deps: ListingDeps,
142
+ ): Promise<string | null> {
143
+ if (!listing.exchange) return null;
144
+ const venues = await listingVenues(listing.symbol, deps).catch(() => []);
145
+ if (venues.length === 0 || venues.some((venue) => venue.exchange === listing.exchange)) return null;
146
+ return `${listing.symbol} does not trade on ${listing.exchange}.${tradesOn(listing.symbol, venues)}`;
147
+ }
148
+
149
+ /** Fails the command with `notTradedMessage`; returns when the symbol does trade there. */
150
+ export async function failIfNotTraded(
151
+ listing: Pick<ListingArg, "symbol" | "exchange">,
152
+ deps: ListingDeps,
153
+ ctx: Pick<CliCommandContext, "fail">,
154
+ ): Promise<void> {
155
+ const message = await notTradedMessage(listing, deps);
156
+ if (message) ctx.fail(message);
157
+ }
158
+
159
+ /**
160
+ * A data request for the listings a command named. When it throws, or `isMiss`
161
+ * calls what it returned empty, and a listing's exchange is one its symbol does
162
+ * not trade on, the command ends in that message instead of the request's own
163
+ * "unavailable". A request that succeeds costs no extra lookup.
164
+ */
165
+ export async function loadForListing<T>(
166
+ listings: Pick<ListingArg, "symbol" | "exchange"> | readonly Pick<ListingArg, "symbol" | "exchange">[],
167
+ deps: ListingDeps,
168
+ ctx: Pick<CliCommandContext, "fail">,
169
+ load: () => Promise<T>,
170
+ isMiss?: (value: T) => boolean,
171
+ ): Promise<T> {
172
+ const named = ("symbol" in listings ? [listings] : listings).filter((listing) => listing.exchange);
173
+ const checkVenues = () => Promise.all(named.map((listing) => failIfNotTraded(listing, deps, ctx)));
174
+ let value: T;
175
+ try {
176
+ value = await load();
177
+ } catch (error) {
178
+ await checkVenues();
179
+ throw error;
180
+ }
181
+ if (isMiss?.(value)) await checkVenues();
182
+ return value;
183
+ }
184
+
185
+ /** The saved ticker for a listing: under its own key, or a saved symbol whose venue it is. */
186
+ export async function loadSavedListing(store: ListingStore, listing: ListingArg): Promise<TickerRecord | null> {
187
+ if (!listing.exchange) return store.loadTicker(listing.symbol);
188
+ for (const key of new Set([listing.key, publicTickerKey(listing.symbol, listing.exchange), listing.symbol])) {
189
+ const ticker = await store.loadTicker(key);
190
+ if (ticker && (key === listing.key || canonicalExchange(ticker.metadata.exchange) === listing.exchange)) return ticker;
191
+ }
192
+ return null;
193
+ }
194
+
195
+ export interface CliListing extends ListingArg {
196
+ saved: TickerRecord | null;
197
+ /**
198
+ * What data requests take: a named listing goes by its key (SAN:EPA), never
199
+ * the bare symbol's cache; a bare symbol goes on its saved venue, as the
200
+ * command bar opens it.
201
+ */
202
+ request: { symbol: string; exchange: string };
203
+ }
204
+
205
+ export async function resolveCliListing(
206
+ raw: string,
207
+ exchangeOption: string | null | undefined,
208
+ deps: ListingDeps,
209
+ options: { ownExchangeWins?: boolean } = {},
210
+ ): Promise<CliListing> {
211
+ const listing = parseListingArg(raw, exchangeOption, options);
212
+ if (!listing.symbol) throw new ListingArgError("Ticker symbol is required.");
213
+ await checkListingExchange(listing, deps);
214
+ const saved = await loadSavedListing(deps.store, listing);
215
+ return {
216
+ ...listing,
217
+ saved,
218
+ request: listing.exchange
219
+ ? { symbol: listing.key, exchange: listing.exchange }
220
+ : { symbol: listing.symbol, exchange: saved?.metadata.exchange ?? "" },
221
+ };
222
+ }
223
+
224
+ /** `resolveCliListing` for a command: a bad exchange fails the command with its message. */
225
+ export async function requireCliListing(
226
+ raw: string,
227
+ exchangeOption: string | null | undefined,
228
+ deps: ListingDeps,
229
+ ctx: Pick<CliCommandContext, "fail">,
230
+ options: { ownExchangeWins?: boolean } = {},
231
+ ): Promise<CliListing> {
232
+ try {
233
+ return await resolveCliListing(raw, exchangeOption, deps, options);
234
+ } catch (error) {
235
+ if (error instanceof ListingArgError) ctx.fail(error.message, error.details);
236
+ throw error;
237
+ }
238
+ }
239
+
240
+ /**
241
+ * The listing for commands that store things by symbol (notes, alerts). The
242
+ * data sources are only opened to check an exchange the app does not know.
243
+ */
244
+ export async function requireListingArg(
245
+ raw: string,
246
+ exchangeOption: string | null | undefined,
247
+ ctx: Pick<CliCommandContext, "fail" | "initMarketData">,
248
+ ): Promise<ListingArg> {
249
+ try {
250
+ const listing = parseListingArg(raw, exchangeOption);
251
+ if (listing.symbol.endsWith(":") || (listing.exchange && !isKnownExchangeCode(listing.exchange))) {
252
+ await withMarketData(ctx, (market) => checkListingExchange(listing, market));
253
+ }
254
+ return listing;
255
+ } catch (error) {
256
+ if (error instanceof ListingArgError) ctx.fail(error.message, error.details);
257
+ throw error;
258
+ }
259
+ }
260
+
261
+ export interface ListingIdentity {
262
+ symbol: string;
263
+ /** Canonical code of the venue the data is for. */
264
+ exchange: string;
265
+ /** The listing's company, from its own quote. */
266
+ name: string | null;
267
+ }
268
+
269
+ export function listingIdentity(
270
+ listing: CliListing,
271
+ quote?: Pick<Quote, "name" | "listingExchangeName" | "exchangeName"> | null,
272
+ ): ListingIdentity {
273
+ const quoteExchange = canonicalExchange(quote?.listingExchangeName || quote?.exchangeName);
274
+ const exchange = listing.exchange || quoteExchange || canonicalExchange(listing.saved?.metadata.exchange);
275
+ // A quote that prices another venue names another listing's company.
276
+ const quoteName = !quoteExchange || quoteExchange === exchange ? quote?.name?.trim() : undefined;
277
+ return { symbol: listing.symbol, exchange, name: quoteName || listing.saved?.metadata.name?.trim() || null };
278
+ }
279
+
280
+ /** The listing's own quote, for its company name and venue; null when it has none. */
281
+ export async function loadListingQuote(dataProvider: DataProvider, listing: CliListing): Promise<Quote | null> {
282
+ try {
283
+ return await dataProvider.getQuote(listing.request.symbol, listing.request.exchange);
284
+ } catch {
285
+ return null;
286
+ }
287
+ }
288
+
289
+ /** One line above a table naming what it is about: "Sanofi · Euronext Paris (EPA)". */
290
+ export function listingHeading(identity: ListingIdentity): string {
291
+ const venue = identity.exchange ? cliStyles.muted(` · ${exchangeLabel(identity.exchange)}`) : "";
292
+ return `${cliStyles.bold(identity.name || identity.symbol)}${venue}`;
293
+ }
294
+
295
+ /** "Sanofi (EPA)", for sentences. */
296
+ export function listingTitle(identity: ListingIdentity): string {
297
+ const name = identity.name || identity.symbol;
298
+ return identity.exchange ? `${name} (${identity.exchange})` : name;
299
+ }
300
+
301
+ export interface SavedListingName {
302
+ symbol: string;
303
+ /** Canonical code of the venue the row is saved for, or "" when it has none. */
304
+ exchange: string;
305
+ /** SAN:EPA, whichever way the row is stored (SAN, SAN:XNYS). */
306
+ key: string;
307
+ name: string | null;
308
+ /** "SAN:EPA (Sanofi)", for sentences. */
309
+ label: string;
310
+ }
311
+
312
+ /** The listing a saved ticker row is, as a collection command names it after adding or removing it. */
313
+ export function savedListingName(ticker: TickerRecord): SavedListingName {
314
+ const { symbol } = parsePublicTickerKey(ticker.metadata.ticker);
315
+ const exchange = canonicalExchange(ticker.metadata.exchange);
316
+ const key = exchange ? `${symbol}:${exchange}` : symbol;
317
+ // A row saved without a company carries its symbol as the name.
318
+ const typed = ticker.metadata.name?.trim();
319
+ const name = typed && typed !== symbol && typed !== ticker.metadata.ticker ? typed : null;
320
+ return { symbol, exchange, key, name, label: name ? `${key} (${name})` : key };
321
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * What keeps a pane from showing everything it has: a Pro lock on part of it,
3
+ * or a wall that needs an account. Reports and screenshots name it, so a
4
+ * failure says "locked" instead of a generic incomplete or empty.
5
+ */
6
+ export type PaneAccessGate = "pro" | "sign-in";
7
+
8
+ // A Pro-gated loader reports what is locked in its errors ("Full history requires Gloom Pro").
9
+ const SIGN_IN_ERROR = /\bsign(?:ed)?[ -]?in\b|\bsignup\b|\bemail verification\b|\bverify your email\b/i;
10
+ const PRO_ERROR = /\bGloom (?:Cloud )?Pro\b|\b(?:requires?|needs?) Pro\b|\bPro access\b/;
11
+
12
+ function errorMessages(errors: unknown): string[] {
13
+ return Array.isArray(errors) ? errors.filter((error): error is string => typeof error === "string") : [];
14
+ }
15
+
16
+ /** Why the output cannot be used as it is, as a clause: "some values need Gloom Cloud Pro (locked)". */
17
+ function accessGateReason(gate: PaneAccessGate): string {
18
+ return gate === "pro" ? "some values need Gloom Cloud Pro (locked)" : "it needs a Gloom Cloud sign-in";
19
+ }
20
+
21
+ /** The reason as a sentence, for a screenshot's "Reason" row. */
22
+ export function accessGateSentence(gate: PaneAccessGate): string {
23
+ const reason = accessGateReason(gate);
24
+ return `${reason.charAt(0).toUpperCase()}${reason.slice(1)}.`;
25
+ }
26
+
27
+ /** The word a screenshot's status line uses in place of "empty" for a gated pane. */
28
+ export function accessGateStatus(gate: PaneAccessGate): string {
29
+ return gate === "pro" ? "locked" : "needs sign-in";
30
+ }
31
+
32
+ /**
33
+ * The failure for an incomplete report whose own errors name a gate, with
34
+ * those errors saying which values; null when they name none.
35
+ */
36
+ export function incompleteReportGateMessage(token: string, errors: unknown): string | null {
37
+ const messages = errorMessages(errors);
38
+ const gate = messages.some((message) => SIGN_IN_ERROR.test(message)) ? "sign-in"
39
+ : messages.some((message) => PRO_ERROR.test(message)) ? "pro" : null;
40
+ const detail = messages.map((message) => message.replace(/\.+$/, "")).join(". ");
41
+ return gate ? `${token} is not bot-safe: ${accessGateReason(gate)}. ${detail}.` : null;
42
+ }