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
@@ -199,6 +199,30 @@ export async function buildPaneCatalogEntries(
199
199
  return entries.sort((left, right) => left.token.localeCompare(right.token));
200
200
  }
201
201
 
202
+ /** The phrase starting a word of the text, so "funding rate" finds "funding rates" but "rate" is not found in "separate". */
203
+ function containsPhrase(text: string, phrase: string): boolean {
204
+ for (let at = text.indexOf(phrase); at >= 0; at = text.indexOf(phrase, at + 1)) {
205
+ if (at === 0 || !/[a-z0-9]/.test(text[at - 1]!)) return true;
206
+ }
207
+ return false;
208
+ }
209
+
210
+ // A multi-word query ranks a function carrying the whole phrase in its name or keywords first, then in its
211
+ // description, then one matching every word somewhere; the rest rank by how many words they match.
212
+ const PHRASE_IN_NAME_BAND = 4000;
213
+ const PHRASE_IN_DESCRIPTION_BAND = 3000;
214
+ const ALL_WORDS_BAND = 2000;
215
+ const PER_MATCHED_WORD = 100;
216
+
217
+ function phraseBand(entry: PaneCatalogEntry, phrase: string): number {
218
+ const lower = (values: Array<string | undefined>) => values
219
+ .filter((value): value is string => !!value).map((value) => value.toLowerCase().replace(/\s+/g, " "));
220
+ const names = lower([entry.token, entry.label, entry.paneName, entry.shortcut, ...entry.aliases, ...entry.keywords, ...entry.capability.aliases]);
221
+ if (names.some((name) => containsPhrase(name, phrase))) return PHRASE_IN_NAME_BAND;
222
+ const descriptions = lower([entry.description, ...entry.capability.intents]);
223
+ return descriptions.some((description) => containsPhrase(description, phrase)) ? PHRASE_IN_DESCRIPTION_BAND : 0;
224
+ }
225
+
202
226
  function paneCatalogSearchScore(entry: PaneCatalogEntry, query: string): number {
203
227
  const terms = query.toLowerCase().split(/\s+/).map((term) => term.trim()).filter(Boolean);
204
228
  if (terms.length === 0) return 1;
@@ -253,7 +277,10 @@ function paneCatalogSearchScore(entry: PaneCatalogEntry, query: string): number
253
277
  if (matchedTerms === 0) return 0;
254
278
  score += Math.round((matchedTerms / terms.length) * 8);
255
279
  if (entry.capability.botSafe) score += 2;
256
- return score;
280
+ // One word has no phrase to prefer: it keeps the plain term scores.
281
+ if (terms.length === 1) return score;
282
+ const band = phraseBand(entry, terms.join(" "));
283
+ return score + matchedTerms * PER_MATCHED_WORD + (band || (matchedTerms === terms.length ? ALL_WORDS_BAND : 0));
257
284
  }
258
285
 
259
286
  export function filterPaneCatalogEntries(entries: PaneCatalogEntry[], query: string): PaneCatalogEntry[] {
@@ -182,5 +182,7 @@ export function collectShotSymbols(resolved: ResolvedPaneFunction, rawArg: strin
182
182
  if (resolved.capability.id === "security-relationship" && symbols.length === 1) {
183
183
  symbols = [...symbols, "SPY"];
184
184
  }
185
- return [...new Set(symbols.map(cleanTickerInput).filter(Boolean))];
185
+ // Entries a ticker list keeps as typed (CORR's GEO:HORMUZ) are not tickers to fetch.
186
+ const keep = resolved.template?.shortcut?.keepArgToken;
187
+ return [...new Set(symbols.filter((symbol) => !keep?.(symbol)).map(cleanTickerInput).filter(Boolean))];
186
188
  }
@@ -1,10 +1,12 @@
1
1
  import type { DesktopPaneShotRenderedRow } from "../desktop-pane-shot";
2
- import { renderSection, renderTable } from "../../utils/cli-output";
2
+ import { cliStyles, renderSection, renderTable } from "../../utils/cli-output";
3
+ import { formatUtcTime } from "../../utils/utc-time";
3
4
  import type { MarketContext } from "../types";
4
5
  import type { PaneFunctionReport } from "./report";
5
6
  import type { ResolvedPaneFunction } from "./resolver";
6
7
  import { collectShotSymbols } from "./data";
7
8
  import { renderDesktopShot, type PaneScreenshotResult } from "./screenshot";
9
+ import { deriveRenderedFreshness, formatFreshnessLine, type ReportFreshness } from "./freshness";
8
10
 
9
11
  const DOM_REPORT_WIDTH = 1280;
10
12
  const DOM_REPORT_HEIGHT = 720;
@@ -32,6 +34,14 @@ function domCellKeys(row: DesktopPaneShotRenderedRow): string[] {
32
34
  });
33
35
  }
34
36
 
37
+ /**
38
+ * A pane may shorten a time to fit ("Wed 11:27", "Oct 2"); the report prints
39
+ * the instant behind it with its date and zone instead.
40
+ */
41
+ function cellText(cell: DesktopPaneShotRenderedRow["cells"][number]): string {
42
+ return cell.instant ? formatUtcTime(cell.instant) || cell.text : cell.text;
43
+ }
44
+
35
45
  function renderDomTables(rows: DesktopPaneShotRenderedRow[]): string[] {
36
46
  const byTable = new Map<number, DesktopPaneShotRenderedRow[]>();
37
47
  for (const row of rows) {
@@ -60,7 +70,7 @@ function renderDomTables(rows: DesktopPaneShotRenderedRow[]): string[] {
60
70
  columns,
61
71
  tableRows.map((row) => {
62
72
  const keys = domCellKeys(row);
63
- const textByKey = new Map(row.cells.map((cell, cellIndex) => [keys[cellIndex]!, cell.text]));
73
+ const textByKey = new Map(row.cells.map((cell, cellIndex) => [keys[cellIndex]!, cellText(cell)]));
64
74
  return columns.map((column) => textByKey.get(column.key) ?? "");
65
75
  }),
66
76
  );
@@ -129,6 +139,10 @@ export function buildDomPaneReportFromRender(
129
139
  textLines.push(failureReason ?? "No rendered values were available.");
130
140
  }
131
141
  if (failureReason && rows.length > 0) textLines.push("", failureReason);
142
+ const freshness = deriveRenderedFreshness(resolved.pane.reportFreshness, {
143
+ footerText: result.render.footerText ?? "",
144
+ cellTimes: rows.flatMap((row) => row.cells.flatMap((cell) => cell.instant ?? [])),
145
+ });
132
146
 
133
147
  return {
134
148
  data: {
@@ -147,6 +161,7 @@ export function buildDomPaneReportFromRender(
147
161
  truncationReasons,
148
162
  limitation: DOM_LIMITATION,
149
163
  ...(failureReason ? { reason: failureReason } : {}),
164
+ freshness,
150
165
  },
151
166
  text: textLines.join("\n").trimEnd(),
152
167
  };
@@ -156,12 +171,14 @@ export function appendDomReportFooter(
156
171
  text: string,
157
172
  elapsedMs: number,
158
173
  truncated: boolean,
174
+ freshness: ReportFreshness,
159
175
  ): string {
160
176
  const clipping = truncated ? "The rendered view is clipped." : "The rendered view may be clipped.";
161
177
  return [
162
178
  text,
163
179
  "",
164
180
  `Rendered view: values come from the visible pane. ${clipping} Render time: ${elapsedMs} ms.`,
181
+ cliStyles.muted(formatFreshnessLine(freshness)),
165
182
  ].join("\n");
166
183
  }
167
184
 
@@ -193,6 +210,7 @@ function failedDomReport(
193
210
  truncationReasons: [],
194
211
  limitation: DOM_LIMITATION,
195
212
  reason,
213
+ freshness: deriveRenderedFreshness(resolved.pane.reportFreshness, { footerText: "", cellTimes: [] }),
196
214
  },
197
215
  text: [resolved.label, "", reason].join("\n"),
198
216
  };
@@ -0,0 +1,400 @@
1
+ import type {
2
+ HeadlessBundleResult,
3
+ HeadlessFreshnessStatus,
4
+ HeadlessPaneDefinition,
5
+ HeadlessPaneFreshness,
6
+ HeadlessPaneResult,
7
+ HeadlessPaneRow,
8
+ HeadlessSeriesResult,
9
+ HeadlessSnapshotResult,
10
+ } from "../../types/plugin";
11
+ import { formatUtcTime, parseReportTime, type ReportTime } from "../../utils/utc-time";
12
+ import { isRecord } from "../../utils/guards";
13
+ import { latestRegularSessionClose } from "../../market-data/market/freshness";
14
+
15
+ /**
16
+ * The four states of docs/usage.md#how-current-a-report-is, plus `unreported`
17
+ * for a report that cannot tell: a rendered view whose footer names no state,
18
+ * or a plugin that declares nothing and carries no feed signal.
19
+ */
20
+ type ReportFreshnessStatus = HeadlessFreshnessStatus | "unreported";
21
+
22
+ /** What every `fn` report cites about its data, in its JSON and its last text line. */
23
+ export interface ReportFreshness {
24
+ source: string;
25
+ /** Newest observation: an ISO instant in UTC, or an ISO date. Null when nothing in the data is dated. */
26
+ asOf: string | null;
27
+ /** Oldest observation, when it is more than a day older than `asOf`. */
28
+ oldest?: string;
29
+ status: ReportFreshnessStatus;
30
+ delayMinutes?: number;
31
+ /** How old the stale data is: the newest observation, or the oldest stale row when only some are. */
32
+ ageMinutes?: number;
33
+ /** When only some rows are stale: how many, of the rows that say whether they are... */
34
+ staleCount?: number;
35
+ observationCount?: number;
36
+ /** ...and what the rest are. */
37
+ feed?: "live" | "delayed";
38
+ basis?: string;
39
+ /** When this report was built. */
40
+ retrievedAt: string;
41
+ }
42
+
43
+ const DEFAULT_REPORT_SOURCE = "Gloom Cloud";
44
+
45
+ /** Top-level row and metadata keys that say when a value was observed. */
46
+ const OBSERVATION_KEYS = [
47
+ "asOf", "asOfDate", "observedAt", "quoteTime",
48
+ "quoteAsOf", "priceAsOf", "sourceAsOf", "lastTradeTime", "timestamp",
49
+ ];
50
+ // Updates can be refresh stamps; use them only when there is no explicit observation.
51
+ const UPDATE_KEYS = ["lastUpdated", "updatedAt"];
52
+ // A stamp a little ahead of this clock is skew; further ahead it is a schedule, not an observation.
53
+ const FUTURE_TOLERANCE_MS = 10 * 60_000;
54
+ const OLDEST_GAP_MS = 24 * 60 * 60_000;
55
+ // A scheduled release can slip by hours; a day past it, the data has missed it.
56
+ const RELEASE_GRACE_MS = 24 * 60 * 60_000;
57
+
58
+ interface FeedSignals {
59
+ live: boolean;
60
+ delayed: boolean;
61
+ delayMinutes?: number;
62
+ /** A record-wide stale flag (metadata), read only when no row says whether it is stale. */
63
+ stale: boolean;
64
+ /** Rows and series that carry a `stale` flag, and the times of those that are stale. */
65
+ flagged: number;
66
+ staleTimes: Array<ReportTime | null>;
67
+ }
68
+
69
+ interface Observations {
70
+ /** One time per row, item or series: what `oldest` compares. */
71
+ units: ReportTime[];
72
+ /** Metadata and snapshot stamps: candidates for `asOf` only. */
73
+ extra: ReportTime[];
74
+ }
75
+
76
+ function emptySignals(): FeedSignals {
77
+ return { live: false, delayed: false, stale: false, flagged: 0, staleTimes: [] };
78
+ }
79
+
80
+ function readFeedSignals(record: Record<string, unknown>, signals: FeedSignals): void {
81
+ if (record.dataSource === "live") signals.live = true;
82
+ if (record.dataSource === "delayed") signals.delayed = true;
83
+ const delay = record.delayMinutes;
84
+ if (typeof delay === "number" && Number.isFinite(delay) && delay > 0) {
85
+ signals.delayed = true;
86
+ signals.delayMinutes = Math.max(signals.delayMinutes ?? 0, delay);
87
+ }
88
+ }
89
+
90
+ /** A row's or series' own stale flag; worst of across them, counted so a partly stale board says how much. */
91
+ function readUnitStale(record: Record<string, unknown>, time: ReportTime | null, signals: FeedSignals): void {
92
+ if (typeof record.stale !== "boolean") return;
93
+ signals.flagged += 1;
94
+ if (record.stale) signals.staleTimes.push(time);
95
+ }
96
+
97
+ function observedTime(record: Record<string, unknown>, now: number, keys: readonly string[] = OBSERVATION_KEYS): ReportTime | null {
98
+ let newest: ReportTime | null = null;
99
+ for (const key of keys) {
100
+ const time = parseReportTime(record[key]);
101
+ if (time && time.time <= now + FUTURE_TOLERANCE_MS && (!newest || time.time > newest.time)) newest = time;
102
+ }
103
+ return newest;
104
+ }
105
+
106
+ function resultRecords(definition: Pick<HeadlessPaneDefinition, "shape">, result: HeadlessPaneResult): HeadlessPaneRow[] {
107
+ switch (definition.shape) {
108
+ case "rows":
109
+ return (result as { rows: HeadlessPaneRow[] }).rows;
110
+ case "bundle":
111
+ return (result as HeadlessBundleResult).sections.flatMap((section) => (
112
+ "rows" in section && section.rows ? section.rows : []
113
+ ));
114
+ case "snapshot":
115
+ return (result as HeadlessSnapshotResult).items;
116
+ case "series":
117
+ return [];
118
+ default: {
119
+ const _exhaustive: never = definition.shape;
120
+ return _exhaustive;
121
+ }
122
+ }
123
+ }
124
+
125
+ function seriesNewestTime(series: HeadlessSeriesResult["series"][number], now: number): ReportTime | null {
126
+ for (let index = series.points.length - 1; index >= 0; index -= 1) {
127
+ const point = series.points[index]!;
128
+ if (point.value == null && point.close == null) continue;
129
+ const time = parseReportTime(point.date);
130
+ if (time && time.time <= now + FUTURE_TOLERANCE_MS) return time;
131
+ }
132
+ return null;
133
+ }
134
+
135
+ function collect(
136
+ definition: Pick<HeadlessPaneDefinition, "shape">,
137
+ result: HeadlessPaneResult,
138
+ now: number,
139
+ { observedKey, ignoreStaleFlags }: Pick<HeadlessPaneFreshness, "observedKey" | "ignoreStaleFlags">,
140
+ ): { signals: FeedSignals; observations: Observations } {
141
+ const signals = emptySignals();
142
+ const observations: Observations = { units: [], extra: [] };
143
+ const rowKeys = observedKey ? [observedKey] : OBSERVATION_KEYS;
144
+ for (const row of resultRecords(definition, result)) {
145
+ if (!isRecord(row)) continue;
146
+ readFeedSignals(row, signals);
147
+ const time = observedTime(row, now, rowKeys)
148
+ ?? (observedKey ? null : observedTime(row, now, UPDATE_KEYS));
149
+ if (!ignoreStaleFlags) readUnitStale(row, time, signals);
150
+ if (time) observations.units.push(time);
151
+ }
152
+ if (definition.shape === "series") {
153
+ for (const series of (result as HeadlessSeriesResult).series) {
154
+ const record = series as unknown as Record<string, unknown>;
155
+ readFeedSignals(record, signals);
156
+ const time = seriesNewestTime(series, now);
157
+ if (!ignoreStaleFlags) readUnitStale(record, time, signals);
158
+ if (time) observations.units.push(time);
159
+ }
160
+ }
161
+ if (isRecord(result.metadata)) {
162
+ readFeedSignals(result.metadata, signals);
163
+ if (result.metadata.stale === true && !ignoreStaleFlags) signals.stale = true;
164
+ // An explicit summary as-of can be a real observation (CRYP's newest quote).
165
+ // A summary update stamp must not supersede dated rows.
166
+ const time = observedKey ? null : observedTime(result.metadata, now)
167
+ ?? (observations.units.length ? null : observedTime(result.metadata, now, UPDATE_KEYS));
168
+ if (time) observations.extra.push(time);
169
+ }
170
+ if (definition.shape === "snapshot" && !observedKey) {
171
+ const time = parseReportTime((result as HeadlessSnapshotResult).asOf);
172
+ if (time && time.time <= now + FUTURE_TOLERANCE_MS) observations.extra.push(time);
173
+ }
174
+ return { signals, observations };
175
+ }
176
+
177
+ function isoTime(time: ReportTime): string {
178
+ return time.dateOnly ? new Date(time.time).toISOString().slice(0, 10) : new Date(time.time).toISOString();
179
+ }
180
+
181
+ function newest(times: ReportTime[]): ReportTime | null {
182
+ return times.reduce<ReportTime | null>((best, time) => (!best || time.time > best.time ? time : best), null);
183
+ }
184
+
185
+ function oldest(times: ReportTime[]): ReportTime | null {
186
+ return times.reduce<ReportTime | null>((best, time) => (!best || time.time < best.time ? time : best), null);
187
+ }
188
+
189
+ /** The declaration with the result's own fields winning over the definition's. */
190
+ function mergeDeclarations(...declarations: Array<HeadlessPaneFreshness | undefined>): HeadlessPaneFreshness {
191
+ const merged: HeadlessPaneFreshness = {};
192
+ for (const declaration of declarations) {
193
+ if (!declaration) continue;
194
+ for (const [key, value] of Object.entries(declaration)) {
195
+ if (value !== undefined) (merged as Record<string, unknown>)[key] = value;
196
+ }
197
+ }
198
+ return merged;
199
+ }
200
+
201
+ const FEED_RANK: Record<"live" | "delayed" | "stale", number> = { live: 0, delayed: 1, stale: 2 };
202
+
203
+ function worstFeedStatus(statuses: Array<"live" | "delayed" | "stale">): "live" | "delayed" | "stale" | null {
204
+ return statuses.reduce<"live" | "delayed" | "stale" | null>((worst, status) => (
205
+ !worst || FEED_RANK[status] > FEED_RANK[worst] ? status : worst
206
+ ), null);
207
+ }
208
+
209
+ /** Completed US sessions after the day of `newest`, counted back from `now`, up to `limit`. */
210
+ function sessionsAfter(newest: ReportTime, now: number, limit: number): number {
211
+ const newestDate = new Date(newest.time).toISOString().slice(0, 10);
212
+ let count = 0;
213
+ let cursor = now;
214
+ while (count < limit) {
215
+ const close = latestRegularSessionClose("NYSE", cursor);
216
+ if (!close || close.date <= newestDate) break;
217
+ count += 1;
218
+ cursor = close.close - 1;
219
+ }
220
+ return count;
221
+ }
222
+
223
+ /** What the data's declared schedule says about its age, whatever kind of data it is. */
224
+ function overdue(declared: HeadlessPaneFreshness, asOf: ReportTime | null, now: number): boolean {
225
+ const nextExpected = declared.nextExpectedAt != null ? parseReportTime(declared.nextExpectedAt) : null;
226
+ if (nextExpected != null && now > nextExpected.time + RELEASE_GRACE_MS) return true;
227
+ if (!asOf) return false;
228
+ if (declared.maxAgeMinutes != null && now - asOf.time > declared.maxAgeMinutes * 60_000) return true;
229
+ return declared.cadence === "daily" && sessionsAfter(asOf, now, 2) > 1;
230
+ }
231
+
232
+ interface FreshnessInputs {
233
+ declared: HeadlessPaneFreshness;
234
+ signals: FeedSignals;
235
+ observations: Observations;
236
+ now: number;
237
+ }
238
+
239
+ function resolveFreshness({ declared, signals, observations, now }: FreshnessInputs): ReportFreshness {
240
+ const declaredAsOf = observedTime({ asOf: declared.asOf }, now, ["asOf"]);
241
+ const asOf = declaredAsOf ?? newest([...observations.units, ...observations.extra]);
242
+ // A loader that dates its data itself also says how old the oldest part is, or nothing;
243
+ // `oldest: null` says the rows are a history, whose first entry is not stale data.
244
+ const oldestTime = declared.oldest != null ? parseReportTime(declared.oldest)
245
+ : declaredAsOf || declared.oldest === null ? null : oldest(observations.units);
246
+ const late = overdue(declared, asOf, now);
247
+
248
+ let status: ReportFreshnessStatus;
249
+ let delayMinutes: number | undefined;
250
+ let staleAt: ReportTime | null = null;
251
+ let partial: { staleCount: number; observationCount: number; feed?: "live" | "delayed" } | null = null;
252
+ if (declared.status === "not-a-feed") {
253
+ // Age alone does not make filed or published data stale. Honor explicit flags,
254
+ // with row-level flags outranking the metadata summary, or a missed schedule.
255
+ const staleRows = signals.staleTimes.length;
256
+ if (late || (signals.flagged > 0 ? staleRows === signals.flagged : signals.stale)) {
257
+ status = "stale";
258
+ staleAt = asOf;
259
+ } else if (staleRows > 0) {
260
+ status = "stale";
261
+ partial = { staleCount: staleRows, observationCount: signals.flagged };
262
+ staleAt = oldest(signals.staleTimes.filter((time): time is ReportTime => time != null));
263
+ } else {
264
+ status = "not-a-feed";
265
+ }
266
+ } else {
267
+ const feed = worstFeedStatus([
268
+ ...(declared.status ? [declared.status] : []),
269
+ ...(signals.live ? ["live" as const] : []),
270
+ ...(signals.delayed ? ["delayed" as const] : []),
271
+ ]);
272
+ const staleRows = signals.staleTimes.length;
273
+ // Rows that say whether they are stale outrank a summary flag beside them.
274
+ const allStale = feed === "stale" || late
275
+ || (signals.flagged > 0 ? staleRows === signals.flagged : signals.stale);
276
+ if (allStale) {
277
+ status = "stale";
278
+ staleAt = asOf;
279
+ } else if (staleRows > 0) {
280
+ status = "stale";
281
+ partial = {
282
+ staleCount: staleRows,
283
+ observationCount: signals.flagged,
284
+ ...(feed === "live" || feed === "delayed" ? { feed } : {}),
285
+ };
286
+ staleAt = oldest(signals.staleTimes.filter((time): time is ReportTime => time != null));
287
+ } else {
288
+ status = feed ?? "unreported";
289
+ }
290
+ // A partly stale board still says how far its fresh rows are held back.
291
+ if (status === "delayed" || partial?.feed === "delayed") delayMinutes = declared.delayMinutes ?? signals.delayMinutes;
292
+ }
293
+
294
+ return {
295
+ source: declared.source?.trim() || DEFAULT_REPORT_SOURCE,
296
+ asOf: asOf ? isoTime(asOf) : null,
297
+ ...(asOf && oldestTime && asOf.time - oldestTime.time > OLDEST_GAP_MS ? { oldest: isoTime(oldestTime) } : {}),
298
+ status,
299
+ ...(delayMinutes != null && delayMinutes > 0 ? { delayMinutes } : {}),
300
+ ...(status === "stale" && staleAt ? { ageMinutes: Math.max(0, Math.floor((now - staleAt.time) / 60_000)) } : {}),
301
+ ...(partial ?? {}),
302
+ ...(status === "not-a-feed" && declared.basis ? { basis: declared.basis } : {}),
303
+ retrievedAt: new Date(now).toISOString(),
304
+ };
305
+ }
306
+
307
+ /**
308
+ * Source, as-of and status for a headless report: what the loader declared
309
+ * (the result's `freshness` over the definition's), the rest read from the
310
+ * standard signals in the result. Never live unless the data says so.
311
+ */
312
+ export function deriveHeadlessFreshness(
313
+ definition: Pick<HeadlessPaneDefinition, "shape" | "freshness">,
314
+ result: HeadlessPaneResult,
315
+ now = Date.now(),
316
+ ): ReportFreshness {
317
+ const declared = mergeDeclarations(definition.freshness, result.freshness);
318
+ const { signals, observations } = collect(definition, result, now, declared);
319
+ return resolveFreshness({ declared, signals, observations, now });
320
+ }
321
+
322
+ /**
323
+ * A rendered view has no structured data: the source is the pane's
324
+ * declaration, the times are the cells that carry an instant, and the state
325
+ * is what the pane's own footer says, or not reported.
326
+ */
327
+ export function deriveRenderedFreshness(
328
+ declared: HeadlessPaneFreshness | undefined,
329
+ input: { footerText: string; cellTimes: unknown[] },
330
+ now = Date.now(),
331
+ ): ReportFreshness {
332
+ const signals = emptySignals();
333
+ const footer = input.footerText;
334
+ const delayed = /\b(\d+)\s*(?:m|min|minutes?)\s+delayed\b/i.exec(footer);
335
+ if (delayed) {
336
+ signals.delayed = true;
337
+ signals.delayMinutes = Number(delayed[1]);
338
+ } else if (/\bdelayed\b/i.test(footer)) {
339
+ signals.delayed = true;
340
+ }
341
+ if (/\bstale\b/i.test(footer)) signals.stale = true;
342
+ if (/\breal-time\b/i.test(footer)) signals.live = true;
343
+ const units = input.cellTimes
344
+ .map((value) => parseReportTime(value))
345
+ .filter((time): time is ReportTime => time != null && time.time <= now + FUTURE_TOLERANCE_MS);
346
+ return resolveFreshness({
347
+ declared: mergeDeclarations(declared),
348
+ signals,
349
+ // Rendered rows are often a history (a news list, a filing feed), so only the newest is cited.
350
+ observations: { units: [], extra: units },
351
+ now,
352
+ });
353
+ }
354
+
355
+ function ageText(minutes: number): string {
356
+ if (minutes < 120) return `${minutes} min`;
357
+ const hours = Math.floor(minutes / 60);
358
+ if (hours < 48) return `${hours} hours`;
359
+ return `${Math.floor(hours / 24)} days`;
360
+ }
361
+
362
+ function delayedText(minutes: number | undefined): string {
363
+ return minutes ? `Delayed ${minutes} min` : "Delayed";
364
+ }
365
+
366
+ function statusText(freshness: ReportFreshness): string {
367
+ switch (freshness.status) {
368
+ case "live":
369
+ return "Live";
370
+ case "delayed":
371
+ return delayedText(freshness.delayMinutes);
372
+ case "stale": {
373
+ if (freshness.staleCount != null && freshness.observationCount != null) {
374
+ const rest = freshness.feed === "live" ? "Live" : freshness.feed === "delayed" ? delayedText(freshness.delayMinutes) : null;
375
+ return `${rest ? `${rest}, ` : ""}${freshness.staleCount} of ${freshness.observationCount} stale`;
376
+ }
377
+ return freshness.ageMinutes != null ? `Stale (${ageText(freshness.ageMinutes)} old)` : "Stale";
378
+ }
379
+ case "not-a-feed":
380
+ return freshness.basis ? `Not a live feed (${freshness.basis})` : "Not a live feed";
381
+ case "unreported":
382
+ return "Status not reported";
383
+ default: {
384
+ const _exhaustive: never = freshness.status;
385
+ return _exhaustive;
386
+ }
387
+ }
388
+ }
389
+
390
+ /**
391
+ * The one line every `fn` text report ends with:
392
+ * `Source: Gloom Cloud | As of 2026-10-09 00:08 UTC | Delayed 10 min`.
393
+ * Without a dated observation it says when the report was retrieved instead.
394
+ */
395
+ export function formatFreshnessLine(freshness: ReportFreshness): string {
396
+ const time = freshness.asOf
397
+ ? `As of ${formatUtcTime(freshness.asOf)}${freshness.oldest ? ` (oldest ${freshness.oldest.slice(0, 10)})` : ""}`
398
+ : `Retrieved ${formatUtcTime(freshness.retrievedAt)}`;
399
+ return [`Source: ${freshness.source}`, time, statusText(freshness)].join(" | ");
400
+ }
@@ -114,8 +114,8 @@ export const FUNCTION_HELP: Readonly<Record<string, FunctionHelp>> = {
114
114
  bloomberg: ["GIP"],
115
115
  },
116
116
  G: {
117
- summary: "Chart any series together: prices, statement lines, valuation multiples, FRED series, indicators and formulas. Series read SYMBOL:field or FRED:series.",
118
- usage: ["G", "G NVDA:revenue, NVDA:net_income"],
117
+ summary: "Chart any series together: prices, statement lines, valuation multiples, FRED series, map series such as chokepoint transits, indicators and formulas. Series read SYMBOL:field, FRED:series or GEO:series.",
118
+ usage: ["G", "G NVDA:revenue, NVDA:net_income", "G XOM, GEO:HORMUZ"],
119
119
  keys: CHART_KEYS,
120
120
  data: { free: "Prices 15 minutes delayed, other series as published", pro: "Prices real-time for US listings, other series as published" },
121
121
  bloomberg: ["G"],
@@ -292,9 +292,9 @@ export const FUNCTION_HELP: Readonly<Record<string, FunctionHelp>> = {
292
292
  bloomberg: ["SEAS"],
293
293
  },
294
294
  RIPL: {
295
- summary: "Which of my holdings are tied to a company that reports soon? Customers your holdings name in their filings, and suppliers whose filings name your holdings, with the disclosed revenue share, by report date.",
295
+ summary: "Which of my holdings are tied to a company that reports soon? Customers your holdings name in their filings, and suppliers whose filings name your holdings, with the disclosed revenue share, by report date. With Pro, the 2 hops tab adds a supplier's supplier or a customer's customer, the company in between and each hop's share.",
296
296
  usage: ["RIPL", "RIPL CRUS QRVO"],
297
- keys: [key("Enter", " supply chain"), key("e", "arnings")],
297
+ keys: [TABS, key("Enter", " supply chain, the route on 2 hops"), key("e", "arnings")],
298
298
  data: ON_RELEASE,
299
299
  bloomberg: [],
300
300
  },
@@ -660,6 +660,13 @@ export const FUNCTION_HELP: Readonly<Record<string, FunctionHelp>> = {
660
660
  data: QUOTES,
661
661
  bloomberg: ["IMAP"],
662
662
  },
663
+ MEMB: {
664
+ summary: "ETF holdings with weights, shares, member returns, daily contributions and index changes. SPX and SPY use IVV holdings.",
665
+ usage: ["MEMB", "MEMB SPY", "MEMB IWM"],
666
+ keys: [TABS, OPEN],
667
+ data: same("Dated fund holdings and partial delayed member returns. Nasdaq-100 is not covered."),
668
+ bloomberg: ["MEMB", "MRR", "IMOV"],
669
+ },
663
670
  THEM: {
664
671
  summary: "Curated thematic baskets with equal-weight returns and breadth. Open a theme to see its members, leaders and laggards. The Themes tab of BI.",
665
672
  usage: ["THEM", "THEM nuclear"],
@@ -675,24 +682,24 @@ export const FUNCTION_HELP: Readonly<Record<string, FunctionHelp>> = {
675
682
  bloomberg: ["RRG"],
676
683
  },
677
684
  HM: {
678
- summary: "The largest US stocks and ETFs as a treemap sized by market cap or assets and colored by the day's move.",
685
+ summary: "The largest US stocks and ETFs as a treemap sized by the square root of market cap or assets, or by plain market cap in its settings, and colored by the day's move.",
679
686
  usage: ["HM"],
680
687
  keys: [OPEN],
681
688
  data: QUOTES,
682
689
  bloomberg: ["IMAP"],
683
690
  },
684
691
  FXC: {
685
- summary: "A cross-rate matrix for the major currencies.",
692
+ summary: "A cross-rate matrix for the major currencies, or for any of 45 chosen in its settings.",
686
693
  usage: ["FXC"],
687
694
  keys: [],
688
695
  data: FX,
689
696
  bloomberg: ["FXC"],
690
697
  },
691
698
  PERP: {
692
- summary: "Perpetual funding, open interest and premiums across crypto and stock, index, commodity and FX contracts. Per-market History and Evidence. Pro history with a latest-value free preview.",
699
+ summary: "Perpetual funding, open interest and premiums across venues, for crypto and stock, index, commodity and FX contracts: a board, rankings, one asset across venues, and a market's History and Evidence.",
693
700
  usage: ["PERP", "PERP BTC", "PERP TSLA"],
694
- keys: [TABS, SEARCH, OPEN_SOURCE, key("a", "lert"), key("e", "vidence"), key("d", "es"), key("f", "a"), key("g", "raph")],
695
- data: { free: "Latest market values", pro: "Observed funding, open interest and stored history; source timestamps retained" },
701
+ keys: [TABS, OPEN, SEARCH, key("e", "vidence"), key("a", "lert")],
702
+ data: { free: "A fixed preview and any one market's latest values", pro: "Every market, full rankings and stored history; source timestamps retained" },
696
703
  bloomberg: [],
697
704
  },
698
705
  CRYP: {
@@ -710,8 +717,8 @@ export const FUNCTION_HELP: Readonly<Record<string, FunctionHelp>> = {
710
717
  bloomberg: ["GLCO"],
711
718
  },
712
719
  CTM: {
713
- summary: "A futures root's listed contracts as a curve against a week and a month ago, with roll yield, contango or backwardation, and each contract's price, open interest and volume.",
714
- usage: ["CTM GC"],
720
+ summary: "A futures root's listed contracts as a curve against a week and a month ago, with roll yield, contango or backwardation, and each contract's price, open interest and volume. Takes a FUT root, VX or a CME crypto root (BTC, ETH, SOL, XRP), which also shows each contract's premium to spot and annualised basis against the USD pair quote.",
721
+ usage: ["CTM GC", "CTM BTC"],
715
722
  keys: [key("d", "ate"), key("c", "urrent"), STEP],
716
723
  data: same("Delayed, usually 10 minutes; VIX at settlement"),
717
724
  bloomberg: ["CTM", "CT"],
@@ -724,8 +731,8 @@ export const FUNCTION_HELP: Readonly<Record<string, FunctionHelp>> = {
724
731
  bloomberg: [],
725
732
  },
726
733
  COT: {
727
- summary: "CFTC Commitments of Traders: net positioning by trader class, the weekly change, and one- and three-year percentiles. Pass a root like CL to chart it under the front-month price.",
728
- usage: ["COT", "COT CL"],
734
+ summary: "CFTC Commitments of Traders: net positioning by trader class, the weekly change, and one- and three-year percentiles. Pass a root like CL or BTC (also ETH, MBT, MET, SOL, XRP) for one market, charted under its front-month price where there is one.",
735
+ usage: ["COT", "COT CL", "COT BTC"],
729
736
  keys: [key("c", "lass"), key("s", "cope"), SEARCH],
730
737
  data: same("Weekly: Tuesday positions, out on Friday"),
731
738
  bloomberg: ["COT"],
@@ -802,10 +809,17 @@ export const FUNCTION_HELP: Readonly<Record<string, FunctionHelp>> = {
802
809
  bloomberg: ["IPO"],
803
810
  },
804
811
  MAP: {
805
- summary: "Trading venues around the world with open or closed status, local time and time to the next session change.",
806
- usage: ["MAP"],
807
- keys: [SEARCH, key("+", " zoom in"), key("-", " zoom out")],
808
- data: same("Live, from exchange calendars"),
812
+ summary: "Trading venues around the world with open or closed status, local time and time to the next session change. Layers add ships, chokepoints, ports, pipelines, fields, LNG terminals and airports to the same map, each with a table of what is in view and the companies it links to.",
813
+ usage: ["MAP", "MAP ships", "MAP energy", "MAP air", "MAP ports"],
814
+ keys: [SEARCH, OPEN, key("d", "es"), key("+", " zoom in")],
815
+ data: same("Venues live from exchange calendars; ships live, chokepoints and ports daily, the rest reference data"),
816
+ bloomberg: [],
817
+ },
818
+ CHOKE: {
819
+ summary: "Daily vessel transits through the main shipping chokepoints charted together, or one of them by name, as series you can mix with anything else in G.",
820
+ usage: ["CHOKE", "CHOKE SUEZ"],
821
+ keys: CHART_KEYS,
822
+ data: same("Daily"),
809
823
  bloomberg: [],
810
824
  },
811
825
 
@@ -946,10 +960,10 @@ export const FUNCTION_HELP: Readonly<Record<string, FunctionHelp>> = {
946
960
  bloomberg: [],
947
961
  },
948
962
  HDS: {
949
- summary: "Institutional holders as a table (value, shares, change, percent held) or as an ownership treemap.",
950
- usage: ["HDS NVDA"],
951
- keys: [TABS, key("o", "pen 13F")],
952
- data: same("Quarterly, as 13Fs are filed"),
963
+ summary: "Institutional holders as a table (value, shares, change, percent held) or as an ownership treemap, and the 13D/G tab: 13D and 13G beneficial owners over 5%, activists and passive stakes, with percent of class, its change and each filer's 13F move.",
964
+ usage: ["HDS NVDA", "HDS CAR"],
965
+ keys: [TABS, OPEN, key("o", "pen 13F or filing")],
966
+ data: same("13F quarterly as filed; 13D and 13G as filed"),
953
967
  bloomberg: ["HDS"],
954
968
  },
955
969
  "13F": {
@@ -976,7 +990,7 @@ export const FUNCTION_HELP: Readonly<Record<string, FunctionHelp>> = {
976
990
 
977
991
  // Run a workspace
978
992
  PF: {
979
- summary: "Your portfolio or watchlist with live quotes, P&L, weights and sparklines. Broker-synced and manual positions sit in the same table.",
993
+ summary: "Your portfolio or watchlist with live quotes, market value, P&L, weights of the total with cash, and sparklines. With target weights set, each holding adds its target, drift and the trade that rebalances it; broker-synced and manual positions sit in the same table.",
980
994
  usage: ["PF"],
981
995
  keys: [key("a", "dd"), OPEN, key("s", " grid")],
982
996
  data: QUOTES,