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,4 +1,5 @@
1
1
  import { FINANCIAL_VINTAGE_NOTICE, SEC_EPS_BASIS_NOTICE } from "../../../utils/financial-statements";
2
+ import { usePaneSharePreparation } from "../../../shares/prepare";
2
3
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
4
  import { Box, useUiCapabilities } from "../../../ui";
4
5
  import {
@@ -116,13 +117,14 @@ import { getActiveQuoteDisplay } from "../../../market-data/market/status";
116
117
  import { resolveEntryData } from "../../../market-data/selectors";
117
118
  import { editPriceLevels, parsePriceLevels, PRICE_LEVELS_KEY, priceLevelTickerKey } from "./price-levels";
118
119
  import { canonicalExchange } from "../../../utils/exchanges";
119
- import { isPlainKey } from "../../../utils/keyboard";
120
120
  import { resolveInstrumentForPane } from "../../../core/state/app/instrument";
121
121
  import { CHART_FOLLOW_SERIES_SETTING_KEY, rebindFollowChartSpec, resolveFollowSeriesIds } from "./follow-binding";
122
122
  import type { InstrumentRef } from "../../../market-data/request-types";
123
123
 
124
124
  const RANGE_OPTIONS = RANGES.map((range, index) => ({ label: range, value: range, hint: String(index + 1) }));
125
125
  const AUTO_VIEWPORT_DEBOUNCE_MS = 350;
126
+ /** A load for a moving view that has not answered in this long no longer holds the next one back. */
127
+ const LOAD_AHEAD_TIMEOUT_MS = 4_000;
126
128
  /**
127
129
  * Drawings persist into pane settings on a short debounce after the pointer
128
130
  * settles. A share reads those settings, so it waits at least that long for a
@@ -144,6 +146,22 @@ interface RuntimeChartViewportState {
144
146
  requestViewport: RuntimeChartViewport;
145
147
  }
146
148
 
149
+ /** The oldest and newest market bars loaded, and whether every listing has said it keeps nothing older. */
150
+ function loadedMarketHistory(series: readonly ResolvedSeries[]): { start: number; end: number; complete: boolean } | null {
151
+ let start = Number.POSITIVE_INFINITY;
152
+ let end = Number.NEGATIVE_INFINITY;
153
+ let complete = true;
154
+ for (const entry of series) {
155
+ if (entry.observationKind !== "market" || entry.points.length === 0) continue;
156
+ const first = entry.points[0]!.date.getTime();
157
+ const last = entry.points.at(-1)!.date.getTime();
158
+ if (Number.isFinite(first)) start = Math.min(start, first);
159
+ if (Number.isFinite(last)) end = Math.max(end, last);
160
+ if (!entry.historyStart) complete = false;
161
+ }
162
+ return Number.isFinite(start) && Number.isFinite(end) ? { start, end, complete } : null;
163
+ }
164
+
147
165
  function runtimeViewportFromSetting(
148
166
  setting: ChartInteractionViewport | null,
149
167
  authoredViewportKey: string,
@@ -258,7 +276,7 @@ function ChartComposerSurface({
258
276
  }: ChartComposerSurfaceProps) {
259
277
  const dialog = useDialog();
260
278
  const dispatch = useAppDispatch();
261
- const { publicSharing, cellWidthPx = 8 } = useUiCapabilities();
279
+ const { cellWidthPx = 8 } = useUiCapabilities();
262
280
  const desktopWeb = useUiCapabilities().nativePaneChrome === true;
263
281
  const paneId = usePaneInstanceId();
264
282
  const liveStreaming = useLiveStreamingSetting();
@@ -351,9 +369,15 @@ function ChartComposerSurface({
351
369
  spec.viewport.range,
352
370
  spec.viewport.resolution,
353
371
  ]);
372
+ // Auto names the bars it is on, which change as the view moves: a pan back
373
+ // past where a source keeps 30-minute bars charts days instead.
374
+ const autoBars = spec.viewport.resolution === "auto" ? resolution.resolution ?? null : null;
354
375
  const resolutionOptions = useMemo(
355
- () => availableResolutions.map((value) => ({ label: formatChartResolution(value), value })),
356
- [availableResolutions],
376
+ () => availableResolutions.map((value) => ({
377
+ label: value === "auto" && autoBars ? `Auto (${formatChartResolution(autoBars)})` : formatChartResolution(value),
378
+ value,
379
+ })),
380
+ [autoBars, availableResolutions],
357
381
  );
358
382
  const selectedStudies = getSelectedBuiltinStudies(spec);
359
383
  const selectedPairStudies = getSelectedPairStudies(spec);
@@ -396,7 +420,7 @@ function ChartComposerSurface({
396
420
  ),
397
421
  [resolution.bufferedSeries, resolution.legendSeries, resolution.series, spec],
398
422
  );
399
- const { sharePane, notify } = usePluginAppActions();
423
+ const { notify } = usePluginAppActions();
400
424
  const { runtime } = usePluginRenderContext();
401
425
  const [levelStore, setLevelStore] = usePluginConfigState<unknown>(PRICE_LEVELS_KEY, null);
402
426
  const alertsJson = useAppSelector((state) => state.config.pluginConfig[PRICE_ALERTS_STORE.pluginId]?.[PRICE_ALERTS_STORE.key]);
@@ -472,10 +496,6 @@ function ChartComposerSurface({
472
496
  ...(alertsOn ? { action: { label: "alert", title: "Alert at Level", run: (level) => { void alertAtLevel(level.value); } } } : {}),
473
497
  };
474
498
  }, [alertAtLevel, alertsJson, alertsOn, editLevels, levelStore, listing]);
475
- const shareTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
476
- useEffect(() => () => {
477
- if (shareTimerRef.current !== null) clearTimeout(shareTimerRef.current);
478
- }, []);
479
499
  const [interactionCaptured, setInteractionCapturedState] = useState(false);
480
500
  // Typing in quick-add must not freeze the plot: it only takes the keyboard.
481
501
  const [modalCaptured, setModalCaptured] = useState(false);
@@ -631,7 +651,19 @@ function ChartComposerSurface({
631
651
  const activatePane = useCallback(() => {
632
652
  if (!focused) dispatch({ type: "FOCUS_PANE", paneId });
633
653
  }, [dispatch, focused, paneId]);
654
+ useEffect(() => () => {
655
+ if (runtimeViewportTimerRef.current !== null) {
656
+ clearTimeout(runtimeViewportTimerRef.current);
657
+ runtimeViewportTimerRef.current = null;
658
+ }
659
+ }, []);
660
+ // The view this pane last saved, so its own write coming back through the
661
+ // settings is not mistaken for another device's view: that would cancel the
662
+ // load a pan still in progress has scheduled and put its window back.
663
+ const savedInteractionViewportRef = useRef<string | null>(null);
634
664
  useEffect(() => {
665
+ if (persistedInteractionViewport && requestViewportOwnerRef.current === authoredViewportKey
666
+ && JSON.stringify(persistedInteractionViewport) === savedInteractionViewportRef.current) return;
635
667
  if (runtimeViewportTimerRef.current !== null) {
636
668
  clearTimeout(runtimeViewportTimerRef.current);
637
669
  runtimeViewportTimerRef.current = null;
@@ -645,30 +677,41 @@ function ChartComposerSurface({
645
677
  requestViewportOwnerRef.current = authoredViewportKey;
646
678
  setRuntimeViewportState((current) => current?.key === authoredViewportKey ? current : restored);
647
679
  if (persistedInteractionViewport && !restored) setStoredInteractionViewport(null);
648
- return () => {
649
- if (runtimeViewportTimerRef.current !== null) {
650
- clearTimeout(runtimeViewportTimerRef.current);
651
- runtimeViewportTimerRef.current = null;
652
- }
653
- };
654
680
  }, [authoredViewportKey, persistedInteractionViewport, setStoredInteractionViewport]);
655
- const commitRuntimeViewport = useCallback(() => {
681
+ // The bars loaded so far, and whether the source has said nothing older exists.
682
+ const loadedHistory = useMemo(() => loadedMarketHistory(plottedSeries), [plottedSeries]);
683
+ const loadedHistoryRef = useRef(loadedHistory);
684
+ loadedHistoryRef.current = loadedHistory;
685
+ // The newest bar seen at all: bars loaded for a moved view (finer ones, after
686
+ // a zoom) can end before it, and a pan forward then has more to ask for.
687
+ const newestBarRef = useRef(Number.NEGATIVE_INFINITY);
688
+ if (loadedHistory) newestBarRef.current = Math.max(newestBarRef.current, loadedHistory.end);
689
+ // A window asked for and not answered yet: the result's view ends where the request does once it lands.
690
+ const loadingWindowRef = useRef<{ end: number; at: number } | null>(null);
691
+ const resultViewportEnd = resolution.viewport?.end.getTime() ?? null;
692
+ if (loadingWindowRef.current && resultViewportEnd !== null
693
+ && Math.abs(resultViewportEnd - loadingWindowRef.current.end) < 1_000) loadingWindowRef.current = null;
694
+ const commitRuntimeViewport = useCallback((save = true) => {
656
695
  const requestViewport = requestViewportRef.current;
657
696
  if (!requestViewport) return;
658
697
  const adaptiveViewport = spec.viewport.resolution === "auto"
659
698
  ? adaptiveViewportRef.current
660
699
  : null;
700
+ loadingWindowRef.current = { end: requestViewport.end.getTime(), at: Date.now() };
661
701
  setRuntimeViewportState({
662
702
  key: authoredViewportKey,
663
703
  adaptiveViewport,
664
704
  requestViewport,
665
705
  });
666
- setStoredInteractionViewport({
706
+ if (!save) return;
707
+ const saved = {
667
708
  authoredViewportKey,
668
709
  start: requestViewport.start.toISOString(),
669
710
  end: requestViewport.end.toISOString(),
670
711
  adaptive: adaptiveViewport !== null,
671
- } satisfies ChartInteractionViewport);
712
+ } satisfies ChartInteractionViewport;
713
+ savedInteractionViewportRef.current = JSON.stringify(parseChartInteractionViewport(saved));
714
+ setStoredInteractionViewport(saved);
672
715
  }, [authoredViewportKey, setStoredInteractionViewport, spec.viewport.resolution]);
673
716
  const handleChartViewportChange = useCallback((
674
717
  next: { start: Date; end: Date } | null,
@@ -681,6 +724,7 @@ function ChartComposerSurface({
681
724
  if (!next) {
682
725
  adaptiveViewportRef.current = null;
683
726
  requestViewportRef.current = null;
727
+ loadingWindowRef.current = null;
684
728
  setRuntimeViewportState(null);
685
729
  setStoredInteractionViewport(null);
686
730
  return;
@@ -694,24 +738,31 @@ function ChartComposerSurface({
694
738
  // A pan can leave the window a provider serves at the current resolution
695
739
  // just as a zoom can, so both re-pick.
696
740
  if (spec.viewport.resolution === "auto") adaptiveViewportRef.current = viewport;
741
+ // Bars are asked for while the view is still moving, once it comes within
742
+ // half a screen of the oldest loaded one (or of the newest, when newer
743
+ // ones exist), so a long pan keeps going instead of running into the end
744
+ // of what is loaded and waiting for the pointer to rest.
745
+ const loaded = loadedHistoryRef.current;
746
+ const loading = loadingWindowRef.current;
747
+ const reach = (end - start) / 2;
748
+ const nearOldest = !!loaded && !loaded.complete && start - loaded.start < reach;
749
+ const nearNewest = !!loaded && loaded.end < newestBarRef.current - reach / 10 && loaded.end - end < reach;
750
+ if ((nearOldest || nearNewest) && (!loading || Date.now() - loading.at > LOAD_AHEAD_TIMEOUT_MS)) {
751
+ commitRuntimeViewport(false);
752
+ }
697
753
  runtimeViewportTimerRef.current = globalThis.setTimeout(() => {
698
754
  runtimeViewportTimerRef.current = null;
699
755
  commitRuntimeViewport();
700
756
  }, AUTO_VIEWPORT_DEBOUNCE_MS);
701
- }, [authoredViewportKey, commitRuntimeViewport, spec.viewport.resolution]);
702
- const shareChart = useCallback(() => {
703
- // The share reads pane settings, so the gesture in flight lands there first.
757
+ }, [authoredViewportKey, commitRuntimeViewport, setStoredInteractionViewport, spec.viewport.resolution]);
758
+ usePaneSharePreparation(paneId, async () => {
704
759
  if (runtimeViewportTimerRef.current !== null) {
705
760
  clearTimeout(runtimeViewportTimerRef.current);
706
761
  runtimeViewportTimerRef.current = null;
707
762
  commitRuntimeViewport();
708
763
  }
709
- if (shareTimerRef.current !== null) return;
710
- shareTimerRef.current = globalThis.setTimeout(() => {
711
- shareTimerRef.current = null;
712
- sharePane(paneId);
713
- }, SHARE_SETTLE_DELAY_MS);
714
- }, [commitRuntimeViewport, paneId, sharePane]);
764
+ await new Promise((resolve) => setTimeout(resolve, SHARE_SETTLE_DELAY_MS));
765
+ });
715
766
 
716
767
  useRemoteUiNode({
717
768
  role: "chart-data",
@@ -800,12 +851,6 @@ function ChartComposerSurface({
800
851
  );
801
852
  useShortcut((event) => {
802
853
  if (interactionCaptureRef.current || dialogOpen) return;
803
- if (publicSharing && isPlainKey(event, "y")) {
804
- event.preventDefault();
805
- event.stopPropagation();
806
- shareChart();
807
- return;
808
- }
809
854
  const shortcut = resolveChartComposerShortcut(event, RANGES.length);
810
855
  if (!shortcut) return;
811
856
  event.preventDefault();
@@ -871,11 +916,10 @@ function ChartComposerSurface({
871
916
  });
872
917
 
873
918
  // Footer registrations compare presentation, so their callbacks must read current actions.
874
- const currentActionsRef = useRef({ openSeriesEditor, openResolutionPicker, shareChart });
875
- currentActionsRef.current = { openSeriesEditor, openResolutionPicker, shareChart };
919
+ const currentActionsRef = useRef({ openSeriesEditor, openResolutionPicker });
920
+ currentActionsRef.current = { openSeriesEditor, openResolutionPicker };
876
921
  const footerSeries = useCallback(() => { void currentActionsRef.current.openSeriesEditor(); }, []);
877
922
  const footerResolution = useCallback(() => { void currentActionsRef.current.openResolutionPicker(); }, []);
878
- const footerShare = useCallback(() => { currentActionsRef.current.shareChart(); }, []);
879
923
  const openIndicators = useCallback((event?: PaneFooterPressEvent) => {
880
924
  indicatorsDialogRef.current?.open(footerAnchorPoint(event));
881
925
  }, []);
@@ -901,9 +945,8 @@ function ChartComposerSurface({
901
945
  { id: "formulas", key: "f", label: "ormulas", onPress: openFormulas, disabled: formulasDisabled },
902
946
  { id: "resolution", key: "t", label: "imeframe", onPress: footerResolution },
903
947
  ...(anchorable ? [{ id: "vwap-anchor", key: "v", label: "wap anchor", title: "Anchor VWAP", onPress: footerAnchor }] : []),
904
- ...(publicSharing ? [{ id: "share", key: "y", label: " share", onPress: footerShare }] : []),
905
948
  ],
906
- }), [resolution.loading, pickingAnchor, footerSeries, openIndicators, indicatorsDisabled, openFormulas, formulasDisabled, footerResolution, anchorable, footerAnchor, publicSharing, footerShare]);
949
+ }), [resolution.loading, pickingAnchor, footerSeries, openIndicators, indicatorsDisabled, openFormulas, formulasDisabled, footerResolution, anchorable, footerAnchor]);
907
950
 
908
951
  // A fixed window (a GIP session) highlights no range, so the bar names it.
909
952
  const dateWindowLabel = useMemo(() => {
@@ -7,11 +7,7 @@ import {
7
7
  type ChartSeriesCatalogItem,
8
8
  } from "../../../capabilities";
9
9
  import type { TimeSeriesFieldDefinition } from "../../../time-series/types";
10
- import {
11
- FUTURES_CONTRACTS,
12
- FUTURES_SECTOR_LABELS,
13
- } from "../futures/contracts";
14
- import { TREASURY_MATURITIES } from "../yield-curve/treasury-data";
10
+ import type { SeriesCatalogEntry } from "../../../series/types";
15
11
  import {
16
12
  canonicalExchange,
17
13
  parsePublicTickerKey,
@@ -271,50 +267,61 @@ function matchesAliasQuery(query: string, ...values: string[]): boolean {
271
267
  return tokens.length > 0 && tokens.every((token) => searchable.includes(token));
272
268
  }
273
269
 
274
- function coreAliasSuggestions(query: string): SeriesCatalogSuggestion[] {
275
- const futures = FUTURES_CONTRACTS
276
- .filter((contract) => matchesAliasQuery(
277
- query,
278
- `FUT:${contract.code}`,
279
- contract.code,
280
- contract.name,
281
- `${contract.name} futures`,
282
- contract.sector,
283
- FUTURES_SECTOR_LABELS[contract.sector],
284
- ))
285
- .map((contract): SeriesCatalogSuggestion => ({
286
- id: `${contract.symbol}:market.ohlcv`,
287
- label: `FUT:${contract.code} · ${contract.name}`,
288
- description: `${FUTURES_SECTOR_LABELS[contract.sector]} futures`,
289
- detail: "Futures",
290
- expression: {
291
- kind: "security",
292
- symbol: contract.symbol,
293
- fieldId: "market.ohlcv",
294
- label: contract.name,
295
- },
296
- }));
297
- const treasuries = TREASURY_MATURITIES
298
- .filter((treasury) => matchesAliasQuery(
299
- query,
300
- `UST:${treasury.maturity}`,
301
- treasury.maturity,
302
- treasury.seriesId,
303
- `${treasury.maturity.replace("M", " month").replace("Y", " year")} US Treasury yield`,
304
- ))
305
- .map((treasury): SeriesCatalogSuggestion => ({
306
- id: `fred:${treasury.seriesId}`,
307
- label: `UST:${treasury.maturity} · Treasury Yield`,
308
- description: `U.S. Treasury ${treasury.maturity} yield · FRED ${treasury.seriesId}`,
309
- detail: "Treasury",
310
- expression: {
311
- kind: "economic",
312
- provider: "fred",
313
- seriesId: treasury.seriesId,
314
- label: `${treasury.maturity} Treasury Yield`,
315
- },
316
- }));
317
- return [...futures, ...treasuries];
270
+ function suggestionId(expression: ParsedSeriesExpression): string {
271
+ if (expression.kind === "economic") return `fred:${expression.seriesId}`;
272
+ if (expression.kind === "capability") {
273
+ return chartSeriesSourceKey({ kind: "capability", capabilityId: expression.capabilityId, seriesId: expression.seriesId });
274
+ }
275
+ return `${publicTickerKey(expression.symbol, expression.exchange)}:${expression.fieldId}`;
276
+ }
277
+
278
+ function registeredMatchRank(entry: SeriesCatalogEntry, query: string): number {
279
+ const name = compact(entry.name);
280
+ const needle = compact(query);
281
+ if (name === needle || compact(entry.expression) === needle) return 0;
282
+ if (name.startsWith(needle)) return 1;
283
+ return 2;
284
+ }
285
+
286
+ /**
287
+ * Registered catalog series the query names: by name, expression, group or
288
+ * tags. A series that takes a ticker is filled in with the one the query
289
+ * names, or the chart's own; ticker fields come from the field ranking instead.
290
+ */
291
+ function registeredSeriesSuggestions(
292
+ query: string,
293
+ registered: readonly SeriesCatalogEntry[],
294
+ analysis: SeriesSearchAnalysis,
295
+ defaultInstrument: SeriesCatalogInstrument,
296
+ ): SeriesCatalogSuggestion[] {
297
+ if (!query.trim() || registered.length === 0) return [];
298
+ const instrument = analysis.directInstrument ?? defaultInstrument;
299
+ const tickerQuery = analysis.directInstrument ? analysis.metricQuery : query;
300
+ const hits: Array<{ entry: SeriesCatalogEntry; rank: number; expression: ParsedSeriesExpression }> = [];
301
+ for (const entry of registered) {
302
+ let template = entry.expression;
303
+ let text = query;
304
+ if (entry.input) {
305
+ // Ticker fields are ranked against the security below; options and pairs need their own symbol.
306
+ if (entry.input !== "ticker" || /^\{ticker\}:[A-Za-z]/.test(template) || !tickerQuery.trim()) continue;
307
+ const symbol = publicTickerKey(instrument.symbol, instrument.exchange);
308
+ template = template.replaceAll("{ticker}", template.startsWith("CAP:") ? encodeURIComponent(symbol) : symbol);
309
+ text = tickerQuery;
310
+ }
311
+ if (!matchesAliasQuery(text, entry.name, entry.expression, entry.id, entry.group ?? "", ...(entry.tags ?? []))) continue;
312
+ const parsed = parseSeriesExpression(template);
313
+ if (!parsed) continue;
314
+ const label = entry.input ? `${publicTickerKey(instrument.symbol, instrument.exchange)} · ${entry.name}` : entry.name;
315
+ hits.push({ entry, rank: registeredMatchRank(entry, text), expression: { ...parsed, label } });
316
+ }
317
+ hits.sort((left, right) => left.rank - right.rank || left.entry.name.length - right.entry.name.length);
318
+ return hits.map(({ entry, expression }): SeriesCatalogSuggestion => ({
319
+ id: suggestionId(expression),
320
+ label: expression.kind === "capability" ? expression.label ?? entry.name : `${entry.expression} · ${entry.name}`,
321
+ description: [entry.group, entry.unit, entry.frequency].filter(Boolean).join(" · "),
322
+ detail: entry.group ?? "Series",
323
+ expression,
324
+ }));
318
325
  }
319
326
 
320
327
  export function buildCapabilitySeriesSuggestions(
@@ -345,6 +352,7 @@ export function buildSeriesCatalogSuggestions(
345
352
  defaultInstrument: SeriesCatalogInstrument,
346
353
  searchedInstruments: readonly SeriesCatalogInstrument[] = [],
347
354
  limit = 8,
355
+ registered: readonly SeriesCatalogEntry[] = [],
348
356
  ): SeriesCatalogSuggestion[] {
349
357
  const exact = exactExpressionSuggestion(query.trim());
350
358
  const analysis = analyzeSeriesSearchQuery(query);
@@ -362,7 +370,7 @@ export function buildSeriesCatalogSuggestions(
362
370
  .sort((left, right) => right.score - left.score || left.field.label.localeCompare(right.field.label));
363
371
 
364
372
  const suggestions: SeriesCatalogSuggestion[] = exact ? [exact] : [];
365
- for (const suggestion of coreAliasSuggestions(query)) {
373
+ for (const suggestion of registeredSeriesSuggestions(query, registered, analysis, defaultInstrument)) {
366
374
  if (!suggestions.some((entry) => entry.id === suggestion.id)) suggestions.push(suggestion);
367
375
  }
368
376
  const fieldLimit = instruments.length > 1 && !analysis.metricQuery ? 1 : rankedFields.length;
@@ -15,7 +15,8 @@ import {
15
15
  isValidChartCapabilityId,
16
16
  isValidChartSeriesId,
17
17
  } from "../../../capabilities/chart-series";
18
- import { FUTURES_CONTRACTS } from "../futures/contracts";
18
+ import { futuresContractByCode } from "../../../market-data/futures-board";
19
+ import { getSharedRegistry } from "../../registry";
19
20
  import { TREASURY_MATURITIES } from "../yield-curve/treasury-data";
20
21
 
21
22
  export const CHART_FIELD_IDS = {
@@ -100,9 +101,9 @@ export function parseSeriesExpression(value: string): ParsedSeriesExpression | n
100
101
  if (separator < 0) return null;
101
102
  const capabilityId = trimmed.slice(4, separator);
102
103
  const seriesId = trimmed.slice(separator + 1);
103
- return isValidChartCapabilityId(capabilityId) && isValidChartSeriesId(seriesId)
104
- ? { kind: "capability", capabilityId, seriesId }
105
- : null;
104
+ if (!isValidChartCapabilityId(capabilityId) || !isValidChartSeriesId(seriesId)) return null;
105
+ const label = registeredSeriesName({ capabilityId, seriesId });
106
+ return { kind: "capability", capabilityId, seriesId, ...(label ? { label } : {}) };
106
107
  }
107
108
  if (parts[0]?.trim().toUpperCase() === "GEO") {
108
109
  const seriesId = trimmed.slice(trimmed.indexOf(":") + 1).trim();
@@ -112,13 +113,13 @@ export function parseSeriesExpression(value: string): ParsedSeriesExpression | n
112
113
  }
113
114
  if (parts[0]?.trim().toUpperCase() === "FRED") {
114
115
  const seriesId = parts.length === 2 ? parts[1]?.trim().toUpperCase() ?? "" : "";
115
- return /^[A-Z0-9._-]{1,80}$/.test(seriesId)
116
- ? { kind: "economic", provider: "fred", seriesId }
117
- : null;
116
+ if (!/^[A-Z0-9._-]{1,80}$/.test(seriesId)) return null;
117
+ // The catalog's name for a listed series, so the legend says what the catalog said.
118
+ const label = getSharedRegistry()?.series?.findByExpression(`FRED:${seriesId}`)?.definition.name;
119
+ return { kind: "economic", provider: "fred", seriesId, ...(label ? { label } : {}) };
118
120
  }
119
121
  if (parts.length === 2 && parts[0]?.trim().toUpperCase() === "FUT") {
120
- const code = parts[1]?.trim().toUpperCase();
121
- const contract = FUTURES_CONTRACTS.find((entry) => entry.code === code);
122
+ const contract = futuresContractByCode(parts[1]);
122
123
  return contract
123
124
  ? { kind: "security", symbol: contract.symbol, fieldId: CHART_FIELD_IDS.price, label: contract.name }
124
125
  : null;
@@ -189,10 +190,17 @@ export function formatSeriesExpression(series: ChartSeriesSpec): string {
189
190
  return `${publicTickerKey(series.source.instrument.symbol, series.source.instrument.exchange)}:${series.source.fieldId}`;
190
191
  }
191
192
 
193
+ /** A registered catalog series' name, with the ticker it was charted for. */
194
+ export function registeredSeriesName(source: { capabilityId: string; seriesId: string }): string | null {
195
+ const found = getSharedRegistry()?.series?.findLoaded(source.capabilityId, source.seriesId);
196
+ if (!found) return null;
197
+ return found.ticker ? `${found.ticker} ${found.series.definition.name}` : found.series.definition.name;
198
+ }
199
+
192
200
  export function chartSeriesLabel(series: ChartSeriesSpec): string {
193
201
  if (series.label?.trim()) return series.label.trim();
194
202
  if (series.source.kind === "economic") return `FRED ${series.source.seriesId}`;
195
- if (series.source.kind === "capability") return series.source.seriesId;
203
+ if (series.source.kind === "capability") return registeredSeriesName(series.source) ?? series.source.seriesId;
196
204
  const generic = getTimeSeriesField(series.source.fieldId)?.unitGroup === "price"
197
205
  ? futuresGenericListing(series.source.instrument.symbol, series.source.instrument.exchange) : null;
198
206
  if (generic) return futuresGenericCaption(generic);
@@ -1,4 +1,4 @@
1
- import { useEffect, useMemo, useState } from "react";
1
+ import { useEffect, useMemo, useState, useSyncExternalStore } from "react";
2
2
  import {
3
3
  buildTickerSearchCandidates,
4
4
  searchTickerCandidates,
@@ -6,6 +6,8 @@ import {
6
6
  import { useOptionalAppSelector } from "../../../state/app/context";
7
7
  import type { TickerRecord } from "../../../types/ticker";
8
8
  import { searchChartSeriesCapabilities } from "../../../capabilities";
9
+ import { SERIES_CATALOG_CAPABILITY_ID } from "../../../series/capability";
10
+ import type { SeriesCatalogEntry } from "../../../series/types";
9
11
  import { getSharedRegistry } from "../../registry";
10
12
  import {
11
13
  analyzeSeriesSearchQuery,
@@ -17,6 +19,9 @@ import {
17
19
 
18
20
  const EMPTY_TICKERS: ReadonlyMap<string, TickerRecord> = new Map();
19
21
  const EMPTY_RECENT: readonly string[] = [];
22
+ const EMPTY_PLUGINS: readonly string[] = [];
23
+ const EMPTY_ENTRIES: readonly SeriesCatalogEntry[] = [];
24
+ const NO_SUBSCRIPTION = () => () => {};
20
25
  const MAX_SERIES_SUGGESTIONS = 8;
21
26
  const DEFAULT_CATALOG_INSTRUMENTS: readonly SeriesCatalogInstrument[] = [
22
27
  { symbol: "AAPL", exchange: "NASDAQ", name: "Apple Inc." },
@@ -72,6 +77,56 @@ function candidateToInstrument(candidate: {
72
77
  };
73
78
  }
74
79
 
80
+ /**
81
+ * Every registered series of the plugins that are switched on. On the
82
+ * desktop, series only the Bun process has (files in the profile's series
83
+ * folder) are asked for once and listed after the rest; elsewhere, sources
84
+ * that change while the app runs catch up when the catalog opens.
85
+ */
86
+ export function useRegisteredSeries(): readonly SeriesCatalogEntry[] {
87
+ const registry = getSharedRegistry();
88
+ const series = registry?.series;
89
+ const version = useSyncExternalStore(
90
+ series ? series.subscribe.bind(series) : NO_SUBSCRIPTION,
91
+ () => series?.getVersion() ?? 0,
92
+ () => 0,
93
+ );
94
+ const disabledPlugins = useOptionalAppSelector((state) => state.config.disabledPlugins, EMPTY_PLUGINS);
95
+ const [remote, setRemote] = useState<readonly SeriesCatalogEntry[] | null>(null);
96
+
97
+ useEffect(() => {
98
+ if (!registry || !series) return;
99
+ if (!registry.usesRemoteCapabilities) {
100
+ void series.refresh();
101
+ return;
102
+ }
103
+ let cancelled = false;
104
+ void registry.invokeCapability<{ entries: SeriesCatalogEntry[] }>(SERIES_CATALOG_CAPABILITY_ID, "list", {})
105
+ .then((result) => {
106
+ if (!cancelled && Array.isArray(result?.entries)) setRemote(result.entries);
107
+ })
108
+ .catch(() => {
109
+ // The view's own series still list; only the Bun process's extras are missing.
110
+ });
111
+ return () => { cancelled = true; };
112
+ }, [registry, series]);
113
+
114
+ return useMemo(() => {
115
+ const local = series?.catalog() ?? EMPTY_ENTRIES;
116
+ let entries = local;
117
+ if (remote?.length) {
118
+ const known = new Set(local.map((entry) => entry.id));
119
+ const extra = remote.filter((entry) => !known.has(entry.id));
120
+ if (extra.length) entries = [...local, ...extra];
121
+ }
122
+ if (disabledPlugins.length === 0) return entries;
123
+ const disabled = new Set(disabledPlugins);
124
+ return entries.some((entry) => disabled.has(entry.pluginId))
125
+ ? entries.filter((entry) => !disabled.has(entry.pluginId))
126
+ : entries;
127
+ }, [disabledPlugins, remote, series, version]);
128
+ }
129
+
75
130
  export function useCatalogUniverse(query: string): {
76
131
  instruments: SeriesCatalogInstrument[];
77
132
  loading: boolean;
@@ -193,6 +248,7 @@ export function useSeriesCatalogSuggestions({
193
248
  enabled: boolean;
194
249
  }): SeriesCatalogSearchResult {
195
250
  const tickers = useOptionalAppSelector((state) => state.tickers, EMPTY_TICKERS);
251
+ const registered = useRegisteredSeries();
196
252
  const analysis = useMemo(() => analyzeSeriesSearchQuery(query), [query]);
197
253
  const [providerSearch, setProviderSearch] = useState<{
198
254
  query: string;
@@ -298,11 +354,11 @@ export function useSeriesCatalogSuggestions({
298
354
  // and they arrive well before plugin catalogs (which can take seconds), so
299
355
  // late plugin results append below instead of pushing the list around.
300
356
  const suggestions = useMemo(() => {
301
- const builtIn = buildSeriesCatalogSuggestions(query, defaultInstrument, instruments);
357
+ const builtIn = buildSeriesCatalogSuggestions(query, defaultInstrument, instruments, MAX_SERIES_SUGGESTIONS, registered);
302
358
  const provider = providerSearch.query === query.trim() ? providerSearch.suggestions : [];
303
359
  return [...builtIn, ...provider.filter((entry) => !builtIn.some((candidate) => candidate.id === entry.id))]
304
360
  .slice(0, MAX_SERIES_SUGGESTIONS);
305
- }, [defaultInstrument, instruments, providerSearch, query]);
361
+ }, [defaultInstrument, instruments, providerSearch, query, registered]);
306
362
 
307
363
  return {
308
364
  suggestions,
@@ -0,0 +1,84 @@
1
+ import { getCurrentPluginTarget } from "../../current-target";
2
+ import { getSharedRegistry } from "../../registry";
3
+ import { listSeriesFiles, seriesFromFile } from "../../../series/files";
4
+ import type { SeriesDefinition } from "../../../series/types";
5
+ import type { GloomPluginContext } from "../../../types/plugin";
6
+ import type { PluginModule } from "../plugin-module";
7
+
8
+ interface RegisteredFile {
9
+ mtimeMs: number;
10
+ dispose: () => void;
11
+ }
12
+
13
+ /**
14
+ * Keeps the catalog in step with the profile's series folder: a file added,
15
+ * changed or removed shows up the next time the catalog opens.
16
+ */
17
+ function watchUserSeriesFolder(ctx: GloomPluginContext): () => void {
18
+ const registered = new Map<string, RegisteredFile>();
19
+ let running: Promise<void> = Promise.resolve();
20
+
21
+ const sync = async () => {
22
+ const files = await listSeriesFiles(ctx.getConfig().dataDir);
23
+ const present = new Set(files.map((file) => file.name));
24
+ for (const [name, entry] of registered) {
25
+ if (present.has(name)) continue;
26
+ entry.dispose();
27
+ registered.delete(name);
28
+ }
29
+ for (const file of files) {
30
+ const existing = registered.get(file.name);
31
+ if (existing?.mtimeMs === file.mtimeMs) continue;
32
+ existing?.dispose();
33
+ registered.delete(file.name);
34
+ let definitions: SeriesDefinition[];
35
+ try {
36
+ definitions = seriesFromFile(file.name, await file.readText(), file.readText);
37
+ } catch (error) {
38
+ ctx.log.warn("Series file skipped", { file: file.name, error: error instanceof Error ? error.message : String(error) });
39
+ continue;
40
+ }
41
+ const disposers = definitions.flatMap((definition) => {
42
+ try {
43
+ return [ctx.registerSeries(definition)];
44
+ } catch (error) {
45
+ ctx.log.warn("Series skipped", { file: file.name, error: error instanceof Error ? error.message : String(error) });
46
+ return [];
47
+ }
48
+ });
49
+ registered.set(file.name, { mtimeMs: file.mtimeMs, dispose: () => { for (const dispose of disposers) dispose(); } });
50
+ }
51
+ };
52
+ const refresh = () => {
53
+ running = running.then(sync, sync);
54
+ return running;
55
+ };
56
+
57
+ void refresh();
58
+ const removeRefresher = getSharedRegistry()?.series.addRefresher(refresh);
59
+ return () => {
60
+ removeRefresher?.();
61
+ for (const entry of registered.values()) entry.dispose();
62
+ registered.clear();
63
+ };
64
+ }
65
+
66
+ let stopWatching: (() => void) | null = null;
67
+
68
+ /**
69
+ * CSV files in `<data dir>/series/` as catalog series, chartable against
70
+ * anything else. Files are read where the app can reach the disk: the
71
+ * terminal, and the desktop's Bun process, which lists them for its view.
72
+ */
73
+ export const userSeriesModule: PluginModule = {
74
+ setup(ctx) {
75
+ const target = getCurrentPluginTarget();
76
+ if (target !== "cli" && target !== "tui") return;
77
+ stopWatching?.();
78
+ stopWatching = watchUserSeriesFolder(ctx);
79
+ },
80
+ dispose() {
81
+ stopWatching?.();
82
+ stopWatching = null;
83
+ },
84
+ };
@@ -11,6 +11,8 @@ import type { ChatContentController } from "./types";
11
11
  import { getComposerCursorOffset, moveComposerCursorToOffset } from "./composer-cursor";
12
12
  import { insertedText, pastedImagePaths } from "../attachments/transfer";
13
13
  import { chatTextWithImages } from "../attachments/model";
14
+ import { isManagedBot } from "../ghost-user";
15
+ import { CHAT_AI_BADGE_WIDTH } from "../message/ai-badge";
14
16
 
15
17
  interface MutableRef<T> {
16
18
  current: T;
@@ -398,7 +400,10 @@ export function useChatComposerRuntime({
398
400
  const replyPreview = replyTo
399
401
  ? formatInlinePreview(
400
402
  chatTextWithImages(replyTo.content, replyTo.attachments?.length ?? 0),
401
- Math.max(contentWidth - ` replying to @${replyTo.user.username}: `.length - COMPOSER_ACTION_WIDTH - 1, 0),
403
+ Math.max(
404
+ contentWidth - ` replying to @${replyTo.user.username}`.length - (isManagedBot(replyTo.user) ? CHAT_AI_BADGE_WIDTH + 1 : 2) - COMPOSER_ACTION_WIDTH - 1,
405
+ 0,
406
+ ),
402
407
  )
403
408
  : "";
404
409
  const editingPreview = editingMessage