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,3 +1,4 @@
1
+ import { registerAccountSession } from "../../../../account/session";
1
2
  import type {
2
3
  AppNotificationDelivery,
3
4
  AppNotificationRequest,
@@ -10,8 +11,11 @@ import {
10
11
  type ChatChannel,
11
12
  type ChatChannelState,
12
13
  type ChatMessage,
14
+ type ChatReaction,
15
+ type ChatReactionsUpdate,
13
16
  type PersistedAuthUser,
14
17
  } from "../../../../api-client";
18
+ import { withOwnReaction } from "../reactions";
15
19
  import { normalizeSessionUser } from "./persistence";
16
20
  import { debugLog } from "../../../../utils/debug-log";
17
21
  import {
@@ -32,7 +36,8 @@ import {
32
36
  updateChatChannelDraft,
33
37
  updateChatChannelNotifications,
34
38
  } from "./channel-actions";
35
- import { retryChatMessageInChannel, sendChatMessageToChannel } from "./send";
39
+ import { postImageMessageToChannel, retryChatMessageInChannel, sendChatMessageToChannel } from "./send";
40
+ import { describeChatImageError } from "../attachments/model";
36
41
  import {
37
42
  addDraftAttachments,
38
43
  discardDraftAttachments,
@@ -143,6 +148,7 @@ export class ChatController {
143
148
  emit: (channelId) => this.emit(channelId),
144
149
  mergeMessages: (channelId, messages, options) => this.mergeMessages(channelId, messages, options),
145
150
  persistChannelState: (channelId) => this.storage.persistChannelState(channelId),
151
+ getReaderId: () => this.session.user?.id ?? null,
146
152
  });
147
153
  private readonly realtime = new ChatControllerRealtime({
148
154
  getAppActive: () => this.appActive,
@@ -150,6 +156,7 @@ export class ChatController {
150
156
  getUser: () => this.session.user,
151
157
  refreshSession: () => this.refreshSession(),
152
158
  handleNotification: (notification) => this.handleChatNotification(notification),
159
+ handleReactions: (update) => this.applyReactionsUpdate(update),
153
160
  setOnlineCount: (onlineCount) => {
154
161
  this.channelCatalog.setOnlineCount(onlineCount);
155
162
  },
@@ -171,6 +178,30 @@ export class ChatController {
171
178
  this.openMessageFn = openMessage;
172
179
  }
173
180
 
181
+ /**
182
+ * Mark all read in the Unread list: each unread channel is read through its
183
+ * newest message the way opening it in Chat reads it, and a channel with
184
+ * nothing on this device yet once its latest messages load. A failed load
185
+ * leaves that channel unread.
186
+ */
187
+ markAllChannelsRead(): void {
188
+ let changed = false;
189
+ for (const [channelId, channel] of this.storage.channelStates) {
190
+ if (channel.unreadCount <= 0) continue;
191
+ if (channel.messages.length > 0) {
192
+ changed = this.markViewedThroughLatestMessage(channelId) || changed;
193
+ continue;
194
+ }
195
+ void this.refreshChannelMessages(channelId)
196
+ .then(() => {
197
+ if (this.ensureChannelState(channelId).messages.length === 0) return;
198
+ if (this.markViewedThroughLatestMessage(channelId)) this.emit(channelId);
199
+ })
200
+ .catch(() => {});
201
+ }
202
+ if (changed) this.emit();
203
+ }
204
+
174
205
  hydrate(): void {
175
206
  hydrateChatControllerSession({
176
207
  session: this.session,
@@ -569,6 +600,47 @@ export class ChatController {
569
600
  };
570
601
  }
571
602
 
603
+ /**
604
+ * Posts one picture with an optional caption as the user's own message, as
605
+ * Share to Chat does: uploads it, then sends it, leaving the channel's
606
+ * draft alone. Rejects with a sentence that says what went wrong.
607
+ */
608
+ async postImage(
609
+ channelId: string,
610
+ upload: ChatAttachmentUpload & { previewUrl?: string | null },
611
+ caption: string,
612
+ options: { signal?: AbortSignal; onProgress?: (fraction: number) => void } = {},
613
+ ): Promise<ChatMessage> {
614
+ const normalizedChannelId = normalizeChannelId(channelId);
615
+ const user = this.session.user;
616
+ if (!user?.emailVerified) throw new Error("Verify your email to post in chat.");
617
+ let attachment;
618
+ try {
619
+ attachment = await this.uploadAttachment(normalizedChannelId, upload, {
620
+ signal: options.signal ?? new AbortController().signal,
621
+ onProgress: options.onProgress ?? (() => {}),
622
+ });
623
+ } catch (error) {
624
+ throw new Error(describeChatImageError(error));
625
+ }
626
+ const channel = this.ensureChannelState(normalizedChannelId);
627
+ return postImageMessageToChannel({
628
+ channelId: normalizedChannelId,
629
+ channel,
630
+ content: caption,
631
+ attachment,
632
+ previewUrl: upload.previewUrl ?? null,
633
+ user,
634
+ getVisibleMessages: () => this.getVisibleMessages(normalizedChannelId),
635
+ nextPendingMessageId: () => `local:${Date.now()}:${this.pendingMessageSeq += 1}`,
636
+ emit: () => this.emit(normalizedChannelId),
637
+ mergeMessages: (messages) => this.mergeMessages(normalizedChannelId, messages),
638
+ send: (content, clientMessageId, attachmentIds) => (
639
+ apiClient.sendMessage(normalizedChannelId, content, undefined, clientMessageId, attachmentIds)
640
+ ),
641
+ });
642
+ }
643
+
572
644
  /** Sends a failed message again with the same images and idempotency key. */
573
645
  retryChannelMessage(channelId: string, messageId: string): boolean {
574
646
  const normalizedChannelId = normalizeChannelId(channelId);
@@ -625,6 +697,55 @@ export class ChatController {
625
697
  }
626
698
  }
627
699
 
700
+ /**
701
+ * Adds or takes back your reaction with one emoji. The chip moves at once;
702
+ * the server's answer settles it, and a refusal puts it back and says why.
703
+ */
704
+ async toggleChannelReaction(channelId: string, messageId: string, emoji: string): Promise<boolean> {
705
+ const normalizedChannelId = normalizeChannelId(channelId);
706
+ const channel = this.ensureChannelState(normalizedChannelId);
707
+ const user = this.session.user;
708
+ if (!user?.emailVerified) return false;
709
+ const message = channel.messages.find((entry) => entry.id === messageId);
710
+ if (!message) return false;
711
+ const reacted = !(message.reactions ?? []).some((reaction) => reaction.emoji === emoji && reaction.me);
712
+ const self = { id: user.id, username: user.username, displayName: user.username };
713
+ this.replaceMessageReactions(normalizedChannelId, messageId, (current) => withOwnReaction(current, emoji, reacted, self));
714
+ try {
715
+ const update = await apiClient.setChatReaction(normalizedChannelId, messageId, emoji, reacted);
716
+ this.replaceMessageReactions(normalizedChannelId, messageId, () => update.reactions);
717
+ return true;
718
+ } catch (error) {
719
+ // Only this change is undone; what others did meanwhile stays.
720
+ this.replaceMessageReactions(normalizedChannelId, messageId, (current) => withOwnReaction(current, emoji, !reacted, self));
721
+ const body = error instanceof Error && error.message ? error.message : "Failed to react.";
722
+ this.notifyFn({ body, type: "error" });
723
+ return false;
724
+ }
725
+ }
726
+
727
+ /** A message's reactions as everyone reading the channel just got them. */
728
+ applyReactionsUpdate(update: ChatReactionsUpdate): void {
729
+ this.replaceMessageReactions(normalizeChannelId(update.channelId), update.messageId, () => update.reactions);
730
+ }
731
+
732
+ private replaceMessageReactions(
733
+ channelId: string,
734
+ messageId: string,
735
+ next: (current: ChatReaction[]) => ChatReaction[],
736
+ ): void {
737
+ const channel = this.storage.channelStates.get(channelId);
738
+ if (!channel) return;
739
+ const index = channel.messages.findIndex((entry) => entry.id === messageId);
740
+ if (index < 0) return;
741
+ const message = channel.messages[index]!;
742
+ channel.messages = channel.messages.map((entry, entryIndex) => (
743
+ entryIndex === index ? { ...message, reactions: next(message.reactions ?? []) } : entry
744
+ ));
745
+ this.storage.persistTranscript(channelId);
746
+ this.emit(channelId);
747
+ }
748
+
628
749
  ensureConnection(channelId = DEFAULT_CHAT_CHANNEL_ID): void {
629
750
  const normalizedChannelId = normalizeChannelId(channelId);
630
751
  const channel = this.ensureChannelState(normalizedChannelId);
@@ -757,3 +878,4 @@ export class ChatController {
757
878
  }
758
879
 
759
880
  export const chatController = new ChatController();
881
+ registerAccountSession(chatController);
@@ -15,6 +15,8 @@ interface ChatControllerMessageLoadingOptions {
15
15
  emit: (channelId?: string) => void;
16
16
  mergeMessages: (channelId: string, messages: ChatMessage[], options?: MergeMessagesOptions) => void;
17
17
  persistChannelState: (channelId: string) => void;
18
+ /** The signed-in account's id, or null. */
19
+ getReaderId?: () => string | null;
18
20
  }
19
21
 
20
22
  export class ChatControllerMessageLoading {
@@ -45,6 +47,7 @@ export class ChatControllerMessageLoading {
45
47
  persistChannelState: (nextChannelId) => {
46
48
  this.options.persistChannelState(nextChannelId);
47
49
  },
50
+ readerId: () => this.options.getReaderId?.() ?? null,
48
51
  })
49
52
  .catch((error: unknown) => {
50
53
  channel.messagesError = error instanceof Error && error.message.trim()
@@ -49,10 +49,15 @@ function mergeStoredMessages(channel: ChannelRuntimeState, messages: ChatMessage
49
49
  const incoming = new Map<string, ChatMessage>();
50
50
  for (const message of channel.messages) merged.set(message.id, message);
51
51
  for (const message of messages) {
52
- if (!merged.has(message.id)) {
52
+ const current = merged.get(message.id);
53
+ if (!current) {
53
54
  incoming.set(message.id, message);
54
55
  }
55
- merged.set(message.id, message);
56
+ // A live copy (an edit) leaves reactions out; the ones held stay.
57
+ merged.set(
58
+ message.id,
59
+ current?.reactions && message.reactions === undefined ? { ...message, reactions: current.reactions } : message,
60
+ );
56
61
  }
57
62
  for (const message of messages) {
58
63
  for (const [id, current] of merged) {
@@ -1,4 +1,4 @@
1
- import { apiClient, type ChatNotification } from "../../../../api-client";
1
+ import { apiClient, type ChatNotification, type ChatReactionsUpdate } from "../../../../api-client";
2
2
  import {
3
3
  SAFETY_REFRESH_MS,
4
4
  SESSION_RETRY_MS,
@@ -11,6 +11,7 @@ interface ChatControllerRealtimeOptions {
11
11
  getUser: () => { emailVerified?: boolean } | null;
12
12
  refreshSession: () => Promise<void>;
13
13
  handleNotification: (notification: ChatNotification) => void;
14
+ handleReactions: (update: ChatReactionsUpdate) => void;
14
15
  setOnlineCount: (onlineCount: number) => void;
15
16
  emit: () => void;
16
17
  getSafetyRefreshChannelIds: () => string[];
@@ -23,6 +24,7 @@ export class ChatControllerRealtime {
23
24
  private safetyRefreshTimer: ReturnType<typeof setInterval> | null = null;
24
25
  private chatNotificationUnsubscribe: (() => void) | null = null;
25
26
  private chatPresenceUnsubscribe: (() => void) | null = null;
27
+ private chatReactionsUnsubscribe: (() => void) | null = null;
26
28
 
27
29
  constructor(private readonly options: ChatControllerRealtimeOptions) {}
28
30
 
@@ -65,6 +67,11 @@ export class ChatControllerRealtime {
65
67
  this.options.handleNotification(notification);
66
68
  });
67
69
  }
70
+ if (!this.chatReactionsUnsubscribe) {
71
+ this.chatReactionsUnsubscribe = apiClient.subscribeChatReactions((update) => {
72
+ this.options.handleReactions(update);
73
+ });
74
+ }
68
75
  if (!this.chatPresenceUnsubscribe) {
69
76
  this.chatPresenceUnsubscribe = apiClient.subscribeChatPresence((onlineCount) => {
70
77
  this.options.setOnlineCount(onlineCount);
@@ -78,6 +85,8 @@ export class ChatControllerRealtime {
78
85
  this.chatNotificationUnsubscribe = null;
79
86
  this.chatPresenceUnsubscribe?.();
80
87
  this.chatPresenceUnsubscribe = null;
88
+ this.chatReactionsUnsubscribe?.();
89
+ this.chatReactionsUnsubscribe = null;
81
90
  }
82
91
 
83
92
  stopVerificationPolling(): void {
@@ -1,5 +1,5 @@
1
1
  import type { AppNotificationRequest } from "../../../../types/plugin";
2
- import type { ChatMessage } from "../../../../api-client";
2
+ import type { ChatAttachment, ChatMessage } from "../../../../api-client";
3
3
  import { describeChatSendError } from "../attachments/model";
4
4
  import { readyDraftAttachments } from "./attachments";
5
5
  import {
@@ -147,6 +147,66 @@ export function sendChatMessageToChannel({
147
147
  return true;
148
148
  }
149
149
 
150
+ /**
151
+ * Posts a message that carries an image uploaded for it (a pane shared to
152
+ * chat), without touching the channel's draft. It shows as sending at once,
153
+ * like a typed message; a failed send stays in the channel to retry, and the
154
+ * returned promise rejects with the reason.
155
+ */
156
+ export async function postImageMessageToChannel({
157
+ channelId,
158
+ channel,
159
+ content,
160
+ attachment,
161
+ previewUrl,
162
+ user,
163
+ getVisibleMessages,
164
+ nextPendingMessageId,
165
+ emit,
166
+ mergeMessages,
167
+ send,
168
+ }: {
169
+ channelId: string;
170
+ channel: ChannelRuntimeState;
171
+ content: string;
172
+ attachment: ChatAttachment;
173
+ /** The local copy to show until the server's answer arrives. */
174
+ previewUrl: string | null;
175
+ user: ChatSessionUser;
176
+ getVisibleMessages: () => ChatMessage[];
177
+ nextPendingMessageId: () => string;
178
+ emit: () => void;
179
+ mergeMessages: (messages: ChatMessage[]) => void;
180
+ send: (content: string, clientMessageId: string, attachmentIds: string[]) => Promise<ChatMessage>;
181
+ }): Promise<ChatMessage> {
182
+ const pendingMessage = createPendingMessage({
183
+ channelId,
184
+ content: content.trim(),
185
+ pendingId: nextPendingMessageId(),
186
+ user,
187
+ visibleMessages: getVisibleMessages(),
188
+ attachments: [{ ...attachment, url: previewUrl ?? attachment.url }],
189
+ clientMessageId: createClientMessageId(),
190
+ });
191
+ channel.pendingMessages = [...channel.pendingMessages, pendingMessage];
192
+ emit();
193
+ try {
194
+ const message = await send(pendingMessage.content, pendingMessage.clientMessageId!, [attachment.id]);
195
+ channel.pendingMessages = channel.pendingMessages.filter((entry) => entry.id !== pendingMessage.id);
196
+ mergeMessages([message]);
197
+ return message;
198
+ } catch (error) {
199
+ const errorMessage = describeChatSendError(error);
200
+ channel.pendingMessages = channel.pendingMessages.map((entry) => (
201
+ entry.id === pendingMessage.id
202
+ ? { ...entry, clientStatus: "failed", clientError: errorMessage }
203
+ : entry
204
+ ));
205
+ emit();
206
+ throw new Error(errorMessage);
207
+ }
208
+ }
209
+
150
210
  /**
151
211
  * Sends a failed message again: same text, same images (not uploaded again)
152
212
  * and the same idempotency key, so a send that did reach the server is not
@@ -92,6 +92,13 @@ export interface ChannelRuntimeState {
92
92
  * never be requested again; one uncursored fetch per session repairs it.
93
93
  */
94
94
  backfilled: boolean;
95
+ /**
96
+ * The account that backfill read the channel as (null signed out). Each
97
+ * message comes back with that reader's own reactions, so a different
98
+ * reader (a pane that mounted before the session was restored, a sign-in)
99
+ * reads the latest page again.
100
+ */
101
+ backfilledAs: string | null;
95
102
  messages: ChatMessage[];
96
103
  pendingMessages: ChatMessage[];
97
104
  draft: string;
@@ -129,6 +136,7 @@ export function createEmptyChannelState(): ChannelRuntimeState {
129
136
  loadOlderMessagesPromise: null,
130
137
  reachedOldestMessage: false,
131
138
  backfilled: false,
139
+ backfilledAs: null,
132
140
  messages: [],
133
141
  pendingMessages: [],
134
142
  draft: "",
@@ -8,6 +8,26 @@ export function isDiscordGhost(user: Pick<ChatUserSummary, "accountType"> | null
8
8
  return user?.accountType === "discord";
9
9
  }
10
10
 
11
+ /**
12
+ * A managed assistant (Gloombot, Gloom Wire, the AI desk personas): an account
13
+ * Gloom runs, not a person. Wherever it signs a message it carries an AI badge.
14
+ */
15
+ export function isManagedBot(user: Pick<ChatUserSummary, "accountType"> | null | undefined): boolean {
16
+ return user?.accountType === "managed_llm";
17
+ }
18
+
19
+ /**
20
+ * A reply quotes its author by name only, so whether that author is a managed
21
+ * assistant comes from the users the pane has seen.
22
+ */
23
+ export function isQuotedAuthorManagedBot(
24
+ quoted: { user: { username?: string | null } },
25
+ userByUsername: ReadonlyMap<string, ChatUserSummary>,
26
+ ): boolean {
27
+ const username = quoted.user.username?.toLowerCase();
28
+ return !!username && isManagedBot(userByUsername.get(username));
29
+ }
30
+
11
31
  /** The name a message is signed with: the username, or for a ghost that has none the Discord name it carries. */
12
32
  export function chatAuthorName(user: Pick<ChatUserSummary, "username" | "displayName" | "accountType">): string {
13
33
  return user.username ?? ((isDiscordGhost(user) && user.displayName?.trim()) || "anon");
@@ -3,6 +3,7 @@ import { teamChannelId } from "../cloud/team/model";
3
3
  import { teamStore } from "../cloud/team/store";
4
4
  import { formatChatPaneTitle } from "./channel-labels";
5
5
  import {
6
+ DEFAULT_CHAT_CHANNEL_ID,
6
7
  buildDmCommandResults,
7
8
  getPreferredChatOpenChannelId,
8
9
  hasOnlyDmUsernameArgs,
@@ -18,6 +19,7 @@ import { ChatPane } from "./pane";
18
19
  import { chatSidebarStore } from "./sidebar-store";
19
20
  import { ChatStatusWidget } from "./status-widget";
20
21
  import { UnreadInboxPane } from "./unread-inbox-pane";
22
+ import { installPaneChatSharing } from "./share/flow";
21
23
  import { UNREAD_INBOX_PANE_ID, UNREAD_INBOX_TEMPLATE_ID } from "./unread-inbox";
22
24
 
23
25
  /**
@@ -37,6 +39,15 @@ async function resolveTypedChannelId(rawArg: string): Promise<string> {
37
39
  }
38
40
  }
39
41
 
42
+ /** A DM, a group or a team channel: what only its members read. */
43
+ function isPrivateConversation(channelId: unknown): boolean {
44
+ const id = typeof channelId === "string" && channelId.trim() ? channelId.trim() : DEFAULT_CHAT_CHANNEL_ID;
45
+ const kind = chatController.getChannels().find((channel) => channel.id === id)?.kind;
46
+ return kind ? kind !== "public" : /^(dm|grp|group|team):/.test(id);
47
+ }
48
+
49
+ let disposePaneChatSharing: (() => void) | undefined;
50
+
40
51
  export const chatModule: PluginModule = {
41
52
  panes: [{
42
53
  id: "chat",
@@ -46,18 +57,21 @@ export const chatModule: PluginModule = {
46
57
  defaultPosition: "right",
47
58
  defaultMode: "floating",
48
59
  defaultFloatingSize: { width: 80, height: 30 },
60
+ personalData: (context) => (isPrivateConversation(context.settings.channelId) ? "messages" : null),
49
61
  portableShare: {
50
62
  private: { title: true, params: true, settings: true, state: true },
51
63
  },
52
64
  }, {
53
65
  id: UNREAD_INBOX_PANE_ID,
54
- reportFreshness: { status: "not-a-feed", basis: "chat messages" },
66
+ reportFreshness: { status: "not-a-feed", basis: "chat messages and missed alerts" },
55
67
  name: "Unread",
68
+ // Mentions and replies from every conversation, DMs included.
69
+ personalData: "messages",
56
70
  icon: "U",
57
71
  component: UnreadInboxPane,
58
72
  defaultPosition: "right",
59
73
  defaultMode: "floating",
60
- defaultFloatingSize: { width: 60, height: 16 },
74
+ defaultFloatingSize: { width: 88, height: 16 },
61
75
  }],
62
76
  paneTemplates: [{
63
77
  id: "new-chat-pane",
@@ -117,9 +131,9 @@ export const chatModule: PluginModule = {
117
131
  }, {
118
132
  id: UNREAD_INBOX_TEMPLATE_ID,
119
133
  paneId: UNREAD_INBOX_PANE_ID,
120
- label: "Unread Chat",
121
- description: "Open unread chat messages",
122
- keywords: ["unread", "chat", "inbox", "mentions"],
134
+ label: "Unread",
135
+ description: "Unread chat, then price alerts, catalysts and team notices you missed",
136
+ keywords: ["unread", "chat", "inbox", "mentions", "missed", "notifications", "alerts"],
123
137
  createInstance: () => ({
124
138
  placement: "floating",
125
139
  instanceId: "unread-inbox",
@@ -131,6 +145,8 @@ export const chatModule: PluginModule = {
131
145
  },
132
146
  setup(ctx) {
133
147
  ctx.registerCommandBarSearchProvider(createChatSearchProvider(ctx));
148
+ disposePaneChatSharing?.();
149
+ disposePaneChatSharing = installPaneChatSharing(ctx);
134
150
  chatController.attachPersistence(ctx.persistence, ctx.resume);
135
151
  chatSidebarStore.attach(ctx.persistence);
136
152
  chatController.setNotifier(ctx.notify, (channelId, messageId) => {
@@ -160,6 +176,8 @@ export const chatModule: PluginModule = {
160
176
  });
161
177
  },
162
178
  dispose() {
179
+ disposePaneChatSharing?.();
180
+ disposePaneChatSharing = undefined;
163
181
  chatController.dispose();
164
182
  },
165
183
  };
@@ -9,10 +9,11 @@ import {
9
9
  type TickerBadgeStatus,
10
10
  } from "../../../components/ticker/badge/format";
11
11
  import type { InlineTickerCatalogEntry } from "../../../state/hooks/inline-tickers";
12
+ import { STICKY_BOTTOM_THRESHOLD_PX } from "../../../ui/sticky-scroll";
13
+ import { terminalReactionRows } from "./reactions";
12
14
 
13
15
  const MESSAGE_GROUP_THRESHOLD_MS = 5 * 60 * 1000;
14
16
  const MESSAGE_SELECTION_BOTTOM_INSET = 1;
15
- const SCROLL_BOTTOM_THRESHOLD_PX = 2;
16
17
 
17
18
  export const CHAT_COMPOSER_MAX_ROWS = 5;
18
19
  export const MESSAGE_ACTION_WIDTH = 9;
@@ -277,7 +278,8 @@ export function estimateMessageHeight(
277
278
  ? getMessageBodyTokenLines(message.content, contentLineWidth, catalog).length
278
279
  : getMessageBodyLines(message, width, catalog).length;
279
280
  const reviewNoteHeight = message.attachmentReview ? 1 : 0;
280
- return headerHeight + (message.replyTo ? 1 : 0) + bodyLineCount + imageCount + reviewNoteHeight;
281
+ const reactionRows = message.reactions?.length ? terminalReactionRows(message.reactions, contentLineWidth).length : 0;
282
+ return headerHeight + (message.replyTo ? 1 : 0) + bodyLineCount + imageCount + reviewNoteHeight + reactionRows;
281
283
  }
282
284
 
283
285
  export function estimateComposerHeight(text: string, width: number) {
@@ -336,7 +338,7 @@ export function isScrolledToBottom(scrollBox: ScrollBoxRenderable | null, prefer
336
338
  const exactPixels = preferPixels && hasPixelScrollMetrics(scrollBox);
337
339
  const scrollTop = getScrollTop(scrollBox, exactPixels);
338
340
  const maxScrollTop = Math.max(0, getScrollHeight(scrollBox, exactPixels) - getViewportHeight(scrollBox, exactPixels));
339
- const threshold = exactPixels ? SCROLL_BOTTOM_THRESHOLD_PX : 0;
341
+ const threshold = exactPixels ? STICKY_BOTTOM_THRESHOLD_PX : 0;
340
342
  return maxScrollTop - scrollTop <= threshold;
341
343
  }
342
344
 
@@ -354,21 +356,31 @@ function getScrollTopForElementIntoView({
354
356
  elementTop,
355
357
  elementHeight,
356
358
  bottomInset = 0,
359
+ center = false,
357
360
  }: {
358
361
  scrollTop: number;
359
362
  viewportHeight: number;
360
363
  elementTop: number;
361
364
  elementHeight: number;
362
365
  bottomInset?: number;
366
+ /** An element out of view is brought to the middle of it, not to the nearest edge. */
367
+ center?: boolean;
363
368
  }) {
364
369
  const visibleHeight = Math.max(viewportHeight - bottomInset, 1);
365
370
  const elementBottom = elementTop + elementHeight;
366
- if (elementTop < scrollTop || elementHeight >= visibleHeight) return elementTop;
371
+ if (elementHeight >= visibleHeight) return elementTop;
372
+ const outOfView = elementTop < scrollTop || elementBottom > scrollTop + visibleHeight;
373
+ if (center && outOfView) return Math.max(0, elementTop - (visibleHeight - elementHeight) / 2);
374
+ if (elementTop < scrollTop) return elementTop;
367
375
  if (elementBottom > scrollTop + visibleHeight) return elementBottom - visibleHeight;
368
376
  return scrollTop;
369
377
  }
370
378
 
371
- export function scrollElementIntoScrollBoxView(scrollBox: ScrollBoxRenderable | null, node: unknown) {
379
+ export function scrollElementIntoScrollBoxView(
380
+ scrollBox: ScrollBoxRenderable | null,
381
+ node: unknown,
382
+ options: { center?: boolean } = {},
383
+ ) {
372
384
  const nodeRect = (node as { getBoundingClientRect?: () => { x?: number; y?: number; top?: number; width?: number; height?: number } } | null)
373
385
  ?.getBoundingClientRect?.();
374
386
  const scrollRect = scrollBox?.getBoundingClientRect?.() as { x?: number; y?: number; top?: number; width?: number; height?: number } | undefined;
@@ -388,6 +400,7 @@ export function scrollElementIntoScrollBoxView(scrollBox: ScrollBoxRenderable |
388
400
  viewportHeight: scrollBox.viewportPx.height,
389
401
  elementTop,
390
402
  elementHeight: Math.max(nodeRect.height ?? 0, 1),
403
+ center: options.center,
391
404
  });
392
405
  if (nextScrollTop !== scrollBox.scrollTopPx) {
393
406
  scrollBox.scrollToPixels(nextScrollTop);
@@ -401,6 +414,66 @@ export function scrollElementIntoScrollBoxView(scrollBox: ScrollBoxRenderable |
401
414
  return true;
402
415
  }
403
416
 
417
+ /** Where a reader is in the list: at the bottom, or which message is at the top of the view and how far down. */
418
+ export interface ScrollPlace {
419
+ atBottom: boolean;
420
+ anchorId: string | null;
421
+ /** In px from the top of the view to the top of the anchor message. */
422
+ anchorOffsetPx: number;
423
+ }
424
+
425
+ function messageRect(node: unknown): { y: number; height: number } | null {
426
+ const rect = (node as { getBoundingClientRect?: () => { y?: number; top?: number; height?: number } } | null)
427
+ ?.getBoundingClientRect?.();
428
+ if (!rect) return null;
429
+ return { y: rect.y ?? rect.top ?? 0, height: rect.height ?? 0 };
430
+ }
431
+
432
+ /**
433
+ * The reader's place in a pixel-scrolled list, to put them back after the list is
434
+ * rebuilt. Null where the list has no pixel layout.
435
+ */
436
+ export function readScrollPlace(
437
+ scrollBox: ScrollBoxRenderable | null,
438
+ messages: ChatMessage[],
439
+ elements: Map<string, unknown>,
440
+ ): ScrollPlace | null {
441
+ const view = scrollBox?.getBoundingClientRect?.();
442
+ if (!scrollBox || !view || !hasPixelScrollMetrics(scrollBox)) return null;
443
+ if (isScrolledToBottom(scrollBox, true)) return { atBottom: true, anchorId: null, anchorOffsetPx: 0 };
444
+ // Rows run down the page in order, so the first with any part in view is found by halving.
445
+ let low = 0;
446
+ let high = messages.length - 1;
447
+ let found: { id: string; y: number } | null = null;
448
+ while (low <= high) {
449
+ const middle = (low + high) >> 1;
450
+ const message = messages[middle]!;
451
+ const rect = messageRect(elements.get(message.id));
452
+ if (!rect) return null;
453
+ if (rect.y + rect.height > view.y + 1) {
454
+ found = { id: message.id, y: rect.y };
455
+ high = middle - 1;
456
+ } else {
457
+ low = middle + 1;
458
+ }
459
+ }
460
+ return found ? { atBottom: false, anchorId: found.id, anchorOffsetPx: found.y - view.y } : null;
461
+ }
462
+
463
+ export function restoreScrollPlace(
464
+ scrollBox: ScrollBoxRenderable | null,
465
+ place: ScrollPlace,
466
+ elements: Map<string, unknown>,
467
+ ) {
468
+ const view = scrollBox?.getBoundingClientRect?.();
469
+ const rect = place.anchorId ? messageRect(elements.get(place.anchorId)) : null;
470
+ if (!scrollBox || !view || place.atBottom || !rect || typeof scrollBox.scrollTopPx !== "number") {
471
+ scrollToBottom(scrollBox, true);
472
+ return;
473
+ }
474
+ scrollToPosition(scrollBox, scrollBox.scrollTopPx + (rect.y - view.y) - place.anchorOffsetPx, true);
475
+ }
476
+
404
477
  export function getSelectedMessageScrollTop({
405
478
  scrollTop,
406
479
  viewportHeight,
@@ -0,0 +1,18 @@
1
+ import { Badge } from "../../../../components/ui";
2
+ import { Box } from "../../../../ui";
3
+
4
+ /** What the badge takes of a terminal line: the cell before it, then "AI" with a cell of padding either side. */
5
+ export const CHAT_AI_BADGE_WIDTH = 5;
6
+
7
+ /**
8
+ * "AI" and a cell of space before it, beside the name of a managed assistant.
9
+ * The neutral badge is the quietest the kit has; a selected row passes its own
10
+ * text color so the chip stays legible on the selection.
11
+ */
12
+ export function ChatAiBadge({ selectedColor }: { selectedColor?: string }) {
13
+ return (
14
+ <Box flexShrink={0} paddingLeft={1} data-gloom-role="chat-ai-badge">
15
+ <Badge label="AI" color={selectedColor} />
16
+ </Box>
17
+ );
18
+ }