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
@@ -1,4 +1,5 @@
1
1
  import { getSharedRegistry } from "../../plugins/registry";
2
+ import { findCachedPortfolioAccount } from "../../plugins/builtin/portfolio-list/cached-account";
2
3
  import { parsePublicTickerKey } from "../../utils/exchanges";
3
4
  import { apiClient } from "../../api-client";
4
5
  import type { MarketContext } from "../types";
@@ -24,6 +25,8 @@ import type { ResolvedSeries } from "../../time-series/types";
24
25
  import type { PaneFunctionReport } from "./report";
25
26
  import type { ResolvedPaneFunction } from "./resolver";
26
27
  import { isRecord } from "../../utils/guards";
28
+ import { formatUtcTime } from "../../utils/utc-time";
29
+ import { deriveHeadlessFreshness, formatFreshnessLine, type ReportFreshness } from "./freshness";
27
30
 
28
31
  interface SerializableHeadlessColumn {
29
32
  key: string;
@@ -149,7 +152,9 @@ async function loadHeadlessPaneModel(
149
152
  */
150
153
  export async function loadResolvedHeadlessPaneModel(
151
154
  resolved: ResolvedPaneFunction,
152
- context: Pick<MarketContext, "config" | "store" | "refresh"> & { dataProvider: HeadlessPaneContext["marketData"] },
155
+ context: Pick<MarketContext, "config" | "store" | "refresh"> & Partial<Pick<MarketContext, "persistence">> & {
156
+ dataProvider: HeadlessPaneContext["marketData"];
157
+ },
153
158
  rawArgument: string,
154
159
  signal: AbortSignal = new AbortController().signal,
155
160
  ): Promise<LoadedHeadlessPaneModel> {
@@ -168,7 +173,7 @@ export async function loadResolvedHeadlessPaneModel(
168
173
  const portfolio = context.config.portfolios.find(row => row.id === id);
169
174
  if (!portfolio) return null;
170
175
  const tickers = (await context.store.loadAllTickers()).filter(row => row.metadata.portfolios.includes(id));
171
- return { portfolio, tickers };
176
+ return { portfolio, tickers, account: findCachedPortfolioAccount(context.config, portfolio, context.persistence?.resources) };
172
177
  },
173
178
  async resolveWatchlist(id) {
174
179
  if (!context.config.watchlists.some(row => row.id === id)) return null;
@@ -244,6 +249,7 @@ export function serializeHeadlessPaneResult(
244
249
  ): Record<string, unknown> {
245
250
  const common = {
246
251
  ...(result.errors ? { errors: result.errors } : {}),
252
+ ...(result.notes?.length ? { notes: result.notes } : {}),
247
253
  ...(result.metadata ? { metadata: result.metadata } : {}),
248
254
  };
249
255
  switch (definition.shape) {
@@ -326,8 +332,7 @@ function float32Shortest(value: number): number | null {
326
332
 
327
333
  function displayTime(time: number): string {
328
334
  if (!Number.isFinite(time)) return "-";
329
- const iso = new Date(time).toISOString();
330
- return iso.endsWith("T00:00:00.000Z") ? iso.slice(0, 10) : `${iso.slice(0, 16).replace("T", " ")} UTC`;
335
+ return formatUtcTime(new Date(time));
331
336
  }
332
337
 
333
338
  const CALENDAR_RESOLUTIONS = new Set(["1d", "1wk", "1mo"]);
@@ -339,7 +344,7 @@ function seriesPointDate(series: HeadlessSeries, date: HeadlessSeries["points"][
339
344
  const resolved = series as HeadlessSeries & Partial<Pick<ResolvedSeries, "historyResolution" | "timeBasis">>;
340
345
  return resolved.historyResolution && CALENDAR_RESOLUTIONS.has(resolved.historyResolution)
341
346
  ? observationDate(time, resolved)
342
- : displayTime(time);
347
+ : formatUtcTime({ time, dateOnly: typeof date === "string" && /^\d{4}-\d{2}-\d{2}$/.test(date) });
343
348
  }
344
349
 
345
350
  function seriesValue(series: HeadlessSeries, value: number | null): string {
@@ -415,18 +420,36 @@ function renderSeries(result: HeadlessSeriesResult): string[] {
415
420
  return lines;
416
421
  }
417
422
 
418
- function reportTitle(definition: HeadlessPaneDefinition, args: HeadlessPaneLoadArgs, fallback: string): string {
419
- if (typeof definition.describe === "function") return definition.describe(args);
423
+ function reportTitle(
424
+ definition: HeadlessPaneDefinition,
425
+ args: HeadlessPaneLoadArgs,
426
+ result: HeadlessPaneResult,
427
+ fallback: string,
428
+ ): string {
429
+ if (typeof definition.describe === "function") return definition.describe(args, result);
420
430
  return definition.describe ?? fallback;
421
431
  }
422
432
 
433
+ /** One message stays on the label's line; several each get a line of their own, so none runs into the next. */
434
+ function renderMessages(label: string, messages: readonly string[]): string[] {
435
+ return messages.length === 1
436
+ ? [cliStyles.warning(`${label}: ${messages[0]}`)]
437
+ : [cliStyles.warning(`${label}:`), ...messages.map((message) => ` ${message}`)];
438
+ }
439
+
440
+ /**
441
+ * The text form of every headless report. It always ends with the source,
442
+ * as-of and status line, so no pane can leave it out; a pane can only make it
443
+ * more accurate through its `freshness` declaration.
444
+ */
423
445
  export function renderHeadlessPaneText(
424
446
  definition: HeadlessPaneDefinition,
425
447
  result: HeadlessPaneResult,
426
448
  args: HeadlessPaneLoadArgs,
427
449
  fallbackTitle: string,
450
+ freshness: ReportFreshness = deriveHeadlessFreshness(definition, result),
428
451
  ): string {
429
- const lines = [cliStyles.bold(reportTitle(definition, args, fallbackTitle)), ""];
452
+ const lines = [cliStyles.bold(reportTitle(definition, args, result, fallbackTitle)), ""];
430
453
  const notices = result.metadata?.notices;
431
454
  if (Array.isArray(notices)) {
432
455
  const textNotices = [...new Set(notices.filter((notice): notice is string => typeof notice === "string" && notice.trim().length > 0))];
@@ -446,7 +469,8 @@ export function renderHeadlessPaneText(
446
469
  break;
447
470
  case "snapshot": {
448
471
  const snapshot = result as HeadlessSnapshotResult;
449
- lines.push(`As of: ${displayValue(snapshot.asOf)}`, "", renderRows(snapshot.items, undefined, definition.columns));
472
+ // The closing source line carries the snapshot's as-of, so it is not printed twice.
473
+ lines.push(renderRows(snapshot.items, undefined, definition.columns));
450
474
  break;
451
475
  }
452
476
  default: {
@@ -454,8 +478,9 @@ export function renderHeadlessPaneText(
454
478
  return _exhaustive;
455
479
  }
456
480
  }
457
- if (result.errors?.length) lines.push("", cliStyles.warning(`Errors: ${result.errors.join(" ")}`));
458
- return lines.join("\n").trimEnd();
481
+ if (result.notes?.length) lines.push("", ...renderMessages("Notes", result.notes));
482
+ if (result.errors?.length) lines.push("", ...renderMessages("Errors", result.errors));
483
+ return [lines.join("\n").trimEnd(), "", cliStyles.muted(formatFreshnessLine(freshness))].join("\n");
459
484
  }
460
485
 
461
486
  function resultRowCount(definition: HeadlessPaneDefinition, result: HeadlessPaneResult): number {
@@ -487,6 +512,7 @@ export async function buildHeadlessFunctionReport(
487
512
  const symbols = loaded.result.symbols ?? loaded.args.symbols;
488
513
  const unavailableSymbols = loaded.result.unavailableSymbols ?? (rowCount === 0 ? symbols : []);
489
514
  const serialized = serializeHeadlessPaneResult(loaded.definition, loaded.result);
515
+ const freshness = deriveHeadlessFreshness(loaded.definition, loaded.result);
490
516
  return {
491
517
  data: {
492
518
  kind: loaded.definition.shape,
@@ -499,12 +525,14 @@ export async function buildHeadlessFunctionReport(
499
525
  complete: loaded.result.complete !== false && unavailableSymbols.length === 0 && !loaded.result.errors?.length,
500
526
  unavailableSymbols,
501
527
  ...serialized,
528
+ freshness,
502
529
  },
503
530
  text: renderHeadlessPaneText(
504
531
  loaded.definition,
505
532
  loaded.result,
506
533
  loaded.args,
507
534
  resolved.label,
535
+ freshness,
508
536
  ),
509
537
  };
510
538
  }
@@ -14,13 +14,15 @@ import {
14
14
  parsePaneFunctionArgs,
15
15
  type ParsedPaneFunctionArgs,
16
16
  } from "./options";
17
- import { resolvePaneFunction, type ResolvedPaneFunction } from "./resolver";
17
+ import { applyListingArgument, resolvePaneFunction, type ResolvedPaneFunction } from "./resolver";
18
18
  import { buildFunctionReport } from "./report";
19
19
  import { defaultScreenshotPath, renderDesktopShot } from "./screenshot";
20
20
  import {
21
21
  buildPaneCatalogEntries,
22
22
  } from "./catalog";
23
+ import { accessGateStatus, incompleteReportGateMessage } from "./access-gate";
23
24
  import { withPersistedCloudSession } from "./cloud-session";
25
+ import { loadForListing } from "../listing-arg";
24
26
 
25
27
  async function withPaneRuntime<T>(
26
28
  ctx: CliCommandContext,
@@ -33,11 +35,11 @@ async function withPaneRuntime<T>(
33
35
  }) => Promise<T>,
34
36
  settings: { strictHeadlessOptions?: boolean } = {},
35
37
  ): Promise<T> {
36
- const parsed = parsePaneFunctionArgs(args, ctx.cliOptions);
37
38
  return withMarketData(ctx, async (market) => {
38
39
  const context: MarketContext = ctx.cliOptions.refresh ? { ...market, refresh: true } : market;
39
40
  const registry = await createPaneCatalog(context, ctx.plugins);
40
41
  try {
42
+ const parsed = await applyListingArgument(registry, context, parsePaneFunctionArgs(args, ctx.cliOptions));
41
43
  const resolved = await resolvePaneFunction(registry, context, parsed, settings);
42
44
  return await run({ parsed, context, registry, resolved });
43
45
  } finally {
@@ -57,14 +59,23 @@ export async function runPaneFunction(args: string[], ctx: CliCommandContext) {
57
59
  + `Use "gloomberb catalog ${resolved.token}" to inspect readiness.`,
58
60
  );
59
61
  }
62
+ // A report that fails or comes back empty for an exchange the symbol is not listed on says so.
60
63
  const report = await withPersistedCloudSession(
61
64
  context,
62
- () => buildFunctionReport(resolved, context, parsed.arg),
65
+ () => loadForListing(
66
+ parsed.listing ?? [],
67
+ context,
68
+ ctx,
69
+ () => buildFunctionReport(resolved, context, parsed.arg),
70
+ (built) => built.data.empty || !built.data.complete,
71
+ ),
63
72
  );
64
73
  if (parsed.requireBotSafe && (report.data.empty || !report.data.complete)) {
65
74
  const unavailable = report.data.unavailableSymbols.length > 0
66
75
  ? ` Missing data for ${report.data.unavailableSymbols.join(", ")}.`
67
76
  : "";
77
+ const gated = incompleteReportGateMessage(resolved.token, report.data.errors);
78
+ if (gated) throw new Error(gated);
68
79
  throw new Error(
69
80
  `${resolved.token} did not produce a complete bot-safe report.${unavailable}`,
70
81
  );
@@ -110,7 +121,7 @@ export async function runPaneScreenshot(args: string[], ctx: CliCommandContext)
110
121
  ctx.printResult({ data: result }, {
111
122
  text: (data) => {
112
123
  const issues = [
113
- data.empty ? "empty" : null,
124
+ data.render.accessGate && (data.empty || !data.usable) ? accessGateStatus(data.render.accessGate) : data.empty ? "empty" : null,
114
125
  data.complete ? null : "incomplete",
115
126
  data.semanticMismatch ? "does not match the data" : null,
116
127
  data.usable ? null : "not usable",
@@ -9,6 +9,7 @@ import {
9
9
  } from "../../plugins/builtin/ticker-detail/financials/ratios";
10
10
  import type { PaneRuntimeState } from "../../core/state/app/state";
11
11
  import type { NormalizedPaneFunctionOptions } from "./capabilities";
12
+ import type { ListingArg } from "../listing-arg";
12
13
 
13
14
  const DEFAULT_SHOT_WIDTH = 1280;
14
15
  const DEFAULT_SHOT_HEIGHT = 720;
@@ -32,6 +33,8 @@ export interface ParsedPaneFunctionArgs {
32
33
  /** Small label drawn in the pane title bar, e.g. a domain; null draws nothing. */
33
34
  watermark: string | null;
34
35
  requireBotSafe: boolean;
36
+ /** The listing a one-ticker function's argument named, once `applyListingArgument` has resolved it. */
37
+ listing?: ListingArg;
35
38
  }
36
39
 
37
40
  export interface ParsedPaneCatalogArgs {
@@ -3,6 +3,7 @@ import type { NormalizedPaneFunctionOptions } from "./capabilities";
3
3
  import type { ResolvedPaneFunction } from "./resolver";
4
4
  import { buildHeadlessFunctionReport } from "./headless";
5
5
  import { appendDomReportFooter, buildDomFunctionReport } from "./dom";
6
+ import type { ReportFreshness } from "./freshness";
6
7
 
7
8
  export type PaneFunctionReportSource = "headless" | "dom";
8
9
 
@@ -20,6 +21,8 @@ interface PaneFunctionReportData {
20
21
  empty: boolean;
21
22
  complete: boolean;
22
23
  unavailableSymbols: string[];
24
+ /** Source, as-of in UTC and live/delayed/stale/not-a-feed status; the last line of the text report. */
25
+ freshness: ReportFreshness;
23
26
  [key: string]: unknown;
24
27
  }
25
28
 
@@ -56,6 +59,7 @@ export async function buildFunctionReport(
56
59
  report.text,
57
60
  elapsedMs,
58
61
  report.data.truncated === true,
62
+ report.data.freshness,
59
63
  );
60
64
  }
61
65
  return report;
@@ -10,6 +10,7 @@ import { applyChartComposerCapabilityOptions } from "../../plugins/builtin/chart
10
10
  import { parseChartSpec } from "../../plugins/builtin/chart-composer/chart-spec";
11
11
  import { normalizeTickerInput } from "../../tickers/search";
12
12
  import { slugifyName } from "../../utils/slugify";
13
+ import { resolveCliListing } from "../listing-arg";
13
14
  import type { MarketContext } from "../types";
14
15
  import {
15
16
  buildPaneFunctionLookup,
@@ -94,6 +95,37 @@ async function buildPaneInstance(
94
95
  };
95
96
  }
96
97
 
98
+ function findPaneFunction(registry: PaneFunctionCatalog, target: string): { template?: PaneTemplateDef; pane?: PaneDef } | null {
99
+ const entry = buildPaneFunctionLookup(registry).get(normalizeLookupToken(target));
100
+ if (!entry) return null;
101
+ const template = "paneId" in entry && "description" in entry ? entry as PaneTemplateDef : undefined;
102
+ return { template, pane: template ? registry.panes.get(template.paneId) : entry as PaneDef };
103
+ }
104
+
105
+ /**
106
+ * `fn ANR SAN --exchange EPA` is `fn ANR SAN:EPA`: a function that takes one
107
+ * ticker gets the listing in its argument, and an exchange the app does not
108
+ * know fails with the venues the symbol trades on.
109
+ */
110
+ export async function applyListingArgument(
111
+ registry: PaneFunctionCatalog,
112
+ context: MarketContext,
113
+ args: ParsedPaneFunctionArgs,
114
+ ): Promise<ParsedPaneFunctionArgs> {
115
+ const found = args.target ? findPaneFunction(registry, args.target) : null;
116
+ if (!found?.pane || !args.arg || /\s/.test(args.arg)) return args;
117
+ const headless = getHeadlessPaneDefinition(found.template, found.pane);
118
+ const takesOneTicker = headless ? headless.argument.kind === "ticker" : found.template?.shortcut?.argKind === "ticker";
119
+ // A function with an exchange option of its own (DIST) keeps it.
120
+ if (!takesOneTicker || getPaneFunctionCapability(found.template, found.pane).options.some((option) => option.key === "exchange")) {
121
+ return args;
122
+ }
123
+ const exchange = typeof args.options.exchange === "string" ? args.options.exchange : undefined;
124
+ const listing = await resolveCliListing(args.arg, exchange, context);
125
+ const { exchange: _exchange, ...options } = args.options;
126
+ return { ...args, arg: listing.key, options, listing };
127
+ }
128
+
97
129
  export async function resolvePaneFunction(
98
130
  registry: PaneFunctionCatalog,
99
131
  context: MarketContext,
@@ -104,9 +136,8 @@ export async function resolvePaneFunction(
104
136
  throw new Error("Usage: gloomberb fn <function-or-pane> [argument] [--key value]");
105
137
  }
106
138
 
107
- const lookup = buildPaneFunctionLookup(registry);
108
- const entry = lookup.get(normalizeLookupToken(args.target));
109
- if (!entry) {
139
+ const found = findPaneFunction(registry, args.target);
140
+ if (!found) {
110
141
  const shortcuts = [...registry.paneTemplates.values()]
111
142
  .map((template) => template.shortcut?.prefix)
112
143
  .filter((prefix): prefix is string => !!prefix)
@@ -114,10 +145,7 @@ export async function resolvePaneFunction(
114
145
  throw new Error(`Unknown function or pane "${args.target}". Try one of: ${shortcuts.slice(0, 18).join(", ")}`);
115
146
  }
116
147
 
117
- const template = "paneId" in entry && "description" in entry ? entry as PaneTemplateDef : undefined;
118
- const pane = template
119
- ? registry.panes.get(template.paneId)
120
- : entry as PaneDef;
148
+ const { template, pane } = found;
121
149
  if (!pane) {
122
150
  throw new Error(`Template "${template?.id}" points at missing pane "${template?.paneId}".`);
123
151
  }
@@ -18,6 +18,7 @@ import { scenarioScreenshotEvidence } from "../../plugins/builtin/options-scenar
18
18
  import { realizedVolScreenshotEvidence } from "../../plugins/builtin/realized-vol/evidence";
19
19
  import { volSurfaceScreenshotEvidence } from "../../plugins/builtin/vol-surface/evidence";
20
20
  import { volatilityScreenshotEvidence } from "../../plugins/builtin/volatility/evidence";
21
+ import { worldMapScreenshotEvidence } from "../../plugins/builtin/world-venue-map/evidence";
21
22
 
22
23
  /** The envelope every pane's rendered chart-data evidence carries. */
23
24
  export interface PaneScreenshotEvidence {
@@ -93,6 +94,7 @@ const PANE_SCREENSHOT_EVIDENCE: readonly PaneScreenshotEvidenceHook[] = [
93
94
  realizedVolScreenshotEvidence,
94
95
  volSurfaceScreenshotEvidence,
95
96
  volatilityScreenshotEvidence,
97
+ worldMapScreenshotEvidence,
96
98
  ];
97
99
 
98
100
  export function paneScreenshotEvidenceHook(resolved: ResolvedPaneFunction): PaneScreenshotEvidenceHook | null {
@@ -72,6 +72,8 @@ import { getCloudApiBaseUrl } from "../../api-client/request";
72
72
  import { collectExternalPluginBundles } from "../../renderers/electrobun/bun/external-plugins";
73
73
  import type { ResolvedSeries } from "../../time-series/types";
74
74
  import { getQuoteMonitorPaneSettings } from "../../plugins/builtin/ticker-detail/settings";
75
+ import { accessGateSentence } from "./access-gate";
76
+ import { findCollection } from "../../plugins/builtin/portfolio-list/cli/render";
75
77
  import {
76
78
  paneEvidenceMismatches,
77
79
  paneScreenshotEvidenceHook,
@@ -651,8 +653,9 @@ async function collectShotSymbolsWithCollections(
651
653
  context: MarketContext,
652
654
  rawArg: string,
653
655
  ): Promise<string[]> {
654
- const symbols = collectShotSymbols(resolved, rawArg);
655
- if (!COLLECTION_PANE_IDS.has(resolved.pane.id)) return symbols;
656
+ if (!COLLECTION_PANE_IDS.has(resolved.pane.id)) return collectShotSymbols(resolved, rawArg);
657
+ // `shot PF Retirement` names a portfolio, not a ticker to fetch.
658
+ const symbols = rawArg.trim() && findCollection(context.config, rawArg) ? [] : collectShotSymbols(resolved, rawArg);
656
659
  const members = (await context.store.loadAllTickers())
657
660
  .filter(({ metadata }) => metadata.portfolios.length > 0 || metadata.watchlists.length > 0)
658
661
  .map(({ metadata }) => metadata.ticker);
@@ -857,7 +860,7 @@ export function filledKeyValueCount(rows: DesktopPaneShotRenderResult["visibleKe
857
860
  export function shotUnusableReasonFor(
858
861
  resolved: ResolvedPaneFunction,
859
862
  payload: DesktopPaneShotPayload,
860
- render: Pick<DesktopPaneShotRenderResult, "loadingStateDetected" | "errorStateDetected" | "emptyStateDetected">,
863
+ render: Pick<DesktopPaneShotRenderResult, "loadingStateDetected" | "errorStateDetected" | "emptyStateDetected" | "accessGate">,
861
864
  unavailableSymbols: string[],
862
865
  semanticMismatch: boolean,
863
866
  ): string {
@@ -871,6 +874,7 @@ export function shotUnusableReasonFor(
871
874
  return `No intraday price history is available for ${symbol} for the requested session window.`;
872
875
  }
873
876
  if (render.loadingStateDetected) return "The pane was still loading when the screenshot was captured.";
877
+ if (render.accessGate) return accessGateSentence(render.accessGate);
874
878
  if (render.errorStateDetected) return "The pane rendered an error state.";
875
879
  if (render.emptyStateDetected) return "The pane rendered an empty state.";
876
880
  if (unavailableSymbols.length > 0) return `Data is unavailable for ${unavailableSymbols.join(", ")}.`;
package/src/cli/result.ts CHANGED
@@ -11,11 +11,19 @@ import {
11
11
  type CliTableColumn,
12
12
  } from "../utils/cli-output";
13
13
  import { serializeCsv } from "../utils/csv";
14
+ import { formatUtcTime, isEpochMilliseconds, isZonedIsoDateTime } from "../utils/utc-time";
15
+ import { formatFreshnessLine, type ReportFreshness } from "./pane-functions/freshness";
14
16
 
15
17
  export interface CliResult<T = unknown> {
16
18
  data: T;
17
19
  metadata?: Record<string, unknown>;
18
20
  warnings?: string[];
21
+ /**
22
+ * Source, as-of and status of market data, as every `fn` report states them
23
+ * (docs/usage.md#how-current-a-report-is): the last line of the text output
24
+ * and `metadata.freshness` in JSON. CSV and NDJSON stay rows only.
25
+ */
26
+ freshness?: ReportFreshness;
19
27
  }
20
28
 
21
29
  export interface CliErrorObject {
@@ -47,21 +55,20 @@ export interface CliResultRenderOptions<T = unknown, Row = Record<string, unknow
47
55
  empty?: string;
48
56
  /** Text-mode block printed above the rows, for figures that are not rows. */
49
57
  summary?: (data: T) => string;
58
+ /** Text-mode line printed first, naming what the result is about, such as the listing a symbol resolved to. */
59
+ heading?: string;
50
60
  }
51
61
 
52
- interface CliResultJsonEnvelope<T> extends CliResult<T> {
62
+ interface CliResultJsonEnvelope<T> extends Omit<CliResult<T>, "freshness"> {
53
63
  ok: true;
54
64
  columns?: Array<Pick<CliResultColumn, "key" | "header" | "align" | "width">>;
55
65
  }
56
66
 
57
67
  type TextCellContext = "table" | "record";
58
68
 
59
- const ISO_DATE_TIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})?$/;
60
- const TIME_KEY = /(?:At|Time|Timestamp)$/;
69
+ // Keys whose epoch-millisecond numbers are times rather than counts or prices.
70
+ const TIME_KEY = /(?:At|Time|Timestamp|Updated|AsOf)$|^(?:asOf|timestamp)$/;
61
71
  const IDENTIFIER_KEY = /^id$|Id$/;
62
- // Epoch milliseconds between 2001 and 2286, so counts and prices are never read as dates.
63
- const EPOCH_MS_MIN = 1e12;
64
- const EPOCH_MS_MAX = 1e13;
65
72
  const KEY_ACRONYMS: Record<string, string> = {
66
73
  api: "API",
67
74
  cik: "CIK",
@@ -106,13 +113,8 @@ export function humanizeCliKey(key: string): string {
106
113
  .join(" ");
107
114
  }
108
115
 
109
- function pad2(value: number): string {
110
- return String(value).padStart(2, "0");
111
- }
112
-
113
- function formatLocalDateTime(date: Date): string {
114
- if (Number.isNaN(date.getTime())) return "";
115
- return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())} ${pad2(date.getHours())}:${pad2(date.getMinutes())}`;
116
+ function isTimeValue(key: string | undefined, value: number): boolean {
117
+ return key != null && TIME_KEY.test(key) && isEpochMilliseconds(value);
116
118
  }
117
119
 
118
120
  // Six significant digits hide float noise (0.9499999999999886) without cutting real precision;
@@ -132,16 +134,13 @@ function formatTextValue(
132
134
  ): string {
133
135
  const missing = context === "record" ? cliStyles.muted("-") : "";
134
136
  if (value == null || value === "") return missing;
135
- if (value instanceof Date) return formatLocalDateTime(value);
137
+ // Times print in UTC with the zone named, never in the host's zone; JSON and CSV keep the raw value.
138
+ if (value instanceof Date) return formatUtcTime(value);
136
139
  if (typeof value === "boolean") return value ? "yes" : "no";
137
- if (typeof value === "number") {
138
- if (key && TIME_KEY.test(key) && value >= EPOCH_MS_MIN && value < EPOCH_MS_MAX) {
139
- return formatLocalDateTime(new Date(value));
140
- }
141
- return formatTextNumber(value);
142
- }
140
+ if (typeof value === "number") return isTimeValue(key, value) ? formatUtcTime(value) : formatTextNumber(value);
143
141
  if (typeof value === "string") {
144
- return ISO_DATE_TIME.test(value) ? formatLocalDateTime(new Date(value)) || value : value;
142
+ // A date and time without a zone stays as the source wrote it: its zone is unknown.
143
+ return isZonedIsoDateTime(value) ? formatUtcTime(value) : value;
145
144
  }
146
145
  if (Array.isArray(value)) {
147
146
  if (value.length === 0) return context === "record" ? cliStyles.muted("none") : "";
@@ -198,9 +197,7 @@ function isEmptyTextValue(value: unknown): boolean {
198
197
  function inferTextColumns(rows: Record<string, unknown>[]): CliResultColumn<Record<string, unknown>>[] {
199
198
  return inferColumns(rows).map((column) => {
200
199
  const values = rows.map((row) => row?.[column.key]).filter((value) => !isEmptyTextValue(value));
201
- const numeric = values.length > 0 && values.every((value) => typeof value === "number" && !(
202
- TIME_KEY.test(column.key) && value >= EPOCH_MS_MIN && value < EPOCH_MS_MAX
203
- ));
200
+ const numeric = values.length > 0 && values.every((value) => typeof value === "number" && !isTimeValue(column.key, value));
204
201
  return {
205
202
  ...column,
206
203
  header: humanizeCliKey(column.key),
@@ -304,22 +301,38 @@ function overflowsTerminal<Row extends Record<string, unknown>>(rows: Row[]): bo
304
301
  return width > terminalWidth;
305
302
  }
306
303
 
304
+ /** The closing source, as-of and status line of a text result, for output printed without `printResult`. */
305
+ export function cliFreshnessFooter(freshness: ReportFreshness): string {
306
+ return cliStyles.muted(formatFreshnessLine(freshness));
307
+ }
308
+
307
309
  export function serializeCliResult<T, Row extends Record<string, unknown> = Record<string, unknown>>(
308
310
  result: CliResult<T>,
309
311
  options: CliGlobalOptions,
310
312
  renderOptions: CliResultRenderOptions<T, Row> = {},
311
313
  ): string {
314
+ const { freshness, ...rest } = result;
312
315
  if (options.format === "json") {
313
316
  const columns = serializeColumns(renderOptions.columns);
314
317
  const envelope: CliResultJsonEnvelope<T> = {
315
318
  ok: true,
316
- ...result,
319
+ ...rest,
320
+ ...(freshness ? { metadata: { ...rest.metadata, freshness } } : {}),
317
321
  data: applyLimit(result.data, options.limit),
318
322
  ...(columns?.length ? { columns } : {}),
319
323
  };
320
324
  return JSON.stringify(envelope, null, 2);
321
325
  }
326
+ const body = serializeCliRows(rest, options, renderOptions);
327
+ if (options.format !== "text" || !freshness) return body;
328
+ return body ? `${body}\n\n${cliFreshnessFooter(freshness)}` : cliFreshnessFooter(freshness);
329
+ }
322
330
 
331
+ function serializeCliRows<T, Row extends Record<string, unknown>>(
332
+ result: CliResult<T>,
333
+ options: CliGlobalOptions,
334
+ renderOptions: CliResultRenderOptions<T, Row>,
335
+ ): string {
323
336
  const rows = asRows(result.data, options.limit, renderOptions.rows);
324
337
  if (options.format === "ndjson") {
325
338
  return rows.map((row) => JSON.stringify(row)).join("\n");
@@ -331,11 +344,12 @@ export function serializeCliResult<T, Row extends Record<string, unknown> = Reco
331
344
  return renderOptions.text(result.data);
332
345
  }
333
346
  const summary = renderOptions.summary?.(result.data) ?? "";
347
+ const withHeading = (text: string) => renderOptions.heading ? `${renderOptions.heading}\n${text}` : text;
334
348
  if (rows.length === 0) {
335
- return summary || cliStyles.muted(renderOptions.empty ?? "No results.");
349
+ return withHeading(summary || cliStyles.muted(renderOptions.empty ?? "No results."));
336
350
  }
337
351
  const body = renderTextRows(rows as Row[], result.data, renderOptions);
338
- return summary ? `${summary}\n\n${body}` : body;
352
+ return withHeading(summary ? `${summary}\n\n${body}` : body);
339
353
  }
340
354
 
341
355
  function renderTextRows<T, Row extends Record<string, unknown>>(
@@ -3,19 +3,21 @@ import type { TickerRecord } from "../types/ticker";
3
3
  import type { TickerRepository } from "../data/ticker-repository";
4
4
  import { resolveTickerSearch, upsertTickerFromSearchResult } from "../tickers/search";
5
5
  import { canonicalExchange } from "../utils/exchanges";
6
+ import { resolveCliListing } from "./listing-arg";
6
7
 
8
+ /** The saved ticker for a symbol (`SAN:EPA`, or `SAN` with `--exchange EPA`), saving it from search first if needed. */
7
9
  export async function resolveTickerForCli(
8
10
  symbol: string,
9
11
  store: TickerRepository,
10
12
  dataProvider: DataProvider,
13
+ exchange?: string,
11
14
  ): Promise<TickerRecord> {
12
- const normalized = symbol.trim().toUpperCase();
13
- if (!normalized) {
15
+ if (!symbol.trim()) {
14
16
  throw new Error("Ticker symbol is required.");
15
17
  }
16
-
17
- const localTicker = await store.loadTicker(normalized);
18
- if (localTicker) return localTicker;
18
+ const listing = await resolveCliListing(symbol, exchange, { store, dataProvider });
19
+ if (listing.saved) return listing.saved;
20
+ const normalized = listing.key;
19
21
 
20
22
  const localTickers = new Map(
21
23
  (await store.loadAllTickers()).map((ticker) => [ticker.metadata.ticker.toUpperCase(), ticker] as const),