gloomberb 0.18.3 → 0.18.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (886) hide show
  1. package/README.md +8 -8
  2. package/README.zh-CN.md +11 -11
  3. package/bin/{gloomberb → gloom} +3 -1
  4. package/package.json +6 -2
  5. package/src/account/checkout-handoff.tsx +225 -0
  6. package/src/account/device-signin-dialog.tsx +2 -2
  7. package/src/account/device-signin.ts +2 -2
  8. package/src/account/upgrade-dialog.tsx +1 -1
  9. package/src/api-client/askg.ts +2 -2
  10. package/src/api-client/auth.ts +2 -2
  11. package/src/api-client/central-bank-rates.ts +6 -0
  12. package/src/api-client/collections.ts +5 -1
  13. package/src/api-client/cot.ts +2 -0
  14. package/src/api-client/crypto-etf-flows.ts +37 -0
  15. package/src/api-client/crypto-markets.ts +60 -0
  16. package/src/api-client/data.ts +84 -5
  17. package/src/api-client/doe.ts +15 -0
  18. package/src/api-client/equity-screener.ts +28 -0
  19. package/src/api-client/exchange-announcements.ts +38 -0
  20. package/src/api-client/fund-facts.ts +39 -0
  21. package/src/api-client/futures-curve.ts +9 -1
  22. package/src/api-client/hiring.ts +301 -0
  23. package/src/api-client/index.ts +22 -5
  24. package/src/api-client/market-discovery.ts +14 -0
  25. package/src/api-client/members.ts +6 -0
  26. package/src/api-client/mna.ts +6 -0
  27. package/src/api-client/paths.ts +18 -1
  28. package/src/api-client/request.ts +21 -4
  29. package/src/api-client/short-side-publications.ts +37 -0
  30. package/src/api-client/socket.ts +64 -4
  31. package/src/api-client/swap-curve.ts +35 -0
  32. package/src/api-client/themes.ts +7 -1
  33. package/src/api-client/types.ts +90 -2
  34. package/src/app/pane-runtime/plugin-bindings.ts +9 -2
  35. package/src/app/runtime/desktop-deeplink.ts +5 -5
  36. package/src/app/runtime/plugin-bindings.ts +2 -2
  37. package/src/app/runtime/startup.ts +13 -0
  38. package/src/app/star-prompt/status-line.tsx +2 -2
  39. package/src/architecture/core-builtin-allowlist.json +5 -2
  40. package/src/architecture/ui-literals-allowlist.json +3 -3
  41. package/src/architecture/ui-tokens-allowlist.json +1 -1
  42. package/src/brokers/broker-portfolio-sync.ts +37 -0
  43. package/src/brokers/directory.ts +11 -0
  44. package/src/brokers/logos.ts +3 -1
  45. package/src/brokers/signed-in/adapter.ts +304 -26
  46. package/src/brokers/signed-in/client.ts +14 -2
  47. package/src/brokers/signed-in/connect.ts +10 -2
  48. package/src/brokers/sync-broker-instance.ts +9 -1
  49. package/src/capabilities/chart-series.ts +22 -6
  50. package/src/cli/bank-section.ts +1 -1
  51. package/src/cli/base-converter.ts +23 -14
  52. package/src/cli/central-bank-events.ts +1 -1
  53. package/src/cli/command-options.ts +59 -4
  54. package/src/cli/commands/api.ts +9 -6
  55. package/src/cli/commands/broker.ts +2 -2
  56. package/src/cli/commands/command-utils.ts +2 -2
  57. package/src/cli/commands/crypto-hints.ts +7 -20
  58. package/src/cli/commands/fred-series.ts +4 -2
  59. package/src/cli/commands/keybindings.ts +2 -2
  60. package/src/cli/commands/market.ts +1117 -264
  61. package/src/cli/commands/news-hints.ts +2 -2
  62. package/src/cli/commands/news-search.ts +59 -6
  63. package/src/cli/commands/options-leaps.ts +41 -26
  64. package/src/cli/commands/overview.ts +121 -48
  65. package/src/cli/commands/plugins.ts +9 -9
  66. package/src/cli/commands/remote.ts +13 -10
  67. package/src/cli/commands/search.ts +64 -44
  68. package/src/cli/commands/system.ts +27 -19
  69. package/src/cli/commands/themes.ts +1 -1
  70. package/src/cli/commands/ticker.ts +192 -47
  71. package/src/cli/context.ts +3 -2
  72. package/src/cli/desktop-pane-shot-view.ts +2 -2
  73. package/src/cli/desktop-pane-shot.ts +1 -1
  74. package/src/cli/earnings-calendar.ts +4 -4
  75. package/src/cli/entry.ts +18 -1
  76. package/src/cli/errors.ts +20 -2
  77. package/src/cli/exit-codes.ts +1 -1
  78. package/src/cli/export-source.ts +10 -4
  79. package/src/cli/freshness.ts +2 -8
  80. package/src/cli/fx-forward.ts +130 -0
  81. package/src/cli/fx-pair.ts +10 -9
  82. package/src/cli/glossary.ts +64 -20
  83. package/src/cli/help.ts +19 -13
  84. package/src/cli/history-export.ts +126 -0
  85. package/src/cli/history-rows.ts +196 -43
  86. package/src/cli/index-roots.ts +5 -45
  87. package/src/cli/index.ts +24 -18
  88. package/src/cli/known-gaps.ts +118 -25
  89. package/src/cli/listing-arg.ts +300 -41
  90. package/src/cli/name-entries.ts +30 -18
  91. package/src/cli/native-smoke.ts +2 -0
  92. package/src/cli/not-a-ticker.ts +19 -9
  93. package/src/cli/opentui-libc.ts +5 -0
  94. package/src/cli/options.ts +12 -0
  95. package/src/cli/pane-functions/capabilities.ts +75 -20
  96. package/src/cli/pane-functions/catalog.ts +24 -23
  97. package/src/cli/pane-functions/discovery.ts +1 -1
  98. package/src/cli/pane-functions/dom.ts +10 -7
  99. package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
  100. package/src/cli/pane-functions/freshness.ts +174 -23
  101. package/src/cli/pane-functions/function-help.ts +66 -27
  102. package/src/cli/pane-functions/headless.ts +24 -11
  103. package/src/cli/pane-functions/index.ts +18 -16
  104. package/src/cli/pane-functions/options.ts +22 -2
  105. package/src/cli/pane-functions/report-notices.ts +12 -4
  106. package/src/cli/pane-functions/report.ts +5 -5
  107. package/src/cli/pane-functions/resolver.ts +47 -10
  108. package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
  109. package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
  110. package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
  111. package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
  112. package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
  113. package/src/cli/pane-functions/screenshot-payload.ts +453 -0
  114. package/src/cli/pane-functions/screenshot-render.ts +316 -0
  115. package/src/cli/pane-functions/screenshot-types.ts +162 -0
  116. package/src/cli/pane-functions/shot-options.ts +8 -3
  117. package/src/cli/peso-dollar-rates.ts +79 -0
  118. package/src/cli/quote-answer.ts +38 -3
  119. package/src/cli/report-tables.ts +61 -16
  120. package/src/cli/restore-plugins.ts +29 -14
  121. package/src/cli/result.ts +111 -22
  122. package/src/cli/series-search.ts +5 -5
  123. package/src/cli/statement-filings.ts +19 -0
  124. package/src/cli/suffixed-listing-rows.ts +49 -0
  125. package/src/cli/symbol-args.ts +50 -15
  126. package/src/cli/symbol-cells.ts +120 -0
  127. package/src/cli/symbol-list.ts +198 -68
  128. package/src/cli/symbol-rows.ts +131 -25
  129. package/src/cli/ticker-resolution.ts +108 -11
  130. package/src/cli/treasury-yields.ts +5 -5
  131. package/src/cli/types.ts +2 -0
  132. package/src/cli/uncovered-instrument.ts +3 -3
  133. package/src/cli/unknown-command.ts +6 -6
  134. package/src/components/chart/composite/chart-layout.ts +131 -0
  135. package/src/components/chart/composite/composite-chart.tsx +373 -16
  136. package/src/components/chart/composite/interactions.ts +7 -2
  137. package/src/components/chart/composite/legend.tsx +75 -3
  138. package/src/components/chart/composite/levels.ts +5 -0
  139. package/src/components/chart/composite/panel-gestures.ts +41 -0
  140. package/src/components/chart/composite/panel-labels.ts +2 -1
  141. package/src/components/chart/composite/panel-surface.tsx +305 -11
  142. package/src/components/chart/composite/price-axis-labels.tsx +27 -3
  143. package/src/components/chart/composite/rasterizer.ts +44 -19
  144. package/src/components/chart/composite/scene.ts +16 -4
  145. package/src/components/chart/composite/text-renderer.ts +48 -21
  146. package/src/components/chart/composite/toolbar.tsx +52 -5
  147. package/src/components/chart/composite/types.ts +13 -0
  148. package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
  149. package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
  150. package/src/components/chart/composite/use-composite-viewport.ts +12 -3
  151. package/src/components/chart/composite/value-scale.ts +149 -0
  152. package/src/components/chart/composite/volume-profile-paint.ts +6 -3
  153. package/src/components/chart/core/pointer.ts +2 -0
  154. package/src/components/chart-table/index.ts +2 -0
  155. package/src/components/chart-table/read.tsx +74 -0
  156. package/src/components/command-bar/commands/collection-list.ts +41 -19
  157. package/src/components/command-bar/commands/collection.ts +9 -3
  158. package/src/components/command-bar/commands/direct/index.ts +1 -1
  159. package/src/components/command-bar/commands/direct/runtime.ts +3 -2
  160. package/src/components/command-bar/pane-templates/items.ts +59 -6
  161. package/src/components/command-bar/pane-templates/workflow.ts +10 -1
  162. package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
  163. package/src/components/command-bar/routes/root/provider-search.ts +42 -11
  164. package/src/components/command-bar/routes/root/results.ts +18 -4
  165. package/src/components/command-bar/routes/root/runtime.ts +15 -3
  166. package/src/components/command-bar/routes/root/search-providers.ts +25 -2
  167. package/src/components/command-bar/routes/root/selection.ts +6 -1
  168. package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
  169. package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
  170. package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
  171. package/src/components/command-bar/selection-runtime.ts +50 -10
  172. package/src/components/command-bar/surface/index.tsx +24 -2
  173. package/src/components/command-bar/view-model.ts +7 -0
  174. package/src/components/command-bar/workflow/broker.ts +2 -2
  175. package/src/components/command-bar/workflow/collection-actions.ts +46 -7
  176. package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
  177. package/src/components/command-bar/workflow/fields.ts +8 -2
  178. package/src/components/command-bar/workflow/ops.ts +18 -4
  179. package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
  180. package/src/components/command-bar/workflow/submit.ts +3 -2
  181. package/src/components/command-bar/workflow/tickers.ts +5 -1
  182. package/src/components/company-logo.tsx +39 -0
  183. package/src/components/data-table/sections.ts +4 -2
  184. package/src/components/form-modal/confirm.tsx +2 -1
  185. package/src/components/form-modal/request.ts +5 -0
  186. package/src/components/form-modal/routes.ts +4 -1
  187. package/src/components/index.ts +12 -6
  188. package/src/components/layout/header.tsx +7 -6
  189. package/src/components/layout/market-summary.ts +9 -6
  190. package/src/components/layout/pane/capture-status.ts +1 -1
  191. package/src/components/layout/pane/footer/model.ts +11 -5
  192. package/src/components/layout/shell/chrome.ts +19 -6
  193. package/src/components/layout/shell/index.tsx +2 -1
  194. package/src/components/layout/shell/pane/layers.tsx +19 -1
  195. package/src/components/layout/status-bar.tsx +2 -2
  196. package/src/components/market-board/index.tsx +11 -3
  197. package/src/components/onboarding/onboarding-wizard.tsx +1 -0
  198. package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
  199. package/src/components/onboarding/wizard-broker-sync.ts +4 -1
  200. package/src/components/pane-settings-dialog/desktop.tsx +20 -7
  201. package/src/components/pane-settings-dialog/tui.tsx +17 -9
  202. package/src/components/pane-settings-dialog/value.ts +8 -1
  203. package/src/components/pane-settings-dialog.tsx +44 -13
  204. package/src/components/sign-in-code-panel.tsx +27 -19
  205. package/src/components/ui/column-grid.tsx +48 -4
  206. package/src/components/ui/country-flag-art.tsx +180 -0
  207. package/src/components/ui/country-flag.tsx +118 -12
  208. package/src/components/ui/data-table/opentui/index.tsx +61 -2
  209. package/src/components/ui/data-table/opentui/model.ts +109 -2
  210. package/src/components/ui/data-table/types.ts +1 -1
  211. package/src/components/ui/display.tsx +5 -1
  212. package/src/components/ui/index.ts +3 -1
  213. package/src/components/ui/logo-mark.tsx +11 -2
  214. package/src/components/ui/query-bar.tsx +1 -1
  215. package/src/components/ui/row-notes.ts +79 -0
  216. package/src/core/state/app/layout.ts +4 -4
  217. package/src/data/cached-query.ts +8 -1
  218. package/src/data/config/chart-settings.ts +3 -3
  219. package/src/data/config/home.ts +10 -2
  220. package/src/data/config/layout.ts +4 -1
  221. package/src/data/config/store/node.ts +4 -0
  222. package/src/data/config/store/normalize.ts +13 -3
  223. package/src/data/config/store/portfolio-as-of-column.ts +2 -2
  224. package/src/data/json-storage.ts +2 -0
  225. package/src/data/saved-copies.ts +84 -0
  226. package/src/docs/snapshot.json +65 -32
  227. package/src/i18n/es.ts +29 -12
  228. package/src/i18n/ja.ts +29 -12
  229. package/src/i18n/ko.ts +29 -12
  230. package/src/i18n/zh-cn.ts +29 -12
  231. package/src/i18n/zh-tw.ts +29 -12
  232. package/src/layout/desks.ts +1 -1
  233. package/src/layout/launch-layout.ts +1 -1
  234. package/src/layout/pane-manager/floating-actions.ts +5 -3
  235. package/src/layout/pane-manager/floating.ts +43 -1
  236. package/src/layout/pane-manager/index.ts +2 -0
  237. package/src/layout/selected-ticker.ts +74 -0
  238. package/src/market-data/depositary-pair.ts +251 -0
  239. package/src/market-data/futures-board.ts +1 -1
  240. package/src/market-data/futures-contract.ts +124 -40
  241. package/src/market-data/fx-closes.ts +17 -2
  242. package/src/market-data/hooks.tsx +19 -11
  243. package/src/market-data/market/change-basis.ts +49 -7
  244. package/src/market-data/market/freshness.ts +34 -5
  245. package/src/market-data/market/period-return.ts +163 -0
  246. package/src/market-data/market/trading-sessions.ts +13 -0
  247. package/src/market-data/market/year-to-date.ts +8 -13
  248. package/src/market-data/performance.ts +20 -14
  249. package/src/market-data/perpetual-premium.ts +32 -0
  250. package/src/market-data/published-apac-sessions.ts +2 -1
  251. package/src/market-data/published-futures-sessions.ts +69 -0
  252. package/src/market-data/quotes/contributions.ts +5 -1
  253. package/src/market-data/quotes/freshness.ts +42 -0
  254. package/src/market-data/quotes/intraday-bar.ts +37 -0
  255. package/src/market-data/quotes/regular-session-valuation.ts +13 -8
  256. package/src/market-data/quotes/resolution.ts +4 -2
  257. package/src/market-data/tax-equivalent.ts +1 -1
  258. package/src/market-data/ticker-price-returns.ts +3 -1
  259. package/src/news/aggregator.ts +5 -1
  260. package/src/news/news-model.ts +4 -0
  261. package/src/news/types.ts +11 -0
  262. package/src/notifications/app-notifier.ts +1 -1
  263. package/src/plugins/auto-update.ts +2 -2
  264. package/src/plugins/builtin/account-management/index.tsx +1 -0
  265. package/src/plugins/builtin/account-management/pane.tsx +9 -8
  266. package/src/plugins/builtin/alerts/alert-engine.ts +29 -19
  267. package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
  268. package/src/plugins/builtin/alerts/cli.ts +485 -76
  269. package/src/plugins/builtin/alerts/command.ts +5 -10
  270. package/src/plugins/builtin/alerts/event-rows.ts +9 -5
  271. package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
  272. package/src/plugins/builtin/alerts/events.ts +107 -5
  273. package/src/plugins/builtin/alerts/fired-log.ts +78 -0
  274. package/src/plugins/builtin/alerts/format.ts +2 -1
  275. package/src/plugins/builtin/alerts/headless.ts +100 -39
  276. package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
  277. package/src/plugins/builtin/alerts/history-rows.ts +89 -0
  278. package/src/plugins/builtin/alerts/index.tsx +45 -18
  279. package/src/plugins/builtin/alerts/iv-level.ts +365 -0
  280. package/src/plugins/builtin/alerts/levels.ts +3 -3
  281. package/src/plugins/builtin/alerts/pane.tsx +97 -29
  282. package/src/plugins/builtin/alerts/price.ts +35 -0
  283. package/src/plugins/builtin/alerts/quotes.ts +24 -0
  284. package/src/plugins/builtin/alerts/research-builder.ts +84 -11
  285. package/src/plugins/builtin/alerts/research-rules.ts +76 -3
  286. package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
  287. package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
  288. package/src/plugins/builtin/alerts/scheduled.ts +188 -29
  289. package/src/plugins/builtin/alerts/storage.ts +13 -10
  290. package/src/plugins/builtin/alerts/targets.ts +12 -3
  291. package/src/plugins/builtin/analytics/index.tsx +8 -2
  292. package/src/plugins/builtin/analytics/metrics.ts +1 -1
  293. package/src/plugins/builtin/analytics/risk-book.ts +215 -0
  294. package/src/plugins/builtin/analytics/risk-client.ts +13 -6
  295. package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
  296. package/src/plugins/builtin/analytics/risk-math.ts +6 -3
  297. package/src/plugins/builtin/analytics/risk-model.ts +297 -104
  298. package/src/plugins/builtin/analytics/risk-options.ts +17 -2
  299. package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
  300. package/src/plugins/builtin/attention/pane.tsx +6 -2
  301. package/src/plugins/builtin/awards/headless.ts +7 -3
  302. package/src/plugins/builtin/awards/model.ts +18 -0
  303. package/src/plugins/builtin/awards/pane.tsx +6 -3
  304. package/src/plugins/builtin/backtest/headless.ts +3 -3
  305. package/src/plugins/builtin/backtest/rules.ts +41 -5
  306. package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
  307. package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
  308. package/src/plugins/builtin/broker-manager/footer.ts +27 -11
  309. package/src/plugins/builtin/broker-manager/index.tsx +21 -12
  310. package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
  311. package/src/plugins/builtin/broker-manager/model.ts +12 -2
  312. package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
  313. package/src/plugins/builtin/broker-manager/table.ts +28 -12
  314. package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
  315. package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
  316. package/src/plugins/builtin/broker-trading/controller.ts +45 -13
  317. package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
  318. package/src/plugins/builtin/broker-trading/headless.ts +2 -1
  319. package/src/plugins/builtin/broker-trading/index.tsx +7 -1
  320. package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
  321. package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
  322. package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
  323. package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
  324. package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
  325. package/src/plugins/builtin/broker-trading/pane.tsx +110 -23
  326. package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
  327. package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
  328. package/src/plugins/builtin/buildout/cells.tsx +4 -0
  329. package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
  330. package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
  331. package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
  332. package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
  333. package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
  334. package/src/plugins/builtin/catalysts/detail.tsx +3 -2
  335. package/src/plugins/builtin/catalysts/index.tsx +1 -1
  336. package/src/plugins/builtin/catalysts/model.ts +49 -4
  337. package/src/plugins/builtin/catalysts/pane.tsx +6 -8
  338. package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
  339. package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
  340. package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
  341. package/src/plugins/builtin/changelog/index.tsx +1 -0
  342. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
  343. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
  344. package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
  345. package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
  346. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
  347. package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
  348. package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
  349. package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
  350. package/src/plugins/builtin/chart-composer/headless.ts +253 -35
  351. package/src/plugins/builtin/chart-composer/index.tsx +12 -2
  352. package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
  353. package/src/plugins/builtin/chart-composer/pane.tsx +127 -28
  354. package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
  355. package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
  356. package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
  357. package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
  358. package/src/plugins/builtin/chart-composer/settings.ts +31 -19
  359. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
  360. package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
  361. package/src/plugins/builtin/chat/attachments/model.ts +3 -1
  362. package/src/plugins/builtin/chat/content/index.tsx +1 -1
  363. package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
  364. package/src/plugins/builtin/chat/people.ts +1 -1
  365. package/src/plugins/builtin/clinical-trials/client.ts +5 -2
  366. package/src/plugins/builtin/clinical-trials/model.ts +13 -4
  367. package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
  368. package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
  369. package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
  370. package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
  371. package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
  372. package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
  373. package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
  374. package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
  375. package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
  376. package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
  377. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  378. package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
  379. package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
  380. package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
  381. package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
  382. package/src/plugins/builtin/company-attention/building-model.ts +222 -0
  383. package/src/plugins/builtin/company-attention/building.tsx +172 -0
  384. package/src/plugins/builtin/company-attention/client.ts +117 -1
  385. package/src/plugins/builtin/company-attention/evidence.ts +16 -3
  386. package/src/plugins/builtin/company-attention/headless.ts +101 -5
  387. package/src/plugins/builtin/company-attention/index.tsx +6 -3
  388. package/src/plugins/builtin/company-attention/model.ts +33 -7
  389. package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
  390. package/src/plugins/builtin/company-attention/moves.tsx +159 -0
  391. package/src/plugins/builtin/company-attention/pane.tsx +79 -23
  392. package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
  393. package/src/plugins/builtin/company-attention/signals.tsx +160 -0
  394. package/src/plugins/builtin/company-kpis/headless.ts +3 -2
  395. package/src/plugins/builtin/company-kpis/model.ts +2 -2
  396. package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
  397. package/src/plugins/builtin/composite-plugins.ts +2 -1
  398. package/src/plugins/builtin/congress-trades/headless.ts +1 -1
  399. package/src/plugins/builtin/connections/index.ts +1 -0
  400. package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
  401. package/src/plugins/builtin/correlation/headless.ts +5 -3
  402. package/src/plugins/builtin/cot/headless.ts +28 -6
  403. package/src/plugins/builtin/cot/model.ts +12 -0
  404. package/src/plugins/builtin/cot/pane.tsx +3 -2
  405. package/src/plugins/builtin/cpi/headless.ts +5 -1
  406. package/src/plugins/builtin/cpi/pane.tsx +11 -9
  407. package/src/plugins/builtin/credit-boards/model.ts +2 -0
  408. package/src/plugins/builtin/credit-documents/headless.ts +1 -1
  409. package/src/plugins/builtin/crypto-board/client.ts +86 -0
  410. package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
  411. package/src/plugins/builtin/crypto-board/defi.ts +239 -0
  412. package/src/plugins/builtin/crypto-board/headless.ts +117 -6
  413. package/src/plugins/builtin/crypto-board/index.tsx +8 -3
  414. package/src/plugins/builtin/crypto-board/model.ts +40 -8
  415. package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
  416. package/src/plugins/builtin/crypto-board/series.ts +19 -1
  417. package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
  418. package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
  419. package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
  420. package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
  421. package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
  422. package/src/plugins/builtin/debug/index.tsx +1 -0
  423. package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
  424. package/src/plugins/builtin/docs/index.tsx +1 -1
  425. package/src/plugins/builtin/docs/pane.tsx +2 -2
  426. package/src/plugins/builtin/docs/targets.ts +1 -1
  427. package/src/plugins/builtin/doe/client.ts +5 -1
  428. package/src/plugins/builtin/doe/headless.ts +12 -6
  429. package/src/plugins/builtin/doe/model.ts +43 -6
  430. package/src/plugins/builtin/doe/pane.tsx +18 -11
  431. package/src/plugins/builtin/earnings/board-model.ts +13 -6
  432. package/src/plugins/builtin/earnings/board-table.ts +4 -1
  433. package/src/plugins/builtin/earnings/board.tsx +253 -50
  434. package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
  435. package/src/plugins/builtin/earnings/calendar.tsx +338 -0
  436. package/src/plugins/builtin/earnings/client.ts +4 -3
  437. package/src/plugins/builtin/earnings/headless.ts +53 -15
  438. package/src/plugins/builtin/earnings/history-model.ts +53 -36
  439. package/src/plugins/builtin/earnings/index.tsx +15 -22
  440. package/src/plugins/builtin/earnings/model.ts +17 -12
  441. package/src/plugins/builtin/earnings/scope.ts +89 -0
  442. package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
  443. package/src/plugins/builtin/earnings-calls/data.ts +146 -2
  444. package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
  445. package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
  446. package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
  447. package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
  448. package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
  449. package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
  450. package/src/plugins/builtin/econ/calendar-model.ts +132 -20
  451. package/src/plugins/builtin/econ/detail-view.tsx +48 -10
  452. package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
  453. package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
  454. package/src/plugins/builtin/econ/index.tsx +112 -25
  455. package/src/plugins/builtin/econ/print-watch.ts +2 -1
  456. package/src/plugins/builtin/econ/types.ts +32 -1
  457. package/src/plugins/builtin/econ-statistics/client.ts +16 -3
  458. package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
  459. package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
  460. package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
  461. package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
  462. package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
  463. package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
  464. package/src/plugins/builtin/econ-statistics/view.ts +16 -1
  465. package/src/plugins/builtin/equity-screener/client.ts +21 -3
  466. package/src/plugins/builtin/equity-screener/headless.ts +68 -6
  467. package/src/plugins/builtin/equity-screener/live.ts +1 -1
  468. package/src/plugins/builtin/equity-screener/model.ts +6 -0
  469. package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
  470. package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
  471. package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
  472. package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
  473. package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
  474. package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
  475. package/src/plugins/builtin/exposure/headless.ts +51 -6
  476. package/src/plugins/builtin/exposure/index.tsx +28 -2
  477. package/src/plugins/builtin/exposure/model.ts +7 -0
  478. package/src/plugins/builtin/exposure/pane.tsx +6 -1
  479. package/src/plugins/builtin/fear-greed/index.tsx +1 -1
  480. package/src/plugins/builtin/filing-events/index.tsx +1 -1
  481. package/src/plugins/builtin/futures/model.ts +10 -9
  482. package/src/plugins/builtin/futures/returns.ts +8 -36
  483. package/src/plugins/builtin/futures/table.tsx +1 -1
  484. package/src/plugins/builtin/futures-curve/client.ts +40 -9
  485. package/src/plugins/builtin/futures-curve/headless.ts +39 -17
  486. package/src/plugins/builtin/futures-curve/model.ts +258 -69
  487. package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
  488. package/src/plugins/builtin/fx-matrix/client.ts +15 -8
  489. package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
  490. package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
  491. package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
  492. package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
  493. package/src/plugins/builtin/gpu/headless.ts +9 -4
  494. package/src/plugins/builtin/help/index.tsx +13 -3
  495. package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
  496. package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
  497. package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
  498. package/src/plugins/builtin/holders/client.ts +13 -1
  499. package/src/plugins/builtin/holders/format.ts +28 -17
  500. package/src/plugins/builtin/holders/headless.ts +46 -7
  501. package/src/plugins/builtin/holders/index-holders.ts +264 -0
  502. package/src/plugins/builtin/holders/pane.tsx +79 -15
  503. package/src/plugins/builtin/holders/report-rows.ts +35 -7
  504. package/src/plugins/builtin/holders/table-model.ts +2 -1
  505. package/src/plugins/builtin/holders/treemap.tsx +2 -2
  506. package/src/plugins/builtin/insider/headless.ts +1 -1
  507. package/src/plugins/builtin/insider/signals-client.ts +1 -1
  508. package/src/plugins/builtin/insider/signals.tsx +1 -1
  509. package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
  510. package/src/plugins/builtin/iv-history/client.ts +20 -0
  511. package/src/plugins/builtin/iv-history/headless.ts +4 -4
  512. package/src/plugins/builtin/iv-history/index.tsx +1 -1
  513. package/src/plugins/builtin/iv-history/model.ts +13 -4
  514. package/src/plugins/builtin/iv-history/series.ts +3 -1
  515. package/src/plugins/builtin/jobs/lock-note.ts +1 -1
  516. package/src/plugins/builtin/jobs/model.ts +4 -15
  517. package/src/plugins/builtin/jobs/pane.tsx +7 -5
  518. package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
  519. package/src/plugins/builtin/jodi/pane.tsx +10 -4
  520. package/src/plugins/builtin/layout-manager/index.tsx +1 -0
  521. package/src/plugins/builtin/macro-day/headless.ts +20 -7
  522. package/src/plugins/builtin/macro-day/index.tsx +3 -2
  523. package/src/plugins/builtin/macro-day/model.ts +29 -8
  524. package/src/plugins/builtin/macro-day/pane.tsx +46 -10
  525. package/src/plugins/builtin/macro-day/releases.ts +55 -13
  526. package/src/plugins/builtin/market-heatmap/data.ts +9 -2
  527. package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
  528. package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
  529. package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
  530. package/src/plugins/builtin/market-heatmap/model.ts +10 -7
  531. package/src/plugins/builtin/market-movers/client.ts +33 -19
  532. package/src/plugins/builtin/market-movers/headless.ts +8 -2
  533. package/src/plugins/builtin/market-movers/index.tsx +16 -10
  534. package/src/plugins/builtin/market-movers/screener.ts +29 -8
  535. package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
  536. package/src/plugins/builtin/market-movers/session-table.ts +4 -2
  537. package/src/plugins/builtin/market-movers/table.ts +4 -1
  538. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  539. package/src/plugins/builtin/market-valuation/view.ts +5 -0
  540. package/src/plugins/builtin/members/headless.ts +6 -5
  541. package/src/plugins/builtin/members/pane.tsx +11 -4
  542. package/src/plugins/builtin/mna/client.ts +1 -0
  543. package/src/plugins/builtin/mna/detail.tsx +20 -32
  544. package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
  545. package/src/plugins/builtin/mna/distress/model.ts +3 -2
  546. package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
  547. package/src/plugins/builtin/mna/headless.ts +6 -13
  548. package/src/plugins/builtin/mna/model.ts +93 -15
  549. package/src/plugins/builtin/mna/pane.tsx +5 -4
  550. package/src/plugins/builtin/news/headless.ts +12 -6
  551. package/src/plugins/builtin/news/index.tsx +10 -1
  552. package/src/plugins/builtin/news/wire/index.tsx +3 -2
  553. package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
  554. package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
  555. package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
  556. package/src/plugins/builtin/notes/cli.ts +49 -14
  557. package/src/plugins/builtin/openfda/pane.tsx +1 -1
  558. package/src/plugins/builtin/options/carry.ts +2 -2
  559. package/src/plugins/builtin/options/index.tsx +1 -1
  560. package/src/plugins/builtin/options/view.tsx +10 -10
  561. package/src/plugins/builtin/options-calculator/headless.ts +46 -7
  562. package/src/plugins/builtin/options-scenario/client.ts +123 -28
  563. package/src/plugins/builtin/options-scenario/collar.ts +8 -6
  564. package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
  565. package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
  566. package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
  567. package/src/plugins/builtin/options-scenario/csp.ts +101 -21
  568. package/src/plugins/builtin/options-scenario/headless.ts +36 -15
  569. package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
  570. package/src/plugins/builtin/options-scenario/index.tsx +28 -3
  571. package/src/plugins/builtin/options-scenario/model.ts +13 -0
  572. package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
  573. package/src/plugins/builtin/perps/equity-row.tsx +11 -3
  574. package/src/plugins/builtin/perps/freshness.ts +8 -5
  575. package/src/plugins/builtin/perps/headless.ts +3 -1
  576. package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
  577. package/src/plugins/builtin/perps/live-rows.ts +161 -0
  578. package/src/plugins/builtin/perps/markets-section.tsx +154 -0
  579. package/src/plugins/builtin/perps/pane.tsx +36 -17
  580. package/src/plugins/builtin/perps/venue-markets.ts +96 -0
  581. package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
  582. package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
  583. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
  584. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
  585. package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
  586. package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
  587. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
  588. package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
  589. package/src/plugins/builtin/portfolio-list/income.ts +13 -2
  590. package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
  591. package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
  592. package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
  593. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
  594. package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
  595. package/src/plugins/builtin/power/client.ts +4 -1
  596. package/src/plugins/builtin/power/evidence.ts +22 -7
  597. package/src/plugins/builtin/power/gas.tsx +5 -1
  598. package/src/plugins/builtin/power/pane.tsx +8 -1
  599. package/src/plugins/builtin/power/prices.tsx +10 -3
  600. package/src/plugins/builtin/research/analyst-headless.ts +25 -8
  601. package/src/plugins/builtin/research/analyst-model.ts +68 -3
  602. package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
  603. package/src/plugins/builtin/research/event-model.ts +3 -1
  604. package/src/plugins/builtin/research/event-sources.ts +12 -4
  605. package/src/plugins/builtin/research/index.tsx +2 -1
  606. package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
  607. package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
  608. package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
  609. package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
  610. package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
  611. package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
  612. package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
  613. package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
  614. package/src/plugins/builtin/risk-factors/index.tsx +2 -2
  615. package/src/plugins/builtin/scanner/lock-note.ts +1 -1
  616. package/src/plugins/builtin/sec/forms.ts +13 -0
  617. package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
  618. package/src/plugins/builtin/sec/fund-facts.ts +68 -8
  619. package/src/plugins/builtin/sec/headless.ts +85 -8
  620. package/src/plugins/builtin/sec/index.tsx +58 -12
  621. package/src/plugins/builtin/sectors/client.ts +2 -1
  622. package/src/plugins/builtin/sectors/sector-model.ts +11 -15
  623. package/src/plugins/builtin/series-inventory.ts +2 -0
  624. package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
  625. package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
  626. package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
  627. package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
  628. package/src/plugins/builtin/shared/earnings-report.ts +3 -3
  629. package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
  630. package/src/plugins/builtin/shared/job-posting.ts +129 -0
  631. package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
  632. package/src/plugins/builtin/shared/report-freshness.ts +3 -0
  633. package/src/plugins/builtin/shared/research-trading.tsx +21 -0
  634. package/src/plugins/builtin/shared/series-cache.ts +2 -0
  635. package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
  636. package/src/plugins/builtin/short-interest/client.ts +2 -0
  637. package/src/plugins/builtin/short-interest/headless.ts +41 -12
  638. package/src/plugins/builtin/short-interest/index.tsx +23 -1
  639. package/src/plugins/builtin/short-interest/model.ts +70 -19
  640. package/src/plugins/builtin/short-interest/pane.tsx +19 -2
  641. package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
  642. package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
  643. package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
  644. package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
  645. package/src/plugins/builtin/short-interest/schedule.ts +35 -2
  646. package/src/plugins/builtin/short-interest/surface.tsx +11 -4
  647. package/src/plugins/builtin/short-interest/types.ts +9 -0
  648. package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
  649. package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
  650. package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
  651. package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
  652. package/src/plugins/builtin/supply-chain/model.ts +51 -3
  653. package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
  654. package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
  655. package/src/plugins/builtin/themes/headless.ts +8 -5
  656. package/src/plugins/builtin/themes/model.ts +14 -4
  657. package/src/plugins/builtin/themes/pane.tsx +24 -5
  658. package/src/plugins/builtin/thirteenf/headless.ts +5 -5
  659. package/src/plugins/builtin/thirteenf/signals.ts +3 -1
  660. package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
  661. package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
  662. package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
  663. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
  664. package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
  665. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
  666. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
  667. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
  668. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
  669. package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
  670. package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
  671. package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
  672. package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
  673. package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
  674. package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
  675. package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
  676. package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
  677. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
  678. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
  679. package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
  680. package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
  681. package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
  682. package/src/plugins/builtin/vol-surface/client.ts +5 -4
  683. package/src/plugins/builtin/vol-surface/headless.ts +12 -3
  684. package/src/plugins/builtin/vol-surface/model.ts +4 -2
  685. package/src/plugins/builtin/volatility/model.ts +5 -10
  686. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
  687. package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
  688. package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
  689. package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
  690. package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
  691. package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
  692. package/src/plugins/builtin/world-venue-map/index.ts +3 -26
  693. package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
  694. package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
  695. package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
  696. package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
  697. package/src/plugins/builtin/yield-curve/client.ts +25 -0
  698. package/src/plugins/builtin/yield-curve/curves.ts +7 -4
  699. package/src/plugins/builtin/yield-curve/headless.ts +38 -4
  700. package/src/plugins/builtin/yield-curve/history.ts +4 -3
  701. package/src/plugins/builtin/yield-curve/index.tsx +12 -6
  702. package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
  703. package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
  704. package/src/plugins/bundle.ts +1 -1
  705. package/src/plugins/catalog-browser.ts +2 -1
  706. package/src/plugins/compat.ts +3 -3
  707. package/src/plugins/dependencies.ts +75 -14
  708. package/src/plugins/extracted-plugins.ts +132 -34
  709. package/src/plugins/host-link.ts +149 -34
  710. package/src/plugins/installer.ts +35 -10
  711. package/src/plugins/loader.ts +206 -38
  712. package/src/plugins/manager-node.ts +2 -2
  713. package/src/plugins/marketplace/deactivation.ts +22 -0
  714. package/src/plugins/marketplace/model.ts +2 -2
  715. package/src/plugins/marketplace/packs.ts +1 -1
  716. package/src/plugins/ownership.ts +1 -1
  717. package/src/plugins/peer-retry.ts +155 -0
  718. package/src/plugins/registry/contributions.ts +3 -1
  719. package/src/plugins/registry/index.ts +4 -3
  720. package/src/plugins/registry/plugin-state.ts +3 -0
  721. package/src/plugins/seed-notice.ts +20 -0
  722. package/src/plugins/shortcut-argument.ts +39 -0
  723. package/src/portfolio/allocation.ts +1 -1
  724. package/src/portfolio/collection-name.ts +31 -0
  725. package/src/portfolio/column-values.ts +10 -8
  726. package/src/portfolio/cost-fx.ts +296 -19
  727. package/src/portfolio/manual-lots.ts +75 -0
  728. package/src/portfolio/mutations.ts +60 -22
  729. package/src/portfolio/suffixed-listings.ts +209 -0
  730. package/src/portfolio/totals-currency.ts +24 -0
  731. package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
  732. package/src/public/time-series.ts +11 -8
  733. package/src/remote/schema.ts +1 -1
  734. package/src/renderers/browser/config-host.ts +3 -0
  735. package/src/renderers/browser/main.tsx +23 -3
  736. package/src/renderers/dom/boot-frame-page.ts +187 -0
  737. package/src/renderers/dom/boot-frame.ts +237 -0
  738. package/src/renderers/dom/build-assets.ts +46 -8
  739. package/src/renderers/dom/dom-ui-host.tsx +4 -29
  740. package/src/renderers/dom/host/ascii-text.ts +16 -2
  741. package/src/renderers/dom/host/box.tsx +43 -2
  742. package/src/renderers/dom/host/chart-surface.tsx +2 -0
  743. package/src/renderers/dom/host/hls.chunk.ts +3 -0
  744. package/src/renderers/dom/host/image-surface.tsx +49 -0
  745. package/src/renderers/dom/host/media-surface.tsx +24 -18
  746. package/src/renderers/dom/host/mouse.ts +30 -0
  747. package/src/renderers/dom/host/size-observer.ts +1 -1
  748. package/src/renderers/dom/host/style.ts +1 -1
  749. package/src/renderers/dom/styles.css +76 -0
  750. package/src/renderers/dom/test-utils.tsx +2 -1
  751. package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
  752. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
  753. package/src/renderers/electrobun/bun/desktop/backend.ts +46 -3
  754. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
  755. package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
  756. package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
  757. package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
  758. package/src/renderers/electrobun/bun/index.ts +11 -1
  759. package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
  760. package/src/renderers/electrobun/bun/window/create.ts +4 -1
  761. package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
  762. package/src/renderers/electrobun/shared/protocol.ts +6 -1
  763. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
  764. package/src/renderers/electrobun/view/config-host.ts +3 -0
  765. package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
  766. package/src/renderers/electrobun/view/main.tsx +30 -4
  767. package/src/renderers/electrobun/view/news-source.ts +5 -5
  768. package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
  769. package/src/renderers/electrobun/view/ui-host.tsx +1 -1
  770. package/src/renderers/opentui/browser-open.ts +88 -0
  771. package/src/renderers/opentui/host.tsx +5 -14
  772. package/src/renderers/opentui/image/loader.ts +3 -2
  773. package/src/renderers/opentui/native-smoke.ts +10 -1
  774. package/src/renderers/opentui/pane-image/index.ts +2 -1
  775. package/src/renderers/opentui/render-lib.ts +253 -0
  776. package/src/renderers/opentui/render-timing-smoke.ts +1 -1
  777. package/src/renderers/opentui/start.tsx +1 -1
  778. package/src/renderers/share/layout-view.tsx +2 -2
  779. package/src/renderers/share/main.tsx +4 -4
  780. package/src/renderers/share/view.tsx +1 -1
  781. package/src/series/resolve.ts +22 -6
  782. package/src/series/standalone.ts +30 -2
  783. package/src/series/types.ts +8 -1
  784. package/src/shares/api.ts +4 -1
  785. package/src/shares/pane.ts +1 -1
  786. package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
  787. package/src/sources/gloomberb-cloud/index.ts +32 -16
  788. package/src/sources/gloomberb-cloud/news.ts +39 -0
  789. package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
  790. package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
  791. package/src/sources/listing-symbols.ts +37 -0
  792. package/src/sources/provider-errors.ts +16 -2
  793. package/src/sources/provider-router/financial-routes.ts +21 -3
  794. package/src/sources/provider-router/financials.ts +15 -2
  795. package/src/sources/provider-router/history.ts +30 -8
  796. package/src/sources/provider-router/primary.ts +1 -1
  797. package/src/state/app/bootstrap.ts +23 -0
  798. package/src/state/hooks/inline-tickers.ts +30 -5
  799. package/src/sync/controller.ts +1 -1
  800. package/src/sync/core-contributors.ts +46 -14
  801. package/src/team/collections-sync.ts +2 -1
  802. package/src/team/collections.ts +178 -17
  803. package/src/telemetry/crash-reports.ts +17 -4
  804. package/src/test-support/builtin-panes.ts +1 -1
  805. package/src/theme/colors.ts +3 -30
  806. package/src/theme/ui-tokens.ts +37 -1
  807. package/src/tickers/company-name-listing.ts +210 -33
  808. package/src/tickers/index-roots.ts +47 -0
  809. package/src/tickers/instrument-label.ts +5 -1
  810. package/src/tickers/metadata.ts +10 -0
  811. package/src/tickers/perpetual-listing.ts +5 -2
  812. package/src/tickers/search/home-listing.ts +75 -0
  813. package/src/tickers/search/index.ts +76 -27
  814. package/src/tickers/search/ranking.ts +54 -4
  815. package/src/tickers/search/upsert.ts +29 -0
  816. package/src/tickers/terminal-codes.ts +416 -40
  817. package/src/time-series/bar-aggregation.ts +243 -0
  818. package/src/time-series/base-series.ts +307 -0
  819. package/src/time-series/chart-bounds.ts +349 -0
  820. package/src/time-series/chart-seed.ts +142 -0
  821. package/src/time-series/economic.ts +5 -0
  822. package/src/time-series/fundamentals.ts +18 -3
  823. package/src/time-series/history-acquisition.ts +499 -0
  824. package/src/time-series/leverage.ts +100 -0
  825. package/src/time-series/market-resolution.ts +4 -2
  826. package/src/time-series/market.ts +2 -1
  827. package/src/time-series/price-comparison.ts +175 -30
  828. package/src/time-series/range.ts +9 -1
  829. package/src/time-series/resolution.ts +174 -16
  830. package/src/time-series/resolve-context.ts +157 -0
  831. package/src/time-series/resolve.ts +126 -1577
  832. package/src/time-series/series-name.ts +38 -0
  833. package/src/time-series/series-presentation.ts +208 -0
  834. package/src/time-series/spec.ts +11 -6
  835. package/src/time-series/studies.ts +109 -12
  836. package/src/time-series/tail-reconcile.ts +121 -0
  837. package/src/time-series/types.ts +29 -2
  838. package/src/time-series/use-chart-resolution.ts +4 -5
  839. package/src/types/broker.ts +10 -0
  840. package/src/types/config.ts +14 -0
  841. package/src/types/data-provider.ts +14 -0
  842. package/src/types/exchange-rate.ts +6 -0
  843. package/src/types/financials.ts +104 -7
  844. package/src/types/headless.ts +76 -6
  845. package/src/types/instrument.ts +3 -0
  846. package/src/types/plugin.ts +65 -8
  847. package/src/types/price-history.ts +2 -0
  848. package/src/types/ticker.ts +13 -0
  849. package/src/types/trading.ts +59 -1
  850. package/src/ui/ascii-font.ts +13 -1
  851. package/src/ui/host.tsx +6 -1
  852. package/src/updater/command-names.ts +175 -0
  853. package/src/updater/index.ts +10 -5
  854. package/src/utils/calendar-date.ts +32 -15
  855. package/src/utils/cash-runway.ts +241 -0
  856. package/src/utils/central-banks.ts +42 -0
  857. package/src/utils/cli-output.ts +259 -80
  858. package/src/utils/contract-month.ts +16 -0
  859. package/src/utils/crypto-pair.ts +61 -3
  860. package/src/utils/currency-units.ts +29 -0
  861. package/src/utils/datetime-format.ts +10 -0
  862. package/src/utils/debug-log.ts +1 -1
  863. package/src/utils/decimal-comma.ts +39 -6
  864. package/src/utils/exchange-announcements.ts +71 -0
  865. package/src/utils/exchange-rate-snapshot.ts +10 -0
  866. package/src/utils/financial-statements.ts +83 -4
  867. package/src/utils/format.ts +34 -16
  868. package/src/utils/fundamentals.ts +150 -34
  869. package/src/utils/fx-market-hours.ts +10 -1
  870. package/src/utils/latest-financial-period.ts +8 -0
  871. package/src/utils/linux-libc.ts +54 -0
  872. package/src/utils/market-capitalization.ts +111 -15
  873. package/src/utils/max-drawdown.ts +64 -0
  874. package/src/utils/network-failure.ts +83 -0
  875. package/src/utils/option-expiry.ts +139 -7
  876. package/src/utils/price-earnings.ts +11 -5
  877. package/src/utils/price-history.ts +18 -8
  878. package/src/utils/price-window.ts +131 -0
  879. package/src/utils/release-date.ts +47 -0
  880. package/src/utils/sec.ts +3 -0
  881. package/src/utils/throttled-fetch.ts +11 -4
  882. package/src/utils/trailing-eps.ts +67 -0
  883. package/src/utils/typed-text.ts +21 -0
  884. package/src/utils/utc-time.ts +24 -1
  885. package/src/version.ts +6 -0
  886. package/src/cli/pane-functions/screenshot.ts +0 -2122
@@ -0,0 +1,93 @@
1
+ import { SWAP_TENORS, type SwapCurvePayload, type SwapPoint, type SwapTenor } from "../../../api-client/swap-curve";
2
+ import type { CurveSeries } from "../../../components/chart/curve";
3
+ import { staticSeries } from "../../../components/chart/static/series";
4
+
5
+ const finite = (value: unknown) => value === null || typeof value === "number" && Number.isFinite(value);
6
+ const count = (value: number) => Number.isInteger(value) && value >= 0;
7
+ const date = (value: unknown) => value === null || typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value)
8
+ && Number.isFinite(Date.parse(value)) && new Date(value).toISOString().slice(0, 10) === value;
9
+ const quality = (value: unknown) => value === "ok" || value === "thin" || value === "missing";
10
+
11
+ /** Reject incompatible observations before they replace the last usable cache. */
12
+ export function validateSwapCurve(payload: SwapCurvePayload): SwapCurvePayload {
13
+ const invalid = () => { throw new Error("The server returned invalid SOFR swap observations"); };
14
+ if (!payload || payload.currency !== "USD" || payload.benchmark !== "SOFR" || typeof payload.stale !== "boolean"
15
+ || !date(payload.asOf) || !date(payload.previousDate) || !date(payload.treasuryDate)
16
+ || !payload.comparisons?.week || !payload.comparisons.month || !payload.history
17
+ || !SWAP_TENORS.includes(payload.history.tenor) || !Array.isArray(payload.history.points)) return invalid();
18
+ for (const snapshot of [{ date: payload.asOf, points: payload.points }, payload.comparisons.week, payload.comparisons.month]) {
19
+ if (!date(snapshot.date) || !Array.isArray(snapshot.points)
20
+ || new Set(snapshot.points.map((point) => point.tenor)).size !== snapshot.points.length) return invalid();
21
+ for (const point of snapshot.points) {
22
+ if (!SWAP_TENORS.includes(point.tenor) || point.years !== Number.parseInt(point.tenor)
23
+ || !finite(point.rate) || !finite(point.changeBp) || !finite(point.spreadBp) || !finite(point.treasuryRate)
24
+ || !count(point.tradeCount) || !count(point.candidateCount) || !count(point.excludedCount)
25
+ || !Number.isFinite(point.notionalUsd) || point.notionalUsd < 0 || !quality(point.quality)
26
+ || point.rate != null && (snapshot.date == null || point.tradeCount < 3 || point.quality === "missing" || point.quality === "ok" && point.tradeCount < 5)
27
+ || point.rate == null && (point.changeBp != null || point.spreadBp != null)
28
+ || point.tenor === "15Y" && point.spreadBp != null) return invalid();
29
+ }
30
+ }
31
+ if (payload.points.length !== SWAP_TENORS.length) return invalid();
32
+ let previous = "";
33
+ for (const point of payload.history.points) {
34
+ if (point.date == null || !date(point.date) || point.date <= previous || !finite(point.rate) || !finite(point.spreadBp)
35
+ || !count(point.tradeCount) || !quality(point.quality)
36
+ || point.rate != null && (point.tradeCount < 3 || point.quality === "missing" || point.quality === "ok" && point.tradeCount < 5)
37
+ || point.rate == null && point.spreadBp != null
38
+ || payload.history.tenor === "15Y" && point.spreadBp != null) return invalid();
39
+ previous = point.date;
40
+ }
41
+ return payload;
42
+ }
43
+
44
+ export function selectedSwapTenor(value: unknown): SwapTenor {
45
+ return SWAP_TENORS.includes(value as SwapTenor) ? value as SwapTenor : "10Y";
46
+ }
47
+
48
+ const curvePoints = (points: readonly SwapPoint[]) => points.map((point) => ({
49
+ id: point.tenor, label: point.tenor, x: point.years, value: point.rate,
50
+ }));
51
+
52
+ /** Missing tenors remain null nodes, which break the line instead of bridging the gap. */
53
+ export function swapCurveSeries(payload: SwapCurvePayload,
54
+ colors: { current: string; thin: string; ghosts: Readonly<Record<string, string>> }): CurveSeries[] {
55
+ const series: CurveSeries[] = [
56
+ { id: "sofr", label: "SOFR", role: "primary", color: colors.current, points: curvePoints(payload.points) },
57
+ ...(["week", "month"] as const).flatMap((key): CurveSeries[] => {
58
+ const snapshot = payload.comparisons[key];
59
+ const id = key === "week" ? "1W" : "1M";
60
+ return snapshot.date == null ? [] : [{ id, label: id, role: "ghost", asOf: snapshot.date,
61
+ color: colors.ghosts[id], points: curvePoints(snapshot.points) }];
62
+ }),
63
+ ];
64
+ // The shared marker layer identifies thin observations on every dated curve.
65
+ // Keep their values in the main series so selection/readouts still show them.
66
+ const snapshots = [payload.points, ...(["week", "month"] as const)
67
+ .filter((key) => payload.comparisons[key].date != null).map((key) => payload.comparisons[key].points)];
68
+ return [...series, ...series.flatMap((entry, index): CurveSeries[] => {
69
+ const points = curvePoints(snapshots[index]!.filter((point) => point.quality === "thin" && point.rate != null));
70
+ return points.length ? [{ id: `${entry.id}-thin`, label: "Thin", role: "marker", color: colors.thin, points }] : [];
71
+ })];
72
+ }
73
+
74
+ /** Preserve missing sessions and their null values on the calendar axis. */
75
+ export function swapHistorySeries(history: SwapCurvePayload["history"], color: string, thinColor: string) {
76
+ const observation = (point: SwapCurvePayload["history"]["points"][number], thin: boolean) => ({
77
+ date: new Date(point.date), observedAt: new Date(point.date),
78
+ value: (point.quality === "thin") === thin ? point.rate : null,
79
+ });
80
+ return [
81
+ staticSeries(history.points.map((point) => observation(point, false)),
82
+ { id: `sofr-${history.tenor}`, label: `${history.tenor} SOFR`, color, calendarSpaced: true }),
83
+ ...(history.points.some((point) => point.quality === "thin" && point.rate != null)
84
+ ? [staticSeries(history.points.map((point) => observation(point, true)),
85
+ { id: `sofr-${history.tenor}-thin`, label: "Thin", color: thinColor, style: "points", calendarSpaced: true })] : []),
86
+ ];
87
+ }
88
+
89
+ /** Already in basis points: never multiply a swap change or spread by 100 again. */
90
+ export function formatSwapBp(value: number): string {
91
+ const rounded = Math.round(value * 10) / 10;
92
+ return `${rounded > 0 ? "+" : ""}${rounded.toFixed(1)}bp`;
93
+ }
@@ -0,0 +1,99 @@
1
+ import { useCallback, useMemo } from "react";
2
+ import type { SwapPoint } from "../../../api-client/swap-curve";
3
+ import {
4
+ ChartTableHeader, CurveSurface, curveGhostColors, DataTableView, formatPercentAxis, QueryBar,
5
+ useChartTableSelection, usePaneNoticeFooter, type ChartTableChart, type DataTableColumn,
6
+ } from "../../../components";
7
+ import { curveStrip, curveSurfaceMinRows } from "../../../components/chart/curve";
8
+ import { usePaneRefreshKey } from "../../../components/data-table/table-pane";
9
+ import { usePaneStatusFooter } from "../../../components/layout/pane/status-footer";
10
+ import { FILL_REST } from "../../../components/ui/fill";
11
+ import { isAccessDenied } from "../../../api-client/errors";
12
+ import { usePluginPaneState } from "../../../public/react";
13
+ import { useAsyncResource } from "../../../react/async-resource";
14
+ import { useAutoRefresh } from "../../../react/auto-refresh";
15
+ import { priceColor } from "../../../theme/colors";
16
+ import { useThemeColors } from "../../../theme/theme-context";
17
+ import { Box } from "../../../ui";
18
+ import { getCachedSwapCurve, loadSwapCurve } from "./client";
19
+ import { formatYield, formatYieldChange } from "./chart";
20
+ import { formatSwapBp, selectedSwapTenor, swapCurveSeries, swapHistorySeries } from "./swaps-model";
21
+
22
+ const COLUMNS: DataTableColumn[] = [
23
+ { id: "tenor", label: "Tenor", width: 7, align: "left" },
24
+ { id: "rate", label: "Rate %", width: 9, align: "right" },
25
+ { id: "changeBp", label: "1D bp", width: 9, align: "right" },
26
+ { id: "spreadBp", label: "Spread bp", width: 10, align: "right" },
27
+ { id: "tradeCount", label: "Trades", width: 10, align: "right" },
28
+ ];
29
+ const EMPTY_ROWS: SwapPoint[] = [];
30
+ const tenorKey = (row: SwapPoint) => row.tenor;
31
+ const tenorPosition = (row: SwapPoint) => new Date(row.years * 86_400_000);
32
+
33
+ export function SwapsTab({ focused, width, height }: { focused: boolean; width: number; height: number }) {
34
+ const colors = useThemeColors();
35
+ const [selected, setSelected] = usePluginPaneState<string>("yield-curve:swap-tenor", "10Y");
36
+ const [view, setView] = usePluginPaneState<"curve" | "history">("yield-curve:swap-view", "curve");
37
+ const tenor = selectedSwapTenor(selected);
38
+ const loader = useCallback((force: boolean) => loadSwapCurve(tenor, force), [tenor]);
39
+ const resource = useAsyncResource(loader, {
40
+ initialData: () => getCachedSwapCurve(tenor), keepPreviousData: true, clearOnError: isAccessDenied,
41
+ });
42
+ const payload = resource.data?.payload;
43
+ const rows = payload?.asOf ? payload.points : EMPTY_ROWS;
44
+ // A new tenor keeps the curve/table in place, but never relabels the old tenor's history.
45
+ const history = payload?.history.tenor === tenor ? payload.history : null;
46
+ const stale = !!payload?.asOf && (payload.stale || resource.data?.stale || false);
47
+ const error = resource.error || resource.data?.refreshError || null;
48
+ useAutoRefresh(stale ? null : resource.updatedAt, resource.load);
49
+ usePaneRefreshKey(resource.reload, { focused });
50
+ usePaneStatusFooter({ registrationId: "yield-curve:swaps", loading: resource.loading, error, stale });
51
+ usePaneNoticeFooter({
52
+ registrationId: "yield-curve:swaps:notices", focused,
53
+ notices: payload?.asOf ? [
54
+ ...(!payload.comparisons.week.date ? ["The one-week comparison is unavailable."] : []),
55
+ ...(!payload.comparisons.month.date ? ["The one-month comparison is unavailable."] : []),
56
+ ...(!payload.treasuryDate ? ["Same-session Treasury yields are unavailable; swap spreads are blank."] : []),
57
+ ] : [],
58
+ });
59
+
60
+ useChartTableSelection({ rows, getId: tenorKey, getDate: tenorPosition, selectedId: tenor, onSelect: setSelected, focused });
61
+ const curve = useMemo(() => payload ? swapCurveSeries(payload, { current: colors.positive, thin: colors.text, ghosts: curveGhostColors(colors) }) : [],
62
+ [payload, colors]);
63
+ const historySeries = useMemo(() => history ? swapHistorySeries(history, colors.positive, colors.text) : [], [history, colors.positive, colors.text]);
64
+ const strip = curveStrip(curve, formatYield, { caption: "SOFR %", selectedPointId: tenor });
65
+ const chart: ChartTableChart | null = !payload?.asOf ? null : view === "history" ? {
66
+ series: historySeries, formatValue: formatYield, formatAxisValue: formatPercentAxis,
67
+ loading: resource.loading && !history, empty: `No history for ${tenor}`,
68
+ } : strip ? {
69
+ render: (size) => <CurveSurface series={curve} width={size.width} height={size.height} display="chart"
70
+ caption="USD SOFR % by maturity" xScale="log" formatValue={formatYield} formatChange={formatYieldChange}
71
+ formatAxisValue={formatPercentAxis} selectedPointId={tenor} onSelectedPointChange={setSelected} />,
72
+ minRows: curveSurfaceMinRows({ series: curve, width, caption: "USD SOFR % by maturity" }), strip,
73
+ } : null;
74
+ const renderCell = useCallback((row: SwapPoint, column: DataTableColumn) => {
75
+ if (column.id === "tenor") return { text: row.tenor };
76
+ if (column.id === "tradeCount") return { text: `${row.tradeCount}${row.quality === "thin" ? " Thin" : ""}`, value: row.tradeCount,
77
+ color: row.quality === "ok" ? undefined : colors.warning };
78
+ const value = row[column.id as "rate" | "changeBp" | "spreadBp"];
79
+ if (value == null) return { text: "--", color: colors.textMuted };
80
+ if (column.id === "rate") return { text: formatYield(value), value };
81
+ return { text: formatSwapBp(value), value,
82
+ color: column.id === "changeBp" ? priceColor(Math.round(value * 10), colors) : undefined };
83
+ }, [colors]);
84
+
85
+ return <Box flexDirection="column" width={width} height={height} {...FILL_REST}>
86
+ <DataTableView<SwapPoint> focused={focused} rootWidth={width} rootHeight={height}
87
+ columns={COLUMNS} items={rows} getItemKey={tenorKey} renderCell={renderCell} selectedTextOverridesCellColor
88
+ selection={{ kind: "id", selectedId: tenor, getId: tenorKey, onChange: setSelected }}
89
+ onActivate={(row) => { setSelected(row.tenor); setView("history"); }} sortColumnId={null} sortDirection="asc"
90
+ emptyStateTitle="No swap rates yet."
91
+ status={{ loading: resource.loading && !payload, error: !payload ? error : null,
92
+ loadingLabel: "Loading swap rates...", subject: "swap rates", retry: { onRetry: resource.reload, pending: resource.loading } }}
93
+ rootBefore={payload && !payload.asOf ? null : <ChartTableHeader width={width} height={height} tableRows={rows.length} tableColumns={COLUMNS}
94
+ query={<QueryBar width={width}
95
+ view={{ value: view, options: [{ value: "curve", label: "Curve" }, { value: "history", label: "History" }], onChange: setView }}
96
+ asOf={payload?.asOf ? `as of ${payload.asOf}` : undefined} />}
97
+ chart={chart} />} />
98
+ </Box>;
99
+ }
@@ -32,7 +32,7 @@ import { PLUGIN_HOST_GLOBAL, SHARED_SPECIFIERS, importPluginHostModule } from ".
32
32
  export function buildSharedModuleSource(specifier: string, exportNames: readonly string[]): string {
33
33
  const lines = [
34
34
  `const mod = globalThis[${JSON.stringify(PLUGIN_HOST_GLOBAL)}]?.[${JSON.stringify(specifier)}];`,
35
- `if (!mod) throw new Error(${JSON.stringify(`Gloomberb host module "${specifier}" is unavailable. The plugin host was not installed before this plugin loaded.`)});`,
35
+ `if (!mod) throw new Error(${JSON.stringify(`Gloom host module "${specifier}" is unavailable. The plugin host was not installed before this plugin loaded.`)});`,
36
36
  "export default mod;",
37
37
  ];
38
38
  for (const name of exportNames) {
@@ -16,6 +16,7 @@ import { treasuryDailyModule } from "./builtin/treasury-daily";
16
16
  import { revenueBreakdownModule } from "./builtin/revenue-breakdown";
17
17
  import { mnaModule } from "./builtin/mna";
18
18
  import { cryptoBoardModule } from "./builtin/crypto-board";
19
+ import { cryptoEtfFlowsModule } from "./builtin/crypto-etf-flows";
19
20
  import { shortInterestModule } from "./builtin/short-interest";
20
21
  import { shortVolumeModule } from "./builtin/short-volume";
21
22
  import { socialMentionsModule } from "./builtin/social-mentions";
@@ -216,7 +217,7 @@ const browserFuturesCommoditiesPlugin = composeBuiltinPlugin({
216
217
 
217
218
  const browserCryptoPlugin = composeBuiltinPlugin({
218
219
  ...cryptoPluginMeta,
219
- modules: [cryptoBoardModule, perpsModule],
220
+ modules: [cryptoBoardModule, cryptoEtfFlowsModule, perpsModule],
220
221
  });
221
222
 
222
223
  const browserAltDataPlugin = composeBuiltinPlugin({
@@ -128,7 +128,7 @@ export interface PluginIncompatibility {
128
128
  export function checkPluginCompatibility(pluginDir: string, hostVersion: string = VERSION): PluginIncompatibility | null {
129
129
  const manifest = readPluginManifest(pluginDir);
130
130
  const needs = requiredGloomberb(manifest.minGloomberb, hostVersion);
131
- if (needs) return { error: `Needs Gloomberb ${needs}, this is ${hostVersion}.`, needsGloomberb: needs };
131
+ if (needs) return { error: `Needs Gloom ${needs}, this is ${hostVersion}.`, needsGloomberb: needs };
132
132
  const peer = missingPeerPlugins(pluginDir)[0];
133
133
  if (peer) return { error: `Needs the ${peer} plugin. Install it from the Plugins pane.`, needsPlugin: peer };
134
134
  const broken = manifest.id ? KNOWN_BROKEN_PLUGINS[manifest.id] : undefined;
@@ -191,8 +191,8 @@ export function explainPluginLoadError(message: string, hostVersion: string = VE
191
191
  if (!missing) return message;
192
192
  const { specifier, name } = missing;
193
193
  const removed = REMOVED_HOST_EXPORTS[specifier]?.[name];
194
- if (removed) return `Uses ${name} from ${specifier}, removed in Gloomberb ${removed.removedIn}. Update the plugin.`;
195
- return `Uses ${name} from ${specifier}, which Gloomberb ${hostVersion} does not have. Update the plugin, or Gloomberb if the plugin is newer.`;
194
+ if (removed) return `Uses ${name} from ${specifier}, removed in Gloom ${removed.removedIn}. Update the plugin.`;
195
+ return `Uses ${name} from ${specifier}, which Gloom ${hostVersion} does not have. Update the plugin, or Gloom if the plugin is newer.`;
196
196
  }
197
197
 
198
198
  /** The plugin's own source files, without tests, dependencies or build output. */
@@ -1,5 +1,5 @@
1
1
  import { existsSync, readFileSync } from "fs";
2
- import { join } from "path";
2
+ import { basename, join } from "path";
3
3
  import { logFailure } from "../utils/log-failure";
4
4
  import { linkHostPackages } from "./host-link";
5
5
 
@@ -55,6 +55,66 @@ export function missingPluginDependencies(pluginDir: string): string[] {
55
55
  return [...new Set(missing)];
56
56
  }
57
57
 
58
+ interface DependencyInstall {
59
+ directory: string;
60
+ startedAt: number;
61
+ endedAt?: number;
62
+ code?: number | null;
63
+ done: Promise<unknown>;
64
+ }
65
+
66
+ /**
67
+ * Every `bun install` this process ran in a plugin folder. It prunes the
68
+ * links to the host and to sibling plugins until they are made again, so an
69
+ * import that fails on a sibling waits for one still running, and its crash
70
+ * report says which ran.
71
+ */
72
+ const installs = new Map<string, DependencyInstall>();
73
+
74
+ /** Runs `install`, a `bun install` in `pluginDir`, on the record. */
75
+ export async function recordDependencyInstall<T extends { code?: number | null } | number | null>(
76
+ pluginDir: string,
77
+ install: () => Promise<T>,
78
+ ): Promise<T> {
79
+ const done = install();
80
+ const settled = done.catch(() => {
81
+ // Intentional ignore: the caller awaits this same promise and handles its failure.
82
+ });
83
+ const entry: DependencyInstall = { directory: basename(pluginDir), startedAt: Date.now(), done: settled };
84
+ installs.set(pluginDir, entry);
85
+ try {
86
+ const result = await done;
87
+ entry.code = typeof result === "number" || result === null ? result : result.code ?? null;
88
+ return result;
89
+ } catch (error) {
90
+ entry.code = null;
91
+ throw error;
92
+ } finally {
93
+ entry.endedAt = Date.now();
94
+ }
95
+ }
96
+
97
+ /** Waits, at most `timeoutMs`, for installs still running in any of `pluginDirs`. */
98
+ export async function settleDependencyInstalls(pluginDirs: readonly string[], timeoutMs: number): Promise<void> {
99
+ const running = pluginDirs.map((dir) => installs.get(dir)).filter((entry) => entry && entry.endedAt === undefined);
100
+ if (running.length === 0) return;
101
+ let timer: ReturnType<typeof setTimeout> | undefined;
102
+ await Promise.race([
103
+ Promise.all(running.map((entry) => entry!.done)),
104
+ new Promise((resolve) => { timer = setTimeout(resolve, timeoutMs); }),
105
+ ]);
106
+ clearTimeout(timer);
107
+ }
108
+
109
+ /** `gloom-ibkr-gateway:0@12s`, one per install this process ran, newest first; `running` while it runs. */
110
+ export function describeDependencyInstalls(now: number = Date.now()): string[] {
111
+ return [...installs.values()]
112
+ .sort((a, b) => b.startedAt - a.startedAt)
113
+ .map((entry) => entry.endedAt === undefined
114
+ ? `${entry.directory}:running`
115
+ : `${entry.directory}:${entry.code ?? "?"}@${Math.round((now - entry.endedAt) / 1000)}s`);
116
+ }
117
+
58
118
  /**
59
119
  * Installs the dependencies of a plugin that was installed without them, and
60
120
  * relinks `gloomberb` and `react`, which `bun install` prunes. Runs through
@@ -64,19 +124,20 @@ export function missingPluginDependencies(pluginDir: string): string[] {
64
124
  export async function installPluginDependencies(pluginDir: string): Promise<boolean> {
65
125
  const bun = bunCommand();
66
126
  if (!bun) return false;
67
- let code: number | null = null;
68
- try {
69
- const child = Bun.spawn([bun.command, "install", "--production"], {
70
- cwd: pluginDir,
71
- env: bun.env ?? process.env,
72
- stdout: "ignore",
73
- stderr: "ignore",
74
- });
75
- code = await child.exited;
76
- } catch (error) {
77
- logFailure("plugin-dependencies", "Dependency installer launch failed")(error);
78
- code = null;
79
- }
127
+ const code = await recordDependencyInstall(pluginDir, async () => {
128
+ try {
129
+ const child = Bun.spawn([bun.command, "install", "--production"], {
130
+ cwd: pluginDir,
131
+ env: bun.env ?? process.env,
132
+ stdout: "ignore",
133
+ stderr: "ignore",
134
+ });
135
+ return await child.exited;
136
+ } catch (error) {
137
+ logFailure("plugin-dependencies", "Dependency installer launch failed")(error);
138
+ return null;
139
+ }
140
+ });
80
141
  linkHostPackages(pluginDir);
81
142
  return code === 0;
82
143
  }
@@ -1,7 +1,7 @@
1
1
  import { existsSync } from "fs";
2
2
  import { join } from "path";
3
3
 
4
- import type { AppConfig } from "../types/config";
4
+ import type { AppConfig, PluginSeedFailure } from "../types/config";
5
5
  import { debugLog } from "../utils/debug-log";
6
6
  import { getPluginsDir } from "./loader";
7
7
  import { encodeBuiltinDisabledPluginIds } from "./ownership";
@@ -21,20 +21,22 @@ export const EXTRACTED_PLUGINS = [
21
21
  // TV was a module inside Macro, so a user who turned Macro off was turning
22
22
  // it off with it. `previousOwnerIds` keeps that choice: the seeder does not
23
23
  // restore what someone disabled.
24
- { id: "tv", repo: "gloom-sh/gloom-tv", directory: "gloom-tv", previousOwnerIds: ["macro", "macro-tv"] },
25
- { id: "substack", repo: "gloom-sh/gloom-substack", directory: "gloom-substack" },
26
- { id: "ibkr", repo: "gloom-sh/gloom-ibkr", directory: "gloom-ibkr" },
27
- { id: "ibkr-gateway", repo: "gloom-sh/gloom-ibkr-gateway", directory: "gloom-ibkr-gateway" },
28
- { id: "public", repo: "gloom-sh/gloom-public", directory: "gloom-public" },
29
- { id: "robinhood", repo: "gloom-sh/gloom-robinhood", directory: "gloom-robinhood" },
30
- { id: "simplefin", repo: "gloom-sh/gloom-simplefin", directory: "gloom-simplefin" },
31
- { id: "polls", repo: "gloom-sh/gloom-polls", directory: "gloom-polls" },
32
- { id: "prediction-markets", repo: "gloom-sh/gloom-prediction-markets", directory: "gloom-prediction-markets" },
24
+ { id: "tv", name: "TV", repo: "gloom-sh/gloom-tv", directory: "gloom-tv", previousOwnerIds: ["macro", "macro-tv"] },
25
+ { id: "substack", name: "Substack", repo: "gloom-sh/gloom-substack", directory: "gloom-substack" },
26
+ { id: "ibkr", name: "Interactive Brokers", repo: "gloom-sh/gloom-ibkr", directory: "gloom-ibkr" },
27
+ { id: "ibkr-gateway", name: "IBKR Gateway", repo: "gloom-sh/gloom-ibkr-gateway", directory: "gloom-ibkr-gateway" },
28
+ { id: "public", name: "Public", repo: "gloom-sh/gloom-public", directory: "gloom-public" },
29
+ { id: "robinhood", name: "Robinhood", repo: "gloom-sh/gloom-robinhood", directory: "gloom-robinhood" },
30
+ { id: "simplefin", name: "SimpleFIN", repo: "gloom-sh/gloom-simplefin", directory: "gloom-simplefin" },
31
+ { id: "polls", name: "Polls", repo: "gloom-sh/gloom-polls", directory: "gloom-polls" },
32
+ { id: "prediction-markets", name: "Prediction Markets", repo: "gloom-sh/gloom-prediction-markets", directory: "gloom-prediction-markets" },
33
33
  // Bring-your-own-key AI left under a new id, so the choice to switch the old
34
34
  // one off is recorded against `ai` rather than against this entry.
35
- { id: "byok-ai", repo: "gloom-sh/gloom-byok-ai", directory: "gloom-byok-ai", previousOwnerIds: ["ai"] },
35
+ { id: "byok-ai", name: "BYOK AI", repo: "gloom-sh/gloom-byok-ai", directory: "gloom-byok-ai", previousOwnerIds: ["ai"] },
36
36
  ] as const;
37
37
 
38
+ type ExtractedPlugin = (typeof EXTRACTED_PLUGINS)[number];
39
+
38
40
  export interface SeedResult {
39
41
  installed: string[];
40
42
  failed: string[];
@@ -52,17 +54,12 @@ function isInstalled(directory: string, pluginsDir: string): boolean {
52
54
  }
53
55
 
54
56
  /**
55
- * Installs any extracted plugin the user has not seen yet.
56
- *
57
- * Best effort by design: a failure is logged and retried on the next launch
58
- * rather than recorded, because the common cause is being offline at startup and
59
- * marking it seeded would silently drop the plugin forever.
57
+ * The plugins left to install, each neither recorded as seeded, installed
58
+ * already, nor switched off before the move, and the ids to record as seeded
59
+ * without installing them. After a launch's seed, `pending` is what it could
60
+ * not install.
60
61
  */
61
- export async function seedExtractedPlugins(
62
- config: AppConfig,
63
- installPlugin: (ref: string) => Promise<unknown>,
64
- pluginsDir: string = getPluginsDir(),
65
- ): Promise<SeedResult> {
62
+ function classifyExtractedPlugins(config: AppConfig, pluginsDir: string): { pending: ExtractedPlugin[]; settled: string[] } {
66
63
  const alreadySeeded = new Set(config.seededPlugins ?? []);
67
64
  // A previous owner that is now a group of built-ins counts as off only while
68
65
  // all of them are, which is when its id is saved.
@@ -70,25 +67,39 @@ export async function seedExtractedPlugins(
70
67
  ...config.disabledPlugins ?? [],
71
68
  ...encodeBuiltinDisabledPluginIds(config.disabledPlugins ?? []),
72
69
  ]);
73
-
74
- const result: SeedResult = { installed: [], failed: [], seeded: [...alreadySeeded] };
75
-
70
+ const pending: ExtractedPlugin[] = [];
71
+ const settled: string[] = [];
76
72
  for (const entry of EXTRACTED_PLUGINS) {
77
73
  if (alreadySeeded.has(entry.id)) continue;
78
-
79
- // Present already: either installed by hand or seeded before this record
80
- // existed. Mark it so we stop looking.
81
- if (isInstalled(entry.directory, pluginsDir)) {
82
- result.seeded.push(entry.id);
74
+ // Present already (installed by hand, or seeded before this record
75
+ // existed), or turned off before the move, which restoring it would
76
+ // override: recorded so we stop looking.
77
+ if (isInstalled(entry.directory, pluginsDir)
78
+ || disabled.has(entry.id) || ("previousOwnerIds" in entry && entry.previousOwnerIds.some((id) => disabled.has(id)))) {
79
+ settled.push(entry.id);
83
80
  continue;
84
81
  }
82
+ pending.push(entry);
83
+ }
84
+ return { pending, settled };
85
+ }
85
86
 
86
- // Turned off before the move: restoring it would override that choice.
87
- if (disabled.has(entry.id) || ("previousOwnerIds" in entry && entry.previousOwnerIds.some((id) => disabled.has(id)))) {
88
- result.seeded.push(entry.id);
89
- continue;
90
- }
87
+ /**
88
+ * Installs any extracted plugin the user has not seen yet.
89
+ *
90
+ * Best effort by design: a failure is logged and retried on the next launch
91
+ * rather than recorded, because the common cause is being offline at startup and
92
+ * marking it seeded would silently drop the plugin forever.
93
+ */
94
+ export async function seedExtractedPlugins(
95
+ config: AppConfig,
96
+ installPlugin: (ref: string) => Promise<unknown>,
97
+ pluginsDir: string = getPluginsDir(),
98
+ ): Promise<SeedResult> {
99
+ const { pending, settled } = classifyExtractedPlugins(config, pluginsDir);
100
+ const result: SeedResult = { installed: [], failed: [], seeded: [...config.seededPlugins ?? [], ...settled] };
91
101
 
102
+ for (const entry of pending) {
92
103
  try {
93
104
  log.info(`Restoring ${entry.id} from ${entry.repo}`);
94
105
  await installPlugin(entry.repo);
@@ -102,3 +113,90 @@ export async function seedExtractedPlugins(
102
113
 
103
114
  return result;
104
115
  }
116
+
117
+ /** `TV, Polls and Substack`. */
118
+ function nameList(names: readonly string[]): string {
119
+ return names.length <= 1 ? names.join("") : `${names.slice(0, -1).join(", ")} and ${names.at(-1)}`;
120
+ }
121
+
122
+ /** Where to get git: Git for Windows on Windows, with its download page when there is room for it. */
123
+ export function gitInstallAdvice(platform: string = process.platform, link = false): string {
124
+ if (platform !== "win32") return "install git";
125
+ return link ? "install Git for Windows (https://git-scm.com/download/win)" : "install Git for Windows";
126
+ }
127
+
128
+ function capitalize(text: string): string {
129
+ return `${text[0]?.toUpperCase() ?? ""}${text.slice(1)}`;
130
+ }
131
+
132
+ /** What a seed's result leaves to record: the plugins it could not install, sorted, or nothing. */
133
+ export function pluginSeedFailure(failedIds: readonly string[], gitMissing: boolean): PluginSeedFailure | undefined {
134
+ return failedIds.length > 0 ? { plugins: [...new Set(failedIds)].sort(), gitMissing } : undefined;
135
+ }
136
+
137
+ /** Whether two recorded seed failures are the same: the same plugins, for the same reason. */
138
+ export function samePluginSeedFailure(a: PluginSeedFailure | undefined, b: PluginSeedFailure | undefined): boolean {
139
+ return a?.gitMissing === b?.gitMissing && (a?.plugins ?? []).join() === (b?.plugins ?? []).join();
140
+ }
141
+
142
+ export interface PluginSeedNotice {
143
+ body: string;
144
+ type: "error" | "info";
145
+ }
146
+
147
+ /**
148
+ * The one notice a launch shows when its seed left official plugins
149
+ * uninstalled. A missing git, the usual cause on Windows, is an error said at
150
+ * every launch until git is there, since nothing else installs them. Anything
151
+ * else (offline, the registry unreadable) the next launch retries on its own,
152
+ * so it is information, said once and not again while the same plugins keep
153
+ * failing (`previous` is the failure the last launch recorded).
154
+ */
155
+ export function pluginSeedNotice(
156
+ failure: PluginSeedFailure | undefined,
157
+ previous: PluginSeedFailure | undefined,
158
+ platform: string = process.platform,
159
+ ): PluginSeedNotice | null {
160
+ const names = EXTRACTED_PLUGINS.filter((entry) => failure?.plugins.includes(entry.id)).map((entry) => entry.name);
161
+ if (!failure || names.length === 0) return null;
162
+ const what = names.length <= 2 ? nameList(names) : `${names.length} official plugins`;
163
+ const one = names.length === 1;
164
+ if (failure.gitMissing) {
165
+ return { type: "error", body: `${what} ${one ? "needs" : "need"} Git and ${one ? "is" : "are"} not installed. ${capitalize(gitInstallAdvice(platform))}, then restart Gloom.` };
166
+ }
167
+ if (samePluginSeedFailure(failure, previous)) return null;
168
+ return { type: "info", body: `${what} could not be installed. Gloom tries again at the next launch.` };
169
+ }
170
+
171
+ /**
172
+ * `doctor`'s check of the official plugins the seed has not installed: which,
173
+ * and what to do. A failure only once a launch tried and could not install
174
+ * them; before any launch has (a terminal-only setup, a container, CI) a
175
+ * warning, git missing or not. Null when none is missing.
176
+ */
177
+ export function officialPluginsCheck(
178
+ config: AppConfig,
179
+ { gitMissing, pluginsDir = getPluginsDir(), platform = process.platform }: { gitMissing: () => boolean; pluginsDir?: string; platform?: string },
180
+ ): { check: string; status: "error" | "warn"; detail: string } | null {
181
+ const { pending } = classifyExtractedPlugins(config, pluginsDir);
182
+ if (pending.length === 0) return null;
183
+ const names = nameList(pending.map((entry) => entry.name));
184
+ const git = gitMissing() ? gitInstallAdvice(platform, true) : null;
185
+ const attempted = pending.some((entry) => config.pluginSeedFailure?.plugins.includes(entry.id));
186
+ if (attempted) {
187
+ return {
188
+ check: "official plugins",
189
+ status: "error",
190
+ detail: git
191
+ ? `Not installed: ${names}. They need Git: ${git}, then restart Gloom.`
192
+ : `Not installed: ${names}. The last launch could not install them; the next one tries again.`,
193
+ };
194
+ }
195
+ return {
196
+ check: "official plugins",
197
+ status: "warn",
198
+ detail: git
199
+ ? `Not installed yet: ${names}. Gloom installs them when the app starts, which needs Git: ${git}.`
200
+ : `Not installed yet: ${names}. Gloom installs them when the app next starts.`,
201
+ };
202
+ }