gloomberb 0.16.4 → 0.16.6

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 (852) hide show
  1. package/README.md +14 -91
  2. package/package.json +5 -1
  3. package/src/{plugins/builtin/cloud → account}/auth-form.tsx +9 -9
  4. package/src/{plugins/builtin/cloud → account}/auth-model.ts +4 -4
  5. package/src/account/billing.ts +57 -0
  6. package/src/{plugins/builtin/cloud → account}/device-signin-dialog.tsx +18 -12
  7. package/src/{plugins/builtin/cloud → account}/device-signin.ts +2 -2
  8. package/src/{plugins/builtin/cloud → account}/email-auth-attempt.ts +2 -2
  9. package/src/account/session.ts +16 -0
  10. package/src/{plugins/builtin/cloud → account}/upgrade-dialog.tsx +16 -15
  11. package/src/{plugins/builtin/cloud → account}/upgrade-personalization.ts +7 -7
  12. package/src/{plugins/builtin/cloud → account}/upgrade-tickers.ts +6 -6
  13. package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
  14. package/src/api-client/central-bank-rates.ts +6 -1
  15. package/src/api-client/chat.ts +26 -0
  16. package/src/api-client/credit-boards.ts +2 -0
  17. package/src/api-client/data.ts +73 -3
  18. package/src/api-client/earnings.ts +6 -0
  19. package/src/api-client/europe-energy.ts +106 -0
  20. package/src/api-client/futures-curve.ts +56 -0
  21. package/src/api-client/index.ts +13 -1
  22. package/src/api-client/market-discovery.ts +13 -1
  23. package/src/api-client/normalizers.ts +32 -0
  24. package/src/api-client/paths.ts +7 -0
  25. package/src/api-client/perps.ts +8 -0
  26. package/src/api-client/request.ts +9 -2
  27. package/src/api-client/research-activity.ts +15 -10
  28. package/src/api-client/socket.ts +29 -0
  29. package/src/api-client/themes.ts +22 -1
  30. package/src/api-client/types.ts +78 -2
  31. package/src/api-client/yield-curves.ts +8 -0
  32. package/src/app/global-shortcuts.ts +50 -2
  33. package/src/app/keybindings/actions.ts +12 -1
  34. package/src/app/pane-runtime/plugin-bindings.ts +2 -2
  35. package/src/app/pane-runtime/ticker-open-runtime.ts +16 -6
  36. package/src/app/runtime/desktop-deeplink.ts +10 -5
  37. package/src/app/runtime/startup.ts +1 -1
  38. package/src/app.tsx +6 -0
  39. package/src/architecture/core-builtin-allowlist.json +8 -26
  40. package/src/ask-gloom/pane-context.ts +114 -0
  41. package/src/ask-gloom/pane-request.ts +70 -0
  42. package/src/ask-gloom/pane-text.ts +201 -0
  43. package/src/brokers/signed-in/sign-in-dialog.tsx +11 -5
  44. package/src/capabilities/chart-series.ts +19 -2
  45. package/src/capabilities/factories.ts +1 -0
  46. package/src/cli/central-bank-events.ts +23 -0
  47. package/src/cli/command-options.ts +17 -5
  48. package/src/cli/commands/crypto-hints.ts +35 -2
  49. package/src/cli/commands/fred-series.ts +146 -0
  50. package/src/cli/commands/market.ts +501 -115
  51. package/src/cli/commands/news-hints.ts +62 -0
  52. package/src/cli/commands/news-search.ts +53 -0
  53. package/src/cli/commands/options-leaps.ts +5 -2
  54. package/src/cli/commands/overview.ts +132 -26
  55. package/src/cli/commands/remote.ts +2 -1
  56. package/src/cli/commands/search.ts +317 -13
  57. package/src/cli/commands/system.ts +55 -8
  58. package/src/cli/commands/ticker.ts +155 -18
  59. package/src/cli/context.ts +45 -14
  60. package/src/cli/desktop-pane-shot.ts +76 -7
  61. package/src/cli/earnings-calendar.ts +71 -0
  62. package/src/cli/errors.ts +7 -5
  63. package/src/cli/exit-codes.ts +8 -0
  64. package/src/cli/export-source.ts +58 -0
  65. package/src/cli/freshness.ts +18 -7
  66. package/src/cli/glossary.ts +483 -0
  67. package/src/cli/help.ts +10 -0
  68. package/src/cli/helpers.ts +2 -5
  69. package/src/cli/history-rows.ts +118 -7
  70. package/src/cli/index-roots.ts +7 -0
  71. package/src/cli/index.ts +29 -9
  72. package/src/cli/known-gaps.ts +84 -0
  73. package/src/cli/listing-arg.ts +551 -97
  74. package/src/cli/not-a-ticker.ts +24 -9
  75. package/src/cli/pane-functions/access-gate.ts +13 -2
  76. package/src/cli/pane-functions/capabilities.ts +4 -3
  77. package/src/cli/pane-functions/catalog.ts +214 -40
  78. package/src/cli/pane-functions/data.ts +42 -8
  79. package/src/cli/pane-functions/discovery.ts +1 -0
  80. package/src/cli/pane-functions/dom.ts +37 -8
  81. package/src/cli/pane-functions/freshness.ts +393 -49
  82. package/src/cli/pane-functions/function-help.ts +31 -15
  83. package/src/cli/pane-functions/headless.ts +98 -30
  84. package/src/cli/pane-functions/index.ts +101 -19
  85. package/src/cli/pane-functions/market-session.ts +22 -8
  86. package/src/cli/pane-functions/options.ts +71 -22
  87. package/src/cli/pane-functions/report-notices.ts +25 -7
  88. package/src/cli/pane-functions/report.ts +15 -8
  89. package/src/cli/pane-functions/resolver.ts +74 -19
  90. package/src/cli/pane-functions/screenshot.ts +250 -27
  91. package/src/cli/perpetual-contract.ts +60 -0
  92. package/src/cli/registry.ts +3 -1
  93. package/src/cli/report-tables.ts +26 -7
  94. package/src/cli/result.ts +45 -11
  95. package/src/cli/series-search.ts +111 -0
  96. package/src/cli/staged-tickers.ts +52 -0
  97. package/src/cli/symbol-args.ts +27 -0
  98. package/src/cli/symbol-list.ts +154 -0
  99. package/src/cli/symbol-rows.ts +154 -0
  100. package/src/cli/ticker-resolution.ts +311 -27
  101. package/src/cli/types.ts +5 -0
  102. package/src/components/chart/composite/axis-overlays.tsx +14 -3
  103. package/src/components/chart/composite/composite-chart.tsx +71 -11
  104. package/src/components/chart/composite/crosshair-readout.tsx +150 -0
  105. package/src/components/chart/composite/downsample.ts +1 -1
  106. package/src/components/chart/composite/format.ts +29 -0
  107. package/src/components/chart/composite/interactions.ts +9 -2
  108. package/src/components/chart/composite/legend.tsx +100 -33
  109. package/src/components/chart/composite/panel-bitmap.ts +70 -35
  110. package/src/components/chart/composite/panel-labels.ts +18 -17
  111. package/src/components/chart/composite/panel-series.ts +1 -0
  112. package/src/components/chart/composite/panel-surface.tsx +46 -21
  113. package/src/components/chart/composite/price-axis-labels.tsx +3 -1
  114. package/src/components/chart/composite/rasterizer.ts +50 -8
  115. package/src/components/chart/composite/scene.ts +2 -1
  116. package/src/components/chart/composite/time-scale.ts +26 -9
  117. package/src/components/chart/composite/types.ts +18 -0
  118. package/src/components/chart/composite/use-composite-viewport.ts +30 -2
  119. package/src/components/chart/native/raster/crosshair.ts +8 -3
  120. package/src/components/chart/native/raster/primitives.ts +85 -21
  121. package/src/components/chart/native/surface/manager.ts +33 -8
  122. package/src/components/chart/surface3d/chart.tsx +1 -1
  123. package/src/components/command-bar/action-runtime.ts +1 -1
  124. package/src/components/command-bar/commands/collection-list.ts +210 -0
  125. package/src/components/command-bar/commands/collection.ts +40 -1
  126. package/src/components/command-bar/commands/direct/index.ts +4 -0
  127. package/src/components/command-bar/commands/registry.ts +8 -0
  128. package/src/components/command-bar/panel/index.tsx +11 -3
  129. package/src/components/command-bar/panel/runtime.ts +3 -0
  130. package/src/components/command-bar/panel/types.ts +2 -0
  131. package/src/components/command-bar/routes/root/plugin-install.ts +4 -4
  132. package/src/components/command-bar/routes/root/provider-search.ts +4 -3
  133. package/src/components/command-bar/routes/ticker-search/results.ts +12 -11
  134. package/src/components/command-bar/routes/ticker-search/route.ts +4 -3
  135. package/src/components/command-bar/routing/actions.ts +1 -1
  136. package/src/components/command-bar/workflow/tickers.ts +42 -17
  137. package/src/components/layout/detached-pane-shell.tsx +68 -39
  138. package/src/components/layout/floating-pane.tsx +10 -1
  139. package/src/components/layout/header.tsx +25 -5
  140. package/src/components/layout/missing-pane.tsx +3 -3
  141. package/src/components/layout/pane/capture-stamp.ts +41 -0
  142. package/src/components/layout/pane/capture-status.ts +12 -0
  143. package/src/components/layout/pane/content.tsx +7 -13
  144. package/src/components/layout/pane/footer/index.tsx +6 -2
  145. package/src/components/layout/pane/footer/keyboard.ts +3 -0
  146. package/src/components/layout/pane/footer/model.ts +41 -1
  147. package/src/components/layout/pane/header.tsx +50 -1
  148. package/src/components/layout/pane/index.tsx +21 -3
  149. package/src/components/layout/pane/sidebar.tsx +88 -21
  150. package/src/components/layout/shell/active-drag.ts +21 -5
  151. package/src/components/layout/shell/cursor-occlusion.ts +2 -1
  152. package/src/components/layout/shell/drag/index.ts +39 -9
  153. package/src/components/layout/shell/drag/live.ts +61 -51
  154. package/src/components/layout/shell/drag/runtime.ts +54 -12
  155. package/src/components/layout/shell/index.tsx +84 -65
  156. package/src/components/layout/shell/menu.ts +14 -1
  157. package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
  158. package/src/components/layout/shell/pane/actions.ts +32 -10
  159. package/src/components/layout/shell/pane/ask.ts +131 -0
  160. package/src/components/layout/shell/pane/capture.ts +162 -0
  161. package/src/components/layout/shell/pane/layers.tsx +218 -50
  162. package/src/components/layout/shell/pane/management-shortcuts.ts +46 -1
  163. package/src/components/layout/shell/shortcuts.ts +21 -4
  164. package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
  165. package/src/components/markdown-text.tsx +62 -20
  166. package/src/components/metric-treemap/heat-surface.tsx +8 -1
  167. package/src/components/onboarding/account-step/form-panel.tsx +1 -1
  168. package/src/components/onboarding/account-step/index.tsx +1 -1
  169. package/src/components/onboarding/account-step/qr-panel.tsx +1 -1
  170. package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
  171. package/src/components/onboarding/onboarding-keyboard.ts +1 -1
  172. package/src/components/onboarding/onboarding-wizard.tsx +2 -2
  173. package/src/components/onboarding/use-onboarding-upgrade.ts +3 -3
  174. package/src/components/onboarding/wizard-account.ts +2 -2
  175. package/src/components/pane-template-wizard.tsx +9 -1
  176. package/src/components/price-selector-dialog.tsx +11 -2
  177. package/src/components/reader/article-reader.tsx +642 -0
  178. package/src/components/reader/article-text.ts +527 -0
  179. package/src/components/sign-in-gate.tsx +3 -3
  180. package/src/components/ticker/list-table-view.tsx +43 -2
  181. package/src/components/ui/action-row.tsx +2 -1
  182. package/src/components/ui/button.tsx +7 -1
  183. package/src/components/ui/choice-dialog.tsx +6 -4
  184. package/src/components/ui/confirm-dialog.tsx +28 -18
  185. package/src/components/ui/data-table/index.tsx +18 -6
  186. package/src/components/ui/data-table/opentui/index.tsx +37 -6
  187. package/src/components/ui/data-table/types.ts +12 -0
  188. package/src/components/ui/dialog-actions.tsx +64 -0
  189. package/src/components/ui/display.tsx +17 -3
  190. package/src/components/ui/frame.tsx +35 -2
  191. package/src/components/ui/icon.tsx +6 -1
  192. package/src/components/ui/query-bar.tsx +10 -1
  193. package/src/components/ui/text-prompt-dialog.tsx +11 -9
  194. package/src/data/cached-query.ts +2 -0
  195. package/src/data/config/store/migrations.ts +7 -0
  196. package/src/data/config/store/normalize.ts +7 -2
  197. package/src/data/config/store/portfolio-as-of-column.ts +57 -0
  198. package/src/data/ticker-repository.ts +5 -0
  199. package/src/data/ticker-store.ts +15 -0
  200. package/src/docs/content.ts +215 -0
  201. package/src/docs/load.ts +139 -0
  202. package/src/docs/requests.ts +39 -0
  203. package/src/docs/snapshot.chunk.ts +8 -0
  204. package/src/docs/snapshot.json +7555 -0
  205. package/src/docs/topics.ts +216 -0
  206. package/src/i18n/es.ts +65 -5
  207. package/src/i18n/ja.ts +65 -5
  208. package/src/i18n/ko.ts +65 -5
  209. package/src/i18n/zh-cn.ts +65 -5
  210. package/src/i18n/zh-tw.ts +65 -5
  211. package/src/layout/desks.ts +1 -1
  212. package/src/layout/pane-manager/dock-tree.ts +18 -0
  213. package/src/layout/pane-manager/index.ts +1 -0
  214. package/src/layout-marketplace/gallery.tsx +1 -1
  215. package/src/market-data/coordinator/chart.ts +10 -4
  216. package/src/market-data/coordinator/index.ts +6 -3
  217. package/src/{plugins/builtin/futures/contracts.ts → market-data/futures-board.ts} +81 -28
  218. package/src/market-data/futures-contract.ts +151 -0
  219. package/src/market-data/hooks.tsx +10 -2
  220. package/src/market-data/market/format.ts +39 -21
  221. package/src/market-data/market/freshness.ts +84 -20
  222. package/src/market-data/market/session-close-note.ts +3 -2
  223. package/src/market-data/market/status.ts +19 -23
  224. package/src/market-data/published-apac-sessions.ts +23 -1
  225. package/src/market-data/quotes/contributions.ts +5 -0
  226. package/src/market-data/quotes/metadata.ts +19 -24
  227. package/src/market-data/quotes/resolution.ts +5 -0
  228. package/src/market-data/quotes/screener-live-quotes.ts +5 -4
  229. package/src/market-data/result-types.ts +2 -0
  230. package/src/notifications/app-notifier.ts +17 -1
  231. package/src/notifications/notification-log.ts +180 -0
  232. package/src/plugins/auto-update-node.ts +2 -2
  233. package/src/plugins/auto-update.ts +2 -2
  234. package/src/plugins/builtin/account-management/index.tsx +1 -0
  235. package/src/plugins/builtin/account-management/model.ts +1 -56
  236. package/src/plugins/builtin/account-management/pane.tsx +6 -4
  237. package/src/plugins/builtin/account-management/password-dialog.tsx +1 -1
  238. package/src/plugins/builtin/alerts/catalysts.ts +1 -1
  239. package/src/plugins/builtin/alerts/cli.ts +313 -47
  240. package/src/plugins/builtin/alerts/events-pane.tsx +45 -7
  241. package/src/plugins/builtin/alerts/events.ts +23 -2
  242. package/src/plugins/builtin/alerts/focus.ts +27 -0
  243. package/src/plugins/builtin/alerts/history-pane.tsx +7 -2
  244. package/src/plugins/builtin/alerts/history.ts +2 -0
  245. package/src/plugins/builtin/alerts/index.tsx +47 -11
  246. package/src/plugins/builtin/alerts/pane.tsx +27 -1
  247. package/src/plugins/builtin/alerts/research-builder.ts +8 -3
  248. package/src/plugins/builtin/alerts/research-rules.ts +18 -2
  249. package/src/plugins/builtin/alerts/scheduled-check.ts +122 -0
  250. package/src/plugins/builtin/alerts/scheduled-sources.ts +25 -0
  251. package/src/plugins/builtin/alerts/scheduled.ts +254 -0
  252. package/src/plugins/builtin/alerts/targets.ts +92 -0
  253. package/src/plugins/builtin/analytics/index.tsx +8 -3
  254. package/src/plugins/builtin/analytics/risk-headless.ts +60 -27
  255. package/src/plugins/builtin/analytics/risk-math.ts +91 -27
  256. package/src/plugins/builtin/analytics/risk-model.ts +35 -5
  257. package/src/plugins/builtin/analytics/risk-pane.tsx +15 -8
  258. package/src/plugins/builtin/attention/headless.ts +1 -1
  259. package/src/plugins/builtin/attention/index.tsx +2 -0
  260. package/src/plugins/builtin/attention/pane.tsx +3 -1
  261. package/src/plugins/builtin/attention/series.ts +26 -0
  262. package/src/plugins/builtin/awards/headless.ts +88 -18
  263. package/src/plugins/builtin/awards/index.tsx +2 -0
  264. package/src/plugins/builtin/awards/model.ts +41 -1
  265. package/src/plugins/builtin/awards/pane.tsx +22 -13
  266. package/src/plugins/builtin/awards/series.ts +29 -0
  267. package/src/plugins/builtin/backtest/headless.ts +2 -2
  268. package/src/plugins/builtin/bond-calculator/model.ts +2 -1
  269. package/src/plugins/builtin/broker-manager/index.tsx +1 -0
  270. package/src/plugins/builtin/catalysts/headless.ts +1 -1
  271. package/src/plugins/builtin/catalysts/pane.tsx +3 -1
  272. package/src/plugins/builtin/cds/client.ts +49 -12
  273. package/src/plugins/builtin/cds/headless.ts +119 -19
  274. package/src/plugins/builtin/cds/index.tsx +3 -1
  275. package/src/plugins/builtin/cds/model.ts +214 -32
  276. package/src/plugins/builtin/cds/pane.tsx +58 -14
  277. package/src/plugins/builtin/cds/series.ts +19 -0
  278. package/src/plugins/builtin/central-bank-rates/client.ts +4 -0
  279. package/src/plugins/builtin/central-bank-rates/headless.ts +46 -16
  280. package/src/plugins/builtin/central-bank-rates/index.tsx +3 -1
  281. package/src/plugins/builtin/central-bank-rates/model.ts +99 -0
  282. package/src/plugins/builtin/central-bank-rates/pane.tsx +1 -1
  283. package/src/plugins/builtin/central-bank-rates/series.ts +36 -0
  284. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +193 -255
  285. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +84 -46
  286. package/src/plugins/builtin/chart-composer/editor.tsx +5 -4
  287. package/src/plugins/builtin/chart-composer/field-series.ts +40 -0
  288. package/src/plugins/builtin/chart-composer/headless-schema.ts +1 -1
  289. package/src/plugins/builtin/chart-composer/headless.ts +70 -5
  290. package/src/plugins/builtin/chart-composer/index.tsx +15 -3
  291. package/src/plugins/builtin/chart-composer/pane.tsx +81 -38
  292. package/src/plugins/builtin/chart-composer/series-catalog.ts +58 -50
  293. package/src/plugins/builtin/chart-composer/series-expression.ts +18 -10
  294. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +59 -3
  295. package/src/plugins/builtin/chart-composer/user-series.ts +84 -0
  296. package/src/plugins/builtin/chat/content/composer-runtime.ts +6 -1
  297. package/src/plugins/builtin/chat/content/composer.tsx +5 -1
  298. package/src/plugins/builtin/chat/content/footer.tsx +12 -0
  299. package/src/plugins/builtin/chat/content/index.tsx +89 -5
  300. package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
  301. package/src/plugins/builtin/chat/content/new-messages.tsx +89 -0
  302. package/src/plugins/builtin/chat/content/row-activity.ts +132 -0
  303. package/src/plugins/builtin/chat/content/scroll.ts +127 -27
  304. package/src/plugins/builtin/chat/content/shortcuts.ts +2 -2
  305. package/src/plugins/builtin/chat/content/transcript.tsx +145 -78
  306. package/src/plugins/builtin/chat/content/types.ts +1 -0
  307. package/src/plugins/builtin/chat/controller/fetch.ts +8 -2
  308. package/src/plugins/builtin/chat/controller/index.ts +123 -1
  309. package/src/plugins/builtin/chat/controller/message-loading.ts +3 -0
  310. package/src/plugins/builtin/chat/controller/messages.ts +7 -2
  311. package/src/plugins/builtin/chat/controller/realtime.ts +10 -1
  312. package/src/plugins/builtin/chat/controller/send.ts +61 -1
  313. package/src/plugins/builtin/chat/controller/state.ts +8 -0
  314. package/src/plugins/builtin/chat/ghost-user.ts +20 -0
  315. package/src/plugins/builtin/chat/index.tsx +23 -5
  316. package/src/plugins/builtin/chat/layout.ts +78 -5
  317. package/src/plugins/builtin/chat/message/ai-badge.tsx +18 -0
  318. package/src/plugins/builtin/chat/message/desktop.tsx +55 -6
  319. package/src/plugins/builtin/chat/message/header.tsx +16 -4
  320. package/src/plugins/builtin/chat/message/profile-popover.tsx +5 -1
  321. package/src/plugins/builtin/chat/message/reactions.tsx +210 -0
  322. package/src/plugins/builtin/chat/message/render-state.ts +18 -2
  323. package/src/plugins/builtin/chat/message/terminal.tsx +43 -4
  324. package/src/plugins/builtin/chat/message/types.ts +12 -0
  325. package/src/plugins/builtin/chat/reactions.ts +197 -0
  326. package/src/plugins/builtin/chat/share/flow.tsx +87 -0
  327. package/src/plugins/builtin/chat/share/targets.ts +27 -0
  328. package/src/plugins/builtin/chat/status-widget.tsx +6 -3
  329. package/src/plugins/builtin/chat/unread-inbox-pane.tsx +148 -27
  330. package/src/plugins/builtin/chat/unread-inbox.ts +22 -0
  331. package/src/plugins/builtin/cloud/askg/attached-pane.tsx +69 -0
  332. package/src/plugins/builtin/cloud/askg/controller.ts +111 -19
  333. package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
  334. package/src/plugins/builtin/cloud/askg/manifest.ts +32 -7
  335. package/src/plugins/builtin/cloud/askg/model.ts +27 -8
  336. package/src/plugins/builtin/cloud/askg/pane-attachment.ts +94 -0
  337. package/src/plugins/builtin/cloud/askg/pane.tsx +141 -12
  338. package/src/plugins/builtin/cloud/askg/pending-question.ts +11 -0
  339. package/src/plugins/builtin/cloud/askg/protocol.ts +10 -1
  340. package/src/plugins/builtin/cloud/askg/tool-display.ts +3 -0
  341. package/src/plugins/builtin/cloud/askg/undo.ts +2 -0
  342. package/src/plugins/builtin/cloud/auth-actions.tsx +1 -1
  343. package/src/plugins/builtin/cloud/auth-commands.ts +1 -1
  344. package/src/plugins/builtin/cloud/auth-dialog.tsx +3 -3
  345. package/src/plugins/builtin/cloud/company-picker.tsx +1 -1
  346. package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +3 -0
  347. package/src/plugins/builtin/cloud/plugin.tsx +19 -2
  348. package/src/plugins/builtin/cloud/team/model.ts +5 -0
  349. package/src/plugins/builtin/cloud/team/module.tsx +1 -0
  350. package/src/plugins/builtin/cloud/team/store.ts +8 -3
  351. package/src/plugins/builtin/cloud/terminal-relay/engine.ts +77 -9
  352. package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +6 -1
  353. package/src/plugins/builtin/cloud/terminal-relay/policy.ts +9 -0
  354. package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +35 -11
  355. package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
  356. package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
  357. package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
  358. package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
  359. package/src/plugins/builtin/company-attention/headless.ts +21 -7
  360. package/src/plugins/builtin/company-attention/index.tsx +2 -0
  361. package/src/plugins/builtin/company-attention/model.ts +26 -7
  362. package/src/plugins/builtin/company-attention/pane.tsx +12 -9
  363. package/src/plugins/builtin/company-attention/series.ts +52 -0
  364. package/src/plugins/builtin/company-kpis/headless.ts +97 -10
  365. package/src/plugins/builtin/company-kpis/model.ts +24 -2
  366. package/src/plugins/builtin/company-kpis/pane.tsx +17 -16
  367. package/src/plugins/builtin/composite-plugins.ts +19 -13
  368. package/src/plugins/builtin/connections/index.ts +1 -0
  369. package/src/plugins/builtin/cot/headless.ts +1 -1
  370. package/src/plugins/builtin/cot/index.tsx +3 -1
  371. package/src/plugins/builtin/cot/model.ts +40 -11
  372. package/src/plugins/builtin/cot/series.ts +27 -0
  373. package/src/plugins/builtin/cpi/headless.ts +3 -3
  374. package/src/plugins/builtin/credit-boards/cdx-pane.tsx +10 -1
  375. package/src/plugins/builtin/credit-boards/client.ts +6 -2
  376. package/src/plugins/builtin/credit-boards/headless.ts +108 -31
  377. package/src/plugins/builtin/credit-boards/index.tsx +2 -0
  378. package/src/plugins/builtin/credit-boards/model.ts +11 -1
  379. package/src/plugins/builtin/credit-boards/series.ts +66 -0
  380. package/src/plugins/builtin/credit-conditions/client.ts +12 -9
  381. package/src/plugins/builtin/credit-conditions/headless.ts +13 -2
  382. package/src/plugins/builtin/credit-conditions/index.tsx +18 -9
  383. package/src/plugins/builtin/credit-conditions/model.ts +19 -11
  384. package/src/plugins/builtin/credit-conditions/series.ts +16 -0
  385. package/src/plugins/builtin/credit-documents/headless.ts +33 -3
  386. package/src/plugins/builtin/credit-documents/pane.tsx +3 -1
  387. package/src/plugins/builtin/crypto-board/headless.ts +2 -3
  388. package/src/plugins/builtin/crypto-board/index.tsx +2 -0
  389. package/src/plugins/builtin/crypto-board/model.ts +12 -0
  390. package/src/plugins/builtin/crypto-board/pane.tsx +19 -12
  391. package/src/plugins/builtin/crypto-board/series.ts +48 -0
  392. package/src/plugins/builtin/custom-view/live-quotes.ts +2 -2
  393. package/src/plugins/builtin/debt-maturities/headless.ts +17 -11
  394. package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
  395. package/src/plugins/builtin/debt-maturities/series.ts +45 -0
  396. package/src/plugins/builtin/dividend-yield/client.ts +3 -0
  397. package/src/plugins/builtin/dividend-yield/headless.ts +7 -4
  398. package/src/plugins/builtin/dividend-yield/index.tsx +3 -1
  399. package/src/plugins/builtin/dividend-yield/pane.tsx +3 -1
  400. package/src/plugins/builtin/dividend-yield/series.ts +20 -0
  401. package/src/plugins/builtin/dividend-yield/types.ts +2 -0
  402. package/src/plugins/builtin/docs/blocks.tsx +181 -0
  403. package/src/plugins/builtin/docs/index.tsx +68 -0
  404. package/src/plugins/builtin/docs/pane.tsx +426 -0
  405. package/src/plugins/builtin/docs/targets.ts +72 -0
  406. package/src/plugins/builtin/docs/use-docs.ts +60 -0
  407. package/src/plugins/builtin/doe/headless.ts +12 -8
  408. package/src/plugins/builtin/doe/index.tsx +2 -0
  409. package/src/plugins/builtin/doe/series.ts +62 -0
  410. package/src/plugins/builtin/earnings/client.ts +3 -2
  411. package/src/plugins/builtin/earnings/format.ts +1 -5
  412. package/src/plugins/builtin/earnings/headless.ts +58 -6
  413. package/src/plugins/builtin/earnings/history-model.ts +15 -1
  414. package/src/plugins/builtin/earnings/history-table.ts +13 -2
  415. package/src/plugins/builtin/earnings/history.tsx +7 -3
  416. package/src/plugins/builtin/earnings/index.tsx +9 -0
  417. package/src/plugins/builtin/earnings-calls/headless.ts +28 -2
  418. package/src/plugins/builtin/earnings-calls/index.tsx +1 -1
  419. package/src/plugins/builtin/earnings-ripple/index.tsx +2 -0
  420. package/src/plugins/builtin/econ/fred-catalog.ts +198 -0
  421. package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
  422. package/src/plugins/builtin/econ/index.tsx +2 -0
  423. package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
  424. package/src/plugins/builtin/econ-statistics/headless.ts +19 -4
  425. package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
  426. package/src/plugins/builtin/equity-screener/headless.ts +3 -3
  427. package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
  428. package/src/plugins/builtin/estimate-revisions/headless.ts +3 -3
  429. package/src/plugins/builtin/exposure/drivers.ts +13 -0
  430. package/src/plugins/builtin/exposure/headless.ts +205 -13
  431. package/src/plugins/builtin/exposure/holdings.ts +1 -1
  432. package/src/plugins/builtin/exposure/index.tsx +1 -0
  433. package/src/plugins/builtin/exposure/model.ts +23 -3
  434. package/src/plugins/builtin/exposure/pane.tsx +14 -12
  435. package/src/plugins/builtin/fear-greed/index.tsx +18 -10
  436. package/src/plugins/builtin/fear-greed/series.ts +52 -0
  437. package/src/plugins/builtin/futures/index.tsx +43 -3
  438. package/src/plugins/builtin/futures/model.ts +1 -1
  439. package/src/plugins/builtin/futures/returns.ts +1 -1
  440. package/src/plugins/builtin/futures/series.ts +13 -0
  441. package/src/plugins/builtin/futures/table.tsx +1 -1
  442. package/src/plugins/builtin/futures/use-front-returns.ts +1 -1
  443. package/src/plugins/builtin/futures-curve/client.ts +12 -3
  444. package/src/plugins/builtin/futures-curve/headless.ts +71 -10
  445. package/src/plugins/builtin/futures-curve/index.tsx +1 -1
  446. package/src/plugins/builtin/futures-curve/model.ts +66 -11
  447. package/src/plugins/builtin/futures-curve/pane.tsx +52 -18
  448. package/src/plugins/builtin/fx-matrix/client.ts +63 -0
  449. package/src/plugins/builtin/fx-matrix/export.ts +2 -1
  450. package/src/plugins/builtin/fx-matrix/headless.ts +154 -0
  451. package/src/plugins/builtin/fx-matrix/index.tsx +4 -4
  452. package/src/plugins/builtin/gpu/board.tsx +13 -10
  453. package/src/plugins/builtin/gpu/changes.tsx +4 -4
  454. package/src/plugins/builtin/gpu/client.ts +19 -1
  455. package/src/plugins/builtin/gpu/equities.tsx +14 -10
  456. package/src/plugins/builtin/gpu/headless.ts +58 -27
  457. package/src/plugins/builtin/gpu/history.tsx +3 -3
  458. package/src/plugins/builtin/gpu/index.tsx +2 -0
  459. package/src/plugins/builtin/gpu/model.ts +101 -16
  460. package/src/plugins/builtin/gpu/pane.tsx +28 -12
  461. package/src/plugins/builtin/gpu/series.ts +38 -0
  462. package/src/plugins/builtin/help/function-card.tsx +25 -6
  463. package/src/plugins/builtin/help/function-index.ts +2 -0
  464. package/src/plugins/builtin/help/index.tsx +31 -9
  465. package/src/plugins/builtin/holders/beneficial-model.ts +90 -3
  466. package/src/plugins/builtin/holders/beneficial-report.ts +57 -5
  467. package/src/plugins/builtin/holders/beneficial-view.tsx +55 -11
  468. package/src/plugins/builtin/holders/client.ts +22 -3
  469. package/src/plugins/builtin/holders/format.ts +18 -3
  470. package/src/plugins/builtin/holders/headless.ts +36 -133
  471. package/src/plugins/builtin/holders/pane.tsx +11 -4
  472. package/src/plugins/builtin/holders/report-header.ts +40 -5
  473. package/src/plugins/builtin/holders/report-rows.ts +240 -0
  474. package/src/plugins/builtin/insider/client.ts +35 -20
  475. package/src/plugins/builtin/insider/headless.ts +41 -11
  476. package/src/plugins/builtin/insider/index.tsx +26 -9
  477. package/src/plugins/builtin/insider/insider-data.ts +10 -0
  478. package/src/plugins/builtin/insider/issuer.ts +49 -0
  479. package/src/plugins/builtin/insider/model.ts +3 -0
  480. package/src/plugins/builtin/ipo-calendar/headless.ts +1 -1
  481. package/src/plugins/builtin/iv-history/client.ts +20 -6
  482. package/src/plugins/builtin/iv-history/format.ts +9 -0
  483. package/src/plugins/builtin/iv-history/headless.ts +56 -21
  484. package/src/plugins/builtin/iv-history/index.tsx +2 -0
  485. package/src/plugins/builtin/iv-history/model.ts +143 -8
  486. package/src/plugins/builtin/iv-history/screen-pane.tsx +5 -9
  487. package/src/plugins/builtin/iv-history/series.ts +29 -0
  488. package/src/plugins/builtin/jobs/headless.ts +26 -3
  489. package/src/plugins/builtin/jobs/index.tsx +3 -1
  490. package/src/plugins/builtin/jobs/series.ts +19 -0
  491. package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
  492. package/src/plugins/builtin/kelly-sizer/pane.tsx +2 -1
  493. package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
  494. package/src/plugins/builtin/macro-day/client.ts +44 -3
  495. package/src/plugins/builtin/macro-day/headless.ts +13 -10
  496. package/src/plugins/builtin/macro-day/model.ts +56 -10
  497. package/src/plugins/builtin/macro-day/pane.tsx +30 -20
  498. package/src/plugins/builtin/market-heatmap/headless.ts +20 -5
  499. package/src/plugins/builtin/market-heatmap/index.tsx +6 -0
  500. package/src/plugins/builtin/market-heatmap/model.ts +19 -11
  501. package/src/plugins/builtin/market-heatmap/portfolio.ts +2 -2
  502. package/src/plugins/builtin/market-movers/client.ts +7 -5
  503. package/src/plugins/builtin/market-movers/index.tsx +3 -2
  504. package/src/plugins/builtin/market-movers/model.ts +30 -0
  505. package/src/plugins/builtin/market-movers/screener.ts +31 -0
  506. package/src/plugins/builtin/market-valuation/chart-series.ts +29 -69
  507. package/src/plugins/builtin/market-valuation/index.tsx +3 -3
  508. package/src/plugins/builtin/market-valuation/indicators.ts +0 -5
  509. package/src/plugins/builtin/members/headless.ts +8 -3
  510. package/src/plugins/builtin/members/model.ts +31 -3
  511. package/src/plugins/builtin/members/pane.tsx +6 -8
  512. package/src/plugins/builtin/mna/distress/headless.ts +4 -4
  513. package/src/plugins/builtin/mna/headless.ts +18 -6
  514. package/src/plugins/builtin/money-markets/headless.ts +5 -4
  515. package/src/plugins/builtin/money-markets/index.tsx +2 -0
  516. package/src/plugins/builtin/money-markets/series.ts +41 -0
  517. package/src/plugins/builtin/news/index.tsx +0 -2
  518. package/src/plugins/builtin/news/wire/news/detail-view.tsx +53 -104
  519. package/src/plugins/builtin/news/wire/news/footer.ts +2 -25
  520. package/src/plugins/builtin/news/wire/news/preset-pane.tsx +0 -2
  521. package/src/plugins/builtin/notes/cli.ts +12 -7
  522. package/src/plugins/builtin/notes/index.tsx +1 -0
  523. package/src/plugins/builtin/options/index.tsx +3 -0
  524. package/src/plugins/builtin/options/view.tsx +1 -1
  525. package/src/plugins/builtin/options-calculator/inputs.ts +2 -1
  526. package/src/plugins/builtin/options-positioning/client.ts +7 -3
  527. package/src/plugins/builtin/options-positioning/headless.ts +4 -3
  528. package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
  529. package/src/plugins/builtin/options-scenario/client.ts +2 -1
  530. package/src/plugins/builtin/options-scenario/headless.ts +1 -0
  531. package/src/plugins/builtin/options-scenario/hedge.ts +2 -1
  532. package/src/plugins/builtin/perps/client.ts +90 -16
  533. package/src/plugins/builtin/perps/equity-row.tsx +52 -17
  534. package/src/plugins/builtin/perps/freshness.ts +66 -0
  535. package/src/plugins/builtin/perps/headless.ts +47 -32
  536. package/src/plugins/builtin/perps/index.tsx +23 -4
  537. package/src/plugins/builtin/perps/list-perpetuals.ts +118 -0
  538. package/src/plugins/builtin/perps/model.ts +20 -5
  539. package/src/plugins/builtin/perps/open-market.ts +15 -0
  540. package/src/plugins/builtin/perps/pane.tsx +76 -20
  541. package/src/plugins/builtin/perps/series.ts +76 -0
  542. package/src/plugins/builtin/plugin-marketplace/index.tsx +1 -1
  543. package/src/plugins/builtin/plugin-marketplace/pane.tsx +73 -67
  544. package/src/plugins/builtin/plugin-module.ts +3 -0
  545. package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
  546. package/src/plugins/builtin/portfolio-list/allocation.ts +5 -4
  547. package/src/plugins/builtin/portfolio-list/cell-version.ts +8 -1
  548. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +161 -0
  549. package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
  550. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +384 -74
  551. package/src/plugins/builtin/portfolio-list/cli/render.ts +437 -71
  552. package/src/plugins/builtin/portfolio-list/cli/shared.ts +21 -4
  553. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +121 -47
  554. package/src/plugins/builtin/portfolio-list/column-values.ts +104 -26
  555. package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
  556. package/src/plugins/builtin/portfolio-list/headless.ts +84 -18
  557. package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
  558. package/src/plugins/builtin/portfolio-list/index.tsx +5 -1
  559. package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
  560. package/src/plugins/builtin/portfolio-list/mutations.ts +2 -9
  561. package/src/plugins/builtin/portfolio-list/pane/data.ts +5 -1
  562. package/src/plugins/builtin/portfolio-list/pane/index.tsx +52 -9
  563. package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +33 -11
  564. package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +21 -1
  565. package/src/plugins/builtin/portfolio-list/settings.ts +17 -0
  566. package/src/plugins/builtin/portfolio-list/summary/index.tsx +12 -0
  567. package/src/plugins/builtin/portfolio-list/summary/totals.ts +9 -4
  568. package/src/plugins/builtin/portfolio-list/table.tsx +37 -7
  569. package/src/plugins/builtin/power/client.ts +16 -0
  570. package/src/plugins/builtin/power/evidence.ts +63 -10
  571. package/src/plugins/builtin/power/headless.ts +77 -9
  572. package/src/plugins/builtin/power/index.tsx +28 -3
  573. package/src/plugins/builtin/power/model.ts +73 -2
  574. package/src/plugins/builtin/power/pane.tsx +37 -9
  575. package/src/plugins/builtin/power/prices-client.ts +139 -0
  576. package/src/plugins/builtin/power/prices-headless.ts +137 -0
  577. package/src/plugins/builtin/power/prices-model.ts +103 -0
  578. package/src/plugins/builtin/power/prices.tsx +179 -0
  579. package/src/plugins/builtin/rate-path/headless.ts +46 -18
  580. package/src/plugins/builtin/realized-vol/headless.ts +5 -0
  581. package/src/plugins/builtin/relative-rotation/headless.ts +3 -3
  582. package/src/plugins/builtin/research/corporate-actions-pane.tsx +5 -2
  583. package/src/plugins/builtin/research/event-model.ts +68 -24
  584. package/src/plugins/builtin/research/events-headless.ts +2 -1
  585. package/src/plugins/builtin/research/headless.ts +2 -1
  586. package/src/plugins/builtin/research/index.tsx +2 -0
  587. package/src/plugins/builtin/research-search/article.ts +65 -0
  588. package/src/plugins/builtin/research-search/document-view.tsx +33 -215
  589. package/src/plugins/builtin/research-search/model.ts +0 -9
  590. package/src/plugins/builtin/research-search/pane.tsx +41 -30
  591. package/src/plugins/builtin/research-search/snippet.ts +0 -29
  592. package/src/plugins/builtin/revenue-breakdown/headless.ts +18 -6
  593. package/src/plugins/builtin/seasonality/client.ts +15 -7
  594. package/src/plugins/builtin/seasonality/headless.ts +36 -12
  595. package/src/plugins/builtin/seasonality/index.tsx +2 -2
  596. package/src/plugins/builtin/seasonality/model.ts +119 -0
  597. package/src/plugins/builtin/seasonality/pane.tsx +108 -37
  598. package/src/plugins/builtin/sec/headless.ts +25 -3
  599. package/src/plugins/builtin/sec/index.tsx +2 -1
  600. package/src/plugins/builtin/series-inventory.ts +93 -0
  601. package/src/plugins/builtin/shared/cloud-denied.ts +15 -0
  602. package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
  603. package/src/plugins/builtin/shared/command-tab.ts +30 -12
  604. package/src/plugins/builtin/shared/earnings-report.ts +55 -0
  605. package/src/plugins/builtin/shared/fred-points.ts +20 -0
  606. package/src/plugins/builtin/shared/free-preview.ts +47 -0
  607. package/src/plugins/builtin/shared/fx-rate-freshness.ts +101 -0
  608. package/src/plugins/builtin/shared/open-description.ts +29 -0
  609. package/src/plugins/builtin/shared/report-freshness.ts +12 -1
  610. package/src/plugins/builtin/shared/series-warning.ts +5 -0
  611. package/src/plugins/builtin/shared/volatility/options.ts +4 -1
  612. package/src/plugins/builtin/short-interest/headless.ts +1 -0
  613. package/src/plugins/builtin/short-interest/index.tsx +2 -0
  614. package/src/plugins/builtin/short-interest/series.ts +36 -0
  615. package/src/plugins/builtin/short-interest/watch-headless.ts +3 -2
  616. package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
  617. package/src/plugins/builtin/short-volume/headless.ts +2 -1
  618. package/src/plugins/builtin/short-volume/index.tsx +2 -0
  619. package/src/plugins/builtin/short-volume/series.ts +23 -0
  620. package/src/plugins/builtin/social-mentions/headless.ts +1 -1
  621. package/src/plugins/builtin/social-mentions/index.tsx +2 -0
  622. package/src/plugins/builtin/social-mentions/series.ts +23 -0
  623. package/src/plugins/builtin/supply-chain/graph-pane.tsx +3 -2
  624. package/src/plugins/builtin/supply-chain/headless.ts +43 -11
  625. package/src/plugins/builtin/supply-chain/model.ts +13 -0
  626. package/src/plugins/builtin/supply-chain/pane.tsx +8 -6
  627. package/src/plugins/builtin/themes/headless.ts +74 -10
  628. package/src/plugins/builtin/themes/model.ts +71 -4
  629. package/src/plugins/builtin/themes/pane.tsx +22 -5
  630. package/src/plugins/builtin/thirteenf/api.ts +1 -0
  631. package/src/plugins/builtin/thirteenf/data.ts +6 -4
  632. package/src/plugins/builtin/thirteenf/headless.ts +217 -36
  633. package/src/plugins/builtin/thirteenf/model.ts +39 -1
  634. package/src/plugins/builtin/thirteenf/overlap.ts +75 -0
  635. package/src/plugins/builtin/thirteenf/pane.tsx +10 -1
  636. package/src/plugins/builtin/thirteenf/report-notes.ts +103 -1
  637. package/src/plugins/builtin/thirteenf/types.ts +2 -0
  638. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +114 -0
  639. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +57 -2
  640. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +19 -55
  641. package/src/plugins/builtin/ticker-detail/headless-schema.ts +30 -0
  642. package/src/plugins/builtin/ticker-detail/headless.ts +86 -0
  643. package/src/plugins/builtin/ticker-detail/index.tsx +26 -11
  644. package/src/plugins/builtin/ticker-detail/overview/components.tsx +1 -1
  645. package/src/plugins/builtin/ticker-detail/overview/futures-contract.ts +31 -0
  646. package/src/plugins/builtin/ticker-detail/overview/model.ts +3 -3
  647. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +2 -1
  648. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +49 -5
  649. package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
  650. package/src/plugins/builtin/time-sales/headless.ts +2 -1
  651. package/src/plugins/builtin/time-sales/index.tsx +2 -1
  652. package/src/plugins/builtin/treasury-auctions/headless.ts +16 -2
  653. package/src/plugins/builtin/treasury-auctions/index.tsx +1 -0
  654. package/src/plugins/builtin/treasury-auctions/model.ts +8 -0
  655. package/src/plugins/builtin/vol-surface/evidence.ts +7 -1
  656. package/src/plugins/builtin/vol-surface/headless.ts +51 -17
  657. package/src/plugins/builtin/vol-surface/heat-grid.tsx +113 -0
  658. package/src/plugins/builtin/vol-surface/model.ts +39 -6
  659. package/src/plugins/builtin/vol-surface/pane.tsx +14 -13
  660. package/src/plugins/builtin/vol-surface/stored.ts +63 -3
  661. package/src/plugins/builtin/vol-surface/surface.tsx +30 -2
  662. package/src/plugins/builtin/volatility/index.tsx +2 -0
  663. package/src/plugins/builtin/volatility/series.ts +84 -0
  664. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +6 -5
  665. package/src/plugins/builtin/world-venue-map/basemap.ts +6 -3
  666. package/src/plugins/builtin/world-venue-map/geo-draw.tsx +2 -1
  667. package/src/plugins/builtin/world-venue-map/geo-series.ts +26 -1
  668. package/src/plugins/builtin/world-venue-map/geo-svg.tsx +6 -6
  669. package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
  670. package/src/plugins/builtin/world-venue-map/index.ts +2 -1
  671. package/src/plugins/builtin/world-venue-map/layered-pane.tsx +24 -13
  672. package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
  673. package/src/plugins/builtin/world-venue-map/map.tsx +144 -13
  674. package/src/plugins/builtin/world-venue-map/model.ts +56 -19
  675. package/src/plugins/builtin/world-venue-map/pane.tsx +5 -2
  676. package/src/plugins/builtin/yield-curve/chart.ts +2 -2
  677. package/src/plugins/builtin/yield-curve/curves.ts +21 -8
  678. package/src/plugins/builtin/yield-curve/headless.ts +71 -18
  679. package/src/plugins/builtin/yield-curve/index.tsx +4 -2
  680. package/src/plugins/builtin/yield-curve/series.ts +86 -0
  681. package/src/plugins/catalog-browser.ts +2 -1
  682. package/src/plugins/installer.ts +2 -2
  683. package/src/plugins/loader.ts +15 -0
  684. package/src/plugins/manager-node.ts +1 -1
  685. package/src/plugins/{builtin/plugin-marketplace → marketplace}/feed.ts +2 -2
  686. package/src/plugins/{builtin/plugin-marketplace → marketplace}/model.ts +6 -6
  687. package/src/plugins/{builtin/plugin-marketplace → marketplace}/store.ts +1 -1
  688. package/src/plugins/registry/host-actions.ts +11 -0
  689. package/src/plugins/registry/index.ts +89 -4
  690. package/src/portfolio/collection-name.ts +31 -0
  691. package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
  692. package/src/portfolio/position-value.ts +40 -0
  693. package/src/portfolio/valuation-basis.ts +79 -0
  694. package/src/public/__snapshots__/public-api.test.ts.snap +7 -0
  695. package/src/public/time-series.ts +17 -0
  696. package/src/react/auto-refresh.ts +13 -3
  697. package/src/react/input.ts +33 -1
  698. package/src/react/key-repeat.ts +86 -0
  699. package/src/remote/app-host.tsx +20 -4
  700. package/src/remote/confirm-change.tsx +85 -0
  701. package/src/remote/controller-utils.ts +8 -1
  702. package/src/remote/controller.ts +144 -7
  703. package/src/remote/pane-screenshot.ts +47 -0
  704. package/src/remote/schema.ts +65 -2
  705. package/src/remote/types.ts +30 -0
  706. package/src/remote/watchlist.ts +306 -0
  707. package/src/renderers/browser/main.tsx +4 -3
  708. package/src/renderers/browser/research-entry.ts +4 -2
  709. package/src/renderers/cloudflare/worker.ts +1 -1
  710. package/src/renderers/dom/data-table/frozen-column.ts +3 -1
  711. package/src/renderers/dom/data-table/index.tsx +33 -6
  712. package/src/renderers/dom/data-table/row.tsx +30 -1
  713. package/src/renderers/dom/desktop/control-styles.ts +63 -1
  714. package/src/renderers/dom/desktop/controls.tsx +30 -23
  715. package/src/renderers/dom/desktop/dialog-actions.tsx +170 -0
  716. package/src/renderers/dom/desktop/icons.tsx +16 -0
  717. package/src/renderers/dom/dom-ui-host.tsx +3 -0
  718. package/src/renderers/dom/host/block-glyph-canvas.tsx +6 -3
  719. package/src/renderers/dom/host/box.tsx +8 -0
  720. package/src/renderers/dom/host/chart-surface.tsx +33 -2
  721. package/src/renderers/dom/host/live-frame.ts +6 -2
  722. package/src/renderers/dom/host/overflow-fade.ts +14 -1
  723. package/src/renderers/dom/host/scroll-box.tsx +32 -0
  724. package/src/renderers/dom/host/size-observer.ts +41 -0
  725. package/src/renderers/dom/host/sticky-scroll.ts +128 -0
  726. package/src/renderers/dom/host/style.ts +1 -1
  727. package/src/renderers/dom/host/surface-3d.tsx +19 -7
  728. package/src/renderers/dom/host/surface-fit.ts +406 -0
  729. package/src/renderers/dom/host/text.tsx +1 -1
  730. package/src/renderers/dom/input-host.tsx +1 -0
  731. package/src/renderers/dom/styles.css +102 -5
  732. package/src/renderers/electrobun/bun/application-menu/click.ts +18 -0
  733. package/src/renderers/electrobun/bun/index.ts +3 -2
  734. package/src/renderers/electrobun/shared/protocol.ts +1 -1
  735. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +29 -2
  736. package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +63 -20
  737. package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
  738. package/src/renderers/electrobun/view/main.tsx +5 -3
  739. package/src/renderers/electrobun/view/remote/asset-data-client.ts +2 -0
  740. package/src/renderers/opentui/chart-surface.tsx +1 -0
  741. package/src/renderers/opentui/frame-capture.ts +33 -0
  742. package/src/renderers/opentui/host.tsx +10 -13
  743. package/src/renderers/opentui/pane-image/glyphs-license.txt +107 -0
  744. package/src/renderers/opentui/pane-image/glyphs.json +1 -0
  745. package/src/renderers/opentui/pane-image/index.ts +107 -0
  746. package/src/renderers/opentui/pane-image/raster.ts +428 -0
  747. package/src/renderers/opentui/start.tsx +3 -3
  748. package/src/renderers/opentui/test-utils.tsx +3 -0
  749. package/src/renderers/opentui/ui-host.tsx +29 -1
  750. package/src/series/capability.ts +75 -0
  751. package/src/series/csv.ts +160 -0
  752. package/src/series/files.ts +107 -0
  753. package/src/series/registry.ts +198 -0
  754. package/src/series/resolve.ts +108 -0
  755. package/src/series/standalone.ts +48 -0
  756. package/src/series/types.ts +153 -0
  757. package/src/series/validate.ts +171 -0
  758. package/src/shares/chat.ts +34 -0
  759. package/src/shares/dialog.tsx +295 -0
  760. package/src/shares/flow.tsx +56 -0
  761. package/src/shares/live.ts +14 -22
  762. package/src/shares/pane-image.ts +152 -0
  763. package/src/shares/personal-pane.ts +64 -0
  764. package/src/shares/portable-layout.ts +4 -2
  765. package/src/shares/prepare.ts +20 -0
  766. package/src/sources/gloomberb-cloud/index.ts +109 -10
  767. package/src/sources/gloomberb-cloud/normalizers.ts +3 -0
  768. package/src/sources/gloomberb-cloud/perpetuals.ts +249 -0
  769. package/src/sources/history-result.ts +1 -0
  770. package/src/sources/history-retention.ts +11 -0
  771. package/src/sources/listing-symbols.ts +4 -1
  772. package/src/sources/listing-target.ts +4 -0
  773. package/src/sources/provider-router/batches.ts +4 -1
  774. package/src/sources/provider-router/cache.ts +4 -2
  775. package/src/sources/provider-router/cached-routes.ts +1 -1
  776. package/src/sources/provider-router/financial-routes.ts +1 -0
  777. package/src/sources/provider-router/financials.ts +13 -0
  778. package/src/sources/provider-router/history.ts +43 -25
  779. package/src/sources/provider-router/index.ts +14 -0
  780. package/src/sources/provider-router/search.ts +1 -0
  781. package/src/state/hooks/inline-tickers.ts +49 -11
  782. package/src/sync/core-contributors.ts +1 -0
  783. package/src/test-support/shell-pane-keys.tsx +1 -0
  784. package/src/theme/theme-context.tsx +15 -1
  785. package/src/tickers/company-name.ts +75 -0
  786. package/src/tickers/instrument-kind.ts +34 -1
  787. package/src/tickers/listing-name.ts +34 -0
  788. package/src/tickers/listing-venues.ts +132 -0
  789. package/src/tickers/open-target.ts +13 -4
  790. package/src/tickers/perpetual-listing.ts +151 -0
  791. package/src/tickers/prediction-listing.ts +26 -0
  792. package/src/tickers/search/index.ts +72 -11
  793. package/src/tickers/search/ranking.ts +98 -20
  794. package/src/tickers/search/types.ts +7 -1
  795. package/src/tickers/ticker-changes.ts +213 -0
  796. package/src/tickers/us-listing.ts +34 -0
  797. package/src/time-series/economic.ts +2 -6
  798. package/src/time-series/hooks.ts +9 -0
  799. package/src/time-series/ice-credit.ts +39 -0
  800. package/src/time-series/resolve.ts +211 -29
  801. package/src/time-series/studies.ts +1 -0
  802. package/src/time-series/types.ts +12 -2
  803. package/src/time-series/use-chart-resolution.ts +32 -0
  804. package/src/types/config.ts +10 -2
  805. package/src/types/data-provider.ts +11 -0
  806. package/src/types/financials.ts +62 -1
  807. package/src/types/headless.ts +113 -0
  808. package/src/types/instrument.ts +4 -0
  809. package/src/types/plugin.ts +52 -2
  810. package/src/types/price-history.ts +7 -0
  811. package/src/types/ticker-changes.ts +26 -0
  812. package/src/types/ticker.ts +14 -0
  813. package/src/ui/context-menu.tsx +13 -1
  814. package/src/ui/host.tsx +57 -3
  815. package/src/ui/live-resize.ts +91 -0
  816. package/src/ui/live-stretch.ts +153 -0
  817. package/src/ui/measured-cells.ts +58 -0
  818. package/src/ui/sticky-scroll.ts +7 -0
  819. package/src/utils/basis-points.ts +17 -0
  820. package/src/utils/central-banks.ts +76 -0
  821. package/src/utils/cli-output.ts +131 -15
  822. package/src/utils/concurrency.ts +25 -0
  823. package/src/utils/crypto-pair.ts +20 -0
  824. package/src/utils/currency-pair.ts +19 -0
  825. package/src/utils/currency-units.ts +11 -0
  826. package/src/utils/datetime-format.ts +27 -6
  827. package/src/utils/decimal-comma.ts +19 -0
  828. package/src/utils/dom-screenshot-css.ts +265 -0
  829. package/src/utils/dom-screenshot-rasters.ts +276 -0
  830. package/src/utils/dom-screenshot.ts +439 -52
  831. package/src/utils/double-escape-close.ts +15 -1
  832. package/src/utils/exchange-rate-snapshot.ts +6 -2
  833. package/src/utils/exchanges.ts +143 -1
  834. package/src/utils/format.ts +35 -5
  835. package/src/utils/forward-dividend.ts +14 -0
  836. package/src/utils/fundamentals.ts +66 -0
  837. package/src/utils/futures-generic.ts +6 -12
  838. package/src/utils/fx-market-hours.ts +15 -5
  839. package/src/utils/fx-status.ts +6 -1
  840. package/src/utils/inline-content-tokenizer.ts +22 -3
  841. package/src/utils/market-capitalization.ts +8 -0
  842. package/src/utils/one-shot.ts +73 -0
  843. package/src/utils/options.ts +37 -8
  844. package/src/utils/price-history.ts +99 -42
  845. package/src/utils/sec-eps-basis.ts +24 -11
  846. package/src/utils/sec.ts +61 -7
  847. package/src/utils/utc-time.ts +63 -4
  848. package/src/plugins/builtin/fx-matrix/freshness.ts +0 -65
  849. /package/src/plugins/{builtin/plugin-marketplace → marketplace}/activation.ts +0 -0
  850. /package/src/plugins/{builtin/plugin-marketplace → marketplace}/ids.ts +0 -0
  851. /package/src/plugins/{builtin/plugin-marketplace → marketplace}/packs.ts +0 -0
  852. /package/src/{plugins/builtin/cloud → tickers}/starter-symbols.ts +0 -0
@@ -1,6 +1,7 @@
1
1
  import type { MarketState, Quote } from "../../types/financials";
2
2
  import { blendHex, colors, priceColor, type ThemeColors } from "../../theme/colors";
3
3
  import { isFiniteNumber } from "../../utils/guards";
4
+ import { canonicalExchange, isKnownExchangeCode } from "../../utils/exchanges";
4
5
  import { quoteTradingDay } from "../quotes/day-range";
5
6
 
6
7
  const CLOSED_CHANGE_MUTING_RATIO = 0.55;
@@ -108,31 +109,14 @@ export function marketChangeColor(change: number | undefined, state?: MarketStat
108
109
  return blendHex(directionalColor, colors.textDim, CLOSED_CHANGE_MUTING_RATIO);
109
110
  }
110
111
 
111
- /** Short exchange display name */
112
+ /**
113
+ * The venue's code as a listing key names it (EPA, JPX), from the app's one
114
+ * venue list, so the code a pane shows is the one to type after the symbol.
115
+ * A venue the list does not know keeps the name it came with.
116
+ */
112
117
  export function exchangeShortName(exchangeName?: string, fullExchangeName?: string): string {
113
- if (!exchangeName && !fullExchangeName) return "";
114
118
  const name = exchangeName || fullExchangeName || "";
115
- // Common market data exchange abbreviations
116
- const map: Record<string, string> = {
117
- NMS: "NASDAQ", NGM: "NASDAQ", NCM: "NASDAQ", NAS: "NASDAQ",
118
- NYQ: "NYSE", NYS: "NYSE",
119
- PCX: "ARCA", NYSEArca: "ARCA", "NYSE Arca": "ARCA", ASE: "AMEX",
120
- HKG: "HKEX",
121
- TYO: "TYO",
122
- LSE: "LSE",
123
- ASX: "ASX",
124
- SGX: "SGX",
125
- KSC: "KRX", KOE: "KOSDAQ",
126
- TAI: "TWSE",
127
- SHH: "SSE", SHZ: "SZSE",
128
- PAR: "EURONEXT", AMS: "EURONEXT", BRU: "EURONEXT",
129
- GER: "XETRA",
130
- OSL: "OSE",
131
- BOM: "BSE", NSI: "NSE",
132
- SAO: "B3",
133
- JPX: "TYO",
134
- };
135
- return map[name] || name;
119
+ return isKnownExchangeCode(name) ? canonicalExchange(name) : name;
136
120
  }
137
121
 
138
122
  /**
@@ -332,3 +316,15 @@ export function getSessionMoveDisplay(
332
316
  ): (ActiveQuoteDisplay & { session?: ExtendedSession }) | null {
333
317
  return getOpenExtendedSessionDisplay(quote) ?? getRegularSessionDisplay(quote);
334
318
  }
319
+
320
+ /**
321
+ * getSessionMoveDisplay for a board that marks an extended move on each tile
322
+ * (the heat map): while a quote says nothing has traded in the open session
323
+ * yet (extendedSessionPrint false), its extended figures are the close
324
+ * carried forward, not a flat print, so the regular session stands.
325
+ */
326
+ export function getTradedSessionMoveDisplay(
327
+ quote: Quote | null | undefined,
328
+ ): (ActiveQuoteDisplay & { session?: ExtendedSession }) | null {
329
+ return quote?.extendedSessionPrint === false ? getRegularSessionDisplay(quote) : getSessionMoveDisplay(quote);
330
+ }
@@ -1,15 +1,22 @@
1
- // Published full-day closures (weekend dates omitted) for Asia-Pacific venues,
1
+ // Published full-day closures (weekend dates omitted) for Asia-Pacific venues and EGX,
2
2
  // not a holiday-rule engine. A year a venue has not published is unknown, not
3
3
  // open: every weekday of it reads as a session. Half-day sessions (HKEX and
4
4
  // SGX eves, ASX's 14:10 closes) are not modelled. Checked 2026-10-09:
5
5
  // KRX, also KOSDAQ: http://open.krx.co.kr/contents/MKD/01/0110/01100305/MKD01100305.jsp
6
6
  // TWSE, whose closures TPEx shares: https://www.twse.com.tw/en/trading/holiday.html
7
7
  // (2027 not yet published; 12 and 13 Feb 2026 are clearing-only days without trading)
8
+ // BHB closes on the dates its own daily closes skip in 2026, which match the holidays it lists
9
+ // (some moved, as its list warns), and on National Day, 16 and 17 Dec. Its week is Sunday to Thursday.
8
10
  // HKEX: https://www.hkex.com.hk/-/media/HKEX-Market/Services/Circulars-and-Notices/Participant-and-Members-Circulars/SEHK/2025/ce_SEHK_CT_075_2025.pdf
9
11
  // and https://www.hkex.com.hk/-/media/HKEX-Market/Services/Circulars-and-Notices/Participant-and-Members-Circulars/SEHK/2026/ce_SEHK_CT_077_2026.pdf
10
12
  // SGX closes on Singapore's gazetted public holidays, one on a Sunday moving to the Monday:
11
13
  // https://www.sgx.com/stock-exchange/trading and https://www.mom.gov.sg/employment-practices/public-holidays
14
+ // MSX closes on the holidays its site lists (msx.om exchange holidays, read 10 Oct 2026).
15
+ // Its week is Sunday to Thursday.
12
16
  // ASX: https://www.asx.com.au/markets/market-resources/trading-hours-calendar/cash-market-trading-hours/trading-calendar
17
+ // EGX closes on Egypt's public holidays, often moved to the Thursday of their
18
+ // week (Armed Forces Day, Tuesday 6 Oct 2026, to Thursday 8 Oct, by the
19
+ // exchange's statement of 5 Oct). Its week is Sunday to Thursday.
13
20
  const KRX_CLOSURES: Record<number, readonly string[]> = {
14
21
  2026: [
15
22
  "01-01", "02-16", "02-17", "02-18", "03-02", "05-01", "05-05", "05-25", "06-03",
@@ -34,6 +41,12 @@ export const PUBLISHED_APAC_CLOSURES: Readonly<Record<string, Record<number, rea
34
41
  KOSDAQ: KRX_CLOSURES,
35
42
  TWSE: TWSE_CLOSURES,
36
43
  TPEX: TWSE_CLOSURES,
44
+ BHB: {
45
+ 2026: [
46
+ "01-01", "03-22", "03-23", "03-24", "05-03", "05-26", "05-27", "05-28", "05-31", "06-16", "06-25", "06-28",
47
+ "08-25", "12-16", "12-17",
48
+ ],
49
+ },
37
50
  HKEX: {
38
51
  2026: [
39
52
  "01-01", "02-17", "02-18", "02-19", "04-03", "04-06", "04-07", "05-01", "05-25",
@@ -48,10 +61,19 @@ export const PUBLISHED_APAC_CLOSURES: Readonly<Record<string, Record<number, rea
48
61
  2026: ["01-01", "02-17", "02-18", "04-03", "05-01", "05-27", "06-01", "08-10", "11-09", "12-25"],
49
62
  2027: ["01-01", "02-08", "03-10", "03-26", "05-17", "05-20", "08-09", "10-28"],
50
63
  },
64
+ MSX: {
65
+ 2026: ["01-15", "01-18", "03-19", "03-22", "03-23", "05-26", "05-27", "05-28", "06-18", "08-27", "11-25", "11-26"],
66
+ },
51
67
  ASX: {
52
68
  2026: ["01-01", "01-26", "04-03", "04-06", "06-08", "12-25", "12-28"],
53
69
  2027: ["01-01", "01-26", "03-26", "03-29", "06-14", "12-27", "12-28"],
54
70
  },
71
+ EGX: {
72
+ 2026: [
73
+ "01-01", "01-07", "01-29", "03-19", "03-22", "03-23", "04-12", "04-13", "05-07",
74
+ "05-26", "05-27", "05-28", "05-31", "06-18", "07-02", "07-23", "08-27", "10-08",
75
+ ],
76
+ },
55
77
  };
56
78
 
57
79
  /** True only for a published full-day closure; unpublished years are unknown, not open. */
@@ -124,6 +124,7 @@ export function finalizeSessionFields(
124
124
  postMarketPrice: undefined,
125
125
  postMarketChange: undefined,
126
126
  postMarketChangePercent: undefined,
127
+ extendedSessionPrint: undefined,
127
128
  };
128
129
  }
129
130
 
@@ -192,6 +193,10 @@ export function mergeQuoteContribution(
192
193
  postMarketChangePercent: next.postMarketChangePercent,
193
194
  } : {}),
194
195
  priceBasis: next.priceBasis,
196
+ // Said of this observation's price; a tick that does not say leaves it unknown.
197
+ extendedSessionPrint: next.extendedSessionPrint,
198
+ // The board this observation was read on; one read on the listing's own line names none.
199
+ tradingExchangeName: next.tradingExchangeName,
195
200
  regularClose: next.regularClose,
196
201
  regularCloseSessionDate: next.regularClose != null ? next.regularCloseSessionDate : undefined,
197
202
  regularChange: next.regularClose != null ? next.regularChange : undefined,
@@ -1,6 +1,7 @@
1
1
  import type { Quote, QuoteMetadata } from "../../types/financials";
2
2
  import { canonicalExchange, parsePublicTickerKey } from "../../utils/exchanges";
3
3
  import { getListingSymbolsToTry } from "../../sources/listing-symbols";
4
+ import { currencyPairCode } from "../../utils/currency-pair";
4
5
 
5
6
  export function quoteMetadataFromQuote(quote: Quote): QuoteMetadata {
6
7
  return {
@@ -17,6 +18,15 @@ export function quoteMetadataFromQuote(quote: Quote): QuoteMetadata {
17
18
  };
18
19
  }
19
20
 
21
+ /**
22
+ * The venue a quote's price comes from: the board Gloom Cloud read it on
23
+ * (247540:KRX on KOSDAQ), else its listing. The listing fields keep the venue
24
+ * asked for, which is what a quote's identity is checked against.
25
+ */
26
+ export function quoteTradingExchange(quote: Pick<Quote, "tradingExchangeName" | "listingExchangeName" | "exchangeName">): string {
27
+ return canonicalExchange(quote.tradingExchangeName || quote.listingExchangeName || quote.exchangeName);
28
+ }
29
+
20
30
  /** Keep known fields and their source when optional enrichment is incomplete. */
21
31
  export function mergeQuoteMetadata(known: QuoteMetadata | null | undefined, loaded: QuoteMetadata | null | undefined): QuoteMetadata | undefined {
22
32
  if (!known) return loaded ?? undefined;
@@ -32,38 +42,23 @@ export function mergeQuoteMetadata(known: QuoteMetadata | null | undefined, load
32
42
  return Object.keys(fields).length ? { ...merged, fieldSources: fields } : merged;
33
43
  }
34
44
 
35
- /** A provider's listing name establishes identity, not a session calendar. */
36
- function metadataExchange(value?: string): string {
37
- const exchange = canonicalExchange(value);
38
- return exchange === "NY MERCANTILE" ? "NYMEX" : exchange;
39
- }
40
-
41
- /**
42
- * The pair an FX symbol names, base then quote: EURUSD for EUR/USD and
43
- * EURUSD=X, USDJPY for USD/JPY, USDJPY=X and JPY=X, the dollar pair's short
44
- * spelling.
45
- */
46
- function currencyPairCode(symbol: string): string | null {
47
- const pair = /^([A-Z]{3})\/([A-Z]{3})$/.exec(symbol) ?? /^([A-Z]{3})([A-Z]{3})=X$/.exec(symbol);
48
- if (pair) return `${pair[1]}${pair[2]}`;
49
- const dollarPair = /^([A-Z]{3})=X$/.exec(symbol);
50
- return dollarPair ? `USD${dollarPair[1]}` : null;
51
- }
52
-
53
45
  /** Qualified listings must agree; provider suffix spellings use the existing exact-listing normalizer. */
54
46
  export function quoteMetadataMatchesTarget(metadata: QuoteMetadata, symbol: string, exchange?: string): boolean {
55
47
  const target = parsePublicTickerKey(symbol);
56
48
  const actual = parsePublicTickerKey(metadata.symbol);
57
- const requestedExchange = metadataExchange(target.exchange || exchange);
58
- const symbolExchange = metadataExchange(actual.exchange);
59
- const actualExchange = metadataExchange(metadata.listingExchangeName) || symbolExchange;
49
+ // An index is one series whatever its venue is called: search files ^VIX under CXI and ^RUT under WCB, while
50
+ // their quotes name CBOE INDICES and CHICAGO OPTIONS. Saved from search, the index must still match its quote.
51
+ if (target.symbol.startsWith("^") && target.symbol === actual.symbol) return true;
52
+ const requestedExchange = canonicalExchange(target.exchange || exchange);
53
+ const symbolExchange = canonicalExchange(actual.exchange);
54
+ const actualExchange = canonicalExchange(metadata.listingExchangeName) || symbolExchange;
60
55
  if (symbolExchange && actualExchange && symbolExchange !== actualExchange) return false;
61
56
  if (requestedExchange && actualExchange !== requestedExchange) return false;
62
57
  if (target.symbol === actual.symbol) return true;
63
58
  // Gloom Cloud answers a currency pair in one spelling however it was asked
64
- // for: EUR/USD comes back as EURUSD=X on its currency venue.
65
- const pair = actualExchange === "CCY" ? currencyPairCode(actual.symbol) : null;
66
- if (pair && pair === currencyPairCode(target.symbol)) return true;
59
+ // for: EUR/USD and EURUSD:CCY come back as EURUSD=X on its currency venue.
60
+ const pair = actualExchange === "CCY" ? currencyPairCode(actual.symbol, actualExchange) : null;
61
+ if (pair && pair === currencyPairCode(target.symbol, requestedExchange)) return true;
67
62
  const listing = requestedExchange || actualExchange;
68
63
  if (!listing) return false;
69
64
  const candidates = getListingSymbolsToTry(target.symbol, listing, { exactExchange: true });
@@ -405,6 +405,8 @@ export function resolveCanonicalQuote(
405
405
  // not declare units for another provider's price or supply incompatible anchors.
406
406
  assignField(resolved, provenance, "priceBasis", priceProvider);
407
407
  assignField(resolved, provenance, "priceObservation", priceProvider);
408
+ // The board whose line gave that price, when the source read another than the listing asked for.
409
+ assignField(resolved, provenance, "tradingExchangeName", priceProvider);
408
410
  const isNav = priceProvider?.priceObservation === "nav";
409
411
  if (isNav) {
410
412
  sessionCandidates = priceProvider ? [priceProvider] : [];
@@ -513,6 +515,7 @@ export function resolveCanonicalQuote(
513
515
  fullExchangeName: resolved.fullExchangeName as Quote["fullExchangeName"],
514
516
  listingExchangeName: resolved.listingExchangeName as Quote["listingExchangeName"],
515
517
  listingExchangeFullName: resolved.listingExchangeFullName as Quote["listingExchangeFullName"],
518
+ tradingExchangeName: resolved.tradingExchangeName as Quote["tradingExchangeName"],
516
519
  routingExchangeName: resolved.routingExchangeName as Quote["routingExchangeName"],
517
520
  routingExchangeFullName: resolved.routingExchangeFullName as Quote["routingExchangeFullName"],
518
521
  marketState: resolved.marketState as Quote["marketState"],
@@ -523,6 +526,8 @@ export function resolveCanonicalQuote(
523
526
  postMarketPrice: resolved.postMarketPrice as Quote["postMarketPrice"],
524
527
  postMarketChange: resolved.postMarketChange as Quote["postMarketChange"],
525
528
  postMarketChangePercent: resolved.postMarketChangePercent as Quote["postMarketChangePercent"],
529
+ // Said of the price, so it comes with it.
530
+ extendedSessionPrint: priceProvider?.extendedSessionPrint,
526
531
  bid: resolved.bid as Quote["bid"],
527
532
  ask: resolved.ask as Quote["ask"],
528
533
  bidSize: resolved.bidSize as Quote["bidSize"],
@@ -5,7 +5,7 @@ import { buildQuoteKey, resolveEntryData } from "../selectors";
5
5
  import type { QueryEntry } from "../result-types";
6
6
  import { resolveCurrencyUnit } from "../../utils/currency-units";
7
7
  import { isFiniteNumber } from "../../utils/guards";
8
- import { getCompletedRegularSessionDisplay, getSessionMoveDisplay, type ExtendedSession } from "../market/status";
8
+ import { getCompletedRegularSessionDisplay, getTradedSessionMoveDisplay, type ExtendedSession } from "../market/status";
9
9
  import { quoteTradingDay } from "./day-range";
10
10
 
11
11
  const STREAM_FRESHNESS_MS = 2 * 60_000;
@@ -31,8 +31,9 @@ export interface ScreenerQuoteRow {
31
31
  export interface ScreenerQuoteOverlayOptions {
32
32
  /**
33
33
  * While a pre-market or after-hours session is open, show its price and its
34
- * move from the regular close, marked with `extendedSession`; otherwise the
35
- * regular session's, which stops at the close. Without it a row shows the
34
+ * move from the regular close, marked with `extendedSession`; otherwise, or
35
+ * while the quote says nothing has traded in that session yet, the regular
36
+ * session's, which stops at the close. Without it a row shows the
36
37
  * live price against the previous close. A row that is a completed regular
37
38
  * session's close and move (`regularChangePercent`) keeps them outside the
38
39
  * regular session when its quote has neither an open extended print nor
@@ -151,7 +152,7 @@ function overlayQuote<T extends ScreenerQuoteRow>(row: T, quote: Quote): T {
151
152
 
152
153
  function overlaySessionQuote<T extends ScreenerQuoteRow>(row: T, quote: Quote): T {
153
154
  const overlaid = overlayQuote(row, quote);
154
- const display = getSessionMoveDisplay(quote);
155
+ const display = getTradedSessionMoveDisplay(quote);
155
156
  if (!display || !isFiniteNumber(display.price)) return overlaid;
156
157
  if (
157
158
  !display.session
@@ -32,6 +32,8 @@ export interface QueryEntry<T> {
32
32
  /** Accepted source response order in this runtime, preserved through cache projections. */
33
33
  responseSequence?: number;
34
34
  asOf?: number;
35
+ /** Exchange rates: how far the snapshot runs behind the market, in minutes; 0 for a real-time one. */
36
+ delayMinutes?: number;
35
37
  staleAt: number | null;
36
38
  error: { reasonCode: string; message: string } | null;
37
39
  attempts: ProviderAttempt[];
@@ -4,6 +4,7 @@ import type {
4
4
  AppNotificationType,
5
5
  } from "../types/plugin";
6
6
  import { debugLog } from "../utils/debug-log";
7
+ import { appendNotificationLog, markNotificationLogRead } from "./notification-log";
7
8
 
8
9
  const DEFAULT_NOTIFICATION_TITLE = "Gloomberb";
9
10
  const notificationLog = debugLog.createLogger("notifications");
@@ -243,7 +244,22 @@ export function createAppNotifier({
243
244
  desktop = typeof Bun !== "undefined" ? createDesktopNotifier() : null,
244
245
  }: CreateAppNotifierOptions): AppNotifier {
245
246
  return {
246
- notify(notification) {
247
+ notify(request) {
248
+ // A missed price, catalyst or team notice waits in the Unread list; using
249
+ // its toast action means it was seen.
250
+ const logged = appendNotificationLog(request);
251
+ const notification: AppNotificationRequest = logged && request.action
252
+ ? {
253
+ ...request,
254
+ action: {
255
+ ...request.action,
256
+ onClick: () => {
257
+ markNotificationLogRead([logged.id]);
258
+ request.action?.onClick();
259
+ },
260
+ },
261
+ }
262
+ : request;
247
263
  const appActive = isAppActive();
248
264
  const toastEnabled = notification.toast !== false;
249
265
  const desktopMode = notification.desktop ?? "never";
@@ -0,0 +1,180 @@
1
+ import type { AppPluginStateStorePort } from "../core/app-service-ports";
2
+ import type { AppNotificationRequest } from "../types/plugin";
3
+
4
+ export const NOTIFICATION_LOG_LIMIT = 300;
5
+
6
+ /**
7
+ * The notices worth finding again after their toast is gone: a price alert or
8
+ * a catalyst that fired, and a team card. Chat keeps its own unread state on
9
+ * the account, and plain info, success and error toasts are not logged.
10
+ */
11
+ export type MissedNoticeKind = "price" | "catalyst" | "team";
12
+
13
+ const KIND_PREFIXES: ReadonlyArray<readonly [MissedNoticeKind, string]> = [
14
+ ["price", "price:"],
15
+ ["catalyst", "catalyst:"],
16
+ ["team", "team:"],
17
+ ];
18
+
19
+ export interface NotificationLogEntry {
20
+ id: string;
21
+ /** `price:<alertId>`, `catalyst:<eventId>` or `team:<cardId>`. A later notice with the same ref updates this row. */
22
+ refId: string;
23
+ title?: string;
24
+ body: string;
25
+ at: number;
26
+ read: boolean;
27
+ }
28
+
29
+ interface NotificationLogStore {
30
+ get(): readonly unknown[];
31
+ set(entries: readonly NotificationLogEntry[]): void;
32
+ }
33
+
34
+ /** What a ref points at, and the id inside it; null for anything the log does not keep. */
35
+ export function parseNoticeRef(refId: string | undefined): { kind: MissedNoticeKind; id: string } | null {
36
+ if (!refId) return null;
37
+ for (const [kind, prefix] of KIND_PREFIXES) {
38
+ if (refId.startsWith(prefix) && refId.length > prefix.length) return { kind, id: refId.slice(prefix.length) };
39
+ }
40
+ return null;
41
+ }
42
+
43
+ let entries: NotificationLogEntry[] = [];
44
+ let store: NotificationLogStore | null = null;
45
+ const listeners = new Set<() => void>();
46
+
47
+ function normalizeEntry(value: unknown): NotificationLogEntry | null {
48
+ if (!value || typeof value !== "object") return null;
49
+ const entry = value as Partial<NotificationLogEntry>;
50
+ if (typeof entry.id !== "string" || typeof entry.body !== "string" || typeof entry.at !== "number") return null;
51
+ if (typeof entry.refId !== "string" || !parseNoticeRef(entry.refId)) return null;
52
+ return {
53
+ id: entry.id,
54
+ refId: entry.refId,
55
+ ...(typeof entry.title === "string" && entry.title ? { title: entry.title } : {}),
56
+ body: entry.body,
57
+ at: entry.at,
58
+ read: entry.read === true,
59
+ };
60
+ }
61
+
62
+ /** One row per ref, oldest first, the newest {@link NOTIFICATION_LOG_LIMIT} kept. */
63
+ function settle(next: readonly NotificationLogEntry[]): NotificationLogEntry[] {
64
+ const byRef = new Map<string, NotificationLogEntry>();
65
+ for (const entry of next) {
66
+ byRef.delete(entry.refId);
67
+ byRef.set(entry.refId, entry);
68
+ }
69
+ return [...byRef.values()].sort((left, right) => left.at - right.at).slice(-NOTIFICATION_LOG_LIMIT);
70
+ }
71
+
72
+ function commit(next: NotificationLogEntry[]): void {
73
+ entries = next;
74
+ try {
75
+ store?.set(entries);
76
+ } catch {
77
+ // The rows stay in memory; the next change tries the write again.
78
+ }
79
+ for (const listener of listeners) listener();
80
+ }
81
+
82
+ /**
83
+ * Loads the log from a device-local store. Notices recorded before the store
84
+ * was attached are kept, so a fire during startup is not lost.
85
+ */
86
+ function configureNotificationLog(nextStore: NotificationLogStore | null): void {
87
+ store = nextStore;
88
+ let saved: readonly unknown[] = [];
89
+ try {
90
+ saved = nextStore?.get() ?? [];
91
+ } catch {
92
+ saved = [];
93
+ }
94
+ const loaded = saved.map(normalizeEntry).filter((entry): entry is NotificationLogEntry => !!entry);
95
+ commit(settle([...loaded, ...entries]));
96
+ }
97
+
98
+ const LOG_STATE_OWNER = "core.notifications";
99
+ const LOG_STATE_KEY = "missed";
100
+
101
+ /**
102
+ * Keeps the log in the app's local state store (SQLite in the terminal and the
103
+ * desktop app, browser storage on the web), never in config.json or synced
104
+ * settings, so team text in a notice stays on this device. Returns the detach.
105
+ */
106
+ export function attachNotificationLog(pluginState: Pick<AppPluginStateStorePort, "get" | "set">): () => void {
107
+ configureNotificationLog({
108
+ get: () => {
109
+ const value = pluginState.get<unknown>(LOG_STATE_OWNER, LOG_STATE_KEY)?.value;
110
+ return Array.isArray(value) ? value : [];
111
+ },
112
+ set: (next) => pluginState.set(LOG_STATE_OWNER, LOG_STATE_KEY, next),
113
+ });
114
+ return () => configureNotificationLog(null);
115
+ }
116
+
117
+ export function subscribeNotificationLog(listener: () => void): () => void {
118
+ listeners.add(listener);
119
+ return () => {
120
+ listeners.delete(listener);
121
+ };
122
+ }
123
+
124
+ export function getNotificationLog(): readonly NotificationLogEntry[] {
125
+ return entries;
126
+ }
127
+
128
+ export function unreadNotificationLogCount(log: readonly NotificationLogEntry[] = entries): number {
129
+ let count = 0;
130
+ for (const entry of log) if (!entry.read) count += 1;
131
+ return count;
132
+ }
133
+
134
+ /**
135
+ * Records a notice whose `refId` names a price alert, a catalyst or a team
136
+ * card; anything else returns null and is not kept. The same ref replaces its
137
+ * row: a price alert that fires again is new and unread again.
138
+ */
139
+ export function appendNotificationLog(
140
+ notification: Pick<AppNotificationRequest, "title" | "body" | "refId">,
141
+ at = Date.now(),
142
+ ): NotificationLogEntry | null {
143
+ const refId = notification.refId;
144
+ if (!refId || !parseNoticeRef(refId)) return null;
145
+ const existing = entries.find((candidate) => candidate.refId === refId);
146
+ const title = notification.title?.trim();
147
+ const entry: NotificationLogEntry = {
148
+ id: existing?.id ?? `notice-${at.toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
149
+ refId,
150
+ ...(title ? { title } : {}),
151
+ body: notification.body,
152
+ at,
153
+ read: false,
154
+ };
155
+ commit(settle([...entries, entry]));
156
+ return entry;
157
+ }
158
+
159
+ export function markNotificationLogRead(ids?: Iterable<string>): void {
160
+ const selected = ids ? new Set(ids) : null;
161
+ let changed = false;
162
+ const next = entries.map((entry) => {
163
+ if (entry.read || (selected && !selected.has(entry.id))) return entry;
164
+ changed = true;
165
+ return { ...entry, read: true };
166
+ });
167
+ if (changed) commit(next);
168
+ }
169
+
170
+ export function markNotificationLogReadByRef(refIds: Iterable<string>): void {
171
+ const wanted = new Set(refIds);
172
+ if (wanted.size === 0) return;
173
+ markNotificationLogRead(entries.filter((entry) => wanted.has(entry.refId)).map((entry) => entry.id));
174
+ }
175
+
176
+ export function resetNotificationLogForTest(): void {
177
+ entries = [];
178
+ store = null;
179
+ listeners.clear();
180
+ }
@@ -9,7 +9,7 @@ import {
9
9
  type PluginAutoUpdateState,
10
10
  type PluginCheckout,
11
11
  } from "./auto-update";
12
- import type { PluginManager } from "./builtin/plugin-marketplace/store";
12
+ import type { PluginManager } from "./marketplace/store";
13
13
  import { checkPluginCompatibility, readPluginManifest } from "./compat";
14
14
  import { installedPeerPlugins } from "./host-link";
15
15
  import { getPluginCacheDir, getPluginsDir, pluginsMissingHostExports, readPluginCommit } from "./loader";
@@ -60,7 +60,7 @@ function createNodeAutoUpdateDeps(manager: PluginManager): PluginAutoUpdateDeps
60
60
  return {
61
61
  checkouts: readCheckouts,
62
62
  registry: async () => {
63
- const { loadRegistry } = await import("./builtin/plugin-marketplace/feed");
63
+ const { loadRegistry } = await import("./marketplace/feed");
64
64
  const feed = await loadRegistry();
65
65
  return feed.error && feed.plugins.length === 0 ? null : feed.plugins;
66
66
  },
@@ -3,8 +3,8 @@ import { requiredGloomberb } from "../utils/semver";
3
3
  import { VERSION } from "../version";
4
4
  import { findAbsorbedPlugin } from "./absorbed";
5
5
  import { applicationPluginMeta } from "./builtin/builtin-plugin-meta";
6
- import { hasUpdate, type RegistryPlugin } from "./builtin/plugin-marketplace/model";
7
- import type { PluginOperationResult, PluginPin } from "./builtin/plugin-marketplace/store";
6
+ import { hasUpdate, type RegistryPlugin } from "./marketplace/model";
7
+ import type { PluginOperationResult, PluginPin } from "./marketplace/store";
8
8
 
9
9
  /**
10
10
  * Keeps official plugins current without their users having to.
@@ -6,6 +6,7 @@ export const accountManagementModule: PluginModule = {
6
6
  id: "account-management",
7
7
  name: "ACM",
8
8
  icon: "A",
9
+ personalData: "account",
9
10
  component: AccountManagementPane,
10
11
  defaultPosition: "right",
11
12
  defaultMode: "floating",
@@ -1,5 +1,5 @@
1
1
  import type { ChoiceDialogChoice } from "../../../components";
2
- import type { AccountProfile, CloudPricing, PublicPortfolioAnalytics } from "../../../api-client";
2
+ import type { AccountProfile, PublicPortfolioAnalytics } from "../../../api-client";
3
3
  import type { Portfolio, TickerRecord } from "../../../types/ticker";
4
4
  import { formatNumber } from "../../../utils/format";
5
5
  import { t, tf } from "../../../i18n";
@@ -86,61 +86,6 @@ export function formatPlan(plan: AccountProfile["plan"] | null | undefined): str
86
86
  return plan === "pro" ? t("Pro") : t("Free");
87
87
  }
88
88
 
89
- const DEFAULT_TRIAL_DAYS = 7;
90
-
91
- function formatUsdCents(cents: number): string {
92
- const dollars = cents / 100;
93
- return Number.isInteger(dollars) ? `$${dollars}` : `$${dollars.toFixed(2)}`;
94
- }
95
-
96
- export type CloudBillingInterval = "month" | "year";
97
-
98
- /**
99
- * Pro price for one billing interval, suffixed with the period. Falls back to
100
- * the current price when `/pricing` is unreachable so the table never renders
101
- * a blank cell.
102
- */
103
- export function formatCloudPrice(
104
- pricing: CloudPricing | null | undefined,
105
- interval: CloudBillingInterval = "month",
106
- ): string {
107
- const yearly = interval === "year";
108
- if (!pricing) return yearly ? t("$630/yr") : t("$70/mo");
109
- const amount = formatUsdCents((yearly ? pricing.yearly : pricing.monthly).amount);
110
- return yearly ? tf("{amount}/yr", { amount }) : tf("{amount}/mo", { amount });
111
- }
112
-
113
- export function formatCloudMonthlyPrice(pricing: CloudPricing | null | undefined): string {
114
- return formatCloudPrice(pricing, "month");
115
- }
116
-
117
- /** Whole months of the monthly price the yearly price leaves unpaid, e.g. 3. */
118
- export function monthsFreeYearly(pricing: CloudPricing | null | undefined): number {
119
- if (!pricing || pricing.monthly.amount <= 0) return 0;
120
- const saved = (pricing.monthly.amount * 12 - pricing.yearly.amount) / pricing.monthly.amount;
121
- return saved > 0 ? Math.round(saved) : 0;
122
- }
123
-
124
- /** Short calendar date for the trial countdown, e.g. "Aug 11". */
125
- export function formatTrialEnd(endsAt: Date | null | undefined): string | null {
126
- if (!endsAt || Number.isNaN(endsAt.getTime())) return null;
127
- return endsAt.toLocaleDateString("en-US", { month: "short", day: "numeric" });
128
- }
129
-
130
- /**
131
- * Pro-column note for the plan comparison, e.g. "7-day free trial". The trial
132
- * is part of the Pro subscription (card required, cancel before it converts),
133
- * so it is never advertised as something the free plan includes.
134
- */
135
- export function formatTrialOffer(pricing: CloudPricing | null | undefined): string {
136
- return tf("{days}-day free trial", { days: trialDaysOf(pricing) });
137
- }
138
-
139
- /** The trial length `/pricing` gives, or today's length when it is unreachable. */
140
- export function trialDaysOf(pricing: CloudPricing | null | undefined): number {
141
- return pricing?.trialDays ?? DEFAULT_TRIAL_DAYS;
142
- }
143
-
144
89
  export function countPortfolioHoldings(tickers: ReadonlyMap<string, TickerRecord>): Record<string, number> {
145
90
  const counts: Record<string, number> = {};
146
91
  for (const record of tickers.values()) {
@@ -34,7 +34,7 @@ import { FRAMED_TEXTAREA_DESKTOP_STYLE } from "../../../components/ui/fields";
34
34
  import { apiClient, type AccountProfile, type CloudPricing } from "../../../api-client";
35
35
  import { chatController } from "../chat/controller";
36
36
  import { SignInWall } from "../cloud/auth-actions";
37
- import { loadUpgradeOffer } from "../cloud/upgrade-dialog";
37
+ import { loadUpgradeOffer } from "../../../account/upgrade-dialog";
38
38
  import { openMcpConnectDialog } from "../cloud/mcp-connect/dialog";
39
39
  import { TeamsAccountTab } from "../cloud/team/acm-tab";
40
40
  import { AgentsAccountTab } from "../cloud/terminal-relay/acm-tab";
@@ -52,15 +52,17 @@ import {
52
52
  computeCumulativeReturn,
53
53
  countPortfolioHoldings,
54
54
  emptyToNull,
55
- formatCloudMonthlyPrice,
56
55
  formatPlan,
57
- formatTrialEnd,
58
- formatTrialOffer,
59
56
  portfolioOptionIds,
60
57
  profileToDraft,
61
58
  type AccountDraft,
62
59
  type AccountFieldKey,
63
60
  } from "./model";
61
+ import {
62
+ formatCloudMonthlyPrice,
63
+ formatTrialEnd,
64
+ formatTrialOffer,
65
+ } from "../../../account/billing";
64
66
  import { PasswordChangeDialog } from "./password-dialog";
65
67
  import { CalendarAccountTab } from "./calendar-tab";
66
68
  import { useAccountManagementFooter } from "./footer";
@@ -7,7 +7,7 @@ import { colors } from "../../../theme/colors";
7
7
  import { isPlainKey } from "../../../utils/keyboard";
8
8
  import { truncateWithEllipsis } from "../../../utils/text-wrap";
9
9
  import { t } from "../../../i18n";
10
- import { MIN_ACCOUNT_PASSWORD_LENGTH } from "../cloud/auth-model";
10
+ import { MIN_ACCOUNT_PASSWORD_LENGTH } from "../../../account/auth-model";
11
11
 
12
12
  type PasswordDialogField = "current" | "new" | "confirm";
13
13
 
@@ -50,7 +50,7 @@ export function startCatalystAlerts(ctx: GloomPluginContext): () => void {
50
50
  const ruleKey = `${rule.id}:${rule.createdAt}`;
51
51
  if (state.delivered[ruleKey] && BigInt(state.delivered[ruleKey]!) >= BigInt(event.revisionId)) continue;
52
52
  if (!catalystMatches(rule, event, watched)) continue;
53
- ctx.notify({ body: `${event.title} · ${event.status}`, type: "info", desktop: "always", persistent: true,
53
+ ctx.notify({ body: `${event.title} · ${event.status}`, type: "info", desktop: "always", persistent: true, refId: `catalyst:${event.id}`,
54
54
  action: { label: "Open catalyst", onClick: () => ctx.createPaneFromTemplate("catalysts-pane", { values: { event: event.id }, symbol: (() => { const party = event.parties.find((party) => party.ticker); return party?.ticker ? publicTickerKey(party.ticker, party.exchange ?? undefined) : undefined; })() }) } });
55
55
  state.delivered[ruleKey] = event.revisionId;
56
56
  }