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
@@ -0,0 +1,306 @@
1
+ import type { AppConfig } from "../types/config";
2
+ import type { InstrumentSearchResult } from "../types/instrument";
3
+ import type { TickerRecord, Watchlist } from "../types/ticker";
4
+ import { AmbiguousTickerError, resolveTickerSearch, type ResolvedTickerSearch } from "../tickers/search";
5
+ import { canonicalExchange, parsePublicTickerKey, publicTickerKey } from "../utils/exchanges";
6
+ import {
7
+ applyCollectionMembershipChange,
8
+ materializeResolvedTicker,
9
+ type SharedWorkflowDeps,
10
+ } from "../components/command-bar/workflow/tickers";
11
+ import {
12
+ AmbiguousCollectionTickerError,
13
+ resolveCollectionTicker,
14
+ } from "../components/command-bar/workflow/collection-ticker";
15
+ import type { RemoteChangePrompt } from "./types";
16
+
17
+ /**
18
+ * `watchlist.add` and `watchlist.remove`: one ticker on one of the person's
19
+ * own watchlists, through the same membership change the AW and RW commands
20
+ * make. A plan resolves the list and the listing without writing anything,
21
+ * so a caller can show it, ask, and then apply exactly that plan.
22
+ */
23
+
24
+ export type WatchlistAction = "add" | "remove";
25
+
26
+ /** A change the app will not make, in words a caller can repeat to the person. */
27
+ class WatchlistRefusal extends Error {
28
+ constructor(message: string) {
29
+ super(message);
30
+ this.name = "WatchlistRefusal";
31
+ }
32
+ }
33
+
34
+ export interface WatchlistChangeInput {
35
+ symbol: string;
36
+ exchange?: string;
37
+ watchlist?: string;
38
+ }
39
+
40
+ type ResolvedListing =
41
+ | { kind: "saved"; ticker: TickerRecord }
42
+ | { kind: "listing"; resolved: Extract<ResolvedTickerSearch, { kind: "provider" }> }
43
+ | { kind: "absent" };
44
+
45
+ export interface WatchlistChangePlan {
46
+ action: WatchlistAction;
47
+ watchlist: Pick<Watchlist, "id" | "name">;
48
+ symbol: string;
49
+ exchange: string;
50
+ name: string | null;
51
+ /** False when the ticker is already on the list (add) or not on it (remove). */
52
+ changes: boolean;
53
+ /** The change in one line, as the person approves it. */
54
+ summary: string;
55
+ /** Names this exact change: action, list and saved listing. */
56
+ confirmKey: string;
57
+ listing: ResolvedListing;
58
+ }
59
+
60
+ type WatchlistChangeOutcome = "added" | "removed" | "already-listed" | "not-listed" | "declined";
61
+
62
+ export interface WatchlistChangeResult {
63
+ changed: boolean;
64
+ outcome: WatchlistChangeOutcome;
65
+ message: string;
66
+ watchlist: Pick<Watchlist, "id" | "name">;
67
+ symbol: string;
68
+ exchange: string | null;
69
+ name: string | null;
70
+ }
71
+
72
+ function isTeamWatchlist(watchlist: Watchlist): boolean {
73
+ return !!watchlist.teamId || watchlist.id.startsWith("team:");
74
+ }
75
+
76
+ function personalWatchlists(config: AppConfig): Watchlist[] {
77
+ return config.watchlists.filter((watchlist) => !isTeamWatchlist(watchlist));
78
+ }
79
+
80
+ function listNames(watchlists: readonly Watchlist[]): string {
81
+ return watchlists.map((watchlist) => `"${watchlist.name}" (id ${watchlist.id})`).join(", ");
82
+ }
83
+
84
+ /**
85
+ * The personal watchlist a call names by id or name, or else the default
86
+ * one: the first personal watchlist, which a new profile calls Watchlist and
87
+ * onboarding fills. The confirmation names it, so a wrong guess is declined.
88
+ * Team watchlists are shared with everyone on the team and portfolios are
89
+ * not watchlists, so both are refused, as the list's own remove key does.
90
+ */
91
+ function resolveWatchlistTarget(config: AppConfig, requested: string | undefined): Watchlist {
92
+ const personal = personalWatchlists(config);
93
+ const raw = requested?.trim() ?? "";
94
+ if (!raw) {
95
+ if (personal[0]) return personal[0];
96
+ throw new WatchlistRefusal("There is no personal watchlist to change. Create one with New Watchlist first.");
97
+ }
98
+ const lower = raw.toLowerCase();
99
+ const matches = (entry: { id: string; name: string }) => entry.id.toLowerCase() === lower || entry.name.toLowerCase() === lower;
100
+ const watchlist = config.watchlists.find((entry) => entry.id === raw) ?? config.watchlists.find(matches);
101
+ if (watchlist) {
102
+ if (isTeamWatchlist(watchlist)) {
103
+ throw new WatchlistRefusal(`Refused: "${watchlist.name}" is a team watchlist, shared with everyone on the team. Only personal watchlists can be changed this way.`);
104
+ }
105
+ return watchlist;
106
+ }
107
+ const portfolio = config.portfolios.find((entry) => entry.id === raw) ?? config.portfolios.find(matches);
108
+ if (portfolio) {
109
+ const kind = portfolio.brokerId || portfolio.brokerInstanceId
110
+ ? "a broker portfolio, whose positions come from the broker"
111
+ : portfolio.teamId ? "a team portfolio" : "a portfolio";
112
+ throw new WatchlistRefusal(`Refused: "${portfolio.name}" is ${kind}, not a watchlist.`);
113
+ }
114
+ throw new WatchlistRefusal(personal.length > 0
115
+ ? `There is no watchlist "${raw}". Personal watchlists: ${listNames(personal)}.`
116
+ : `There is no watchlist "${raw}", and no personal watchlist at all.`);
117
+ }
118
+
119
+ function listingExchange(result: InstrumentSearchResult): string {
120
+ return result.exchange === "SMART" ? result.primaryExchange || result.exchange
121
+ : result.exchange || result.primaryExchange || "";
122
+ }
123
+
124
+ function listingLabel(symbol: string, exchange: string): string {
125
+ return exchange ? `${symbol} (${exchange})` : symbol;
126
+ }
127
+
128
+ async function resolveListing(
129
+ input: WatchlistChangeInput,
130
+ deps: SharedWorkflowDeps,
131
+ ): Promise<ResolvedTickerSearch | null> {
132
+ const symbol = input.symbol.trim().toUpperCase();
133
+ const exchange = input.exchange?.trim().toUpperCase();
134
+ if (!symbol) throw new WatchlistRefusal("symbol is required.");
135
+ const query = exchange ? `${parsePublicTickerKey(symbol).symbol}:${exchange}` : symbol;
136
+ try {
137
+ return await resolveTickerSearch({
138
+ query,
139
+ activeTicker: null,
140
+ tickers: deps.getState().tickers,
141
+ dataProvider: deps.dataProvider,
142
+ searchContext: { preferBroker: true, interactive: true },
143
+ });
144
+ } catch (error) {
145
+ if (error instanceof AmbiguousTickerError) {
146
+ throw new WatchlistRefusal(error.listings.length > 0
147
+ ? `${query} matches more than one listing: ${error.listings.slice(0, 6).join(", ")}. Pass exchange to pick one.`
148
+ : error.message);
149
+ }
150
+ throw error;
151
+ }
152
+ }
153
+
154
+ /** The saved record that owns this listing on the list, as the AW command picks it. */
155
+ function savedOwner(ticker: TickerRecord, deps: SharedWorkflowDeps, watchlistId: string): TickerRecord {
156
+ try {
157
+ return resolveCollectionTicker(ticker, deps.getState().tickers, "watchlist", watchlistId);
158
+ } catch (error) {
159
+ if (error instanceof AmbiguousCollectionTickerError) throw new WatchlistRefusal(error.message);
160
+ throw error;
161
+ }
162
+ }
163
+
164
+ /** What the call would change, resolved without writing anything. */
165
+ export async function planWatchlistChange(
166
+ action: WatchlistAction,
167
+ input: WatchlistChangeInput,
168
+ deps: SharedWorkflowDeps,
169
+ ): Promise<WatchlistChangePlan> {
170
+ const watchlist = resolveWatchlistTarget(deps.getState().config, input.watchlist);
171
+ const resolved = await resolveListing(input, deps);
172
+ let listing: ResolvedListing;
173
+ let symbol: string;
174
+ let exchange: string;
175
+ let name: string | null;
176
+ let key: string;
177
+ let member: boolean;
178
+ if (resolved?.kind === "local") {
179
+ const ticker = savedOwner(resolved.ticker, deps, watchlist.id);
180
+ listing = { kind: "saved", ticker };
181
+ symbol = parsePublicTickerKey(ticker.metadata.ticker).symbol;
182
+ exchange = canonicalExchange(ticker.metadata.exchange);
183
+ name = ticker.metadata.name && ticker.metadata.name !== ticker.metadata.ticker ? ticker.metadata.name : null;
184
+ key = ticker.metadata.ticker;
185
+ member = ticker.metadata.watchlists.includes(watchlist.id);
186
+ } else if (resolved?.kind === "provider") {
187
+ if (action === "add") {
188
+ listing = { kind: "listing", resolved };
189
+ } else {
190
+ listing = { kind: "absent" };
191
+ }
192
+ symbol = parsePublicTickerKey(resolved.symbol).symbol;
193
+ exchange = canonicalExchange(listingExchange(resolved.result));
194
+ name = resolved.result.name?.trim() || null;
195
+ key = publicTickerKey(resolved.symbol, listingExchange(resolved.result));
196
+ member = false;
197
+ } else {
198
+ if (action === "add") throw new WatchlistRefusal(`No listing found for ${input.symbol.trim().toUpperCase()}.`);
199
+ listing = { kind: "absent" };
200
+ symbol = parsePublicTickerKey(input.symbol.trim().toUpperCase()).symbol;
201
+ exchange = canonicalExchange(input.exchange);
202
+ name = null;
203
+ key = symbol;
204
+ member = false;
205
+ }
206
+ const label = listingLabel(symbol, exchange);
207
+ return {
208
+ action,
209
+ watchlist: { id: watchlist.id, name: watchlist.name },
210
+ symbol,
211
+ exchange,
212
+ name,
213
+ changes: action === "add" ? !member : member,
214
+ summary: action === "add" ? `Add ${label} to ${watchlist.name}` : `Remove ${label} from ${watchlist.name}`,
215
+ confirmKey: `${action}|${watchlist.id}|${key}`,
216
+ listing,
217
+ };
218
+ }
219
+
220
+ /** The dialog the app shows before it applies a plan. */
221
+ export function watchlistChangePrompt(plan: WatchlistChangePlan): RemoteChangePrompt {
222
+ return {
223
+ title: plan.action === "add"
224
+ ? `Add ${plan.symbol} to ${plan.watchlist.name}?`
225
+ : `Remove ${plan.symbol} from ${plan.watchlist.name}?`,
226
+ lines: watchlistChangeLines(plan),
227
+ confirmLabel: plan.action === "add" ? "Add" : "Remove",
228
+ destructive: plan.action === "remove",
229
+ };
230
+ }
231
+
232
+ function watchlistChangeLines(plan: WatchlistChangePlan): RemoteChangePrompt["lines"] {
233
+ return [
234
+ { label: "Watchlist", value: plan.watchlist.name },
235
+ { label: "Ticker", value: plan.symbol },
236
+ { label: "Exchange", value: plan.exchange || "not known" },
237
+ ...(plan.name ? [{ label: "Name", value: plan.name }] : []),
238
+ ];
239
+ }
240
+
241
+ /** What a dry run reports: the plan a caller can show, and the key it passes back once approved. */
242
+ export function describeWatchlistPlan(plan: WatchlistChangePlan) {
243
+ return {
244
+ dryRun: true,
245
+ action: plan.action,
246
+ watchlist: plan.watchlist,
247
+ symbol: plan.symbol,
248
+ exchange: plan.exchange || null,
249
+ name: plan.name,
250
+ changes: plan.changes,
251
+ summary: plan.changes ? plan.summary : unchangedMessage(plan),
252
+ lines: watchlistChangeLines(plan),
253
+ confirmKey: plan.confirmKey,
254
+ };
255
+ }
256
+
257
+ function result(plan: WatchlistChangePlan, outcome: WatchlistChangeOutcome, message: string, ticker?: TickerRecord): WatchlistChangeResult {
258
+ return {
259
+ changed: outcome === "added" || outcome === "removed",
260
+ outcome,
261
+ message,
262
+ watchlist: plan.watchlist,
263
+ symbol: ticker ? parsePublicTickerKey(ticker.metadata.ticker).symbol : plan.symbol,
264
+ exchange: (ticker ? canonicalExchange(ticker.metadata.exchange) : plan.exchange) || null,
265
+ name: plan.name,
266
+ };
267
+ }
268
+
269
+ function unchangedMessage(plan: WatchlistChangePlan): string {
270
+ const label = listingLabel(plan.symbol, plan.exchange);
271
+ return plan.action === "add"
272
+ ? `${label} is already on ${plan.watchlist.name}; nothing changed.`
273
+ : `${label} is not on ${plan.watchlist.name}; nothing changed.`;
274
+ }
275
+
276
+ export function unchangedWatchlistResult(plan: WatchlistChangePlan): WatchlistChangeResult {
277
+ return result(plan, plan.action === "add" ? "already-listed" : "not-listed", unchangedMessage(plan));
278
+ }
279
+
280
+ export function declinedWatchlistResult(plan: WatchlistChangePlan): WatchlistChangeResult {
281
+ return result(plan, "declined", `Declined in the app: ${plan.watchlist.name} is unchanged.`);
282
+ }
283
+
284
+ /**
285
+ * Writes an approved plan through the AW command's membership change. The
286
+ * list is checked again first: it may have been deleted or shared with a
287
+ * team while the person decided.
288
+ */
289
+ export async function applyWatchlistChange(
290
+ plan: WatchlistChangePlan,
291
+ deps: SharedWorkflowDeps,
292
+ ): Promise<WatchlistChangeResult> {
293
+ const watchlist = resolveWatchlistTarget(deps.getState().config, plan.watchlist.id);
294
+ if (watchlist.id !== plan.watchlist.id) throw new WatchlistRefusal(`${plan.watchlist.name} changed while the app asked; nothing changed.`);
295
+ if (plan.listing.kind === "absent") return unchangedWatchlistResult(plan);
296
+ const ticker = plan.listing.kind === "saved"
297
+ ? deps.getState().tickers.get(plan.listing.ticker.metadata.ticker) ?? plan.listing.ticker
298
+ : (await materializeResolvedTicker(plan.listing.resolved, deps)).ticker;
299
+ const owner = savedOwner(ticker, deps, watchlist.id);
300
+ const { changed, ticker: saved } = await applyCollectionMembershipChange(owner, "watchlist", plan.action, watchlist.id, deps);
301
+ if (!changed) return result(plan, plan.action === "add" ? "already-listed" : "not-listed", unchangedMessage(plan), saved);
302
+ const label = listingLabel(parsePublicTickerKey(saved.metadata.ticker).symbol, canonicalExchange(saved.metadata.exchange));
303
+ return plan.action === "add"
304
+ ? result(plan, "added", `Added ${label} to ${watchlist.name}.`, saved)
305
+ : result(plan, "removed", `Removed ${label} from ${watchlist.name}.`, saved);
306
+ }
@@ -20,7 +20,7 @@ import { browserRendererHost, browserUiHost } from "./ui-host";
20
20
  import { createBrowserDeepLinkBridge } from "./deeplink-bridge";
21
21
  import { initializeBrowserResearchActivity, recordResearchActivity } from "../../api-client/research-activity";
22
22
  import { flushPendingPersistence } from "../../state/persist-scheduler";
23
- import { loadOfficialPluginIds } from "../../plugins/builtin/plugin-marketplace/feed";
23
+ import { loadOfficialPluginIds } from "../../plugins/marketplace/feed";
24
24
  import { crashReportsEnabled, installCrashReporter, reportCrash } from "../../telemetry/crash-reports";
25
25
  import {
26
26
  browserDoNotTrack,
@@ -71,6 +71,9 @@ async function boot(): Promise<void> {
71
71
  if (document.visibilityState === "hidden") void flushPendingPersistence();
72
72
  });
73
73
  installBrowserFetchTransports();
74
+ // Read the saved Usage switch before any research activity or attribution.
75
+ const config = await loadConfig(BROWSER_DATA_DIR);
76
+ loadedConfig = config;
74
77
  initializeBrowserResearchActivity();
75
78
  installFocusScopeRelease();
76
79
  installDomMarketDataFrames();
@@ -84,8 +87,6 @@ async function boot(): Promise<void> {
84
87
  recordResearchActivity("workspace_opened");
85
88
  // Nothing was restored on a first visit, only the starter workspace shown.
86
89
  if (!hasSavedBrowserConfig()) recordRestoredFunctions([]);
87
- const config = await loadConfig(BROWSER_DATA_DIR);
88
- loadedConfig = config;
89
90
  applyLanguageFromConfig(config);
90
91
  const externalPlugins = await bundledPlugins;
91
92
  const deepLinkBridge = createBrowserDeepLinkBridge();
@@ -1,5 +1,5 @@
1
1
  import { tickerHasListingSuffix } from "../../sources/listing-symbols";
2
- import { parsePublicTickerKey, publicTickerKey } from "../../utils/exchanges";
2
+ import { isSharedExchangeCode, parsePublicTickerKey, publicTickerKey } from "../../utils/exchanges";
3
3
 
4
4
  export function researchEntryFromSearch(search: string): { symbol: string; tab: string } | null {
5
5
  const params = new URLSearchParams(search);
@@ -13,8 +13,10 @@ export function researchEntryFromSearch(search: string): { symbol: string; tab:
13
13
  if ([exchange, requested.exchange].some((venue) => venue && !/^[A-Z0-9][A-Z0-9 ._-]{0,31}$/.test(venue))) return null;
14
14
  // Carry a separate venue through the same listing-qualified resolver used by
15
15
  // search and deep links. An explicit symbol suffix/key remains authoritative.
16
+ // A code that names several venues (TSE: Tokyo or Toronto) stays as typed for
17
+ // the resolver to read as the one the symbol trades on.
16
18
  const target = exchange && !requested.exchange && !tickerHasListingSuffix(symbol)
17
- ? publicTickerKey(symbol, exchange)
19
+ ? isSharedExchangeCode(exchange) ? `${symbol}:${exchange}` : publicTickerKey(symbol, exchange)
18
20
  : symbol;
19
21
  const tab = params.get("tab") ?? "overview";
20
22
  return { symbol: target, tab: /^[a-z-]{1,40}$/.test(tab) ? tab : "overview" };
@@ -54,7 +54,7 @@ type ApiFetch = (request: Request) => Promise<Response>;
54
54
  const proxySessions = createProxySessionGate({ sessionUrl: `${API_ORIGIN}/auth/get-session` });
55
55
 
56
56
  export const SECURITY_HEADERS = {
57
- "content-security-policy": "default-src 'self'; base-uri 'none'; object-src 'none'; frame-ancestors 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; media-src 'self' https:; connect-src 'self' https://api.github.com https://api.fiscaldata.treasury.gov https://plugins.gloom.sh; form-action 'self'; upgrade-insecure-requests",
57
+ "content-security-policy": "default-src 'self'; base-uri 'none'; object-src 'none'; frame-ancestors 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; media-src 'self' https:; connect-src 'self' https://api.github.com https://api.fiscaldata.treasury.gov https://plugins.gloom.sh https://gloom.sh; form-action 'self'; upgrade-insecure-requests",
58
58
  "cross-origin-opener-policy": "same-origin",
59
59
  "cross-origin-resource-policy": "same-origin",
60
60
  "permissions-policy": "camera=(), geolocation=(), microphone=(), payment=(), usb=()",
@@ -7,7 +7,9 @@ export function useFrozenColumnInsets(enabled: boolean, scrollLeft: number, view
7
7
  useLayoutEffect(() => {
8
8
  const cells = ref.current?.children;
9
9
  if (!enabled || !cells?.length) {
10
- setInsets((current) => current.length ? [] : current);
10
+ // Most tables freeze nothing: leave their rows' state alone, since a
11
+ // state update from a layout effect costs every render a second commit.
12
+ if (insets.length) setInsets([]);
11
13
  return;
12
14
  }
13
15
  const first = cells[0]!.getBoundingClientRect();
@@ -26,6 +26,7 @@ import {
26
26
  hasMeaningfulTableHorizontalOverflow,
27
27
  } from "../../../components/ui/table-layout";
28
28
  import { WEB_CELL_HEIGHT, WEB_CELL_WIDTH } from "../../../theme/font-scale";
29
+ import { isLiveResizing, onLiveResizeEnd } from "../../../ui/live-resize";
29
30
  import { useScrollbarActivity } from "../scrollbar-activity";
30
31
  import { useHorizontalScrollEdges } from "../host/overflow-fade";
31
32
  import {
@@ -214,12 +215,29 @@ export function WebDataTable<T, C extends DataTableColumn = DataTableColumn>({
214
215
  scheduleVisibleRangeMeasure();
215
216
  const element = bodyElementRef.current;
216
217
  if (!element || typeof ResizeObserver === "undefined") return;
217
- const observer = new ResizeObserver(() => {
218
+ const measure = () => {
218
219
  scheduleViewportWidthMeasure();
219
220
  scheduleVisibleRangeMeasure();
221
+ };
222
+ // While the pointer resizes the pane, its columns stretch by CSS and the
223
+ // pane renders the table at the new size a few times a second; measuring
224
+ // on every cell the body crosses would render it once per cell. It is
225
+ // measured once the resize ends, a frame after its layout lands.
226
+ let measureAfterResize = false;
227
+ const observer = new ResizeObserver(() => {
228
+ if (isLiveResizing()) measureAfterResize = true;
229
+ else measure();
230
+ });
231
+ const stopListening = onLiveResizeEnd(() => {
232
+ if (!measureAfterResize) return;
233
+ measureAfterResize = false;
234
+ measure();
220
235
  });
221
236
  observer.observe(element);
222
- return () => observer.disconnect();
237
+ return () => {
238
+ observer.disconnect();
239
+ stopListening();
240
+ };
223
241
  }, [measureViewportWidth, scheduleViewportWidthMeasure, scheduleVisibleRangeMeasure]);
224
242
 
225
243
  useEffect(() => {
@@ -310,8 +328,9 @@ export function WebDataTable<T, C extends DataTableColumn = DataTableColumn>({
310
328
  const next = frozenCell && body
311
329
  ? Math.max(0, frozenCell.getBoundingClientRect().right - body.getBoundingClientRect().left + columnGap * WEB_CELL_WIDTH)
312
330
  : 0;
313
- setFrozenEdgePx((current) => current === next ? current : next);
314
- }, [columnGap, columns, freezeFirstColumn, overflowEdges.start, viewportWidth]);
331
+ // Set only on a change: a state update from a layout effect costs the render a second commit.
332
+ if (next !== frozenEdgePx) setFrozenEdgePx(next);
333
+ }, [columnGap, columns, freezeFirstColumn, frozenEdgePx, overflowEdges.start, viewportWidth]);
315
334
 
316
335
  const rootStyle: CSSProperties = {
317
336
  position: "relative",
@@ -323,6 +342,12 @@ export function WebDataTable<T, C extends DataTableColumn = DataTableColumn>({
323
342
  minHeight: 0,
324
343
  backgroundColor: CSS_BG,
325
344
  overflow: "hidden",
345
+ // Its width comes from where it sits, never from its columns. When the
346
+ // columns overflow, the content is laid out at their full width; in a box
347
+ // that sizes to its content (a pane's side beside a sidebar), that widened
348
+ // the box until they fit, which turned the scrolling off and narrowed it
349
+ // again: a measure and a render every frame, at rest.
350
+ contain: "inline-size",
326
351
  };
327
352
  const bodyScrollerStyle: CSSProperties = {
328
353
  width: "100%",
@@ -386,7 +411,7 @@ export function WebDataTable<T, C extends DataTableColumn = DataTableColumn>({
386
411
  columns={columns}
387
412
  freezeFirstColumn={freezeFirstColumn}
388
413
  scrollLeft={frozenScrollLeft}
389
- viewportWidth={viewportWidth}
414
+ viewportWidth={freezeFirstColumn ? viewportWidth : 0}
390
415
  columnGap={columnGap}
391
416
  horizontalPadding={horizontalPadding}
392
417
  focusPane={focusPane}
@@ -433,7 +458,9 @@ export function WebDataTable<T, C extends DataTableColumn = DataTableColumn>({
433
458
  columns={columns}
434
459
  freezeFirstColumn={freezeFirstColumn}
435
460
  scrollLeft={frozenScrollLeft}
436
- viewportWidth={viewportWidth}
461
+ // Only a frozen first column places itself by it: every
462
+ // other row stays memoized when the viewport changes width.
463
+ viewportWidth={freezeFirstColumn ? viewportWidth : 0}
437
464
  columnGap={columnGap}
438
465
  horizontalPadding={horizontalPadding}
439
466
  focusPane={focusPane}
@@ -267,6 +267,7 @@ function WebDataTableRowInner<
267
267
  if (sectionHeader) {
268
268
  // A header the cursor can land on (a collapsible group) shows it like a row.
269
269
  const headerColor = sectionHeader.color ?? (selected ? CSS_SELECTED_TEXT : CSS_TEXT_BRIGHT);
270
+ const action = sectionHeader.action;
270
271
  return (
271
272
  <div
272
273
  key={itemKey}
@@ -298,12 +299,37 @@ function WebDataTableRowInner<
298
299
  display: "flex",
299
300
  alignItems: "center",
300
301
  gap: 4,
302
+ // Kept to the columns in view, so a table wider than its pane does not push the action out of sight.
303
+ ...(action && viewportWidth > 0 ? { maxWidth: Math.max(0, viewportWidth * WEB_CELL_WIDTH - inlinePaddingPx(horizontalPadding) * 2) } : {}),
301
304
  }}
302
305
  >
303
306
  {sectionHeader.expanded !== undefined && (
304
307
  <DisclosureMarker expanded={sectionHeader.expanded} color={headerColor} />
305
308
  )}
306
- {sectionHeader.text}
309
+ {action ? (
310
+ <>
311
+ <span style={{ flex: "0 1 auto", minWidth: 0, overflow: "hidden", textOverflow: "ellipsis" }}>{sectionHeader.text}</span>
312
+ <button
313
+ type="button"
314
+ data-gloom-role="data-table-section-action"
315
+ title={action.title ?? action.label}
316
+ aria-haspopup="dialog"
317
+ style={{ color: selected ? CSS_SELECTED_TEXT : CSS_TEXT }}
318
+ onMouseDown={(event) => {
319
+ // The action, not the header's own press (a group's collapse).
320
+ event.stopPropagation();
321
+ focusPane();
322
+ }}
323
+ onClick={(event) => {
324
+ event.stopPropagation();
325
+ action.onPress();
326
+ }}
327
+ >
328
+ {action.label}
329
+ <WebIcon name="chevron-down" size={9} />
330
+ </button>
331
+ </>
332
+ ) : sectionHeader.text}
307
333
  </div>
308
334
  </div>
309
335
  );
@@ -355,6 +381,8 @@ function WebDataTableRowInner<
355
381
  data-gloom-role="data-table-cell"
356
382
  // The instant behind a shortened time ("Wed 11:27"), so a rendered-view report can print it whole.
357
383
  data-gloom-cell-instant={cell.value instanceof Date && Number.isFinite(cell.value.getTime()) ? cell.value.toISOString() : undefined}
384
+ // The full-precision number behind a rounded cell (a trade of -9.4596 for -9.45963753), for the same reports.
385
+ data-gloom-cell-value={typeof cell.value === "number" && Number.isFinite(cell.value) ? String(cell.value) : undefined}
358
386
  style={{
359
387
  minWidth: 0,
360
388
  position: freezeFirstColumn && columnIndex === 0 ? "sticky" : undefined,
@@ -365,6 +393,7 @@ function WebDataTableRowInner<
365
393
  boxSizing: "border-box",
366
394
  height: WEB_CELL_HEIGHT,
367
395
  overflow: "hidden",
396
+ cursor: cell.onMouseDown ? "pointer" : undefined,
368
397
  backgroundColor: cell.backgroundColor ?? rowBg,
369
398
  boxShadow: freezeFirstColumn && columnIndex === 0 ? `-${inlinePaddingPx(horizontalPadding)}px 0 0 ${cell.backgroundColor ?? rowBg}, ${columnGap * WEB_CELL_WIDTH}px 0 0 ${cell.backgroundColor ?? rowBg}` : undefined,
370
399
  }}
@@ -25,12 +25,74 @@ export function controlBorderColor(focused = false, active = false, palette: The
25
25
  return panelBorder(palette);
26
26
  }
27
27
 
28
+ function activeHalo(palette: ThemeColors): string {
29
+ return `0 0 0 1px ${blendHex(palette.bg, palette.borderFocused, 0.18)}`;
30
+ }
31
+
28
32
  export function controlShadow(active = false, palette: ThemeColors = colors): string {
29
33
  return active
30
- ? `0 0 0 1px ${blendHex(palette.bg, palette.borderFocused, 0.18)}, inset 0 1px 0 ${blendHex(palette.bg, palette.textBright, 0.06)}`
34
+ ? `${activeHalo(palette)}, inset 0 1px 0 ${blendHex(palette.bg, palette.textBright, 0.06)}`
31
35
  : `inset 0 1px 0 ${blendHex(palette.bg, palette.textBright, 0.04)}`;
32
36
  }
33
37
 
38
+ const WHITE = "#ffffff";
39
+ const BLACK = "#000000";
40
+
41
+ function withAlpha(hex: string, alpha: number): string {
42
+ return `${hex}${Math.round(alpha * 255).toString(16).padStart(2, "0")}`;
43
+ }
44
+
45
+ /** How far a raised button's tones move from its fill, toward white at the top and black below. */
46
+ const SOLID_RELIEF = { light: 0.12, shade: 0.06, edge: 0.18, shadow: 0.3 };
47
+ const SURFACE_RELIEF = { light: 0.05, shade: 0.03, edge: 0.08, shadow: 0.14 };
48
+
49
+ interface ButtonRelief {
50
+ backgroundImage?: string;
51
+ boxShadow: string;
52
+ /** Replaces the border colour, so a solid fill runs to its edge. */
53
+ borderColor?: string;
54
+ /** What the button shows while it is held down. */
55
+ pressedImage?: string;
56
+ pressedShadow?: string;
57
+ }
58
+
59
+ /**
60
+ * Light from above, built from the button's own fill so it reads the same on
61
+ * any surface and in every theme: a little lighter at the top, a little darker
62
+ * toward the bottom, a darker band on the bottom edge and a soft shadow under
63
+ * it. Nothing draws a line along the top edge. Held down, the light flips and
64
+ * the shadow goes, so the button sinks.
65
+ */
66
+ function raisedRelief(fill: string, tone: typeof SOLID_RELIEF, ring?: string): ButtonRelief {
67
+ const shade = blendHex(fill, BLACK, tone.shade);
68
+ const edge = blendHex(fill, BLACK, tone.edge);
69
+ const drop = `0 1px 2px ${withAlpha(blendHex(fill, BLACK, 0.75), tone.shadow)}`;
70
+ return {
71
+ backgroundImage: `linear-gradient(${blendHex(fill, WHITE, tone.light)}, ${shade} calc(100% - 1px), ${edge} calc(100% - 1px))`,
72
+ boxShadow: ring ? `${ring}, ${drop}` : drop,
73
+ pressedImage: `linear-gradient(${shade}, ${fill})`,
74
+ pressedShadow: ring ?? "none",
75
+ };
76
+ }
77
+
78
+ /**
79
+ * A button's relief. Primary, danger and a selected button are raised from
80
+ * their fill; a secondary one gets the same light, fainter. Ghost and plain
81
+ * buttons have no fill to light and stay flat, and so does a disabled one.
82
+ */
83
+ export function buttonRelief(
84
+ props: Pick<ButtonProps, "variant" | "active" | "disabled">,
85
+ palette: ThemeColors = colors,
86
+ ): ButtonRelief {
87
+ if (props.variant === "plain" || props.variant === "ghost" || props.disabled) return { boxShadow: "none" };
88
+ const fill = buttonPalette(props, palette).bg;
89
+ if (props.active) return raisedRelief(fill, SOLID_RELIEF, `0 0 0 1px ${withAlpha(palette.borderFocused, 0.18)}`);
90
+ if (props.variant === "primary" || props.variant === "danger") {
91
+ return { ...raisedRelief(fill, SOLID_RELIEF), borderColor: "transparent" };
92
+ }
93
+ return raisedRelief(fill, SURFACE_RELIEF);
94
+ }
95
+
34
96
  export function buttonPalette(
35
97
  props: Pick<ButtonProps, "variant" | "active" | "disabled">,
36
98
  palette: ThemeColors = colors,