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,45 +1,15 @@
1
+ import { RangeTrack } from "../../../components/ui/range-track";
1
2
  import { useThemeColors } from "../../../theme/theme-context";
2
- import { Box, Text, useUiCapabilities } from "../../../ui";
3
-
4
- /** Where a marker sits on a track of `cells`, and whether it is past an end. */
5
- function rangeMarker(position: number, cells: number): { index: number; outside: "below" | "above" | null } {
6
- const last = Math.max(0, cells - 1);
7
- if (position < 0) return { index: 0, outside: "below" };
8
- if (position > 100) return { index: last, outside: "above" };
9
- return { index: Math.round((position / 100) * last), outside: null };
10
- }
3
+ import { Text } from "../../../ui";
11
4
 
12
5
  /**
13
- * The value's place in its five-year range: the low at the left, the high at
14
- * the right, a marker past an end when the value is outside it. The desktop
15
- * draws real elements; the terminal a rule of cells, so box-drawing glyphs
16
- * never reach the browser renderer.
6
+ * The value's place in its five-year range (`position` 0 to 100): the low at
7
+ * the left, the high at the right, an amber arrow past an end when the value
8
+ * is outside it.
17
9
  */
18
10
  export function DoeRangeBar({ position, width }: { position: number | null; width: number }) {
19
11
  const colors = useThemeColors();
20
- const isDesktopWeb = useUiCapabilities().nativePaneChrome === true;
21
12
  if (position == null || width < 3) return <Text fg={colors.textDim}>{""}</Text>;
22
- const cells = Math.max(3, width - 1);
23
- const marker = rangeMarker(position, cells);
24
- const markerColor = marker.outside ? colors.warning : colors.textBright;
25
- if (isDesktopWeb) {
26
- const left = marker.outside === "below" ? 0 : marker.outside === "above" ? 100 : position;
27
- return (
28
- <Box width={cells} height={1} style={{ position: "relative", justifyContent: "center" }}>
29
- <Box style={{ position: "absolute", left: 0, right: 0, height: "2px", borderRadius: "1px", backgroundColor: colors.border }} />
30
- <Box style={{
31
- position: "absolute", left: `${left}%`, width: "8px", height: "8px", marginLeft: "-4px",
32
- borderRadius: marker.outside ? "1px" : "50%", backgroundColor: markerColor,
33
- }} />
34
- </Box>
35
- );
36
- }
37
- const glyph = marker.outside === "below" ? "◂" : marker.outside === "above" ? "▸" : "●";
38
- return (
39
- <Box width={cells} flexDirection="row">
40
- <Text fg={colors.border}>{"─".repeat(marker.index)}</Text>
41
- <Text fg={markerColor}>{glyph}</Text>
42
- <Text fg={colors.border}>{"─".repeat(Math.max(0, cells - marker.index - 1))}</Text>
43
- </Box>
44
- );
13
+ const outside = position < 0 || position > 100;
14
+ return <RangeTrack position={position / 100} width={Math.max(3, width - 1)} markerColor={outside ? colors.warning : colors.textBright} outside />;
45
15
  }
@@ -70,9 +70,9 @@ export async function fetchEarningsCalendar(query: EarningsCalendarQuery, client
70
70
  }
71
71
  }
72
72
 
73
- export async function fetchEarningsHistory(symbol: string, client: HistoryClient = apiClient) {
73
+ export async function fetchEarningsHistory(symbol: string, client: HistoryClient = apiClient, limit?: number) {
74
74
  try {
75
- return validateEarningsHistory(await client.getCloudEarningsHistory(symbol), symbol);
75
+ return validateEarningsHistory(await client.getCloudEarningsHistory(symbol, limit), symbol);
76
76
  } catch (error) {
77
77
  throw unavailableOnServer(error, "Earnings history is not available yet.", [404, 503]);
78
78
  }
@@ -3,6 +3,7 @@ import type {
3
3
  HeadlessPaneColumn,
4
4
  HeadlessPaneContext,
5
5
  HeadlessPaneDefinition,
6
+ HeadlessPaneFreshness,
6
7
  HeadlessPaneLoadArgs,
7
8
  HeadlessRowsResult,
8
9
  } from "../../../types/plugin";
@@ -137,9 +138,12 @@ async function historyReport(symbol: string, context: HeadlessPaneContext, deps:
137
138
  }
138
139
 
139
140
  /** EVTS: the market board, whatever ticker is given. */
141
+ const EARNINGS_CALENDAR: HeadlessPaneFreshness = { status: "not-a-feed", basis: "calendar" };
142
+
140
143
  function createEarningsBoardHeadless(deps: EarningsHeadlessDependencies = defaultDependencies): HeadlessPaneDefinition<"rows"> {
141
144
  return {
142
145
  shape: "rows",
146
+ freshness: EARNINGS_CALENDAR,
143
147
  argument: { kind: "ticker", placeholder: "ticker", description: "Optional; the board is the same.", minimum: 0, maximum: 1 },
144
148
  options: [
145
149
  { key: "limit", description: "Maximum rows.", type: "integer", defaultValue: 200, minimum: 1, maximum: 1000 },
@@ -155,6 +159,7 @@ function createEarningsBoardHeadless(deps: EarningsHeadlessDependencies = defaul
155
159
  function createEarningsHeadless(deps: EarningsHeadlessDependencies = defaultDependencies): HeadlessPaneDefinition<"rows"> {
156
160
  return {
157
161
  shape: "rows",
162
+ freshness: EARNINGS_CALENDAR,
158
163
  argument: {
159
164
  kind: "symbol-list",
160
165
  placeholder: "tickers",
@@ -186,6 +186,7 @@ export function createEarningsCallsHeadless(
186
186
  ): HeadlessPaneDefinition<"rows"> {
187
187
  return {
188
188
  shape: "rows",
189
+ freshness: { source: "Company earnings calls", status: "not-a-feed", basis: "transcripts" },
189
190
  argument: {
190
191
  kind: "ticker",
191
192
  placeholder: "ticker",
@@ -36,6 +36,7 @@ export const earningsCallsModule: PluginModule = {
36
36
  icon: "C",
37
37
  component: EarningsCallsPane,
38
38
  defaultPosition: "right",
39
+ tickerFollower: true,
39
40
  defaultMode: "floating",
40
41
  defaultFloatingSize: { width: 100, height: 30 },
41
42
  tableExport: true,
@@ -1,60 +1,133 @@
1
1
  import type { EarningsCalendarPayload, EarningsCalendarQuery } from "../../../api-client/earnings";
2
2
  import type { SupplyChainPayload } from "../../../api-client/supply-chain";
3
+ import { DEFAULT_GRAPH_OPTIONS, type GraphOptions, type GraphPayload } from "../../../api-client/supply-chain-graph";
3
4
  import { errorMessage } from "../../../utils/errors";
4
5
  import { addDays, newYorkToday } from "../earnings/board-model";
5
6
  import { loadEarningsBoard } from "../earnings/client";
6
7
  import { loadSupplyChain } from "../supply-chain/client";
7
- import { projectRipple, rippleCompanyTickers, RIPPLE_DAYS, type RippleRow } from "./model";
8
+ import { cachedGraph, loadGraph } from "../supply-chain/graph-client";
9
+ import { projectRipple, projectSecondHop, rippleCompanyTickers, RIPPLE_DAYS, secondHopLinks, type RippleRow, type SecondHopRow } from "./model";
8
10
 
9
11
  export interface RippleSources {
10
12
  supplyChain(symbol: string): Promise<SupplyChainPayload>;
11
13
  calendar(query: EarningsCalendarQuery): Promise<EarningsCalendarPayload>;
14
+ /** SPLC's graph, which returns both hops around a holding in one call. Absent when the account sees one hop only. */
15
+ graph?(symbol: string, options: GraphOptions): Promise<GraphPayload>;
12
16
  }
13
17
 
18
+ /**
19
+ * The graph query behind the 2 hops tab. Supplier and customer links only, and
20
+ * only evidence from filings, company announcements and calls (graph classes
21
+ * structured and primary), the tiers the 1 hop tab's disclosures are read with.
22
+ * The server filters before it ranks and caps each direction, so news and
23
+ * partner routes cannot use up the 50 companies a direction returns.
24
+ */
25
+ const RIPPLE_GRAPH_OPTIONS: GraphOptions = { ...DEFAULT_GRAPH_OPTIONS, depth: 2, roles: ["customer", "supplier"], tiers: ["structured", "primary"] };
26
+
27
+ /**
28
+ * What opens SPLC's Path view on a 2 hops row: from the holding to the company
29
+ * that reports, on RIPL's own query in the row's direction, so the route the
30
+ * row shows is the one Path lists.
31
+ */
32
+ export function rippleRouteSettings(row: Pick<SecondHopRow, "company" | "link">): Record<string, string> {
33
+ return { tab: "path", to: row.company, depth: String(RIPPLE_GRAPH_OPTIONS.depth), direction: row.link === "supplier" ? "upstream" : "downstream",
34
+ roles: RIPPLE_GRAPH_OPTIONS.roles.join(","), tiers: RIPPLE_GRAPH_OPTIONS.tiers.join(",") };
35
+ }
36
+
37
+ interface Failure { symbol: string; error: string }
38
+
14
39
  export interface RippleSnapshot {
15
40
  rows: RippleRow[];
16
41
  /** Holdings whose disclosures could not be read, with the reason. */
17
- failures: { symbol: string; error: string }[];
42
+ failures: Failure[];
18
43
  /** Holdings whose disclosures the free preview cut short, so a missing link may only be hidden. */
19
44
  truncated: string[];
45
+ /**
46
+ * Companies two hops away, when asked for. `locked`: the account sees one hop
47
+ * only. `truncated`: holdings whose graph search stopped at a limit, with the
48
+ * server's reasons, so a company missing there may only be cut off.
49
+ */
50
+ secondHop: { rows: SecondHopRow[]; failures: Failure[]; truncated: { symbol: string; reasons: string[] }[]; locked: boolean } | null;
20
51
  stale: boolean;
21
52
  from: string;
22
53
  to: string;
23
54
  }
24
55
 
25
- /** The same caches SPLC and ERN fill, so opening either pane after this costs nothing. */
26
- export function cachedRippleSources(accessKey: string, force = false): RippleSources & { staleFlags: boolean[] } {
56
+ /**
57
+ * The same caches SPLC and ERN fill, so opening either pane after this costs
58
+ * nothing. `graph`: no graph source, graphs read through the cache, or graphs
59
+ * from the cache alone (fetched only when missing) while 2 hops is not on screen.
60
+ */
61
+ export function cachedRippleSources(accessKey: string, force = false, graph: "off" | "load" | "cached" = "off"): RippleSources & { staleFlags: boolean[] } {
27
62
  const staleFlags: boolean[] = [];
28
63
  return {
29
64
  staleFlags,
30
65
  supplyChain: async (symbol) => { const result = await loadSupplyChain(symbol, accessKey, force); staleFlags.push(result.stale); return result.payload; },
31
66
  calendar: async (query) => { const result = await loadEarningsBoard(query, force); staleFlags.push(result.stale); return result.payload; },
67
+ // Cached by the full query, apart from SPLC Graph's default one.
68
+ ...(graph !== "off" ? { graph: async (symbol: string, options: GraphOptions) => {
69
+ const cached = graph === "cached" ? cachedGraph(symbol, "", options, accessKey) : null;
70
+ const result = cached ?? await loadGraph(symbol, "", options, accessKey, force); staleFlags.push(result.stale); return result.payload;
71
+ } } : {}),
32
72
  };
33
73
  }
34
74
 
35
75
  const CONCURRENCY = 6;
36
76
 
37
- export async function loadRipple(holdings: readonly string[], sources: RippleSources & { staleFlags?: boolean[] }, now = new Date()): Promise<RippleSnapshot> {
77
+ async function eachLimited(symbols: readonly string[], load: (symbol: string) => Promise<void>) {
78
+ const queue = [...symbols];
79
+ await Promise.all(Array.from({ length: Math.min(CONCURRENCY, queue.length) }, async () => {
80
+ for (let symbol = queue.shift(); symbol; symbol = queue.shift()) await load(symbol);
81
+ }));
82
+ }
83
+
84
+ const locked = () => ({ graphs: new Map<string, GraphPayload>(), failures: [] as Failure[], locked: true });
85
+ const isPreview = (graphs: ReadonlyMap<string, GraphPayload>) => [...graphs.values()].some((graph) => graph.access === "preview");
86
+
87
+ /** One graph call per holding. The first answer says whether the account sees two hops; a one-hop preview skips the rest. */
88
+ async function loadGraphs(holdings: readonly string[], graph: NonNullable<RippleSources["graph"]>) {
89
+ const graphs = new Map<string, GraphPayload>();
90
+ const failures: Failure[] = [];
91
+ const load = async (symbol: string) => {
92
+ try { graphs.set(symbol, await graph(symbol, RIPPLE_GRAPH_OPTIONS)); }
93
+ catch (error) { failures.push({ symbol, error: errorMessage(error) }); }
94
+ };
95
+ const [first, ...rest] = holdings;
96
+ if (first) await load(first);
97
+ if (isPreview(graphs)) return locked();
98
+ await eachLimited(rest, load);
99
+ // Only when the first holding failed can a preview get this far.
100
+ if (isPreview(graphs)) return locked();
101
+ return { graphs, failures: failures.sort((a, b) => a.symbol.localeCompare(b.symbol)), locked: false };
102
+ }
103
+
104
+ export async function loadRipple(holdings: readonly string[], sources: RippleSources & { staleFlags?: boolean[] }, now = new Date(), { secondHop = false } = {}): Promise<RippleSnapshot> {
38
105
  const from = newYorkToday(now);
39
106
  const to = addDays(from, RIPPLE_DAYS);
107
+ const symbols = [...new Set(holdings.map((symbol) => symbol.toUpperCase()))];
40
108
  const chains = new Map<string, SupplyChainPayload>();
41
- const failures: RippleSnapshot["failures"] = [];
42
- const queue = [...new Set(holdings.map((symbol) => symbol.toUpperCase()))];
43
- await Promise.all(Array.from({ length: Math.min(CONCURRENCY, queue.length) }, async () => {
44
- for (let symbol = queue.shift(); symbol; symbol = queue.shift()) {
45
- try { chains.set(symbol, await sources.supplyChain(symbol)); }
46
- catch (error) { failures.push({ symbol, error: errorMessage(error) }); }
47
- }
48
- }));
49
- const companies = rippleCompanyTickers(chains);
109
+ const failures: Failure[] = [];
110
+ await eachLimited(symbols, async (symbol) => {
111
+ try { chains.set(symbol, await sources.supplyChain(symbol)); }
112
+ catch (error) { failures.push({ symbol, error: errorMessage(error) }); }
113
+ });
114
+ const second = !secondHop ? null : sources.graph ? await loadGraphs(symbols, sources.graph) : locked();
115
+ const graphs = second?.graphs ?? new Map<string, GraphPayload>();
116
+ const companies = [...rippleCompanyTickers(chains), ...secondHopLinks(chains, graphs).map((link) => link.company.ticker!.toUpperCase())];
50
117
  const reports: EarningsCalendarPayload["reports"] = [];
51
118
  if (companies.length) {
52
- const symbols = [...new Set([...companies, ...holdings.map((symbol) => symbol.toUpperCase())])].sort();
53
- for (let offset = 0; offset < symbols.length; offset += 200) {
54
- const payload = await sources.calendar({ from, to, perDay: 0, symbols: symbols.slice(offset, offset + 200) });
119
+ const calendarSymbols = [...new Set([...companies, ...symbols])].sort();
120
+ for (let offset = 0; offset < calendarSymbols.length; offset += 200) {
121
+ const payload = await sources.calendar({ from, to, perDay: 0, symbols: calendarSymbols.slice(offset, offset + 200) });
55
122
  reports.push(...payload.reports);
56
123
  }
57
124
  }
58
125
  const truncated = [...chains].filter(([, chain]) => chain.truncated).map(([symbol]) => symbol).sort();
59
- return { rows: projectRipple(chains, reports), failures, truncated, stale: !!sources.staleFlags?.some(Boolean), from, to };
126
+ return {
127
+ rows: projectRipple(chains, reports), failures, truncated,
128
+ secondHop: second ? { rows: projectSecondHop(chains, graphs, reports), failures: second.failures, locked: second.locked,
129
+ truncated: [...graphs].filter(([, graph]) => graph.truncated || !graph.search.complete)
130
+ .map(([symbol, graph]) => ({ symbol, reasons: graph.search.reasons })).sort((a, b) => a.symbol.localeCompare(b.symbol)) } : null,
131
+ stale: !!sources.staleFlags?.some(Boolean), from, to,
132
+ };
60
133
  }
@@ -1,35 +1,55 @@
1
1
  import type { HeadlessPaneDefinition } from "../../../types/plugin";
2
2
  import { fetchEarningsCalendar } from "../earnings/client";
3
3
  import { fetchSupplyChain } from "../supply-chain/client";
4
+ import { fetchSupplyGraph } from "../supply-chain/graph-client";
4
5
  import { loadRipple } from "./client";
5
- import { revenueOwner } from "./model";
6
+ import { hopLabel, revenueOwner } from "./model";
6
7
 
7
8
  const percent = (value: unknown) => typeof value === "number" ? `${(value * 100).toFixed(1)}%` : "--";
8
9
 
9
10
  export const earningsRippleHeadless: HeadlessPaneDefinition<"bundle"> = {
10
11
  shape: "bundle",
12
+ freshness: { source: "SEC filings and Gloom Cloud", status: "not-a-feed", basis: "filings and earnings calendar" },
11
13
  argument: { kind: "symbol-list", placeholder: "tickers", description: "Holdings to check against their customers' and suppliers' report dates.", minimum: 1, maximum: 60 },
12
- options: [],
14
+ options: [{ key: "tab", type: "enum", settingKey: "tab", defaultValue: "direct", values: [{ value: "direct" }, { value: "two-hop" }],
15
+ description: "Direct customers and suppliers, or also companies two hops away (Pro)." }],
13
16
  describe: (args) => `RIPL ${args.symbols.join(", ")}`,
14
- discovery: { screenshotReadiness: "live-dom", limitations: ["Customers each holding names in its own US filings, and suppliers whose US filings name it, with a share of revenue."] },
17
+ discovery: { screenshotReadiness: "live-dom", limitations: ["Customers each holding names in its own US filings, and suppliers whose US filings name it, with a share of revenue.",
18
+ "Two hops: a supplier's supplier or a customer's customer from the supply chain graph, read from filings, company announcements and calls only, Pro only; companies already one hop away are left out."] },
15
19
  async load(args, ctx) {
20
+ const secondHop = args.options.tab === "two-hop";
16
21
  const snapshot = await loadRipple(args.symbols, {
17
22
  supplyChain: (symbol) => fetchSupplyChain(symbol, ctx.apiClient),
18
23
  calendar: (query) => fetchEarningsCalendar(query, ctx.apiClient),
19
- });
24
+ graph: (symbol, options) => fetchSupplyGraph(symbol, options, "", ctx.apiClient),
25
+ }, undefined, { secondHop });
20
26
  ctx.signal.throwIfAborted();
27
+ const second = snapshot.secondHop;
21
28
  return {
22
29
  sections: [{ title: `Customers and suppliers reporting ${snapshot.from} to ${snapshot.to}`, columns: [
23
30
  { key: "date", header: "Date" }, { key: "timing", header: "Time" }, { key: "company", header: "Reports" }, { key: "link", header: "Link" },
24
31
  { key: "holding", header: "Holding" }, { key: "pctOfRevenue", header: "Revenue %" }, { key: "revenueOf", header: "Of" }, { key: "averageMove", header: "Avg move", format: percent },
25
32
  { key: "holdingDate", header: "Holding reports" }, { key: "period", header: "Filing period" },
26
- ], rows: snapshot.rows.map((row) => ({ ...row, timing: row.timing?.toUpperCase() ?? null, link: row.link === "customer" ? "customer of" : "supplier to", revenueOf: revenueOwner(row) })) }],
27
- complete: snapshot.failures.length === 0 && snapshot.truncated.length === 0,
33
+ ], rows: snapshot.rows.map((row) => ({ ...row, timing: row.timing?.toUpperCase() ?? null, link: row.link === "customer" ? "customer of" : "supplier to", revenueOf: revenueOwner(row) })) },
34
+ ...(second && !second.locked ? [{ title: `Two hops away, reporting ${snapshot.from} to ${snapshot.to}`, columns: [
35
+ { key: "date", header: "Date" }, { key: "timing", header: "Time" }, { key: "company", header: "Reports" }, { key: "link", header: "Link" },
36
+ { key: "via", header: "Via" }, { key: "holding", header: "Holding" }, { key: "hop1", header: "Holding to via" }, { key: "hop2", header: "Via to company" },
37
+ { key: "exposure", header: "Estimated exposure" }, { key: "averageMove", header: "Avg move", format: percent }, { key: "holdingDate", header: "Holding reports" },
38
+ ], rows: second.rows.map((row) => ({ ...row, timing: row.timing?.toUpperCase() ?? null, link: row.link === "customer" ? "customer's customer" : "supplier's supplier",
39
+ hop1: hopLabel(row.hops[0]), hop2: hopLabel(row.hops[1]) })) }] : []),
40
+ ],
41
+ complete: snapshot.failures.length === 0 && snapshot.truncated.length === 0 && !second?.locked && !second?.failures.length && !second?.truncated.length,
28
42
  unavailableSymbols: snapshot.failures.map((failure) => failure.symbol),
29
43
  // Same wording as SPLC: the preview's cut hides relationships, it does not mean there are none.
30
44
  errors: [...snapshot.failures.map((failure) => `${failure.symbol}: ${failure.error}`),
31
- ...(snapshot.truncated.length ? ["Additional relationships need Gloom Pro"] : [])],
32
- metadata: { from: snapshot.from, to: snapshot.to, truncated: snapshot.truncated, unit: "percent of the seller's revenue, as the seller's filing discloses it", methodology: "docs/research-data.md#earnings-ripple" },
45
+ ...(snapshot.truncated.length ? ["Additional relationships need Gloom Pro"] : []),
46
+ ...(second?.locked ? ["Companies two hops away need Gloom Pro"] : []),
47
+ ...(second?.failures ?? []).map((failure) => `${failure.symbol} graph: ${failure.error}`),
48
+ // As SPLC words it: the graph stopped at a limit, so companies two hops away may be missing.
49
+ ...(second?.truncated ?? []).map(({ symbol, reasons }) => `${symbol}: ${reasons.length
50
+ ? `Graph search incomplete: ${reasons.join(", ").replaceAll("_", " ")}` : "Graph results are truncated"}`)],
51
+ metadata: { from: snapshot.from, to: snapshot.to, truncated: snapshot.truncated, ...(second ? { twoHopTruncated: second.truncated.map(({ symbol }) => symbol) } : {}),
52
+ unit: "percent of the seller's revenue, as the seller's filing discloses it", methodology: "docs/research-data.md#earnings-ripple" },
33
53
  };
34
54
  },
35
55
  };
@@ -18,8 +18,8 @@ export const earningsRippleModule: PluginModule = {
18
18
  }],
19
19
  paneTemplates: [{
20
20
  id: "earnings-ripple-pane", paneId: "earnings-ripple", label: "Earnings Ripple",
21
- description: "Customers of your holdings that report soon, with the share of each holding's revenue they make up.",
22
- keywords: ["ripl", "ripple", "earnings", "customers", "supply chain", "exposure", "read-through"],
21
+ description: "Customers and suppliers of your holdings that report soon, with the disclosed revenue share, and with Pro the companies two hops away.",
22
+ keywords: ["ripl", "ripple", "earnings", "customers", "supply chain", "exposure", "read-through", "suppliers", "two hop", "second order"],
23
23
  shortcut: { prefix: "RIPL", argPlaceholder: "tickers", argKind: "ticker-list", argOptional: true, openWithoutArg: true },
24
24
  headless: earningsRippleHeadless,
25
25
  canCreate: () => true,
@@ -1,7 +1,9 @@
1
1
  import type { EarningsCalendarReport, EarningsTiming } from "../../../api-client/earnings";
2
- import type { SupplyChainPayload, SupplyRow } from "../../../api-client/supply-chain";
2
+ import type { SupplyChainPayload, SupplyEntity, SupplyRow } from "../../../api-client/supply-chain";
3
+ import type { GraphPath, GraphPayload } from "../../../api-client/supply-chain-graph";
3
4
  import { isUsListingExchange } from "../../../utils/exchanges";
4
5
  import { MIN_AVERAGE_REPORTS } from "../earnings/board-model";
6
+ import { exposureLabel } from "../supply-chain/graph-model";
5
7
 
6
8
  /** Days ahead the calendar is read. */
7
9
  export const RIPPLE_DAYS = 30;
@@ -71,18 +73,24 @@ export function rippleCompanyTickers(chains: ReadonlyMap<string, SupplyChainPayl
71
73
  return [...companies];
72
74
  }
73
75
 
74
- /**
75
- * Customers a holding names in its own filings (`says`), and suppliers whose
76
- * filings name the holding as a customer (`names`), that report in the
77
- * calendar: soonest first, then by the share.
78
- */
79
- export function projectRipple(chains: ReadonlyMap<string, SupplyChainPayload>, reports: readonly EarningsCalendarReport[]): RippleRow[] {
76
+ /** Each company's soonest report in the window. */
77
+ function nextReports(reports: readonly EarningsCalendarReport[]) {
80
78
  const next = new Map<string, EarningsCalendarReport>();
81
79
  for (const report of reports) {
82
80
  const key = report.symbol.toUpperCase();
83
81
  const current = next.get(key);
84
82
  if (!current || report.date < current.date) next.set(key, report);
85
83
  }
84
+ return next;
85
+ }
86
+
87
+ /**
88
+ * Customers a holding names in its own filings (`says`), and suppliers whose
89
+ * filings name the holding as a customer (`names`), that report in the
90
+ * calendar: soonest first, then by the share.
91
+ */
92
+ export function projectRipple(chains: ReadonlyMap<string, SupplyChainPayload>, reports: readonly EarningsCalendarReport[]): RippleRow[] {
93
+ const next = nextReports(reports);
86
94
  const rows: RippleRow[] = [];
87
95
  for (const [holding, chain] of chains) {
88
96
  for (const { row, link } of rippleLinks(chain)) {
@@ -96,3 +104,85 @@ export function projectRipple(chains: ReadonlyMap<string, SupplyChainPayload>, r
96
104
  }
97
105
  return rows.sort((a, b) => a.date.localeCompare(b.date) || b.pctOfRevenue - a.pctOfRevenue || a.holding.localeCompare(b.holding));
98
106
  }
107
+
108
+ /** One hop of a two-hop route, with the share the reporting company's filing discloses. */
109
+ export interface RippleHop {
110
+ /** Whose figure it is: the reporting company. */
111
+ owner: string;
112
+ pct: number | null;
113
+ basis: SupplyRow["pctBasis"];
114
+ scoped: boolean;
115
+ }
116
+
117
+ export interface SecondHopRow extends Omit<RippleRow, "pctOfRevenue" | "pctScope" | "period"> {
118
+ /** The company between the holding and the one that reports. */
119
+ via: string;
120
+ viaName: string;
121
+ /** Holding to via, then via to the company. */
122
+ hops: [RippleHop, RippleHop];
123
+ /** Chained estimate along the route, when every hop's figure is compatible. */
124
+ exposure: string | null;
125
+ }
126
+
127
+ const entityLabel = (entity: SupplyEntity) => entity.ticker?.toUpperCase() ?? entity.name;
128
+
129
+ interface SecondHopLink { holding: string; company: SupplyEntity; via: SupplyEntity; link: "customer" | "supplier"; path: GraphPath; graph: GraphPayload }
130
+
131
+ /**
132
+ * Companies two disclosed hops from each holding: a supplier's supplier
133
+ * (upstream) or a customer's customer (downstream). Anyone the holding already
134
+ * has a direct link with, in its disclosures or in the graph, is hop 1 and is
135
+ * left out, as are companies outside the US calendar. One row per holding and
136
+ * company: the higher-scoring route when both directions reach it.
137
+ */
138
+ export function secondHopLinks(chains: ReadonlyMap<string, SupplyChainPayload>, graphs: ReadonlyMap<string, GraphPayload>): SecondHopLink[] {
139
+ const result: SecondHopLink[] = [];
140
+ for (const [holding, graph] of graphs) {
141
+ const chain = chains.get(holding);
142
+ const nodes = new Map(graph.nodes.map((node) => [node.id, node]));
143
+ const reaches = [...graph.upstream, ...graph.downstream];
144
+ const direct = new Set([holding.toUpperCase(),
145
+ ...[...chain?.says ?? [], ...chain?.names ?? []].flatMap((row) => row.counterparty.ticker ? [row.counterparty.ticker.toUpperCase()] : []),
146
+ ...reaches.filter((reach) => reach.hops === 1).flatMap((reach) => nodes.get(reach.entityId)?.ticker?.toUpperCase() ?? [])]);
147
+ const best = new Map<string, SecondHopLink>();
148
+ for (const reach of reaches) {
149
+ const path = reach.shortestPath;
150
+ const company = nodes.get(reach.entityId);
151
+ const via = nodes.get(path.nodeIds[1] ?? "");
152
+ const ticker = company?.ticker?.toUpperCase();
153
+ if (reach.hops !== 2 || path.hops !== 2 || !company || !via || !ticker || company.aggregate || direct.has(ticker)) continue;
154
+ if (company.exchange && !isUsListingExchange(company.exchange)) continue;
155
+ const current = best.get(ticker);
156
+ if (!current || path.score > current.path.score) best.set(ticker, { holding, company, via, link: reach.direction === "upstream" ? "supplier" : "customer", path, graph });
157
+ }
158
+ result.push(...best.values());
159
+ }
160
+ return result;
161
+ }
162
+
163
+ function hopShare(graph: GraphPayload, linkId: string): RippleHop {
164
+ const link = graph.links.find((entry) => entry.id === linkId);
165
+ const evidence = link?.evidence.find((item) => item.id === link.primaryEvidenceId);
166
+ return { owner: evidence ? entityLabel(evidence.reporter) : "--", pct: evidence?.pctOfRevenue ?? null, basis: evidence?.pctBasis ?? null, scoped: !!evidence?.pctScope };
167
+ }
168
+
169
+ /** `30% of TSM`, `12% of AVGO purchases`, or `--` where the filing names the link without a figure. */
170
+ export function hopLabel(hop: RippleHop) {
171
+ if (hop.pct == null) return "--";
172
+ return `${hop.pct}%${hop.scoped ? "*" : ""} of ${hop.owner}${hop.basis && hop.basis !== "revenue" ? ` ${hop.basis}` : ""}`;
173
+ }
174
+
175
+ export function projectSecondHop(chains: ReadonlyMap<string, SupplyChainPayload>, graphs: ReadonlyMap<string, GraphPayload>, reports: readonly EarningsCalendarReport[]): SecondHopRow[] {
176
+ const next = nextReports(reports);
177
+ const rows: SecondHopRow[] = [];
178
+ for (const { holding, company, via, link, path, graph } of secondHopLinks(chains, graphs)) {
179
+ const ticker = company.ticker!.toUpperCase();
180
+ const report = next.get(ticker);
181
+ if (!report) continue;
182
+ rows.push({ id: `${holding}:${link}:2:${ticker}`, company: ticker, companyName: report.name ?? company.name, link, date: report.date, timing: report.timing,
183
+ averageMove: report.averageReports >= MIN_AVERAGE_REPORTS ? report.averageMove : null, holding, holdingDate: next.get(holding.toUpperCase())?.date ?? null,
184
+ via: entityLabel(via), viaName: via.name, hops: [hopShare(graph, path.linkIds[0]!), hopShare(graph, path.linkIds[1]!)],
185
+ exposure: path.exposure ? exposureLabel(path, graph) : null });
186
+ }
187
+ return rows.sort((a, b) => a.date.localeCompare(b.date) || a.holding.localeCompare(b.holding) || a.company.localeCompare(b.company));
188
+ }