gloomberb 0.18.4 → 0.19.0

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 (600) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/package.json +1 -1
  4. package/patches/electrobun@1.18.1.patch +169 -5
  5. package/src/account/auth-model.ts +7 -3
  6. package/src/api-client/auth.ts +9 -4
  7. package/src/api-client/catalysts.ts +2 -1
  8. package/src/api-client/cot.ts +6 -2
  9. package/src/api-client/credit-documents.ts +6 -0
  10. package/src/api-client/data.ts +31 -6
  11. package/src/api-client/equity-screener.ts +24 -0
  12. package/src/api-client/fund-facts.ts +45 -4
  13. package/src/api-client/index.ts +171 -11
  14. package/src/api-client/live-scan.ts +91 -0
  15. package/src/api-client/market-discovery.ts +10 -0
  16. package/src/api-client/market-movers.ts +7 -0
  17. package/src/api-client/members.ts +13 -1
  18. package/src/api-client/perps.ts +43 -0
  19. package/src/api-client/request.ts +222 -41
  20. package/src/api-client/research-activity.ts +6 -12
  21. package/src/api-client/types.ts +74 -0
  22. package/src/app/keybindings/index.ts +3 -0
  23. package/src/app/keybindings/labels.ts +18 -1
  24. package/src/app/keybindings/resolve.ts +14 -0
  25. package/src/app/pane-runtime/plugin-bindings.ts +9 -5
  26. package/src/app/runtime/broker-import.ts +42 -27
  27. package/src/app/runtime/plugin-bindings.ts +73 -56
  28. package/src/architecture/core-builtin-allowlist.json +1 -1
  29. package/src/architecture/pane-tabs-allowlist.json +3 -0
  30. package/src/architecture/ttl-caches-allowlist.json +19 -0
  31. package/src/brokers/sync-broker-instance.ts +2 -8
  32. package/src/capabilities/chart-series.ts +1 -1
  33. package/src/cli/commands/crypto-hints.ts +40 -24
  34. package/src/cli/commands/fred-series.ts +5 -0
  35. package/src/cli/commands/keybindings.ts +23 -0
  36. package/src/cli/commands/market.ts +138 -46
  37. package/src/cli/commands/options-chain.ts +107 -10
  38. package/src/cli/commands/options-leaps.ts +9 -3
  39. package/src/cli/commands/overview.ts +176 -39
  40. package/src/cli/commands/search.ts +39 -3
  41. package/src/cli/commands/themes.ts +11 -2
  42. package/src/cli/commands/ticker.ts +57 -35
  43. package/src/cli/company-name-hint.ts +41 -0
  44. package/src/cli/earnings-calendar.ts +1 -1
  45. package/src/cli/errors.ts +10 -2
  46. package/src/cli/export-source.ts +29 -1
  47. package/src/cli/glossary.ts +73 -1
  48. package/src/cli/history-rows.ts +87 -16
  49. package/src/cli/index.ts +2 -0
  50. package/src/cli/known-gaps.ts +5 -2
  51. package/src/cli/listing-arg.ts +195 -56
  52. package/src/cli/output-file.ts +68 -0
  53. package/src/cli/pane-functions/capabilities.ts +3 -0
  54. package/src/cli/pane-functions/catalog.ts +80 -7
  55. package/src/cli/pane-functions/dom.ts +13 -3
  56. package/src/cli/pane-functions/freshness.ts +111 -16
  57. package/src/cli/pane-functions/function-help.ts +23 -13
  58. package/src/cli/pane-functions/headless.ts +56 -12
  59. package/src/cli/pane-functions/index.ts +58 -16
  60. package/src/cli/pane-functions/market-session.ts +81 -9
  61. package/src/cli/pane-functions/options.ts +19 -1
  62. package/src/cli/pane-functions/report.ts +5 -1
  63. package/src/cli/pane-functions/resolver.ts +35 -8
  64. package/src/cli/pane-functions/screenshot-assessment.ts +6 -4
  65. package/src/cli/pane-functions/screenshot-types.ts +5 -0
  66. package/src/cli/quote-answer.ts +30 -13
  67. package/src/cli/report-tables.ts +18 -7
  68. package/src/cli/restore-plugins.ts +13 -1
  69. package/src/cli/result.ts +57 -5
  70. package/src/cli/ticker-resolution.ts +3 -2
  71. package/src/components/chart/composite/composite-chart.tsx +26 -4
  72. package/src/components/chart/composite/format.ts +27 -0
  73. package/src/components/chart/composite/interactions.ts +6 -0
  74. package/src/components/chart/composite/legend.tsx +45 -7
  75. package/src/components/chart/composite/levels.ts +2 -0
  76. package/src/components/chart/composite/panel-gestures.ts +33 -0
  77. package/src/components/chart/composite/panel-series.ts +1 -0
  78. package/src/components/chart/composite/panel-surface.tsx +61 -5
  79. package/src/components/chart/composite/range-statistics.ts +62 -0
  80. package/src/components/chart/composite/rasterizer.ts +24 -13
  81. package/src/components/chart/composite/scene.ts +46 -7
  82. package/src/components/chart/composite/series-axis-tags.tsx +16 -9
  83. package/src/components/chart/composite/series-cues.ts +14 -0
  84. package/src/components/chart/composite/text-renderer.ts +9 -2
  85. package/src/components/chart/composite/tool-catalog.ts +36 -0
  86. package/src/components/chart/composite/tools.ts +203 -44
  87. package/src/components/chart/composite/types.ts +4 -0
  88. package/src/components/chart/composite/use-composite-chart-keyboard.ts +11 -4
  89. package/src/components/command-bar/assist/inventory.ts +2 -1
  90. package/src/components/command-bar/commands/direct/index.ts +28 -13
  91. package/src/components/command-bar/pane-templates/items.ts +3 -2
  92. package/src/components/command-bar/panel/prompt-binding.ts +0 -8
  93. package/src/components/command-bar/workflow/alert.ts +1 -1
  94. package/src/components/command-bar/workflow/collection-actions.ts +3 -3
  95. package/src/components/layout/header.tsx +26 -40
  96. package/src/components/layout/pane/footer/index.tsx +1 -0
  97. package/src/components/layout/pane/footer/model.ts +27 -0
  98. package/src/components/onboarding/onboarding-frame.tsx +1 -1
  99. package/src/components/onboarding/onboarding-wizard.tsx +4 -1
  100. package/src/components/onboarding/portfolio-step/positions-panel.tsx +14 -9
  101. package/src/components/onboarding/wizard-broker-sync.ts +0 -1
  102. package/src/components/onboarding/wizard-positions.ts +3 -3
  103. package/src/components/ticker/list-table-view.tsx +4 -1
  104. package/src/components/ui/choice-dialog.tsx +23 -18
  105. package/src/components/ui/choice-groups.ts +18 -0
  106. package/src/components/ui/data-table/opentui/index.tsx +9 -7
  107. package/src/components/ui/data-table/opentui/model.ts +26 -1
  108. package/src/components/ui/data-table/types.ts +2 -0
  109. package/src/components/ui/display.tsx +5 -1
  110. package/src/components/ui/list-view.tsx +8 -4
  111. package/src/components/ui/query-bar-keys.tsx +2 -0
  112. package/src/components/ui/query-bar.tsx +1 -0
  113. package/src/components/ui/select-button.tsx +5 -1
  114. package/src/components/ui/select-field.tsx +1 -0
  115. package/src/components/ui/table-layout.ts +8 -5
  116. package/src/core/app-runtime.ts +2 -0
  117. package/src/core/app-services.ts +2 -2
  118. package/src/core/state/app/layout.ts +2 -0
  119. package/src/core/state/app/state.ts +9 -0
  120. package/src/core/state/app/types.ts +3 -0
  121. package/src/data/config/chart-settings.ts +1 -1
  122. package/src/data/json-ticker-repository.ts +17 -8
  123. package/src/data/saved-copies.ts +55 -16
  124. package/src/data/ticker-repository.ts +16 -9
  125. package/src/data/ticker-writes.ts +81 -0
  126. package/src/data/ttl-cache.ts +165 -0
  127. package/src/docs/snapshot.json +427 -216
  128. package/src/i18n/es.ts +19 -3
  129. package/src/i18n/ja.ts +19 -3
  130. package/src/i18n/ko.ts +19 -3
  131. package/src/i18n/zh-cn.ts +19 -3
  132. package/src/i18n/zh-tw.ts +19 -3
  133. package/src/market-data/coordinator/financials.ts +10 -2
  134. package/src/market-data/coordinator/index.ts +3 -1
  135. package/src/market-data/coordinator/quotes.ts +4 -2
  136. package/src/market-data/depositary-pair.ts +2 -2
  137. package/src/market-data/fund-facts.ts +50 -0
  138. package/src/market-data/market/change-basis.ts +48 -7
  139. package/src/market-data/market/dated-previous-close.ts +203 -0
  140. package/src/market-data/market/format.ts +25 -0
  141. package/src/market-data/market/freshness.ts +2 -1
  142. package/src/market-data/market/futures-week.ts +68 -0
  143. package/src/market-data/market/status.ts +16 -4
  144. package/src/market-data/options-alternatives.ts +141 -4
  145. package/src/market-data/quotes/contributions.ts +20 -2
  146. package/src/market-data/quotes/resolution.ts +3 -0
  147. package/src/market-data/selectors.ts +3 -0
  148. package/src/news/aggregator.ts +113 -9
  149. package/src/news/cloud-session.ts +21 -0
  150. package/src/news/hooks.ts +1 -0
  151. package/src/news/news-model.ts +1 -0
  152. package/src/news/types.ts +11 -0
  153. package/src/notifications/notification-log.ts +6 -4
  154. package/src/plugins/builtin/alerts/alert-engine.ts +25 -2
  155. package/src/plugins/builtin/alerts/alert-log.ts +33 -0
  156. package/src/plugins/builtin/alerts/calendar-events.ts +57 -6
  157. package/src/plugins/builtin/alerts/cli-forms.ts +216 -0
  158. package/src/plugins/builtin/alerts/cli.ts +380 -82
  159. package/src/plugins/builtin/alerts/command.ts +31 -0
  160. package/src/plugins/builtin/alerts/constants.ts +1 -1
  161. package/src/plugins/builtin/alerts/events-pane.tsx +19 -4
  162. package/src/plugins/builtin/alerts/fired-log.ts +113 -8
  163. package/src/plugins/builtin/alerts/format.ts +80 -4
  164. package/src/plugins/builtin/alerts/headless.ts +30 -7
  165. package/src/plugins/builtin/alerts/history-rows.ts +7 -3
  166. package/src/plugins/builtin/alerts/history.ts +2 -0
  167. package/src/plugins/builtin/alerts/index.tsx +135 -22
  168. package/src/plugins/builtin/alerts/live.ts +3 -3
  169. package/src/plugins/builtin/alerts/metric-command.ts +134 -0
  170. package/src/plugins/builtin/alerts/metric-data.ts +111 -0
  171. package/src/plugins/builtin/alerts/metric-model.ts +324 -0
  172. package/src/plugins/builtin/alerts/metric-parity-fixture.json +725 -0
  173. package/src/plugins/builtin/alerts/pane.tsx +90 -39
  174. package/src/plugins/builtin/alerts/quotes.ts +6 -0
  175. package/src/plugins/builtin/alerts/storage.ts +37 -10
  176. package/src/plugins/builtin/alerts/types.ts +7 -0
  177. package/src/plugins/builtin/analytics/index.tsx +2 -1
  178. package/src/plugins/builtin/analytics/risk-client.ts +16 -5
  179. package/src/plugins/builtin/analytics/risk-fx.ts +70 -15
  180. package/src/plugins/builtin/analytics/risk-headless.ts +27 -0
  181. package/src/plugins/builtin/analytics/risk-model.ts +55 -9
  182. package/src/plugins/builtin/analytics/risk-pane.tsx +8 -2
  183. package/src/plugins/builtin/attention/index.tsx +2 -1
  184. package/src/plugins/builtin/attention/listing.ts +14 -0
  185. package/src/plugins/builtin/backtest/headless.ts +10 -5
  186. package/src/plugins/builtin/backtest/pane.tsx +9 -4
  187. package/src/plugins/builtin/backtest/presets.ts +29 -3
  188. package/src/plugins/builtin/broker-manager/index.tsx +10 -5
  189. package/src/plugins/builtin/broker-manager/model.ts +6 -1
  190. package/src/plugins/builtin/broker-trading/controller.ts +22 -12
  191. package/src/plugins/builtin/broker-trading/index.tsx +13 -1
  192. package/src/plugins/builtin/broker-trading/order-feed.ts +9 -4
  193. package/src/plugins/builtin/broker-trading/pane.tsx +1 -1
  194. package/src/plugins/builtin/buildout/cells.tsx +12 -4
  195. package/src/plugins/builtin/buildout/format.ts +38 -0
  196. package/src/plugins/builtin/buildout/model/normalizers.ts +36 -1
  197. package/src/plugins/builtin/buildout/pane/index.tsx +4 -1
  198. package/src/plugins/builtin/buildout/table-model.ts +23 -2
  199. package/src/plugins/builtin/builtin-plugin-meta.ts +7 -3
  200. package/src/plugins/builtin/catalysts/model.ts +2 -1
  201. package/src/plugins/builtin/changelog/index.tsx +9 -6
  202. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +6 -1
  203. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +1 -1
  204. package/src/plugins/builtin/chart-composer/cli-options.ts +9 -5
  205. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +12 -2
  206. package/src/plugins/builtin/chart-composer/editor/controller.ts +4 -2
  207. package/src/plugins/builtin/chart-composer/editor/model.ts +2 -0
  208. package/src/plugins/builtin/chart-composer/editor.tsx +7 -5
  209. package/src/plugins/builtin/chart-composer/formula.ts +71 -18
  210. package/src/plugins/builtin/chart-composer/headless-schema.ts +21 -4
  211. package/src/plugins/builtin/chart-composer/headless.ts +19 -3
  212. package/src/plugins/builtin/chart-composer/index.tsx +1 -1
  213. package/src/plugins/builtin/chart-composer/pane.tsx +53 -9
  214. package/src/plugins/builtin/chart-composer/presets.ts +50 -15
  215. package/src/plugins/builtin/chart-composer/quick-add.tsx +40 -25
  216. package/src/plugins/builtin/chart-composer/session-history.ts +18 -9
  217. package/src/plugins/builtin/chart-composer/settings.ts +27 -0
  218. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +40 -26
  219. package/src/plugins/builtin/chat/content/command-suggestions.ts +93 -0
  220. package/src/plugins/builtin/chat/content/composer.tsx +13 -6
  221. package/src/plugins/builtin/chat/content/footer.tsx +6 -3
  222. package/src/plugins/builtin/chat/content/index.tsx +50 -21
  223. package/src/plugins/builtin/chat/content/open-targets.ts +14 -3
  224. package/src/plugins/builtin/chat/controller/session-runtime.ts +4 -2
  225. package/src/plugins/builtin/chat/index.tsx +23 -0
  226. package/src/plugins/builtin/chat/message/desktop.tsx +1 -0
  227. package/src/plugins/builtin/chat/message/inline-tokens.tsx +23 -0
  228. package/src/plugins/builtin/chat/message/pane-chip.tsx +50 -20
  229. package/src/plugins/builtin/chat/pane-links/commands.ts +271 -0
  230. package/src/plugins/builtin/chat/pane-links/model.ts +12 -3
  231. package/src/plugins/builtin/chat/pane-links/open.ts +8 -1
  232. package/src/plugins/builtin/chat/unread-inbox-pane.tsx +10 -1
  233. package/src/plugins/builtin/clinical-trials/model.ts +0 -9
  234. package/src/plugins/builtin/clinical-trials/pane.tsx +15 -22
  235. package/src/plugins/builtin/clinical-trials/sponsor-tickers.ts +8 -6
  236. package/src/plugins/builtin/cloud/askg/manifest.ts +2 -0
  237. package/src/plugins/builtin/cloud/plugin.tsx +1 -1
  238. package/src/plugins/builtin/company-attention/building.tsx +5 -1
  239. package/src/plugins/builtin/company-attention/client.ts +8 -9
  240. package/src/plugins/builtin/company-attention/evidence.ts +4 -1
  241. package/src/plugins/builtin/company-attention/moves.tsx +5 -1
  242. package/src/plugins/builtin/company-attention/pane.tsx +9 -2
  243. package/src/plugins/builtin/company-attention/signals.tsx +5 -1
  244. package/src/plugins/builtin/correlation/headless.ts +13 -5
  245. package/src/plugins/builtin/correlation/history.ts +22 -0
  246. package/src/plugins/builtin/cot/client.ts +22 -18
  247. package/src/plugins/builtin/cot/headless.ts +15 -10
  248. package/src/plugins/builtin/cot/model.ts +14 -1
  249. package/src/plugins/builtin/cot/pane.tsx +22 -14
  250. package/src/plugins/builtin/credit-boards/client.ts +6 -10
  251. package/src/plugins/builtin/credit-conditions/headless.ts +8 -2
  252. package/src/plugins/builtin/credit-conditions/index.tsx +5 -1
  253. package/src/plugins/builtin/credit-conditions/model.ts +4 -0
  254. package/src/plugins/builtin/credit-conditions/series.ts +3 -1
  255. package/src/plugins/builtin/credit-documents/detail.tsx +2 -2
  256. package/src/plugins/builtin/credit-documents/export.ts +173 -0
  257. package/src/plugins/builtin/credit-documents/headless.ts +7 -7
  258. package/src/plugins/builtin/credit-documents/model.ts +104 -14
  259. package/src/plugins/builtin/credit-documents/pane.tsx +12 -5
  260. package/src/plugins/builtin/custom-view/sources.ts +2 -0
  261. package/src/plugins/builtin/dividend-yield/client.ts +131 -23
  262. package/src/plugins/builtin/dividend-yield/headless.ts +44 -16
  263. package/src/plugins/builtin/dividend-yield/model.ts +8 -5
  264. package/src/plugins/builtin/dividend-yield/pane.tsx +38 -13
  265. package/src/plugins/builtin/dividend-yield/ranking.ts +37 -14
  266. package/src/plugins/builtin/dividend-yield/types.ts +20 -2
  267. package/src/plugins/builtin/dividend-yield/view.ts +30 -2
  268. package/src/plugins/builtin/docs/targets.ts +5 -1
  269. package/src/plugins/builtin/earnings/board-model.ts +16 -15
  270. package/src/plugins/builtin/earnings/board.tsx +62 -71
  271. package/src/plugins/builtin/earnings/headless.ts +40 -4
  272. package/src/plugins/builtin/earnings/scope.ts +31 -43
  273. package/src/plugins/builtin/earnings-calls/calendar.tsx +2 -2
  274. package/src/plugins/builtin/earnings-calls/format.ts +31 -2
  275. package/src/plugins/builtin/earnings-calls/headless.ts +7 -2
  276. package/src/plugins/builtin/earnings-calls/model.ts +6 -1
  277. package/src/plugins/builtin/earnings-calls/pane.tsx +5 -4
  278. package/src/plugins/builtin/econ/calendar-model.ts +14 -9
  279. package/src/plugins/builtin/econ/figures.ts +72 -0
  280. package/src/plugins/builtin/econ/index.tsx +33 -3
  281. package/src/plugins/builtin/econ/types.ts +4 -0
  282. package/src/plugins/builtin/econ-statistics/defs.ts +6 -0
  283. package/src/plugins/builtin/econ-statistics/headless.ts +85 -35
  284. package/src/plugins/builtin/econ-statistics/stats.ts +37 -9
  285. package/src/plugins/builtin/econ-statistics/view.ts +3 -0
  286. package/src/plugins/builtin/equity-screener/categories.ts +179 -0
  287. package/src/plugins/builtin/equity-screener/client.ts +4 -2
  288. package/src/plugins/builtin/equity-screener/headless.ts +144 -13
  289. package/src/plugins/builtin/equity-screener/ideas.ts +49 -0
  290. package/src/plugins/builtin/equity-screener/model.ts +99 -10
  291. package/src/plugins/builtin/equity-screener/pane.tsx +70 -15
  292. package/src/plugins/builtin/exposure/charts.tsx +2 -2
  293. package/src/plugins/builtin/exposure/model.ts +13 -1
  294. package/src/plugins/builtin/exposure/pane.tsx +4 -4
  295. package/src/plugins/builtin/fixed-income/pane.tsx +2 -1
  296. package/src/plugins/builtin/futures/index.tsx +1 -0
  297. package/src/plugins/builtin/futures/model.ts +2 -1
  298. package/src/plugins/builtin/futures/table.tsx +2 -2
  299. package/src/plugins/builtin/futures/use-board-terms.ts +42 -28
  300. package/src/plugins/builtin/futures/use-front-returns.ts +45 -28
  301. package/src/plugins/builtin/fx-matrix/client.ts +11 -3
  302. package/src/plugins/builtin/fx-matrix/headless.ts +6 -3
  303. package/src/plugins/builtin/fx-matrix/index.tsx +16 -4
  304. package/src/plugins/builtin/fx-matrix/live-legs.ts +54 -3
  305. package/src/plugins/builtin/gpu/headless.ts +8 -2
  306. package/src/plugins/builtin/help/function-index.ts +4 -1
  307. package/src/plugins/builtin/help/index.tsx +1 -0
  308. package/src/plugins/builtin/help/keybindings-editor.tsx +18 -14
  309. package/src/plugins/builtin/help/shortcut-model.ts +1 -1
  310. package/src/plugins/builtin/holders/fund-holders.ts +51 -0
  311. package/src/plugins/builtin/holders/headless.ts +18 -1
  312. package/src/plugins/builtin/iv-history/client.ts +52 -11
  313. package/src/plugins/builtin/iv-history/format.ts +36 -23
  314. package/src/plugins/builtin/iv-history/headless.ts +36 -18
  315. package/src/plugins/builtin/iv-history/index.tsx +2 -2
  316. package/src/plugins/builtin/iv-history/model.ts +163 -27
  317. package/src/plugins/builtin/iv-history/pane.tsx +10 -6
  318. package/src/plugins/builtin/iv-history/screen-pane.tsx +22 -15
  319. package/src/plugins/builtin/iv-history/universe.ts +5 -1
  320. package/src/plugins/builtin/jobs/client.ts +25 -29
  321. package/src/plugins/builtin/kelly-sizer/model.ts +12 -8
  322. package/src/plugins/builtin/kelly-sizer/pane.tsx +9 -9
  323. package/src/plugins/builtin/kelly-sizer/sections.tsx +19 -10
  324. package/src/plugins/builtin/kelly-sizer/types.ts +10 -4
  325. package/src/plugins/builtin/macro-day/pane.tsx +7 -5
  326. package/src/plugins/builtin/macro-day/release-table.ts +2 -2
  327. package/src/plugins/builtin/market-heatmap/data.ts +8 -33
  328. package/src/plugins/builtin/market-movers/client.ts +25 -7
  329. package/src/plugins/builtin/market-movers/footer.ts +2 -2
  330. package/src/plugins/builtin/market-movers/headless.ts +32 -12
  331. package/src/plugins/builtin/market-movers/index.tsx +26 -14
  332. package/src/plugins/builtin/market-movers/min-float.ts +74 -0
  333. package/src/plugins/builtin/market-movers/model.ts +4 -1
  334. package/src/plugins/builtin/market-movers/screener.ts +14 -0
  335. package/src/plugins/builtin/market-movers/session-body.tsx +13 -8
  336. package/src/plugins/builtin/market-movers/session-table.ts +4 -3
  337. package/src/plugins/builtin/market-movers/table.ts +17 -5
  338. package/src/plugins/builtin/members/breadth-pane.tsx +82 -0
  339. package/src/plugins/builtin/members/client.ts +19 -4
  340. package/src/plugins/builtin/members/headless.ts +20 -7
  341. package/src/plugins/builtin/members/index.tsx +9 -9
  342. package/src/plugins/builtin/members/model.ts +23 -4
  343. package/src/plugins/builtin/members/pane.tsx +25 -15
  344. package/src/plugins/builtin/news/index.tsx +1 -0
  345. package/src/plugins/builtin/news/wire/categories.ts +19 -3
  346. package/src/plugins/builtin/news/wire/industry-pane.tsx +1 -0
  347. package/src/plugins/builtin/news/wire/news/footer.ts +31 -5
  348. package/src/plugins/builtin/news/wire/news/preset-pane.tsx +6 -1
  349. package/src/plugins/builtin/news/wire/news/table.tsx +2 -2
  350. package/src/plugins/builtin/openfda/client.ts +14 -2
  351. package/src/plugins/builtin/openfda/index.tsx +3 -2
  352. package/src/plugins/builtin/openfda/model.ts +9 -0
  353. package/src/plugins/builtin/openfda/pane.tsx +42 -6
  354. package/src/plugins/builtin/options/analytics.ts +54 -6
  355. package/src/plugins/builtin/options/enrichment.ts +17 -5
  356. package/src/plugins/builtin/options/model-spot.ts +5 -2
  357. package/src/plugins/builtin/options/strike-window.ts +2 -1
  358. package/src/plugins/builtin/options/table.ts +6 -9
  359. package/src/plugins/builtin/options/types.ts +2 -0
  360. package/src/plugins/builtin/options/view.tsx +42 -12
  361. package/src/plugins/builtin/options-positioning/client.ts +30 -0
  362. package/src/plugins/builtin/options-positioning/headless.ts +74 -21
  363. package/src/plugins/builtin/options-positioning/index.tsx +4 -4
  364. package/src/plugins/builtin/options-positioning/model.ts +122 -14
  365. package/src/plugins/builtin/options-positioning/pane.tsx +87 -42
  366. package/src/plugins/builtin/options-scenario/client.ts +116 -47
  367. package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +142 -10
  368. package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +206 -55
  369. package/src/plugins/builtin/options-scenario/csp-screen.ts +63 -23
  370. package/src/plugins/builtin/options-scenario/csp.ts +8 -2
  371. package/src/plugins/builtin/options-scenario/index.tsx +9 -7
  372. package/src/plugins/builtin/options-scenario/strategy-screen.ts +532 -0
  373. package/src/plugins/builtin/pe-band/model.ts +12 -49
  374. package/src/plugins/builtin/perps/cascade-tabs.tsx +161 -0
  375. package/src/plugins/builtin/perps/cascade.ts +236 -0
  376. package/src/plugins/builtin/perps/client.ts +56 -2
  377. package/src/plugins/builtin/perps/freshness.ts +12 -10
  378. package/src/plugins/builtin/perps/headless.ts +65 -9
  379. package/src/plugins/builtin/perps/index.tsx +7 -5
  380. package/src/plugins/builtin/perps/live-rows.ts +10 -3
  381. package/src/plugins/builtin/perps/model.ts +18 -4
  382. package/src/plugins/builtin/perps/pane.tsx +32 -31
  383. package/src/plugins/builtin/perps/status-line.ts +25 -0
  384. package/src/plugins/builtin/plugin-module.ts +5 -1
  385. package/src/plugins/builtin/portfolio-list/cached-account.ts +3 -1
  386. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +2 -8
  387. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +4 -4
  388. package/src/plugins/builtin/portfolio-list/cli/render.ts +12 -7
  389. package/src/plugins/builtin/portfolio-list/headless.ts +1 -1
  390. package/src/plugins/builtin/portfolio-list/pane/futures-front.ts +40 -0
  391. package/src/plugins/builtin/portfolio-list/pane/index.tsx +4 -1
  392. package/src/plugins/builtin/portfolio-list/pane/streaming.ts +5 -2
  393. package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +3 -2
  394. package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +3 -1
  395. package/src/plugins/builtin/portfolio-list/summary/index.tsx +11 -8
  396. package/src/plugins/builtin/portfolio-list/table.tsx +11 -3
  397. package/src/plugins/builtin/primary-dealers/client.ts +13 -38
  398. package/src/plugins/builtin/rate-path/pane.tsx +2 -2
  399. package/src/plugins/builtin/realized-vol/index.tsx +2 -2
  400. package/src/plugins/builtin/realized-vol/pane.tsx +3 -3
  401. package/src/plugins/builtin/relative-rotation/client.ts +18 -4
  402. package/src/plugins/builtin/relative-rotation/headless.ts +3 -3
  403. package/src/plugins/builtin/relative-rotation/index.tsx +2 -1
  404. package/src/plugins/builtin/relative-rotation/model.ts +16 -40
  405. package/src/plugins/builtin/relative-rotation/pane.tsx +3 -2
  406. package/src/plugins/builtin/research/corporate-actions-pane.tsx +3 -2
  407. package/src/plugins/builtin/research/event-model.ts +10 -8
  408. package/src/plugins/builtin/research/headless.ts +1 -1
  409. package/src/plugins/builtin/research/relative-valuation-headless.ts +5 -1
  410. package/src/plugins/builtin/research/relative-valuation-model.ts +31 -3
  411. package/src/plugins/builtin/research/relative-valuation-pane.tsx +11 -9
  412. package/src/plugins/builtin/reverse-dcf/headless.ts +5 -3
  413. package/src/plugins/builtin/reverse-dcf/model.ts +61 -6
  414. package/src/plugins/builtin/reverse-dcf/pane.tsx +7 -4
  415. package/src/plugins/builtin/scanner/feed.ts +2 -2
  416. package/src/plugins/builtin/scanner/flow-model.ts +50 -4
  417. package/src/plugins/builtin/scanner/flow-pane.tsx +367 -65
  418. package/src/plugins/builtin/scanner/flow-session.ts +146 -0
  419. package/src/plugins/builtin/scanner/headless.ts +204 -35
  420. package/src/plugins/builtin/scanner/index.ts +40 -6
  421. package/src/plugins/builtin/scanner/live-condition-editor.tsx +222 -0
  422. package/src/plugins/builtin/scanner/live-feed.ts +168 -0
  423. package/src/plugins/builtin/scanner/live-headless.ts +138 -0
  424. package/src/plugins/builtin/scanner/live-model.ts +362 -0
  425. package/src/plugins/builtin/scanner/live-pane.tsx +677 -0
  426. package/src/plugins/builtin/scanner/live-track.ts +186 -0
  427. package/src/plugins/builtin/scanner/lock-note.ts +3 -2
  428. package/src/plugins/builtin/seasonality/headless.ts +10 -1
  429. package/src/plugins/builtin/sec/fund-facts-view.tsx +5 -2
  430. package/src/plugins/builtin/sec/fund-facts.ts +116 -34
  431. package/src/plugins/builtin/sec/headless.ts +2 -1
  432. package/src/plugins/builtin/series-inventory.ts +3 -0
  433. package/src/plugins/builtin/shared/cloud-resource.ts +3 -2
  434. package/src/plugins/builtin/shared/cloud-upgrade.ts +4 -3
  435. package/src/plugins/builtin/shared/earnings-calendar.ts +6 -2
  436. package/src/plugins/builtin/shared/earnings-report.ts +2 -2
  437. package/src/plugins/builtin/shared/job-posting.ts +1 -0
  438. package/src/plugins/builtin/shared/macro-releases.ts +65 -0
  439. package/src/plugins/builtin/shared/members-menu.tsx +3 -2
  440. package/src/plugins/builtin/shared/pro-lock-note.ts +12 -12
  441. package/src/plugins/builtin/shared/report-freshness.ts +3 -2
  442. package/src/plugins/builtin/shared/scanner-capture.ts +3 -0
  443. package/src/plugins/builtin/shared/ticker-choice.tsx +2 -1
  444. package/src/plugins/builtin/shared/ticker-company.ts +77 -0
  445. package/src/plugins/builtin/shared/use-quote-board.ts +10 -3
  446. package/src/plugins/builtin/shared/volatility/live-session.ts +34 -8
  447. package/src/plugins/builtin/shared/volatility/pricing.ts +26 -1
  448. package/src/plugins/builtin/shared/wall-view-lifecycle.ts +3 -1
  449. package/src/plugins/builtin/themes/headless.ts +6 -4
  450. package/src/plugins/builtin/themes/model.ts +17 -8
  451. package/src/plugins/builtin/themes/pane.tsx +7 -7
  452. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +43 -18
  453. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +3 -2
  454. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +62 -0
  455. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +83 -46
  456. package/src/plugins/builtin/ticker-detail/headless.ts +31 -16
  457. package/src/plugins/builtin/ticker-detail/overview/model.ts +1 -1
  458. package/src/plugins/builtin/ticker-detail/pane.tsx +3 -2
  459. package/src/plugins/builtin/ticker-detail/quote-footer.ts +6 -1
  460. package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +2 -1
  461. package/src/plugins/builtin/ticker-detail/settings.ts +1 -0
  462. package/src/plugins/builtin/time-sales/pane.tsx +31 -19
  463. package/src/plugins/builtin/treasury-daily/client.ts +41 -5
  464. package/src/plugins/builtin/treasury-daily/headless.ts +2 -2
  465. package/src/plugins/builtin/treasury-daily/index.tsx +1 -1
  466. package/src/plugins/builtin/treasury-daily/model.ts +50 -3
  467. package/src/plugins/builtin/treasury-daily/pane.tsx +81 -2
  468. package/src/plugins/builtin/vol-surface/charts.tsx +9 -4
  469. package/src/plugins/builtin/vol-surface/client.ts +9 -17
  470. package/src/plugins/builtin/vol-surface/headless.ts +63 -14
  471. package/src/plugins/builtin/vol-surface/index.tsx +2 -2
  472. package/src/plugins/builtin/vol-surface/model.ts +22 -7
  473. package/src/plugins/builtin/vol-surface/pane.tsx +48 -9
  474. package/src/plugins/builtin/vol-surface/tables.ts +31 -3
  475. package/src/plugins/builtin/volatility/dvol.ts +46 -0
  476. package/src/plugins/builtin/volatility/index.tsx +2 -2
  477. package/src/plugins/builtin/volatility/pane.tsx +4 -4
  478. package/src/plugins/builtin/volatility/series.ts +26 -0
  479. package/src/plugins/builtin/world-indices/footer.ts +1 -1
  480. package/src/plugins/builtin/world-venue-map/headless.ts +3 -3
  481. package/src/plugins/catalog-browser.ts +13 -8
  482. package/src/plugins/catalog-manifest.ts +2 -1
  483. package/src/plugins/marketplace/model.ts +18 -5
  484. package/src/portfolio/column-values.ts +5 -5
  485. package/src/portfolio/futures-positions.ts +6 -3
  486. package/src/portfolio/position-quantity.ts +15 -9
  487. package/src/public/__snapshots__/public-api.test.ts.snap +1 -0
  488. package/src/remote/resources.ts +2 -1
  489. package/src/renderers/browser/app-services.ts +1 -7
  490. package/src/renderers/browser/config-host.ts +2 -55
  491. package/src/renderers/browser/main.tsx +7 -57
  492. package/src/renderers/dom/data-table/row.tsx +26 -0
  493. package/src/renderers/dom/desktop/list-view.tsx +13 -10
  494. package/src/renderers/dom/desktop/query-bar.tsx +4 -2
  495. package/src/renderers/dom/desktop/select-field.tsx +4 -2
  496. package/src/renderers/dom/host/chart-surface.tsx +21 -0
  497. package/src/renderers/electrobun/bun/desktop/app-name.ts +222 -0
  498. package/src/renderers/electrobun/bun/desktop/backend.ts +29 -7
  499. package/src/renderers/electrobun/bun/desktop/host-requests.ts +7 -0
  500. package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -0
  501. package/src/renderers/electrobun/bun/desktop/relaunch.ts +74 -25
  502. package/src/renderers/electrobun/bun/desktop/state-broadcaster.ts +1 -0
  503. package/src/renderers/electrobun/bun/desktop/update.ts +173 -5
  504. package/src/renderers/electrobun/bun/desktop/view-ids.ts +52 -0
  505. package/src/renderers/electrobun/bun/desktop/workspace/index.ts +2 -0
  506. package/src/renderers/electrobun/bun/index.ts +25 -1
  507. package/src/renderers/electrobun/shared/app-name.ts +30 -0
  508. package/src/renderers/electrobun/shared/protocol.ts +10 -0
  509. package/src/renderers/electrobun/view/backend-rpc.ts +6 -0
  510. package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +3 -3
  511. package/src/renderers/electrobun/view/desktop/window/snapshot.ts +1 -0
  512. package/src/renderers/electrobun/view/main.tsx +24 -1
  513. package/src/renderers/electrobun/view/news-source.ts +3 -1
  514. package/src/renderers/electrobun/view/remote/ticker-repository.ts +14 -7
  515. package/src/renderers/electrobun/view/view-ids.ts +85 -0
  516. package/src/renderers/opentui/start.tsx +5 -0
  517. package/src/renderers/opentui/toast-host.tsx +71 -43
  518. package/src/series/registry.ts +1 -0
  519. package/src/series/types.ts +6 -0
  520. package/src/series/validate.ts +1 -0
  521. package/src/sources/gloomberb-cloud/index.ts +1 -0
  522. package/src/sources/gloomberb-cloud/news.ts +47 -7
  523. package/src/sources/gloomberb-cloud/normalizers.ts +2 -0
  524. package/src/sources/provider-router/batches.ts +10 -2
  525. package/src/sources/provider-router/financial-routes.ts +3 -3
  526. package/src/sources/provider-router/financials.ts +15 -3
  527. package/src/sources/provider-router/history.ts +28 -7
  528. package/src/sources/provider-router/index.ts +149 -10
  529. package/src/sources/provider-router/search.ts +13 -2
  530. package/src/state/app/context/index.tsx +3 -0
  531. package/src/state/ticker-cleanup.ts +50 -0
  532. package/src/sync/auth-transition.ts +19 -9
  533. package/src/sync/baseline.ts +10 -4
  534. package/src/sync/controller.ts +70 -19
  535. package/src/sync/core-contributors.ts +90 -31
  536. package/src/sync/react.ts +4 -1
  537. package/src/sync/types.ts +3 -0
  538. package/src/telemetry/stall-reports-dom.ts +38 -0
  539. package/src/telemetry/stall-reports-node.ts +75 -0
  540. package/src/telemetry/stall-reports.ts +214 -0
  541. package/src/telemetry/usage-counts.ts +0 -18
  542. package/src/test-support/preload.ts +14 -0
  543. package/src/theme/colors.ts +8 -0
  544. package/src/theme/themes.ts +10 -0
  545. package/src/tickers/company-name.ts +103 -3
  546. package/src/tickers/listing-venues.ts +38 -3
  547. package/src/tickers/search/bare-symbol.ts +36 -0
  548. package/src/tickers/search/index.ts +36 -7
  549. package/src/tickers/search/ranking.ts +10 -1
  550. package/src/tickers/search/types.ts +5 -0
  551. package/src/tickers/terminal-codes.ts +19 -0
  552. package/src/time-series/alignment.ts +1 -1
  553. package/src/time-series/base-series.ts +13 -5
  554. package/src/time-series/daily-valuation.ts +62 -0
  555. package/src/time-series/economic.ts +18 -4
  556. package/src/time-series/field-catalog.ts +2 -4
  557. package/src/time-series/filed-trailing-eps.ts +197 -0
  558. package/src/time-series/forward-valuation.ts +32 -0
  559. package/src/time-series/fundamentals.ts +198 -7
  560. package/src/time-series/hooks.ts +1 -0
  561. package/src/time-series/ice-credit.ts +3 -0
  562. package/src/time-series/price-comparison.ts +30 -2
  563. package/src/time-series/price-units.ts +72 -2
  564. package/src/time-series/resolve-context.ts +7 -1
  565. package/src/time-series/resolve.ts +116 -15
  566. package/src/time-series/series-presentation.ts +40 -6
  567. package/src/time-series/session-bar.ts +11 -0
  568. package/src/time-series/spec.ts +5 -3
  569. package/src/time-series/studies.ts +278 -74
  570. package/src/time-series/total-return.ts +160 -0
  571. package/src/time-series/transforms.ts +3 -3
  572. package/src/time-series/types.ts +27 -1
  573. package/src/time-series/valuation-releases.ts +39 -0
  574. package/src/types/data-provider.ts +9 -1
  575. package/src/types/desktop-window.ts +2 -0
  576. package/src/types/financials.ts +73 -2
  577. package/src/types/headless.ts +61 -5
  578. package/src/types/instrument.ts +3 -0
  579. package/src/types/news-source.ts +1 -0
  580. package/src/types/plugin.ts +10 -1
  581. package/src/ui/host.tsx +3 -0
  582. package/src/updater/command-names.ts +12 -7
  583. package/src/updater/failure.ts +4 -1
  584. package/src/utils/cli-output.ts +42 -1
  585. package/src/utils/crypto-pair.ts +44 -0
  586. package/src/utils/financial-statements.ts +6 -1
  587. package/src/utils/forward-dividend.ts +2 -0
  588. package/src/utils/fundamentals.ts +24 -3
  589. package/src/utils/fx-market-hours.ts +26 -3
  590. package/src/utils/main-thread-stall.ts +35 -2
  591. package/src/utils/market-capitalization.ts +24 -1
  592. package/src/utils/network-failure.ts +9 -6
  593. package/src/utils/option-expiry.ts +48 -1
  594. package/src/utils/options.ts +10 -0
  595. package/src/utils/plugin-proxy-hosts.json +1 -0
  596. package/src/utils/price-history.ts +12 -1
  597. package/src/utils/shell-word.ts +8 -0
  598. package/src/utils/trailing-dividend.ts +53 -4
  599. package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +0 -17
  600. package/src/renderers/browser/first-screen.ts +0 -193
@@ -67,6 +67,8 @@ export const ASSIST_ARG_OPTION_LIMIT = 128;
67
67
  const ASSIST_ARG_OPTION_VALUE_MAX_LENGTH = 40;
68
68
  const ASSIST_ARG_OPTION_LABEL_MAX_LENGTH = 60;
69
69
  const ASSIST_REQUEST_TIMEOUT_MS = 6_000;
70
+ const SESSION_REVALIDATION_INITIAL_MS = 1_000;
71
+ const SESSION_REVALIDATION_MAX_MS = 30_000;
70
72
 
71
73
  /**
72
74
  * Fits a command's argument values inside the server caps. The value is what
@@ -94,8 +96,15 @@ interface PendingSessionRequest {
94
96
 
95
97
  class GloomApiClient {
96
98
  private currentUser: AuthUser | null = null;
97
- /** Local identity of a verified user/credential pair, never serialized. */
99
+ /** Local user/credential binding, masked until verified and never serialized. */
98
100
  private verifiedSessionIdentity: object | null = null;
101
+ private verifiedSessionCredential: string | null = null;
102
+ private sessionTransitions = 0;
103
+ private sessionTransition: Promise<void> | null = null;
104
+ /** Device adoption and external session installs supersede pending email auth. */
105
+ private sessionInstallationGeneration = 0;
106
+ private sessionRevalidationGeneration = 0;
107
+ private sessionRevalidationTimer: ReturnType<typeof setTimeout> | null = null;
99
108
  private sessionChecked = false;
100
109
  /** Last few session transitions, content-free, for app://auth. */
101
110
  private authTrace: Array<{ at: number; event: string; token: boolean; user: string }> = [];
@@ -110,7 +119,7 @@ class GloomApiClient {
110
119
  request: (path, options, canApplySession) => this.request(path, options, canApplySession),
111
120
  requireCapturedSession: (message) => this.requireCapturedSession(message),
112
121
  setCurrentUser: (user) => this.setCurrentUser(user),
113
- setSessionToken: (token) => this.setSessionToken(token),
122
+ setSessionToken: (token) => this.installSessionToken(token),
114
123
  updateCurrentUser: (updater) => this.updateCurrentUser(updater),
115
124
  });
116
125
  private readonly socket: CloudApiSocket = new CloudApiSocket({
@@ -123,7 +132,6 @@ class GloomApiClient {
123
132
  markCurrentUserUnverified: () => {
124
133
  if (this.currentUser) {
125
134
  this.currentUser = { ...this.currentUser, emailVerified: false };
126
- this.verifiedSessionIdentity = null;
127
135
  this.emitCurrentUserChange();
128
136
  }
129
137
  },
@@ -165,6 +173,8 @@ class GloomApiClient {
165
173
  }
166
174
 
167
175
  setCookieSessionMode(enabled: boolean): void {
176
+ this.cancelSessionRevalidation();
177
+ this.sessionInstallationGeneration += 1;
168
178
  this.sessionChecked = false;
169
179
  this.verifiedSessionIdentity = null;
170
180
  this.transport.setCookieSessionMode(enabled);
@@ -172,12 +182,21 @@ class GloomApiClient {
172
182
  }
173
183
 
174
184
  setSessionToken(token: string | null): void {
185
+ if (this.transport.getSessionToken() !== token || !token) {
186
+ this.cancelSessionRevalidation();
187
+ this.sessionInstallationGeneration += 1;
188
+ }
189
+ this.installSessionToken(token);
190
+ }
191
+
192
+ private installSessionToken(token: string | null): void {
175
193
  const changed = this.transport.getSessionToken() !== token;
176
194
  this.sessionChecked = false;
177
195
  this.transport.setSessionToken(token);
178
196
  if (changed) this.verifiedSessionIdentity = null;
179
197
  this.traceAuth(changed ? "setSessionToken:changed" : "setSessionToken:same");
180
198
  if (!token) {
199
+ this.cancelSessionRevalidation();
181
200
  this.currentUser = null;
182
201
  this.verifiedSessionIdentity = null;
183
202
  }
@@ -206,6 +225,14 @@ class GloomApiClient {
206
225
  return !!this.transport.getSessionToken() || !!this.currentUser;
207
226
  }
208
227
 
228
+ /**
229
+ * Whether a request sent now carries a session: the token this client
230
+ * holds, or, in the browser, the cookie it cannot see and assumes is there.
231
+ */
232
+ hasSessionCredential(): boolean {
233
+ return this.transport.hasSessionCredential();
234
+ }
235
+
209
236
  /** Notifies when the user or credential changes, including plan and trial entitlement. */
210
237
  subscribeCurrentUser(listener: () => void): () => void {
211
238
  this.currentUserListeners.add(listener);
@@ -224,7 +251,9 @@ class GloomApiClient {
224
251
 
225
252
  /** Null while a replacement credential still awaits its matching user. */
226
253
  getVerifiedSessionIdentity(): object | null {
227
- return this.isVerified() ? this.verifiedSessionIdentity : null;
254
+ return this.sessionTransitions === 0 && this.isVerified()
255
+ && this.verifiedSessionCredential === this.transport.getSessionToken()
256
+ ? this.verifiedSessionIdentity : null;
228
257
  }
229
258
 
230
259
  /**
@@ -276,11 +305,18 @@ class GloomApiClient {
276
305
  if (this.authTrace.length > 24) this.authTrace.shift();
277
306
  }
278
307
 
279
- private setCurrentUser(user: AuthUser | null): void {
308
+ private setCurrentUser(user: AuthUser | null, confirmSession = true): void {
309
+ const sameAccount = this.currentUser?.id === user?.id;
280
310
  const changed = this.socketEntitlementKey(this.currentUser) !== this.socketEntitlementKey(user);
281
311
  this.traceAuth("setCurrentUser", user);
282
312
  this.currentUser = user;
283
- this.verifiedSessionIdentity = this.isVerified() ? {} : null;
313
+ if (confirmSession) {
314
+ this.clearSessionRevalidationTimer();
315
+ this.verifiedSessionIdentity = user ? {} : null;
316
+ this.verifiedSessionCredential = this.transport.getSessionToken();
317
+ } else if (!sameAccount || !user) {
318
+ this.verifiedSessionIdentity = null;
319
+ }
284
320
  this.socket.syncAuthState({ reconnect: changed });
285
321
  this.emitCurrentUserChange();
286
322
  }
@@ -291,7 +327,9 @@ class GloomApiClient {
291
327
 
292
328
  private updateCurrentUser(updater: (user: AuthUser) => AuthUser): void {
293
329
  if (!this.currentUser) return;
294
- this.setCurrentUser(updater(this.currentUser));
330
+ // A socket/profile update is metadata, not proof that a replacement
331
+ // credential belongs to this user. Keep its existing binding, even null.
332
+ this.setCurrentUser(updater(this.currentUser), false);
295
333
  }
296
334
 
297
335
  private socketEntitlementKey(user: AuthUser | null): string {
@@ -326,11 +364,123 @@ class GloomApiClient {
326
364
  return this.currentUser?.emailVerified ? this.currentUser : null;
327
365
  }
328
366
 
329
- signUp = this.auth.signUp.bind(this.auth);
330
- signIn = this.auth.signIn.bind(this.auth);
367
+ signUp = (email: string, username: string, name: string, password: string) =>
368
+ this.withSessionTransition((isCurrent) => this.auth.signUp(email, username, name, password, isCurrent));
369
+ signIn = (email: string, password: string) =>
370
+ this.withSessionTransition((isCurrent) => this.auth.signIn(email, password, isCurrent));
331
371
  startDeviceSignIn = this.auth.startDeviceSignIn.bind(this.auth);
332
372
  pollDeviceSignIn = this.auth.pollDeviceSignIn.bind(this.auth);
333
- signOut = this.auth.signOut.bind(this.auth);
373
+ signOut = () => this.withSessionTransition((isCurrent) => this.auth.signOut(isCurrent), false);
374
+
375
+ /** Cookies can change before an auth response's body arrives, including ones the browser hides. */
376
+ private withSessionTransition<T>(run: (isCurrent: () => boolean) => Promise<T>, reconcileFailure = true): Promise<T> {
377
+ const previous = this.sessionTransition;
378
+ this.cancelSessionRevalidation();
379
+ let revalidationGeneration = this.sessionRevalidationGeneration;
380
+ const generation = this.sessionInstallationGeneration;
381
+ const isCurrent = () => generation === this.sessionInstallationGeneration;
382
+ this.sessionTransitions += 1;
383
+ this.sessionChecked = false;
384
+ this.verifiedSessionIdentity = null;
385
+ this.sessionRequestGeneration += 1;
386
+ this.emitCurrentUserChange();
387
+ let needsRevalidation = false;
388
+ const operation = (async () => {
389
+ // Serialize credential-changing requests so a late response cannot pair
390
+ // one account's user with another request's installed cookie.
391
+ if (previous) await previous;
392
+ try {
393
+ if (!isCurrent()) throw new Error("Another sign-in replaced this request.");
394
+ // An earlier queued sign-out may have retired retries while clearing its token.
395
+ revalidationGeneration = this.sessionRevalidationGeneration;
396
+ this.sessionRequestGeneration += 1;
397
+ const result = await run(isCurrent);
398
+ if (!isCurrent()) throw new Error("Another sign-in replaced this request.");
399
+ return result;
400
+ } catch (error) {
401
+ if (isCurrent()) {
402
+ this.verifiedSessionIdentity = null;
403
+ this.sessionChecked = false;
404
+ }
405
+ if (isCurrent() && reconcileFailure && this.transport.hasSessionCredential()) {
406
+ // A failed body may already have changed the cookie. A fresh session
407
+ // check is the only way to resume; retry if it cannot validate yet.
408
+ needsRevalidation = true;
409
+ this.sessionRequestGeneration += 1;
410
+ await this.revalidateSession(() => isCurrent()
411
+ && revalidationGeneration === this.sessionRevalidationGeneration).catch((failure) => {
412
+ if (!isCurrent()) return;
413
+ this.verifiedSessionIdentity = null;
414
+ logFailure("cloud.auth", "Restore session after failed sign-in failed")(failure);
415
+ });
416
+ }
417
+ throw error;
418
+ } finally {
419
+ if (isCurrent()) this.sessionRequestGeneration += 1;
420
+ this.sessionTransitions -= 1;
421
+ if (isCurrent() && needsRevalidation) this.scheduleSessionRevalidation(revalidationGeneration);
422
+ this.emitCurrentUserChange();
423
+ }
424
+ })();
425
+ const settled = operation.then(() => {}, () => {
426
+ // Intentional ignore: the caller receives the error while the auth queue continues.
427
+ });
428
+ this.sessionTransition = settled;
429
+ void settled.then(() => { if (this.sessionTransition === settled) this.sessionTransition = null; });
430
+ return operation;
431
+ }
432
+
433
+ private clearSessionRevalidationTimer(): void {
434
+ if (this.sessionRevalidationTimer !== null) clearTimeout(this.sessionRevalidationTimer);
435
+ this.sessionRevalidationTimer = null;
436
+ }
437
+
438
+ private cancelSessionRevalidation(): void {
439
+ this.sessionRevalidationGeneration += 1;
440
+ this.clearSessionRevalidationTimer();
441
+ }
442
+
443
+ /** A failed auth response can replace a cookie even when its recovery read is offline. */
444
+ private scheduleSessionRevalidation(generation: number, delay = SESSION_REVALIDATION_INITIAL_MS): void {
445
+ const isCurrent = () => generation === this.sessionRevalidationGeneration;
446
+ const needsRevalidation = () => isCurrent() && this.sessionTransitions === 0
447
+ && !this.sessionChecked && this.verifiedSessionIdentity === null && this.transport.hasSessionCredential();
448
+ if (!needsRevalidation() || this.sessionRevalidationTimer !== null) return;
449
+ this.sessionRevalidationTimer = setTimeout(() => {
450
+ this.sessionRevalidationTimer = null;
451
+ if (!needsRevalidation()) return;
452
+ void this.revalidateSession(isCurrent).catch((error) => {
453
+ if (isCurrent()) logFailure("cloud.auth", "Retry session validation failed")(error);
454
+ }).finally(() => {
455
+ this.scheduleSessionRevalidation(generation, Math.min(delay * 2, SESSION_REVALIDATION_MAX_MS));
456
+ });
457
+ }, delay);
458
+ this.sessionRevalidationTimer.unref?.();
459
+ }
460
+
461
+ private async revalidateSession(isCurrent: () => boolean): Promise<void> {
462
+ const user = await this.getSession(isCurrent);
463
+ const credential = this.getSessionToken();
464
+ if (user || !credential || !isCurrent()) return;
465
+ // A native null-session response can retain a usable token. Validate it
466
+ // through the account endpoint, without pairing it with a cached user.
467
+ this.sessionChecked = false;
468
+ const previousUser = this.currentUser;
469
+ const canApply = () => isCurrent() && this.getSessionToken() === credential && this.currentUser === previousUser;
470
+ try {
471
+ const profile = await this.auth.getAccountProfile(canApply);
472
+ if (!canApply()) return;
473
+ this.sessionChecked = true;
474
+ this.auth.restoreCachedUser({ ...profile, updatedAt: profile.updatedAt ?? undefined });
475
+ } catch (error) {
476
+ if (!canApply()) return;
477
+ if (error instanceof ApiRequestError && error.status === 401) {
478
+ this.installSessionToken(null);
479
+ return;
480
+ }
481
+ throw error;
482
+ }
483
+ }
334
484
 
335
485
  async getSession(isCurrent: () => boolean = () => true): Promise<AuthUser | null> {
336
486
  if (!isCurrent()) return this.currentUser;
@@ -353,7 +503,10 @@ class GloomApiClient {
353
503
  credential: this.getSessionToken(),
354
504
  promise: this.auth.getSession(canApply)
355
505
  .then(({ user, validated }) => {
356
- if (validated && canApply()) this.sessionChecked = true;
506
+ if (validated && canApply()) {
507
+ this.sessionChecked = true;
508
+ this.clearSessionRevalidationTimer();
509
+ }
357
510
  this.traceAuth(validated ? "getSession:done" : "getSession:retained", user);
358
511
  return user;
359
512
  })
@@ -753,6 +906,8 @@ class GloomApiClient {
753
906
  subscribeScanner = this.socket.subscribeScanner.bind(this.socket);
754
907
 
755
908
  dispose(): void {
909
+ this.cancelSessionRevalidation();
910
+ this.sessionInstallationGeneration += 1;
756
911
  this.sessionRequestGeneration += 1;
757
912
  this.sessionRequest = null;
758
913
  this.socket.dispose();
@@ -799,11 +954,14 @@ class GloomApiClient {
799
954
  getCloudCentralBankRates = this.data.getCloudCentralBankRates.bind(this.data);
800
955
  getMobileAlertHistory = this.data.getMobileAlertHistory.bind(this.data);
801
956
  getScannerFlowHistory = this.data.getScannerFlowHistory.bind(this.data);
957
+ getScannerFlowSession = this.data.getScannerFlowSession.bind(this.data);
958
+ getLiveScan = this.data.getLiveScan.bind(this.data);
802
959
  getCloudEstimateRevisions = this.data.getCloudEstimateRevisions.bind(this.data);
803
960
  getCloudMoneyMarkets = this.data.getCloudMoneyMarkets.bind(this.data);
804
961
  equityScreener = this.data.equityScreener.bind(this.data);
805
962
  getMemberFunds = this.data.getMemberFunds.bind(this.data);
806
963
  getFundMembers = this.data.getFundMembers.bind(this.data);
964
+ getFundBreadth = this.data.getFundBreadth.bind(this.data);
807
965
  getFundChanges = this.data.getFundChanges.bind(this.data);
808
966
  getFundFacts = this.data.getFundFacts.bind(this.data);
809
967
  getCloudExchangeAnnouncements = this.data.getCloudExchangeAnnouncements.bind(this.data);
@@ -855,6 +1013,8 @@ class GloomApiClient {
855
1013
  getCloudPerpsHistory = this.data.getCloudPerpsHistory.bind(this.data);
856
1014
  getCloudPerpsRankings = this.data.getCloudPerpsRankings.bind(this.data);
857
1015
  getCloudPerpsCompare = this.data.getCloudPerpsCompare.bind(this.data);
1016
+ getCloudPerpsLiquidations = this.data.getCloudPerpsLiquidations.bind(this.data);
1017
+ getCloudPerpsDepth = this.data.getCloudPerpsDepth.bind(this.data);
858
1018
  getCloudPerpsEquity = this.data.getCloudPerpsEquity.bind(this.data);
859
1019
  getCloudPerpsEquities = this.data.getCloudPerpsEquities.bind(this.data);
860
1020
  getCloudPerpsMarket = this.data.getCloudPerpsMarket.bind(this.data);
@@ -0,0 +1,91 @@
1
+ /**
2
+ * The live scanner's wire format: a user's own intraday conditions over a
3
+ * universe of US stocks, evaluated by Gloom Cloud against a market-wide
4
+ * snapshot it refreshes every few seconds (real-time for Pro, 15 minutes
5
+ * delayed otherwise). `GET /market/scanner/live?scan=<definition JSON>`.
6
+ */
7
+
8
+ /** Minutes a move, a volume window or an event can look back over. */
9
+ export const LIVE_SCAN_WINDOWS = [1, 5, 15, 30, 60] as const;
10
+ export type LiveScanWindow = (typeof LIVE_SCAN_WINDOWS)[number];
11
+
12
+ export const LIVE_SCAN_INDEXES = ["sp500", "sp400", "sp600", "russell1000", "russell2000"] as const;
13
+ export type LiveScanIndex = (typeof LIVE_SCAN_INDEXES)[number];
14
+
15
+ /** The universe as Gloom Cloud reads it; a watchlist goes as its symbols. */
16
+ type LiveScanWireUniverse =
17
+ | { kind: "all" }
18
+ | { kind: "index"; index: LiveScanIndex }
19
+ | { kind: "sector"; sector: string }
20
+ | { kind: "symbols"; symbols: string[] };
21
+
22
+ export type LiveScanDirection = "up" | "down" | "either";
23
+
24
+ export type LiveScanCondition =
25
+ /** Volume over the window (or the session so far) against the 20-session average's pace. */
26
+ | { kind: "volume_spike"; window: LiveScanWindow | "day"; ratio: number }
27
+ /** Percent move over the last `window` minutes. */
28
+ | { kind: "move"; window: LiveScanWindow; direction: LiveScanDirection; percent: number }
29
+ /** A new session high (low) printed in the last `within` minutes. */
30
+ | { kind: "new_high" | "new_low"; within: LiveScanWindow }
31
+ /** Crossed the session VWAP in the last `within` minutes, and still on that side. */
32
+ | { kind: "vwap_cross"; direction: "above" | "below" | "either"; within: LiveScanWindow }
33
+ /** The session's open against the previous close. */
34
+ | { kind: "gap"; direction: LiveScanDirection; percent: number };
35
+
36
+ export interface LiveScanWireDefinition {
37
+ version: 1;
38
+ universe: LiveScanWireUniverse;
39
+ conditions: LiveScanCondition[];
40
+ minPrice?: number;
41
+ minMarketCap?: number;
42
+ minVolume?: number;
43
+ }
44
+
45
+ type LiveScanStatus = "live" | "starting" | "closed" | "degraded";
46
+
47
+ export interface LiveScanMatch {
48
+ symbol: string;
49
+ name: string | null;
50
+ /** Its US venue (NASDAQ, NYSE, ...), null when the screener does not list it. */
51
+ exchange?: string | null;
52
+ price: number;
53
+ changePercent: number | null;
54
+ volume: number | null;
55
+ /** The session's volume against the 20-session average's pace so far. */
56
+ relativeVolume: number | null;
57
+ /** Price against the session VWAP, in percent. */
58
+ vwapPercent: number | null;
59
+ gapPercent: number | null;
60
+ /**
61
+ * The figure each condition matched on, in the definition's order: a
62
+ * percent for a move or a gap, a multiple for a volume spike, the time of
63
+ * the event (epoch ms) for a new high or low or a VWAP cross.
64
+ */
65
+ values: Array<number | null>;
66
+ /** The latest event a condition matched on. */
67
+ signalAt: number | null;
68
+ /** When the price printed. */
69
+ at: number | null;
70
+ }
71
+
72
+ export interface LiveScanPayload {
73
+ status: LiveScanStatus;
74
+ access: "realtime" | "delayed";
75
+ delayMinutes: number;
76
+ /** The market time the snapshot shows. */
77
+ asOf: number | null;
78
+ /** When the snapshot was refreshed. */
79
+ takenAt: number | null;
80
+ /** How often the snapshot refreshes. */
81
+ refreshMs: number;
82
+ scanned: number;
83
+ matched: number;
84
+ matches: LiveScanMatch[];
85
+ /** Windows the scanner cannot measure yet after it started; a condition over one matches nothing until then. */
86
+ warmingWindows: LiveScanWindow[];
87
+ warnings: string[];
88
+ }
89
+
90
+ /** The scan travels in a POST body: a watchlist of 1,000 symbols would not fit a request line. */
91
+ export const LIVE_SCAN_PATH = "/market/scanner/live";
@@ -21,6 +21,12 @@ export interface ScreenerQuote {
21
21
  previousClose?: number;
22
22
  /** The quote's sessions beside the live print the server ranked the row by, when the server sends them. */
23
23
  sessions?: CloudMoverSessionFields;
24
+ /** The listing's float as the equity screener serves it; absent where the server serves none or predates it. */
25
+ floatShares?: number;
26
+ /** Set with a float the source states no measurement date for: `partial`. */
27
+ floatSharesState?: "partial";
28
+ /** Why the float is partial, as the server says it. */
29
+ floatSharesReason?: string;
24
30
  }
25
31
 
26
32
 
@@ -105,6 +111,8 @@ export interface DividendSummary {
105
111
  /** The ex-date of the distribution that rate annualizes, YYYY-MM-DD. */
106
112
  forwardRateAsOf?: string | null;
107
113
  payoutRatio: number | null;
114
+ /** The trailing EPS fundamentals serve for the listing; only its sign is read, since a payout over a loss is not meaningful. Absent from older servers. */
115
+ trailingEps?: number | null;
108
116
  exDividendDate: number | null;
109
117
  dividendDate: number | null;
110
118
  currency: string | null;
@@ -117,4 +125,6 @@ export interface MarketDividendsPayload {
117
125
  summary: DividendSummary | null;
118
126
  historyError?: string;
119
127
  summaryError?: string;
128
+ /** When Gloom Cloud last asked for the history and the summary, ISO. Absent from older servers. */
129
+ triedAt?: string;
120
130
  }
@@ -37,7 +37,14 @@ export interface CloudSessionMoverItem {
37
37
  /** Regular-session VWAP. */
38
38
  vwap: number | null;
39
39
  vwapPercent: number | null;
40
+ /** The equity screener's float, null where it serves none. */
40
41
  floatShares: number | null;
42
+ /** Set with a float the source states no measurement date for: `partial`. */
43
+ floatSharesState?: "partial";
44
+ /** Why the float is partial, as the server says it. */
45
+ floatSharesReason?: string;
46
+ /** When the statistics the float is read from were retrieved (ISO). */
47
+ floatSharesRetrievedAt?: string;
41
48
  catalysts: CloudSessionCatalyst[];
42
49
  lastUpdated: number;
43
50
  }
@@ -1,7 +1,7 @@
1
1
  interface MemberFund { ticker: string; name: string; aliases: string[]; changes: "sp500" | "announcements" | "none" }
2
2
  export interface FundMember {
3
3
  id: string; symbol: string | null; name: string; sector: string | null;
4
- weight: number | null; shares: number; holdingPrice: number; marketValue: number;
4
+ weight: number | null; shares: number; holdingPrice: number | null; marketValue: number | null;
5
5
  price: number | null; priceAsOf: string | null; changePercent: number | null; dailyAsOf: string | null;
6
6
  return1WPercent: number | null; return1MPercent: number | null; returnYtdPercent: number | null;
7
7
  contribution: number | null; stale: boolean;
@@ -30,3 +30,15 @@ export interface FundChangesPayload {
30
30
  estimateLabel: string; attribution: { text: string; url: string } | null;
31
31
  }
32
32
  export interface MemberFundsPayload { funds: (MemberFund & { asOf: string | null })[] }
33
+
34
+ interface BreadthCount { above: number; eligible: number; percent: number | null }
35
+ export interface BreadthDay {
36
+ date: string; asOf: string; membershipAsOf: string; memberCount: number; observed: number;
37
+ advances: number; declines: number; unchanged: number; advanceDeclineEligible: number;
38
+ ma20: BreadthCount; ma50: BreadthCount; ma200: BreadthCount;
39
+ newHighs: number; newLows: number; highLowEligible: number; adLine: number | null;
40
+ }
41
+ export interface FundBreadthPayload {
42
+ fund: MemberFund; basis: "daily-close" | "intraday"; access?: "realtime" | "delayed"; membershipBasis: "current-members";
43
+ latest: BreadthDay | null; history: BreadthDay[]; stale: boolean;
44
+ }
@@ -174,3 +174,46 @@ export interface PerpMarketPayload extends PerpBoardPayload {
174
174
  evidence: { kind: string; period_at: string; received_at: string; superseded_at: string | null; fingerprint: string; payload: PerpMarket | PerpFunding | PerpCandle }[];
175
175
  methodologyUrl: string;
176
176
  }
177
+
178
+ /** One contract's liquidations: long is longs liquidated (forced sells), short is shorts; quote notional. */
179
+ export interface PerpLiquidationMarket {
180
+ marketId: string; venue: string; symbol: string; dex: string; quoteCurrency: string;
181
+ long24h: number; short24h: number; long7d: number; short7d: number; count24h: number; count7d: number; lastEventAt: string | null;
182
+ }
183
+ export interface PerpLiquidationPrint {
184
+ marketId: string; venue: string; symbol: string; dex: string;
185
+ side: "long" | "short"; priceKind: "fill" | "bankruptcy"; price: number; quantity: number; notionalUsd: number;
186
+ /** The venue's time for the liquidation. */
187
+ eventAt: string;
188
+ /** When Gloom Cloud received it. */
189
+ receivedAt: string;
190
+ }
191
+ /** One base asset's liquidations across the venues' public streams. */
192
+ export interface PerpLiquidationsPayload {
193
+ status: string; baseAsset: string; asOf: string; from: string; collectingSince: string | null;
194
+ markets: PerpLiquidationMarket[];
195
+ totals: Pick<PerpLiquidationMarket, "long24h" | "short24h" | "long7d" | "short7d" | "count24h" | "count7d">;
196
+ /** Pro: UTC hours with liquidations over the last 7 days; empty for a preview. */
197
+ hourly: { time: string; long: number; short: number; count: number }[];
198
+ largest: PerpLiquidationPrint[];
199
+ streams: { venue: string; state: "live" | "down"; lastOkAt: string | null; error: string | null }[];
200
+ notes: string[];
201
+ locked: boolean; access: "pro" | "preview";
202
+ }
203
+ /** Quote notional resting within 0.5%, 1% and 2% of mid; reach is how far the returned book went, as a fraction of mid. */
204
+ export interface PerpDepthSnapshot {
205
+ marketId: string; bucket: string; observedAt: string; sourceAsOf: string | null; mid: number;
206
+ bid05: number; ask05: number; bid1: number; ask1: number; bid2: number; ask2: number;
207
+ bidReach: number; askReach: number; levels: number; grouping: number | null;
208
+ }
209
+ export interface PerpDepthRow extends PerpDepthSnapshot { venue: string; symbol: string; dex: string; quoteCurrency: string; stale: boolean }
210
+ /** One base asset's hourly order book depth across the venues. */
211
+ export interface PerpDepthPayload {
212
+ status: string; baseAsset: string; asOf: string;
213
+ rows: PerpDepthRow[];
214
+ /** Pro: every market's hourly snapshots over the last 7 days; empty for a preview. */
215
+ history: PerpDepthSnapshot[];
216
+ sources: { venue: string; lastOkAt: string | null; error: string | null }[];
217
+ notes: string[];
218
+ locked: boolean; access: "pro" | "preview";
219
+ }