gloomberb 0.18.2 → 0.18.4

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 (954) hide show
  1. package/README.md +8 -8
  2. package/README.zh-CN.md +11 -11
  3. package/bin/{gloomberb → gloom} +3 -1
  4. package/package.json +6 -2
  5. package/patches/electrobun@1.18.1.patch +106 -5
  6. package/src/account/checkout-handoff.tsx +225 -0
  7. package/src/account/device-signin-dialog.tsx +2 -2
  8. package/src/account/device-signin.ts +2 -2
  9. package/src/account/upgrade-dialog.tsx +1 -1
  10. package/src/api-client/askg.ts +2 -2
  11. package/src/api-client/auth.ts +2 -2
  12. package/src/api-client/central-bank-rates.ts +6 -0
  13. package/src/api-client/collections.ts +5 -1
  14. package/src/api-client/cot.ts +2 -0
  15. package/src/api-client/crypto-etf-flows.ts +37 -0
  16. package/src/api-client/crypto-markets.ts +60 -0
  17. package/src/api-client/data.ts +99 -5
  18. package/src/api-client/doe.ts +15 -0
  19. package/src/api-client/equity-screener.ts +28 -0
  20. package/src/api-client/exchange-announcements.ts +38 -0
  21. package/src/api-client/fund-facts.ts +39 -0
  22. package/src/api-client/futures-curve.ts +9 -1
  23. package/src/api-client/hiring.ts +301 -0
  24. package/src/api-client/index.ts +24 -5
  25. package/src/api-client/market-discovery.ts +14 -0
  26. package/src/api-client/members.ts +6 -0
  27. package/src/api-client/mna.ts +6 -0
  28. package/src/api-client/paths.ts +18 -1
  29. package/src/api-client/request.ts +26 -7
  30. package/src/api-client/short-side-publications.ts +37 -0
  31. package/src/api-client/socket.ts +64 -4
  32. package/src/api-client/swap-curve.ts +35 -0
  33. package/src/api-client/telemetry.ts +17 -0
  34. package/src/api-client/themes.ts +7 -1
  35. package/src/api-client/types.ts +90 -2
  36. package/src/app/global-shortcuts.ts +1 -16
  37. package/src/app/pane-runtime/plugin-bindings.ts +9 -2
  38. package/src/app/runtime/desktop-deeplink.ts +5 -5
  39. package/src/app/runtime/plugin-bindings.ts +2 -2
  40. package/src/app/runtime/startup.ts +13 -0
  41. package/src/app/runtime/update.ts +28 -8
  42. package/src/app/star-prompt/status-line.tsx +2 -2
  43. package/src/architecture/core-builtin-allowlist.json +5 -2
  44. package/src/architecture/pane-tabs-allowlist.json +65 -0
  45. package/src/architecture/ui-literals-allowlist.json +3 -3
  46. package/src/architecture/ui-tokens-allowlist.json +1 -1
  47. package/src/brokers/broker-portfolio-sync.ts +37 -0
  48. package/src/brokers/directory.ts +11 -0
  49. package/src/brokers/logos.ts +3 -1
  50. package/src/brokers/signed-in/adapter.ts +304 -26
  51. package/src/brokers/signed-in/client.ts +14 -2
  52. package/src/brokers/signed-in/connect.ts +10 -2
  53. package/src/brokers/sync-broker-instance.ts +9 -1
  54. package/src/capabilities/chart-series.ts +22 -6
  55. package/src/cli/bank-section.ts +1 -1
  56. package/src/cli/base-converter.ts +23 -14
  57. package/src/cli/central-bank-events.ts +1 -1
  58. package/src/cli/command-options.ts +59 -4
  59. package/src/cli/commands/api.ts +9 -6
  60. package/src/cli/commands/broker.ts +2 -2
  61. package/src/cli/commands/command-utils.ts +2 -2
  62. package/src/cli/commands/crypto-hints.ts +7 -20
  63. package/src/cli/commands/fred-series.ts +4 -2
  64. package/src/cli/commands/keybindings.ts +2 -2
  65. package/src/cli/commands/market.ts +1189 -296
  66. package/src/cli/commands/news-hints.ts +2 -2
  67. package/src/cli/commands/news-search.ts +59 -6
  68. package/src/cli/commands/options-leaps.ts +41 -26
  69. package/src/cli/commands/overview.ts +121 -48
  70. package/src/cli/commands/plugins.ts +9 -9
  71. package/src/cli/commands/remote.ts +13 -10
  72. package/src/cli/commands/search.ts +64 -44
  73. package/src/cli/commands/system.ts +27 -19
  74. package/src/cli/commands/themes.ts +1 -1
  75. package/src/cli/commands/ticker.ts +272 -70
  76. package/src/cli/context.ts +3 -2
  77. package/src/cli/desktop-pane-shot-view.ts +2 -2
  78. package/src/cli/desktop-pane-shot.ts +1 -1
  79. package/src/cli/earnings-calendar.ts +4 -4
  80. package/src/cli/entry.ts +18 -1
  81. package/src/cli/errors.ts +20 -2
  82. package/src/cli/exit-codes.ts +1 -1
  83. package/src/cli/export-source.ts +10 -4
  84. package/src/cli/freshness.ts +2 -8
  85. package/src/cli/fx-forward.ts +130 -0
  86. package/src/cli/fx-pair.ts +10 -9
  87. package/src/cli/glossary.ts +64 -20
  88. package/src/cli/help.ts +20 -14
  89. package/src/cli/history-export.ts +126 -0
  90. package/src/cli/history-rows.ts +196 -43
  91. package/src/cli/index-roots.ts +5 -45
  92. package/src/cli/index.ts +32 -18
  93. package/src/cli/issuer-membership.ts +103 -0
  94. package/src/cli/known-gaps.ts +118 -25
  95. package/src/cli/listing-arg.ts +315 -43
  96. package/src/cli/name-entries.ts +73 -22
  97. package/src/cli/native-smoke.ts +2 -0
  98. package/src/cli/not-a-ticker.ts +19 -9
  99. package/src/cli/opentui-libc.ts +5 -0
  100. package/src/cli/options.ts +12 -0
  101. package/src/cli/pane-functions/capabilities.ts +77 -20
  102. package/src/cli/pane-functions/catalog.ts +40 -23
  103. package/src/cli/pane-functions/discovery.ts +1 -1
  104. package/src/cli/pane-functions/dom.ts +12 -8
  105. package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
  106. package/src/cli/pane-functions/freshness.ts +174 -23
  107. package/src/cli/pane-functions/function-help.ts +66 -27
  108. package/src/cli/pane-functions/headless.ts +48 -16
  109. package/src/cli/pane-functions/index.ts +82 -21
  110. package/src/cli/pane-functions/options.ts +22 -2
  111. package/src/cli/pane-functions/report-notices.ts +12 -4
  112. package/src/cli/pane-functions/report.ts +5 -5
  113. package/src/cli/pane-functions/resolver.ts +65 -14
  114. package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
  115. package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
  116. package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
  117. package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
  118. package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
  119. package/src/cli/pane-functions/screenshot-payload.ts +453 -0
  120. package/src/cli/pane-functions/screenshot-render.ts +316 -0
  121. package/src/cli/pane-functions/screenshot-types.ts +162 -0
  122. package/src/cli/pane-functions/shot-options.ts +8 -3
  123. package/src/cli/peso-dollar-rates.ts +79 -0
  124. package/src/cli/quote-answer.ts +38 -3
  125. package/src/cli/report-tables.ts +190 -27
  126. package/src/cli/restore-plugins.ts +29 -14
  127. package/src/cli/result.ts +122 -25
  128. package/src/cli/series-search.ts +5 -5
  129. package/src/cli/statement-filings.ts +19 -0
  130. package/src/cli/suffixed-listing-rows.ts +49 -0
  131. package/src/cli/symbol-args.ts +50 -15
  132. package/src/cli/symbol-cells.ts +120 -0
  133. package/src/cli/symbol-list.ts +226 -60
  134. package/src/cli/symbol-rows.ts +131 -25
  135. package/src/cli/ticker-resolution.ts +108 -11
  136. package/src/cli/treasury-yields.ts +5 -5
  137. package/src/cli/types.ts +2 -0
  138. package/src/cli/uncovered-instrument.ts +3 -3
  139. package/src/cli/unknown-command.ts +6 -6
  140. package/src/components/chart/composite/chart-layout.ts +131 -0
  141. package/src/components/chart/composite/composite-chart.tsx +387 -21
  142. package/src/components/chart/composite/drawing-store.ts +26 -6
  143. package/src/components/chart/composite/interactions.ts +9 -3
  144. package/src/components/chart/composite/legend.tsx +75 -3
  145. package/src/components/chart/composite/levels.ts +5 -0
  146. package/src/components/chart/composite/panel-gestures.ts +41 -0
  147. package/src/components/chart/composite/panel-labels.ts +2 -1
  148. package/src/components/chart/composite/panel-surface.tsx +316 -11
  149. package/src/components/chart/composite/price-axis-labels.tsx +27 -3
  150. package/src/components/chart/composite/rasterizer.ts +44 -19
  151. package/src/components/chart/composite/scene.ts +16 -4
  152. package/src/components/chart/composite/text-renderer.ts +48 -21
  153. package/src/components/chart/composite/toolbar.tsx +52 -5
  154. package/src/components/chart/composite/types.ts +19 -0
  155. package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
  156. package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
  157. package/src/components/chart/composite/use-composite-viewport.ts +12 -3
  158. package/src/components/chart/composite/value-scale.ts +149 -0
  159. package/src/components/chart/composite/volume-profile-paint.ts +6 -3
  160. package/src/components/chart/core/pointer.ts +2 -0
  161. package/src/components/chart-table/index.ts +2 -0
  162. package/src/components/chart-table/read.tsx +74 -0
  163. package/src/components/command-bar/commands/collection-list.ts +41 -19
  164. package/src/components/command-bar/commands/collection.ts +9 -3
  165. package/src/components/command-bar/commands/direct/index.ts +1 -1
  166. package/src/components/command-bar/commands/direct/runtime.ts +3 -2
  167. package/src/components/command-bar/pane-templates/items.ts +59 -6
  168. package/src/components/command-bar/pane-templates/workflow.ts +10 -1
  169. package/src/components/command-bar/routes/root/command-items.ts +32 -6
  170. package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
  171. package/src/components/command-bar/routes/root/provider-search.ts +42 -11
  172. package/src/components/command-bar/routes/root/results.ts +18 -4
  173. package/src/components/command-bar/routes/root/runtime.ts +15 -3
  174. package/src/components/command-bar/routes/root/search-providers.ts +25 -2
  175. package/src/components/command-bar/routes/root/selection.ts +6 -1
  176. package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
  177. package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
  178. package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
  179. package/src/components/command-bar/selection-runtime.ts +50 -10
  180. package/src/components/command-bar/surface/index.tsx +24 -2
  181. package/src/components/command-bar/view-model.ts +7 -0
  182. package/src/components/command-bar/workflow/broker.ts +2 -2
  183. package/src/components/command-bar/workflow/collection-actions.ts +46 -7
  184. package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
  185. package/src/components/command-bar/workflow/fields.ts +8 -2
  186. package/src/components/command-bar/workflow/ops.ts +18 -4
  187. package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
  188. package/src/components/command-bar/workflow/submit.ts +3 -2
  189. package/src/components/command-bar/workflow/tickers.ts +5 -1
  190. package/src/components/company-logo.tsx +39 -0
  191. package/src/components/data-table/sections.ts +4 -2
  192. package/src/components/data-table/view.tsx +23 -3
  193. package/src/components/form-modal/confirm.tsx +2 -1
  194. package/src/components/form-modal/request.ts +5 -0
  195. package/src/components/form-modal/routes.ts +4 -1
  196. package/src/components/index.ts +13 -6
  197. package/src/components/layout/detached-pane-shell.tsx +1 -0
  198. package/src/components/layout/floating-pane.tsx +1 -0
  199. package/src/components/layout/header.tsx +234 -60
  200. package/src/components/layout/market-summary.ts +9 -6
  201. package/src/components/layout/pane/capture-status.ts +1 -1
  202. package/src/components/layout/pane/footer/model.ts +11 -5
  203. package/src/components/layout/pane/header.tsx +10 -3
  204. package/src/components/layout/pane/index.tsx +1 -0
  205. package/src/components/layout/pane/pane-tabs.tsx +9 -1
  206. package/src/components/layout/shell/chrome.ts +19 -6
  207. package/src/components/layout/shell/index.tsx +2 -1
  208. package/src/components/layout/shell/pane/layers.tsx +19 -1
  209. package/src/components/layout/status-bar.tsx +2 -2
  210. package/src/components/market-board/index.tsx +11 -3
  211. package/src/components/onboarding/onboarding-wizard.tsx +1 -0
  212. package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
  213. package/src/components/onboarding/wizard-broker-sync.ts +4 -1
  214. package/src/components/pane-settings-dialog/desktop.tsx +20 -7
  215. package/src/components/pane-settings-dialog/tui.tsx +17 -9
  216. package/src/components/pane-settings-dialog/value.ts +8 -1
  217. package/src/components/pane-settings-dialog.tsx +44 -13
  218. package/src/components/sign-in-code-panel.tsx +27 -19
  219. package/src/components/ui/column-grid.tsx +48 -4
  220. package/src/components/ui/country-flag-art.tsx +180 -0
  221. package/src/components/ui/country-flag.tsx +118 -12
  222. package/src/components/ui/data-table/opentui/index.tsx +61 -2
  223. package/src/components/ui/data-table/opentui/model.ts +109 -2
  224. package/src/components/ui/data-table/types.ts +1 -1
  225. package/src/components/ui/display.tsx +5 -1
  226. package/src/components/ui/index.ts +3 -1
  227. package/src/components/ui/logo-mark.tsx +11 -2
  228. package/src/components/ui/query-bar.tsx +1 -1
  229. package/src/components/ui/row-notes.ts +79 -0
  230. package/src/components/ui/stat-grid.tsx +28 -3
  231. package/src/components/ui/status.tsx +3 -1
  232. package/src/core/app-services.ts +4 -0
  233. package/src/core/state/app/layout.ts +4 -4
  234. package/src/data/cached-query.ts +8 -1
  235. package/src/data/config/chart-settings.ts +3 -3
  236. package/src/data/config/home.ts +10 -2
  237. package/src/data/config/layout.ts +4 -1
  238. package/src/data/config/store/node.ts +4 -0
  239. package/src/data/config/store/normalize.ts +13 -3
  240. package/src/data/config/store/portfolio-as-of-column.ts +2 -2
  241. package/src/data/json-storage.ts +2 -0
  242. package/src/data/saved-copies.ts +84 -0
  243. package/src/docs/snapshot.json +65 -32
  244. package/src/i18n/es.ts +51 -12
  245. package/src/i18n/ja.ts +51 -12
  246. package/src/i18n/ko.ts +51 -12
  247. package/src/i18n/zh-cn.ts +51 -12
  248. package/src/i18n/zh-tw.ts +51 -12
  249. package/src/layout/desks.ts +1 -1
  250. package/src/layout/launch-layout.ts +1 -1
  251. package/src/layout/pane-manager/floating-actions.ts +5 -3
  252. package/src/layout/pane-manager/floating.ts +43 -1
  253. package/src/layout/pane-manager/index.ts +2 -0
  254. package/src/layout/selected-ticker.ts +74 -0
  255. package/src/market-data/depositary-pair.ts +251 -0
  256. package/src/market-data/futures-board.ts +1 -1
  257. package/src/market-data/futures-contract.ts +124 -40
  258. package/src/market-data/fx-closes.ts +17 -2
  259. package/src/market-data/hooks.tsx +19 -11
  260. package/src/market-data/market/change-basis.ts +49 -7
  261. package/src/market-data/market/freshness.ts +34 -5
  262. package/src/market-data/market/period-return.ts +163 -0
  263. package/src/market-data/market/trading-sessions.ts +13 -0
  264. package/src/market-data/market/year-to-date.ts +8 -13
  265. package/src/market-data/performance.ts +20 -14
  266. package/src/market-data/perpetual-premium.ts +32 -0
  267. package/src/market-data/published-apac-sessions.ts +2 -1
  268. package/src/market-data/published-futures-sessions.ts +69 -0
  269. package/src/market-data/quotes/contributions.ts +5 -1
  270. package/src/market-data/quotes/freshness.ts +42 -0
  271. package/src/market-data/quotes/intraday-bar.ts +37 -0
  272. package/src/market-data/quotes/regular-session-valuation.ts +13 -8
  273. package/src/market-data/quotes/resolution.ts +4 -2
  274. package/src/market-data/tax-equivalent.ts +1 -1
  275. package/src/market-data/ticker-price-returns.ts +3 -1
  276. package/src/news/aggregator.ts +5 -1
  277. package/src/news/news-model.ts +4 -0
  278. package/src/news/types.ts +11 -0
  279. package/src/notifications/app-notifier.ts +1 -1
  280. package/src/plugins/auto-update.ts +2 -2
  281. package/src/plugins/builtin/account-management/index.tsx +1 -0
  282. package/src/plugins/builtin/account-management/pane.tsx +9 -8
  283. package/src/plugins/builtin/alerts/alert-engine.ts +30 -18
  284. package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
  285. package/src/plugins/builtin/alerts/cli.ts +485 -76
  286. package/src/plugins/builtin/alerts/command.ts +5 -10
  287. package/src/plugins/builtin/alerts/event-rows.ts +9 -5
  288. package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
  289. package/src/plugins/builtin/alerts/events.ts +108 -5
  290. package/src/plugins/builtin/alerts/fired-log.ts +78 -0
  291. package/src/plugins/builtin/alerts/format.ts +2 -1
  292. package/src/plugins/builtin/alerts/headless.ts +100 -39
  293. package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
  294. package/src/plugins/builtin/alerts/history-rows.ts +89 -0
  295. package/src/plugins/builtin/alerts/index.tsx +45 -18
  296. package/src/plugins/builtin/alerts/iv-level.ts +365 -0
  297. package/src/plugins/builtin/alerts/levels.ts +3 -3
  298. package/src/plugins/builtin/alerts/pane.tsx +97 -29
  299. package/src/plugins/builtin/alerts/price.ts +35 -0
  300. package/src/plugins/builtin/alerts/quotes.ts +24 -0
  301. package/src/plugins/builtin/alerts/research-builder.ts +84 -11
  302. package/src/plugins/builtin/alerts/research-rules.ts +77 -3
  303. package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
  304. package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
  305. package/src/plugins/builtin/alerts/scheduled.ts +188 -29
  306. package/src/plugins/builtin/alerts/storage.ts +13 -10
  307. package/src/plugins/builtin/alerts/targets.ts +12 -3
  308. package/src/plugins/builtin/analytics/index.tsx +8 -2
  309. package/src/plugins/builtin/analytics/metrics.ts +1 -1
  310. package/src/plugins/builtin/analytics/risk-book.ts +215 -0
  311. package/src/plugins/builtin/analytics/risk-client.ts +13 -6
  312. package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
  313. package/src/plugins/builtin/analytics/risk-math.ts +6 -3
  314. package/src/plugins/builtin/analytics/risk-model.ts +297 -104
  315. package/src/plugins/builtin/analytics/risk-options.ts +17 -2
  316. package/src/plugins/builtin/analytics/risk-pane.tsx +107 -43
  317. package/src/plugins/builtin/attention/pane.tsx +22 -16
  318. package/src/plugins/builtin/awards/headless.ts +7 -3
  319. package/src/plugins/builtin/awards/model.ts +18 -0
  320. package/src/plugins/builtin/awards/pane.tsx +12 -9
  321. package/src/plugins/builtin/backtest/export.ts +1 -1
  322. package/src/plugins/builtin/backtest/headless.ts +3 -3
  323. package/src/plugins/builtin/backtest/rules.ts +41 -5
  324. package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
  325. package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
  326. package/src/plugins/builtin/broker-manager/footer.ts +27 -11
  327. package/src/plugins/builtin/broker-manager/index.tsx +21 -12
  328. package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
  329. package/src/plugins/builtin/broker-manager/model.ts +12 -2
  330. package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
  331. package/src/plugins/builtin/broker-manager/table.ts +28 -12
  332. package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
  333. package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
  334. package/src/plugins/builtin/broker-trading/controller.ts +45 -13
  335. package/src/plugins/builtin/broker-trading/dock.tsx +24 -4
  336. package/src/plugins/builtin/broker-trading/headless.ts +2 -1
  337. package/src/plugins/builtin/broker-trading/index.tsx +7 -1
  338. package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
  339. package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
  340. package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
  341. package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
  342. package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
  343. package/src/plugins/builtin/broker-trading/pane.tsx +115 -26
  344. package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
  345. package/src/plugins/builtin/broker-trading/ticket.tsx +122 -36
  346. package/src/plugins/builtin/buildout/cells.tsx +4 -0
  347. package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
  348. package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
  349. package/src/plugins/builtin/buildout/pane/index.tsx +34 -18
  350. package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
  351. package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
  352. package/src/plugins/builtin/catalysts/client.ts +2 -2
  353. package/src/plugins/builtin/catalysts/detail.tsx +3 -2
  354. package/src/plugins/builtin/catalysts/index.tsx +1 -1
  355. package/src/plugins/builtin/catalysts/model.ts +49 -4
  356. package/src/plugins/builtin/catalysts/pane.tsx +9 -11
  357. package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
  358. package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
  359. package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
  360. package/src/plugins/builtin/changelog/index.tsx +1 -0
  361. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
  362. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
  363. package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
  364. package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
  365. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
  366. package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
  367. package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
  368. package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
  369. package/src/plugins/builtin/chart-composer/headless.ts +253 -35
  370. package/src/plugins/builtin/chart-composer/index.tsx +12 -2
  371. package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
  372. package/src/plugins/builtin/chart-composer/pane.tsx +128 -28
  373. package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
  374. package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
  375. package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
  376. package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
  377. package/src/plugins/builtin/chart-composer/settings.ts +31 -19
  378. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
  379. package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
  380. package/src/plugins/builtin/chat/attachments/model.ts +3 -1
  381. package/src/plugins/builtin/chat/content/index.tsx +1 -1
  382. package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
  383. package/src/plugins/builtin/chat/people.ts +1 -1
  384. package/src/plugins/builtin/clinical-trials/client.ts +5 -2
  385. package/src/plugins/builtin/clinical-trials/model.ts +13 -4
  386. package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
  387. package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
  388. package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
  389. package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
  390. package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
  391. package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
  392. package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
  393. package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
  394. package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
  395. package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
  396. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  397. package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
  398. package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
  399. package/src/plugins/builtin/commodity-balances/pane.tsx +14 -8
  400. package/src/plugins/builtin/company-attention/app-rank.tsx +11 -10
  401. package/src/plugins/builtin/company-attention/building-model.ts +222 -0
  402. package/src/plugins/builtin/company-attention/building.tsx +172 -0
  403. package/src/plugins/builtin/company-attention/client.ts +117 -1
  404. package/src/plugins/builtin/company-attention/evidence.ts +16 -3
  405. package/src/plugins/builtin/company-attention/headless.ts +101 -5
  406. package/src/plugins/builtin/company-attention/index.tsx +6 -3
  407. package/src/plugins/builtin/company-attention/model.ts +33 -7
  408. package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
  409. package/src/plugins/builtin/company-attention/moves.tsx +159 -0
  410. package/src/plugins/builtin/company-attention/pane.tsx +89 -31
  411. package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
  412. package/src/plugins/builtin/company-attention/signals.tsx +160 -0
  413. package/src/plugins/builtin/company-kpis/headless.ts +3 -2
  414. package/src/plugins/builtin/company-kpis/model.ts +2 -2
  415. package/src/plugins/builtin/company-kpis/pane.tsx +5 -4
  416. package/src/plugins/builtin/composite-plugins.ts +2 -1
  417. package/src/plugins/builtin/congress-trades/headless.ts +1 -1
  418. package/src/plugins/builtin/connections/index.ts +1 -0
  419. package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
  420. package/src/plugins/builtin/correlation/headless.ts +7 -4
  421. package/src/plugins/builtin/correlation/relationship/model.ts +1 -0
  422. package/src/plugins/builtin/correlation/settings.ts +1 -0
  423. package/src/plugins/builtin/cot/headless.ts +28 -6
  424. package/src/plugins/builtin/cot/model.ts +12 -0
  425. package/src/plugins/builtin/cot/pane.tsx +7 -5
  426. package/src/plugins/builtin/cpi/headless.ts +5 -1
  427. package/src/plugins/builtin/cpi/pane.tsx +11 -9
  428. package/src/plugins/builtin/credit-boards/model.ts +2 -0
  429. package/src/plugins/builtin/credit-documents/headless.ts +1 -1
  430. package/src/plugins/builtin/credit-documents/pane.tsx +8 -7
  431. package/src/plugins/builtin/crypto-board/client.ts +86 -0
  432. package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
  433. package/src/plugins/builtin/crypto-board/defi.ts +239 -0
  434. package/src/plugins/builtin/crypto-board/headless.ts +117 -6
  435. package/src/plugins/builtin/crypto-board/index.tsx +8 -3
  436. package/src/plugins/builtin/crypto-board/model.ts +40 -8
  437. package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
  438. package/src/plugins/builtin/crypto-board/series.ts +19 -1
  439. package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
  440. package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
  441. package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
  442. package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
  443. package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
  444. package/src/plugins/builtin/debt-maturities/pane.tsx +4 -3
  445. package/src/plugins/builtin/debug/index.tsx +1 -0
  446. package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
  447. package/src/plugins/builtin/docs/index.tsx +1 -1
  448. package/src/plugins/builtin/docs/pane.tsx +2 -2
  449. package/src/plugins/builtin/docs/targets.ts +1 -1
  450. package/src/plugins/builtin/doe/client.ts +5 -1
  451. package/src/plugins/builtin/doe/headless.ts +12 -6
  452. package/src/plugins/builtin/doe/model.ts +43 -6
  453. package/src/plugins/builtin/doe/pane.tsx +19 -12
  454. package/src/plugins/builtin/earnings/board-model.ts +13 -6
  455. package/src/plugins/builtin/earnings/board-table.ts +4 -1
  456. package/src/plugins/builtin/earnings/board.tsx +253 -50
  457. package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
  458. package/src/plugins/builtin/earnings/calendar.tsx +338 -0
  459. package/src/plugins/builtin/earnings/client.ts +4 -3
  460. package/src/plugins/builtin/earnings/headless.ts +53 -15
  461. package/src/plugins/builtin/earnings/history-model.ts +53 -36
  462. package/src/plugins/builtin/earnings/index.tsx +15 -22
  463. package/src/plugins/builtin/earnings/model.ts +17 -12
  464. package/src/plugins/builtin/earnings/scope.ts +89 -0
  465. package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
  466. package/src/plugins/builtin/earnings-calls/data.ts +146 -2
  467. package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
  468. package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
  469. package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
  470. package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
  471. package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
  472. package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
  473. package/src/plugins/builtin/econ/calendar-model.ts +132 -20
  474. package/src/plugins/builtin/econ/detail-view.tsx +48 -10
  475. package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
  476. package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
  477. package/src/plugins/builtin/econ/index.tsx +112 -25
  478. package/src/plugins/builtin/econ/print-watch.ts +2 -1
  479. package/src/plugins/builtin/econ/types.ts +32 -1
  480. package/src/plugins/builtin/econ-statistics/client.ts +16 -3
  481. package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
  482. package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
  483. package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
  484. package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
  485. package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
  486. package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
  487. package/src/plugins/builtin/econ-statistics/view.ts +16 -1
  488. package/src/plugins/builtin/equity-screener/client.ts +21 -3
  489. package/src/plugins/builtin/equity-screener/headless.ts +77 -5
  490. package/src/plugins/builtin/equity-screener/live.ts +1 -1
  491. package/src/plugins/builtin/equity-screener/model.ts +34 -0
  492. package/src/plugins/builtin/equity-screener/pane.tsx +148 -106
  493. package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
  494. package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
  495. package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
  496. package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
  497. package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
  498. package/src/plugins/builtin/exposure/headless.ts +51 -6
  499. package/src/plugins/builtin/exposure/index.tsx +28 -2
  500. package/src/plugins/builtin/exposure/model.ts +7 -0
  501. package/src/plugins/builtin/exposure/pane.tsx +16 -10
  502. package/src/plugins/builtin/fear-greed/index.tsx +1 -1
  503. package/src/plugins/builtin/filing-events/index.tsx +1 -1
  504. package/src/plugins/builtin/futures/model.ts +10 -9
  505. package/src/plugins/builtin/futures/returns.ts +8 -36
  506. package/src/plugins/builtin/futures/table.tsx +1 -1
  507. package/src/plugins/builtin/futures-curve/client.ts +40 -9
  508. package/src/plugins/builtin/futures-curve/headless.ts +39 -17
  509. package/src/plugins/builtin/futures-curve/model.ts +258 -69
  510. package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
  511. package/src/plugins/builtin/fx-matrix/client.ts +15 -8
  512. package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
  513. package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
  514. package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
  515. package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
  516. package/src/plugins/builtin/gpu/board.tsx +4 -1
  517. package/src/plugins/builtin/gpu/changes.tsx +10 -10
  518. package/src/plugins/builtin/gpu/equities.tsx +4 -1
  519. package/src/plugins/builtin/gpu/headless.ts +9 -4
  520. package/src/plugins/builtin/gpu/history.tsx +4 -2
  521. package/src/plugins/builtin/gpu/pane.tsx +5 -3
  522. package/src/plugins/builtin/help/index.tsx +13 -3
  523. package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
  524. package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
  525. package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
  526. package/src/plugins/builtin/holders/client.ts +15 -2
  527. package/src/plugins/builtin/holders/format.ts +28 -17
  528. package/src/plugins/builtin/holders/headless.ts +48 -8
  529. package/src/plugins/builtin/holders/index-holders.ts +264 -0
  530. package/src/plugins/builtin/holders/pane.tsx +79 -15
  531. package/src/plugins/builtin/holders/report-rows.ts +35 -7
  532. package/src/plugins/builtin/holders/table-model.ts +2 -1
  533. package/src/plugins/builtin/holders/thirteenf-match.ts +3 -1
  534. package/src/plugins/builtin/holders/treemap.tsx +2 -2
  535. package/src/plugins/builtin/insider/base-values.ts +11 -7
  536. package/src/plugins/builtin/insider/client.ts +3 -0
  537. package/src/plugins/builtin/insider/headless.ts +20 -7
  538. package/src/plugins/builtin/insider/index.tsx +17 -8
  539. package/src/plugins/builtin/insider/issuer.ts +34 -4
  540. package/src/plugins/builtin/insider/signals-client.ts +3 -3
  541. package/src/plugins/builtin/insider/signals.tsx +1 -1
  542. package/src/plugins/builtin/insider/table-model.ts +35 -13
  543. package/src/plugins/builtin/insider/table.tsx +5 -2
  544. package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
  545. package/src/plugins/builtin/iv-history/client.ts +20 -0
  546. package/src/plugins/builtin/iv-history/events.ts +145 -0
  547. package/src/plugins/builtin/iv-history/format.ts +3 -0
  548. package/src/plugins/builtin/iv-history/headless.ts +91 -7
  549. package/src/plugins/builtin/iv-history/index.tsx +1 -1
  550. package/src/plugins/builtin/iv-history/model.ts +13 -4
  551. package/src/plugins/builtin/iv-history/series.ts +3 -1
  552. package/src/plugins/builtin/jobs/lock-note.ts +1 -1
  553. package/src/plugins/builtin/jobs/model.ts +4 -15
  554. package/src/plugins/builtin/jobs/pane.tsx +7 -5
  555. package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
  556. package/src/plugins/builtin/jodi/pane.tsx +14 -8
  557. package/src/plugins/builtin/layout-manager/index.tsx +1 -0
  558. package/src/plugins/builtin/macro-day/headless.ts +20 -7
  559. package/src/plugins/builtin/macro-day/index.tsx +3 -2
  560. package/src/plugins/builtin/macro-day/model.ts +29 -8
  561. package/src/plugins/builtin/macro-day/pane.tsx +46 -10
  562. package/src/plugins/builtin/macro-day/releases.ts +55 -13
  563. package/src/plugins/builtin/market-heatmap/data.ts +9 -2
  564. package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
  565. package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
  566. package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
  567. package/src/plugins/builtin/market-heatmap/model.ts +10 -7
  568. package/src/plugins/builtin/market-movers/client.ts +36 -21
  569. package/src/plugins/builtin/market-movers/headless.ts +8 -2
  570. package/src/plugins/builtin/market-movers/index.tsx +16 -10
  571. package/src/plugins/builtin/market-movers/screener.ts +33 -11
  572. package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
  573. package/src/plugins/builtin/market-movers/session-table.ts +4 -2
  574. package/src/plugins/builtin/market-movers/table.ts +4 -1
  575. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  576. package/src/plugins/builtin/market-valuation/view.ts +5 -0
  577. package/src/plugins/builtin/members/headless.ts +6 -5
  578. package/src/plugins/builtin/members/pane.tsx +11 -4
  579. package/src/plugins/builtin/mna/client.ts +1 -0
  580. package/src/plugins/builtin/mna/detail.tsx +20 -32
  581. package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
  582. package/src/plugins/builtin/mna/distress/model.ts +3 -2
  583. package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
  584. package/src/plugins/builtin/mna/headless.ts +6 -13
  585. package/src/plugins/builtin/mna/model.ts +93 -15
  586. package/src/plugins/builtin/mna/pane.tsx +5 -4
  587. package/src/plugins/builtin/news/headless.ts +12 -6
  588. package/src/plugins/builtin/news/index.tsx +10 -1
  589. package/src/plugins/builtin/news/wire/index.tsx +3 -2
  590. package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
  591. package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
  592. package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
  593. package/src/plugins/builtin/notes/cli.ts +50 -15
  594. package/src/plugins/builtin/notes/export.ts +17 -6
  595. package/src/plugins/builtin/notes/files.ts +16 -5
  596. package/src/plugins/builtin/openfda/pane.tsx +1 -1
  597. package/src/plugins/builtin/options/carry.ts +2 -2
  598. package/src/plugins/builtin/options/enrichment-model.ts +10 -9
  599. package/src/plugins/builtin/options/index.tsx +1 -1
  600. package/src/plugins/builtin/options/model-spot.ts +70 -4
  601. package/src/plugins/builtin/options/view.tsx +51 -23
  602. package/src/plugins/builtin/options-calculator/headless.ts +46 -7
  603. package/src/plugins/builtin/options-calculator/pane.tsx +3 -2
  604. package/src/plugins/builtin/options-positioning/headless.ts +11 -3
  605. package/src/plugins/builtin/options-positioning/model.ts +24 -0
  606. package/src/plugins/builtin/options-positioning/pane.tsx +10 -12
  607. package/src/plugins/builtin/options-scenario/client.ts +142 -29
  608. package/src/plugins/builtin/options-scenario/collar.ts +8 -6
  609. package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
  610. package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
  611. package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
  612. package/src/plugins/builtin/options-scenario/csp.ts +101 -21
  613. package/src/plugins/builtin/options-scenario/headless.ts +49 -21
  614. package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
  615. package/src/plugins/builtin/options-scenario/index.tsx +28 -3
  616. package/src/plugins/builtin/options-scenario/model.ts +13 -0
  617. package/src/plugins/builtin/options-scenario/pane.tsx +22 -10
  618. package/src/plugins/builtin/perps/equity-row.tsx +11 -3
  619. package/src/plugins/builtin/perps/freshness.ts +8 -5
  620. package/src/plugins/builtin/perps/headless.ts +3 -1
  621. package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
  622. package/src/plugins/builtin/perps/live-rows.ts +161 -0
  623. package/src/plugins/builtin/perps/markets-section.tsx +154 -0
  624. package/src/plugins/builtin/perps/pane.tsx +36 -17
  625. package/src/plugins/builtin/perps/venue-markets.ts +96 -0
  626. package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
  627. package/src/plugins/builtin/plugin-marketplace/pane.tsx +145 -60
  628. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +78 -27
  629. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
  630. package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
  631. package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
  632. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
  633. package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
  634. package/src/plugins/builtin/portfolio-list/income.ts +13 -2
  635. package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
  636. package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
  637. package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
  638. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
  639. package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
  640. package/src/plugins/builtin/power/client.ts +6 -3
  641. package/src/plugins/builtin/power/evidence.ts +22 -7
  642. package/src/plugins/builtin/power/gas.tsx +5 -1
  643. package/src/plugins/builtin/power/pane.tsx +44 -32
  644. package/src/plugins/builtin/power/prices.tsx +10 -3
  645. package/src/plugins/builtin/research/analyst-headless.ts +25 -8
  646. package/src/plugins/builtin/research/analyst-model.ts +68 -3
  647. package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
  648. package/src/plugins/builtin/research/event-model.ts +3 -1
  649. package/src/plugins/builtin/research/event-sources.ts +12 -4
  650. package/src/plugins/builtin/research/index.tsx +2 -1
  651. package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
  652. package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
  653. package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
  654. package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
  655. package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
  656. package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
  657. package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
  658. package/src/plugins/builtin/reverse-dcf/client.ts +2 -1
  659. package/src/plugins/builtin/reverse-dcf/model.ts +10 -5
  660. package/src/plugins/builtin/risk-factors/index.tsx +2 -2
  661. package/src/plugins/builtin/scanner/lock-note.ts +1 -1
  662. package/src/plugins/builtin/seasonality/client.ts +2 -1
  663. package/src/plugins/builtin/sec/forms.ts +13 -0
  664. package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
  665. package/src/plugins/builtin/sec/fund-facts.ts +68 -8
  666. package/src/plugins/builtin/sec/headless.ts +85 -8
  667. package/src/plugins/builtin/sec/index.tsx +58 -12
  668. package/src/plugins/builtin/sectors/client.ts +6 -4
  669. package/src/plugins/builtin/sectors/sector-model.ts +11 -15
  670. package/src/plugins/builtin/series-inventory.ts +2 -0
  671. package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
  672. package/src/plugins/builtin/shared/cloud-resource.ts +15 -2
  673. package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
  674. package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
  675. package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
  676. package/src/plugins/builtin/shared/earnings-report.ts +3 -3
  677. package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
  678. package/src/plugins/builtin/shared/job-posting.ts +129 -0
  679. package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
  680. package/src/plugins/builtin/shared/report-freshness.ts +3 -0
  681. package/src/plugins/builtin/shared/research-trading.tsx +23 -0
  682. package/src/plugins/builtin/shared/series-cache.ts +2 -0
  683. package/src/plugins/builtin/shared/series-list-detail.tsx +3 -1
  684. package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
  685. package/src/plugins/builtin/shared/volatility/options.ts +2 -1
  686. package/src/plugins/builtin/short-interest/client.ts +2 -0
  687. package/src/plugins/builtin/short-interest/headless.ts +41 -12
  688. package/src/plugins/builtin/short-interest/index.tsx +23 -1
  689. package/src/plugins/builtin/short-interest/model.ts +70 -19
  690. package/src/plugins/builtin/short-interest/pane.tsx +19 -2
  691. package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
  692. package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
  693. package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
  694. package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
  695. package/src/plugins/builtin/short-interest/schedule.ts +35 -2
  696. package/src/plugins/builtin/short-interest/surface.tsx +11 -4
  697. package/src/plugins/builtin/short-interest/types.ts +9 -0
  698. package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
  699. package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
  700. package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
  701. package/src/plugins/builtin/social-mentions/client.ts +2 -1
  702. package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
  703. package/src/plugins/builtin/supply-chain/model.ts +51 -3
  704. package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
  705. package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
  706. package/src/plugins/builtin/themes/headless.ts +8 -5
  707. package/src/plugins/builtin/themes/model.ts +14 -4
  708. package/src/plugins/builtin/themes/pane.tsx +24 -5
  709. package/src/plugins/builtin/thirteenf/headless.ts +5 -5
  710. package/src/plugins/builtin/thirteenf/signals.ts +3 -1
  711. package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
  712. package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
  713. package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
  714. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
  715. package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
  716. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
  717. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
  718. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
  719. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
  720. package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
  721. package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
  722. package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
  723. package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
  724. package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
  725. package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
  726. package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
  727. package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
  728. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
  729. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
  730. package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
  731. package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
  732. package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
  733. package/src/plugins/builtin/vol-surface/client.ts +28 -7
  734. package/src/plugins/builtin/vol-surface/headless.ts +43 -15
  735. package/src/plugins/builtin/vol-surface/model.ts +34 -12
  736. package/src/plugins/builtin/vol-surface/pane.tsx +33 -13
  737. package/src/plugins/builtin/vol-surface/stored.ts +34 -3
  738. package/src/plugins/builtin/vol-surface/tables.ts +14 -0
  739. package/src/plugins/builtin/volatility/model.ts +5 -10
  740. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
  741. package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
  742. package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
  743. package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
  744. package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
  745. package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
  746. package/src/plugins/builtin/world-venue-map/index.ts +3 -26
  747. package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
  748. package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
  749. package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
  750. package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
  751. package/src/plugins/builtin/yield-curve/client.ts +25 -0
  752. package/src/plugins/builtin/yield-curve/curves.ts +7 -4
  753. package/src/plugins/builtin/yield-curve/headless.ts +38 -4
  754. package/src/plugins/builtin/yield-curve/history.ts +4 -3
  755. package/src/plugins/builtin/yield-curve/index.tsx +12 -6
  756. package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
  757. package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
  758. package/src/plugins/bundle.ts +1 -1
  759. package/src/plugins/catalog-browser.ts +2 -1
  760. package/src/plugins/compat.ts +3 -3
  761. package/src/plugins/dependencies.ts +75 -14
  762. package/src/plugins/extracted-plugins.ts +132 -34
  763. package/src/plugins/host-link.ts +149 -34
  764. package/src/plugins/installer.ts +35 -10
  765. package/src/plugins/loader.ts +206 -38
  766. package/src/plugins/manager-node.ts +2 -2
  767. package/src/plugins/marketplace/deactivation.ts +22 -0
  768. package/src/plugins/marketplace/model.ts +2 -2
  769. package/src/plugins/marketplace/packs.ts +1 -1
  770. package/src/plugins/ownership.ts +1 -1
  771. package/src/plugins/peer-retry.ts +155 -0
  772. package/src/plugins/registry/contributions.ts +3 -1
  773. package/src/plugins/registry/index.ts +4 -3
  774. package/src/plugins/registry/plugin-state.ts +3 -0
  775. package/src/plugins/seed-notice.ts +20 -0
  776. package/src/plugins/shortcut-argument.ts +39 -0
  777. package/src/portfolio/allocation.ts +1 -1
  778. package/src/portfolio/collection-name.ts +31 -0
  779. package/src/portfolio/column-values.ts +10 -8
  780. package/src/portfolio/cost-fx.ts +296 -19
  781. package/src/portfolio/manual-lots.ts +75 -0
  782. package/src/portfolio/mutations.ts +60 -22
  783. package/src/portfolio/suffixed-listings.ts +209 -0
  784. package/src/portfolio/totals-currency.ts +24 -0
  785. package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
  786. package/src/public/time-series.ts +11 -8
  787. package/src/remote/schema.ts +1 -1
  788. package/src/renderers/browser/config-host.ts +3 -0
  789. package/src/renderers/browser/main.tsx +23 -3
  790. package/src/renderers/dom/boot-frame-page.ts +187 -0
  791. package/src/renderers/dom/boot-frame.ts +237 -0
  792. package/src/renderers/dom/build-assets.ts +46 -8
  793. package/src/renderers/dom/desktop/controls.tsx +1 -1
  794. package/src/renderers/dom/desktop/query-bar.tsx +2 -0
  795. package/src/renderers/dom/dom-ui-host.tsx +4 -29
  796. package/src/renderers/dom/host/ascii-text.ts +16 -2
  797. package/src/renderers/dom/host/box.tsx +43 -2
  798. package/src/renderers/dom/host/chart-surface.tsx +2 -0
  799. package/src/renderers/dom/host/hls.chunk.ts +3 -0
  800. package/src/renderers/dom/host/image-surface.tsx +49 -0
  801. package/src/renderers/dom/host/media-surface.tsx +24 -18
  802. package/src/renderers/dom/host/mouse.ts +30 -0
  803. package/src/renderers/dom/host/size-observer.ts +1 -1
  804. package/src/renderers/dom/host/style.ts +1 -1
  805. package/src/renderers/dom/host/tabs.tsx +16 -5
  806. package/src/renderers/dom/host/top-surface.ts +127 -0
  807. package/src/renderers/dom/styles.css +115 -0
  808. package/src/renderers/dom/test-utils.tsx +2 -1
  809. package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
  810. package/src/renderers/electrobun/bun/core-capabilities.ts +9 -1
  811. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
  812. package/src/renderers/electrobun/bun/desktop/backend.ts +56 -3
  813. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
  814. package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
  815. package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
  816. package/src/renderers/electrobun/bun/desktop/update.ts +210 -30
  817. package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
  818. package/src/renderers/electrobun/bun/index.ts +11 -1
  819. package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
  820. package/src/renderers/electrobun/bun/window/create.ts +4 -1
  821. package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
  822. package/src/renderers/electrobun/shared/protocol.ts +6 -1
  823. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
  824. package/src/renderers/electrobun/view/config-host.ts +3 -0
  825. package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
  826. package/src/renderers/electrobun/view/main.tsx +30 -4
  827. package/src/renderers/electrobun/view/news-source.ts +9 -7
  828. package/src/renderers/electrobun/view/remote/asset-data-client.ts +9 -2
  829. package/src/renderers/electrobun/view/ui-host.tsx +1 -1
  830. package/src/renderers/opentui/browser-open.ts +88 -0
  831. package/src/renderers/opentui/host.tsx +5 -14
  832. package/src/renderers/opentui/image/loader.ts +3 -2
  833. package/src/renderers/opentui/native-smoke.ts +10 -1
  834. package/src/renderers/opentui/pane-image/index.ts +2 -1
  835. package/src/renderers/opentui/render-lib.ts +253 -0
  836. package/src/renderers/opentui/render-timing-smoke.ts +1 -1
  837. package/src/renderers/opentui/start.tsx +8 -1
  838. package/src/renderers/share/layout-view.tsx +2 -2
  839. package/src/renderers/share/main.tsx +4 -4
  840. package/src/renderers/share/view.tsx +1 -1
  841. package/src/series/resolve.ts +22 -6
  842. package/src/series/standalone.ts +30 -2
  843. package/src/series/types.ts +8 -1
  844. package/src/shares/api.ts +4 -1
  845. package/src/shares/pane.ts +1 -1
  846. package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
  847. package/src/sources/gloomberb-cloud/index.ts +39 -16
  848. package/src/sources/gloomberb-cloud/news.ts +39 -0
  849. package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
  850. package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
  851. package/src/sources/listing-symbols.ts +37 -0
  852. package/src/sources/provider-errors.ts +16 -2
  853. package/src/sources/provider-router/financial-routes.ts +21 -3
  854. package/src/sources/provider-router/financials.ts +15 -2
  855. package/src/sources/provider-router/history.ts +30 -8
  856. package/src/sources/provider-router/index.ts +16 -0
  857. package/src/sources/provider-router/primary.ts +1 -1
  858. package/src/state/app/bootstrap.ts +23 -0
  859. package/src/state/hooks/inline-tickers.ts +30 -5
  860. package/src/sync/controller.ts +1 -1
  861. package/src/sync/core-contributors.ts +46 -14
  862. package/src/team/collections-sync.ts +2 -1
  863. package/src/team/collections.ts +178 -17
  864. package/src/telemetry/crash-reports.ts +21 -4
  865. package/src/telemetry/update-failures-node.ts +59 -0
  866. package/src/telemetry/update-failures.ts +307 -0
  867. package/src/test-support/builtin-panes.ts +1 -1
  868. package/src/theme/colors.ts +3 -30
  869. package/src/theme/ui-tokens.ts +37 -1
  870. package/src/tickers/company-name-listing.ts +215 -36
  871. package/src/tickers/company-name.ts +43 -0
  872. package/src/tickers/index-roots.ts +47 -0
  873. package/src/tickers/instrument-label.ts +5 -1
  874. package/src/tickers/listing-fate.ts +30 -0
  875. package/src/tickers/metadata.ts +10 -0
  876. package/src/tickers/perpetual-listing.ts +5 -2
  877. package/src/tickers/search/home-listing.ts +75 -0
  878. package/src/tickers/search/index.ts +76 -27
  879. package/src/tickers/search/ranking.ts +54 -4
  880. package/src/tickers/search/upsert.ts +29 -0
  881. package/src/tickers/terminal-codes.ts +416 -40
  882. package/src/time-series/bar-aggregation.ts +243 -0
  883. package/src/time-series/base-series.ts +307 -0
  884. package/src/time-series/chart-bounds.ts +349 -0
  885. package/src/time-series/chart-seed.ts +142 -0
  886. package/src/time-series/economic.ts +5 -0
  887. package/src/time-series/fundamentals.ts +18 -3
  888. package/src/time-series/history-acquisition.ts +499 -0
  889. package/src/time-series/leverage.ts +100 -0
  890. package/src/time-series/market-resolution.ts +4 -2
  891. package/src/time-series/market.ts +2 -1
  892. package/src/time-series/price-comparison.ts +175 -30
  893. package/src/time-series/range.ts +9 -1
  894. package/src/time-series/resolution.ts +174 -16
  895. package/src/time-series/resolve-context.ts +157 -0
  896. package/src/time-series/resolve.ts +126 -1577
  897. package/src/time-series/series-name.ts +38 -0
  898. package/src/time-series/series-presentation.ts +208 -0
  899. package/src/time-series/spec.ts +11 -6
  900. package/src/time-series/studies.ts +109 -12
  901. package/src/time-series/tail-reconcile.ts +121 -0
  902. package/src/time-series/types.ts +29 -2
  903. package/src/time-series/use-chart-resolution.ts +4 -5
  904. package/src/types/broker.ts +10 -0
  905. package/src/types/config.ts +14 -0
  906. package/src/types/data-provider.ts +20 -0
  907. package/src/types/exchange-rate.ts +6 -0
  908. package/src/types/financials.ts +104 -7
  909. package/src/types/headless.ts +83 -6
  910. package/src/types/instrument.ts +3 -0
  911. package/src/types/issuer-listings.ts +28 -0
  912. package/src/types/plugin.ts +65 -8
  913. package/src/types/price-history.ts +2 -0
  914. package/src/types/ticker.ts +13 -0
  915. package/src/types/trading.ts +59 -1
  916. package/src/ui/ascii-font.ts +13 -1
  917. package/src/ui/host.tsx +6 -1
  918. package/src/updater/command-names.ts +175 -0
  919. package/src/updater/failure.ts +163 -0
  920. package/src/updater/index.ts +97 -28
  921. package/src/utils/calendar-date.ts +32 -15
  922. package/src/utils/cash-runway.ts +241 -0
  923. package/src/utils/central-banks.ts +42 -0
  924. package/src/utils/cli-output.ts +259 -80
  925. package/src/utils/contract-month.ts +16 -0
  926. package/src/utils/crypto-pair.ts +61 -3
  927. package/src/utils/currency-pair.ts +26 -0
  928. package/src/utils/currency-units.ts +29 -0
  929. package/src/utils/datetime-format.ts +10 -0
  930. package/src/utils/debug-log.ts +1 -1
  931. package/src/utils/decimal-comma.ts +39 -6
  932. package/src/utils/exchange-announcements.ts +71 -0
  933. package/src/utils/exchange-rate-snapshot.ts +10 -0
  934. package/src/utils/financial-statements.ts +83 -4
  935. package/src/utils/format.ts +34 -16
  936. package/src/utils/fundamentals.ts +150 -34
  937. package/src/utils/fx-market-hours.ts +10 -1
  938. package/src/utils/latest-financial-period.ts +8 -0
  939. package/src/utils/linux-libc.ts +54 -0
  940. package/src/utils/market-capitalization.ts +111 -15
  941. package/src/utils/max-drawdown.ts +64 -0
  942. package/src/utils/network-failure.ts +83 -0
  943. package/src/utils/option-expiry.ts +139 -7
  944. package/src/utils/price-earnings.ts +11 -5
  945. package/src/utils/price-history.ts +18 -8
  946. package/src/utils/price-window.ts +131 -0
  947. package/src/utils/release-date.ts +47 -0
  948. package/src/utils/sec.ts +71 -0
  949. package/src/utils/throttled-fetch.ts +11 -4
  950. package/src/utils/trailing-eps.ts +67 -0
  951. package/src/utils/typed-text.ts +21 -0
  952. package/src/utils/utc-time.ts +24 -1
  953. package/src/version.ts +6 -0
  954. package/src/cli/pane-functions/screenshot.ts +0 -2122
@@ -14,9 +14,11 @@ export interface BacktestBar {
14
14
  export type Operand =
15
15
  | { kind: "number"; value: number }
16
16
  | { kind: "field"; field: "close" | "open" | "high" | "low" }
17
+ | { kind: "calendar"; name: CalendarName }
17
18
  | { kind: "indicator"; name: IndicatorName; args: number[] };
18
19
  type IndicatorName = "sma" | "ema" | "rsi" | "macd" | "macd_signal" | "bb_upper" | "bb_lower" | "highest" | "lowest";
19
- type Comparator = ">" | "<" | ">=" | "<=" | "crosses above" | "crosses below";
20
+ type CalendarName = "weekday" | "day_of_month";
21
+ type Comparator = ">" | "<" | ">=" | "<=" | "==" | "!=" | "crosses above" | "crosses below";
20
22
  interface Condition { left: Operand; comparator: Comparator; right: Operand }
21
23
  /** Conditions are ANDed. */
22
24
  export type Rule = Condition[];
@@ -35,6 +37,11 @@ const INDICATORS: Record<IndicatorName, IndicatorSpec> = {
35
37
  lowest: { defaults: [20], bounds: [PERIOD], usage: "lowest(n)" },
36
38
  };
37
39
  const FIELDS = new Set(["close", "open", "high", "low"]);
40
+ /** The session's UTC calendar date as a number, so a rule can trade a day of the week or of the month. */
41
+ const CALENDAR: Record<CalendarName, { min: number; max: number; values: string; of: (date: Date) => number }> = {
42
+ weekday: { min: 1, max: 7, values: "1 Monday to 7 Sunday", of: (date) => (date.getUTCDay() + 6) % 7 + 1 },
43
+ day_of_month: { min: 1, max: 31, values: "1 to 31", of: (date) => date.getUTCDate() },
44
+ };
38
45
  const COMPARATORS: Array<[RegExp, Comparator]> = [
39
46
  [/^crosses\s+above$/, "crosses above"],
40
47
  [/^crosses\s+below$/, "crosses below"],
@@ -42,16 +49,29 @@ const COMPARATORS: Array<[RegExp, Comparator]> = [
42
49
  [/^(<|below)$/, "<"],
43
50
  [/^>=$/, ">="],
44
51
  [/^<=$/, "<="],
52
+ [/^==?$/, "=="],
53
+ [/^!=$/, "!="],
45
54
  ];
46
55
 
56
+ /** Every operand a rule takes, as an error and `--help` list them. */
57
+ const RULE_OPERANDS = [
58
+ "close", "open", "high", "low", "a number",
59
+ ...Object.entries(CALENDAR).map(([name, entry]) => `${name} (${entry.values})`),
60
+ ...Object.values(INDICATORS).map((entry) => entry.usage),
61
+ ].join(", ");
62
+ const RULE_COMPARISONS = ">, <, >=, <=, ==, !=, crosses above, crosses below";
63
+ /** What a rule is written from, for a message that sends the reader back to the syntax. */
64
+ export const RULE_SYNTAX = `Operands: ${RULE_OPERANDS}. Comparisons: ${RULE_COMPARISONS}. Join conditions with "and".`;
65
+
47
66
  function parseOperand(text: string): Operand {
48
67
  const value = text.trim().toLowerCase();
49
68
  if (/^[+-]?(\d+(\.\d*)?|\.\d+)$/.test(value)) return { kind: "number", value: Number(value) };
50
69
  if (FIELDS.has(value)) return { kind: "field", field: value as "close" };
70
+ if (Object.hasOwn(CALENDAR, value)) return { kind: "calendar", name: value as CalendarName };
51
71
  const match = /^([a-z_]+)\s*(?:\(([^)]*)\))?$/.exec(value);
52
72
  const name = match?.[1] as IndicatorName | undefined;
53
73
  const spec = name ? INDICATORS[name] : undefined;
54
- if (!match || !name || !spec) throw new Error(`Unknown operand "${text.trim()}". Use close, open, high, low, a number or ${Object.values(INDICATORS).map((entry) => entry.usage).join(", ")}.`);
74
+ if (!match || !name || !spec) throw new Error(`Unknown operand "${text.trim()}". Use ${RULE_OPERANDS}.`);
55
75
  const given = match[2]?.trim() ? match[2].split(",").map((part) => part.trim()) : [];
56
76
  if (given.length > spec.defaults.length) throw new Error(`${spec.usage} takes at most ${spec.defaults.length} values.`);
57
77
  const args = spec.defaults.map((fallback, index) => {
@@ -72,12 +92,19 @@ export function parseRule(text: string): Rule {
72
92
  const source = text.trim();
73
93
  if (!source) throw new Error("Enter a rule, for example: sma(50) crosses above sma(200)");
74
94
  return source.split(/\s+and\s+/i).map((part) => {
75
- const match = /^(.+?)\s+(crosses\s+above|crosses\s+below|>=|<=|>|<|above|below)\s+(.+)$/i.exec(part.trim());
76
- if (!match) throw new Error(`Cannot read "${part.trim()}". Write <operand> <comparison> <operand>, for example close > sma(200).`);
95
+ const match = /^(.+?)\s+(crosses\s+above|crosses\s+below|>=|<=|==|!=|=|>|<|above|below)\s+(.+)$/i.exec(part.trim());
96
+ if (!match) throw new Error(`Cannot read "${part.trim()}". Write <operand> <comparison> <operand>, for example close > sma(200). ${RULE_SYNTAX}`);
77
97
  const comparator = COMPARATORS.find(([pattern]) => pattern.test(match[2]!.toLowerCase().replace(/\s+/g, " ")))![1];
78
98
  const left = parseOperand(match[1]!);
79
99
  const right = parseOperand(match[3]!);
80
- if (left.kind === "number" && right.kind === "number") throw new Error("Compare at least one price or indicator.");
100
+ if (left.kind === "number" && right.kind === "number") throw new Error("Compare at least one price, date or indicator.");
101
+ for (const [calendar, other] of [[left, right], [right, left]] as const) {
102
+ if (calendar.kind !== "calendar" || other.kind !== "number") continue;
103
+ const { min, max, values } = CALENDAR[calendar.name];
104
+ if (!Number.isInteger(other.value) || other.value < min || other.value > max) {
105
+ throw new Error(`${calendar.name} is ${values}, not ${other.value}.`);
106
+ }
107
+ }
81
108
  return { left, comparator, right };
82
109
  });
83
110
  }
@@ -105,6 +132,13 @@ export function evaluateOperand(operand: Operand, bars: readonly BacktestBar[]):
105
132
  const length = bars.length;
106
133
  if (operand.kind === "number") return new Float64Array(length).fill(operand.value);
107
134
  if (operand.kind === "field") return Float64Array.from(bars, (bar) => bar[operand.field] ?? Number.NaN);
135
+ if (operand.kind === "calendar") {
136
+ // A session's date is its UTC calendar day; a bar without a readable one has no weekday.
137
+ return Float64Array.from(bars, (bar) => {
138
+ const time = Date.parse(`${bar.date.slice(0, 10)}T00:00:00Z`);
139
+ return Number.isFinite(time) ? CALENDAR[operand.name].of(new Date(time)) : Number.NaN;
140
+ });
141
+ }
108
142
  const closes = bars.map((bar) => bar.close);
109
143
  const [a = 0, b = 0, c = 0] = operand.args;
110
144
  switch (operand.name) {
@@ -161,6 +195,8 @@ export function evaluateRule(rule: Rule, bars: readonly BacktestBar[]): boolean[
161
195
  else if (condition.comparator === "<") met = l < r;
162
196
  else if (condition.comparator === ">=") met = l >= r;
163
197
  else if (condition.comparator === "<=") met = l <= r;
198
+ else if (condition.comparator === "==") met = l === r;
199
+ else if (condition.comparator === "!=") met = l !== r;
164
200
  else {
165
201
  const pl = left[index - 1], pr = right[index - 1];
166
202
  met = pl !== undefined && pr !== undefined && !Number.isNaN(pl) && !Number.isNaN(pr)
@@ -2,6 +2,7 @@ import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore
2
2
  import { apiClient } from "../../../api-client";
3
3
  import {
4
4
  brokerMethodLabel,
5
+ brokerDirectorySummary,
5
6
  brokerMethodSummary,
6
7
  buildBrokerDirectory,
7
8
  type BrokerDirectoryEntry,
@@ -39,7 +40,7 @@ import { isPlainKey } from "../../../utils/keyboard";
39
40
  import { usePluginAppActions, usePluginBrokerActions } from "../../runtime";
40
41
  import { BrokerProfileForm, profileFieldWidth, type BrokerEditKey } from "./detail";
41
42
  import { useBrokerManagerKeyboard } from "./keyboard";
42
- import type { BrokerManagerMessage } from "./pane-actions";
43
+ import type { BrokerManagerMessage, BrokerRowNote } from "./pane-actions";
43
44
 
44
45
  /**
45
46
  * Adding a profile, one step at a time in the pane's detail: the broker, how
@@ -84,10 +85,13 @@ let attemptSequence = 0;
84
85
  export function useBrokerAddFlow({
85
86
  setBusy,
86
87
  setMessage,
88
+ setRowNote,
87
89
  onProfileAdded,
88
90
  }: {
89
91
  setBusy: (busy: string | null) => void;
90
92
  setMessage: (message: BrokerManagerMessage | null) => void;
93
+ /** Says on the new profile's row why its first sync failed. */
94
+ setRowNote: (profileId: string, note: BrokerRowNote | null) => void;
91
95
  /** Lands the pane on the profile the flow made, with the flow closed. */
92
96
  onProfileAdded: (instanceId: string) => void;
93
97
  }) {
@@ -95,7 +99,7 @@ export function useBrokerAddFlow({
95
99
  const dispatch = useAppDispatch();
96
100
  const getState = useAppGetState();
97
101
  const { notify } = usePluginAppActions();
98
- const { listBrokerAdapters, createBrokerInstance, syncBrokerInstance } = usePluginBrokerActions();
102
+ const { listBrokerAdapters, createBrokerInstance, updateBrokerInstance, syncBrokerInstance } = usePluginBrokerActions();
99
103
  const [flow, setFlowState] = useState<BrokerAddFlowState | null>(null);
100
104
  // Async work reads the flow as it is now, not as it was when it started.
101
105
  const flowRef = useRef<BrokerAddFlowState | null>(null);
@@ -165,13 +169,13 @@ export function useBrokerAddFlow({
165
169
  if (portfolio) showCollectionInPortfolioPane(state, dispatch, portfolio.id);
166
170
  notify({ body: t("Connected! Positions will sync automatically."), type: "success" });
167
171
  } catch (error) {
168
- // The profile stays: its detail and the footer say why it did not sync.
172
+ // The profile stays: its row says why it did not sync.
169
173
  land();
170
- setMessage({ tone: "error", text: errorText(error, tf("Failed to sync {label}.", { label })) });
174
+ setRowNote(instanceId, { tone: "error", status: t("Sync failed"), text: errorText(error, tf("Failed to sync {label}.", { label })) });
171
175
  } finally {
172
176
  setBusy(null);
173
177
  }
174
- }, [dispatch, getState, notify, onProfileAdded, setBusy, setFlow, setMessage, syncBrokerInstance]);
178
+ }, [dispatch, getState, notify, onProfileAdded, setBusy, setFlow, setRowNote, syncBrokerInstance]);
175
179
 
176
180
  const connectDevice = useCallback(async () => {
177
181
  const current = flowRef.current;
@@ -240,6 +244,7 @@ export function useBrokerAddFlow({
240
244
  connected = await connectSignedInBrokerProfile(broker, {
241
245
  getConfig: () => getState().config,
242
246
  createBrokerInstance,
247
+ enableBrokerInstance: (instanceId) => updateBrokerInstance(instanceId, {}, { enabled: true }),
243
248
  // The first sync runs below, with its progress in the pane.
244
249
  syncBrokerInstance: async () => {},
245
250
  // Gloom's sign-in over the pane when needed, again after a session Gloom refused.
@@ -278,7 +283,7 @@ export function useBrokerAddFlow({
278
283
  } finally {
279
284
  if (committing) committingRef.current = false;
280
285
  }
281
- }, [createBrokerInstance, dialog, getState, setMessage, setStep, showAttempt, syncNewProfile]);
286
+ }, [createBrokerInstance, dialog, getState, setMessage, setStep, showAttempt, syncNewProfile, updateBrokerInstance]);
282
287
 
283
288
  const chooseMethod = useCallback((entry: BrokerDirectoryEntry, method: BrokerMethod) => {
284
289
  const current = flowRef.current;
@@ -384,7 +389,7 @@ export function BrokerAddFlowContent({
384
389
  label: entry.name,
385
390
  // The desktop says how it connects under the name, beside its logo.
386
391
  ...(desktop
387
- ? { description: brokerMethodSummary(entry), leading: <LogoMark src={brokerDirectoryLogo(entry, getBrokerLogo)} name={entry.name} size="lead" /> }
392
+ ? { description: brokerDirectorySummary(entry), leading: <LogoMark src={brokerDirectoryLogo(entry, getBrokerLogo)} name={entry.name} size="lead" /> }
388
393
  : { detail: brokerMethodSummary(entry) }),
389
394
  }))}
390
395
  rowDescriptions={desktop}
@@ -1,6 +1,7 @@
1
- import { useRef } from "react";
1
+ import { useEffect, useRef, type Ref } from "react";
2
2
  import { Box, ScrollBox, Text, TextAttributes, type BoxRenderable, type ScrollBoxRenderable } from "../../../ui";
3
3
  import { Button, FieldLabel, NumberField, SectionHeading, SegmentedControl, TextField, useFieldRing } from "../../../components";
4
+ import { afterLayout, revealInScrollBox } from "../../../components/ui/reveal-in-scroll-box";
4
5
  import {
5
6
  PRESERVED_PASSWORD_HINT,
6
7
  type BrokerProfileDraft,
@@ -13,9 +14,9 @@ import { formatRelativeAge } from "../../../utils/datetime-format";
13
14
  import { formatCurrency, truncateToDisplayWidth } from "../../../utils/format";
14
15
  import { t, tf } from "../../../i18n";
15
16
  import type { BrokerProfileRow } from "./model";
16
- import type { BrokerManagerMessage } from "./pane-actions";
17
+ import type { BrokerRowActivity } from "./pane-actions";
17
18
  import { signInEndNote } from "./sign-in-end";
18
- import { stateColor } from "./table";
19
+ import { brokerRowStatus } from "./table";
19
20
 
20
21
  export type BrokerEditKey = "label" | "enabled" | "localOnly" | string;
21
22
 
@@ -88,9 +89,10 @@ function BrokerConfigFieldEditor({
88
89
  );
89
90
  }
90
91
 
92
+ /** An account by the name its broker gives it, as its portfolio is named; its id when it has none. */
91
93
  function accountDetail(account: BrokerAccount): string {
92
94
  const parts = [
93
- account.accountId,
95
+ account.name?.trim() || account.accountId,
94
96
  account.netLiquidation != null ? tf("{value} net liq", { value: formatCurrency(account.netLiquidation, account.currency || "") }) : null,
95
97
  account.buyingPower != null ? tf("{value} buying power", { value: formatCurrency(account.buyingPower, account.currency || "") }) : null,
96
98
  ];
@@ -112,6 +114,8 @@ export function BrokerProfileForm({
112
114
  scope,
113
115
  paneFocused,
114
116
  submitLabel,
117
+ error,
118
+ actionsRef,
115
119
  rowRef,
116
120
  onActiveKeyChange,
117
121
  onLabelChange,
@@ -134,6 +138,10 @@ export function BrokerProfileForm({
134
138
  /** The form's fields take keys only while the pane has the keyboard. */
135
139
  paneFocused: boolean;
136
140
  submitLabel: string;
141
+ /** What stopped the last submit, said beside the buttons. */
142
+ error?: string | null;
143
+ /** The error and the buttons, for the detail to scroll into view when the error shows. */
144
+ actionsRef?: Ref<BoxRenderable>;
137
145
  /** Each field's outer box, for the form's field ring to scroll into view. */
138
146
  rowRef: (key: BrokerEditKey) => RowRef;
139
147
  onActiveKeyChange: (key: BrokerEditKey) => void;
@@ -209,9 +217,12 @@ export function BrokerProfileForm({
209
217
  </Text>
210
218
  ) : null}
211
219
  </Box>
212
- <Box flexDirection="row" gap={1}>
213
- <Button label={submitLabel} shortcut="Enter" variant="primary" onPress={onSubmit} disabled={!!busy} />
214
- <Button label={t("Cancel")} shortcut="Esc" variant="secondary" onPress={onCancel} disabled={!!busy} />
220
+ <Box ref={actionsRef} flexDirection="column">
221
+ {error ? <Text fg={colors.negative} width={width} wrapText>{error}</Text> : null}
222
+ <Box flexDirection="row" gap={1}>
223
+ <Button label={submitLabel} shortcut="Enter" variant="primary" onPress={onSubmit} disabled={!!busy} />
224
+ <Button label={t("Cancel")} shortcut="Esc" variant="secondary" onPress={onCancel} disabled={!!busy} />
225
+ </Box>
215
226
  </Box>
216
227
  </>
217
228
  );
@@ -230,7 +241,8 @@ export function BrokerDetailContent({
230
241
  activeEditKey,
231
242
  editKeys,
232
243
  busy,
233
- message,
244
+ activity,
245
+ editError,
234
246
  width,
235
247
  editScope,
236
248
  paneFocused,
@@ -250,7 +262,10 @@ export function BrokerDetailContent({
250
262
  /** The edit form's fields in Tab order. */
251
263
  editKeys: readonly BrokerEditKey[];
252
264
  busy: string | null;
253
- message: BrokerManagerMessage | null;
265
+ /** The pane's action running on this profile, and what the last one came to. */
266
+ activity: BrokerRowActivity;
267
+ /** What stops the edit form from saving. */
268
+ editError: string | null;
254
269
  width: number;
255
270
  /** The edit form's shortcut scope, shared with the pane's field ring. */
256
271
  editScope: string;
@@ -276,29 +291,40 @@ export function BrokerDetailContent({
276
291
  wrap: true,
277
292
  scrollRef,
278
293
  });
294
+ // Enter saves from any field, so what stopped the save can be below the
295
+ // fold; bring it and the buttons into view.
296
+ const actionsRef = useRef<BoxRenderable | null>(null);
297
+ useEffect(() => {
298
+ if (!editError) return;
299
+ return afterLayout(() => revealInScrollBox(scrollRef.current, actionsRef.current));
300
+ }, [editError]);
279
301
 
280
302
  if (!row) return <Box flexGrow={1} />;
281
303
 
282
- // A failed action outranks the profile's own status until the next action.
283
- const actionError = message?.tone === "error" ? message.text : null;
284
- const detailStatusMessage = actionError ?? (row.message || t("No status message."));
304
+ // The row's STATUS, and in full what the last action on the profile came to,
305
+ // which outranks the profile's own status message until it is news no more.
306
+ // The sign-in's end has a line of its own below.
307
+ const status = brokerRowStatus({ ...row, signInEndsAt: null }, activity);
308
+ const note = activity.note ?? null;
309
+ const detailStatusMessage = note?.text ?? (row.message || t("No status message."));
310
+ const statusMessageColor = note
311
+ ? note.tone === "error" ? colors.negative : colors.textDim
312
+ : row.state === "error" ? colors.negative
313
+ : row.state === "sign-in" || row.state === "disabled" ? colors.warning
314
+ : colors.textDim;
285
315
  const editAdapter = row.adapter;
286
316
 
287
317
  return (
288
318
  <ScrollBox ref={scrollRef} flexGrow={1} scrollY>
289
319
  <Box flexDirection="column" paddingX={1}>
290
320
  {/* The stack title already names the profile; the body starts with its state. */}
291
- <Text fg={stateColor(row.state)} attributes={TextAttributes.BOLD}>
292
- {truncateToDisplayWidth(row.stateLabel, width)}
321
+ <Text fg={status.color} attributes={TextAttributes.BOLD}>
322
+ {truncateToDisplayWidth(status.text, width)}
293
323
  </Text>
294
324
  <Text fg={colors.textDim}>
295
325
  {truncateToDisplayWidth(`${row.brokerName} · ${row.mode} · ${row.id}`, width)}
296
326
  </Text>
297
- <Text
298
- fg={actionError || row.state === "error" ? colors.negative : colors.textDim}
299
- width={width}
300
- wrapText
301
- >
327
+ <Text fg={statusMessageColor} width={width} wrapText>
302
328
  {detailStatusMessage}
303
329
  </Text>
304
330
  {row.signInEndsAt !== null && (
@@ -323,6 +349,8 @@ export function BrokerDetailContent({
323
349
  scope={editScope}
324
350
  paneFocused={paneFocused}
325
351
  submitLabel={t("Save")}
352
+ error={editError}
353
+ actionsRef={actionsRef}
326
354
  rowRef={rowRef}
327
355
  onActiveKeyChange={onActiveEditKeyChange}
328
356
  onLabelChange={onDraftLabelChange}
@@ -1,9 +1,11 @@
1
1
  import { useMemo, useRef } from "react";
2
2
  import { usePaneFooter, type PaneFooterSegment, type PaneHint } from "../../../components";
3
+ import { enableBrokerHint } from "../shared/broker-reconnect";
3
4
  import type { BrokerManagerMessage } from "./pane-actions";
4
5
 
5
6
  interface BrokerManagerFooterActions {
6
7
  connectSelected: () => Promise<void>;
8
+ enableSelected: () => Promise<void>;
7
9
  startAdd: () => void;
8
10
  openProfileAction: () => void;
9
11
  removeSelected: () => void;
@@ -15,21 +17,30 @@ interface BrokerManagerFooterActions {
15
17
  export function useBrokerManagerFooter({
16
18
  actions,
17
19
  busy,
20
+ paneBusy,
18
21
  canOpenSelectedAction,
19
22
  canRemoveSelected,
20
23
  canUseSelectedBroker,
24
+ disabledSelected,
21
25
  editing,
22
26
  message,
23
27
  }: {
24
28
  actions: BrokerManagerFooterActions;
25
29
  /** What is running right now, or null. */
26
30
  busy: string | null;
31
+ /** What is running that has no row to show it on: adding a profile. */
32
+ paneBusy: string | null;
27
33
  canOpenSelectedAction: boolean;
28
34
  canRemoveSelected: boolean;
29
35
  canUseSelectedBroker: boolean;
36
+ /**
37
+ * The selected profile is turned off, so it is never connected or synced:
38
+ * its broker's name for `[b] enable`, which turns it back on.
39
+ */
40
+ disabledSelected: string | null;
30
41
  /** Editing a profile or adding one. */
31
42
  editing: boolean;
32
- /** The last result of an action, or null. */
43
+ /** The last result that is the whole pane's, or null. */
33
44
  message: BrokerManagerMessage | null;
34
45
  }) {
35
46
  const actionsRef = useRef(actions);
@@ -44,11 +55,16 @@ export function useBrokerManagerFooter({
44
55
  { id: "add", key: "a", label: "dd", onPress: () => actionsRef.current.startAdd() },
45
56
  ];
46
57
  if (canUseSelectedBroker) {
47
- hints.push(
48
- { id: "edit", key: "e", label: "dit", onPress: () => actionsRef.current.startEdit() },
49
- { id: "connect", key: "c", label: "onnect", onPress: () => actionsRef.current.connectSelected().catch(() => {}) },
50
- { id: "sync", key: "s", label: "ync", onPress: () => actionsRef.current.syncSelected().catch(() => {}) },
51
- );
58
+ hints.push({ id: "edit", key: "e", label: "dit", onPress: () => actionsRef.current.startEdit() });
59
+ if (disabledSelected === null) {
60
+ hints.push(
61
+ { id: "connect", key: "c", label: "onnect", onPress: () => actionsRef.current.connectSelected().catch(() => {}) },
62
+ { id: "sync", key: "s", label: "ync", onPress: () => actionsRef.current.syncSelected().catch(() => {}) },
63
+ );
64
+ }
65
+ }
66
+ if (disabledSelected !== null && !busy) {
67
+ hints.push(enableBrokerHint(disabledSelected, () => { void actionsRef.current.enableSelected(); }));
52
68
  }
53
69
  if (canOpenSelectedAction) {
54
70
  hints.push({ id: "open", key: "o", label: "pen", onPress: () => actionsRef.current.openProfileAction() });
@@ -57,14 +73,14 @@ export function useBrokerManagerFooter({
57
73
  hints.push({ id: "disconnect", key: "d", label: "isconnect", onPress: () => actionsRef.current.removeSelected() });
58
74
  }
59
75
  return hints;
60
- }, [canOpenSelectedAction, canRemoveSelected, canUseSelectedBroker, editing]);
76
+ }, [busy, canOpenSelectedAction, canRemoveSelected, canUseSelectedBroker, disabledSelected, editing]);
61
77
 
62
- // The pane's rows already say which profiles exist and how they are doing,
63
- // so the footer carries only what changes: the running action and its result.
78
+ // An action on one profile, and what it came to, is said on that profile's
79
+ // row. The footer carries only the pane's own: adding a profile.
64
80
  const info = useMemo<PaneFooterSegment[]>(() => [
65
- ...(busy ? [{ id: "busy", parts: [{ text: busy, tone: "muted" as const }] }] : []),
81
+ ...(paneBusy ? [{ id: "busy", parts: [{ text: paneBusy, tone: "muted" as const }] }] : []),
66
82
  ...(message ? [{ id: "message", parts: [{ text: message.text, tone: message.tone === "error" ? "negative" as const : "muted" as const }] }] : []),
67
- ], [busy, message]);
83
+ ], [message, paneBusy]);
68
84
 
69
85
  usePaneFooter("broker-manager", () => ({
70
86
  info,
@@ -118,17 +118,24 @@ export function BrokersPane({ focused, width, height }: PaneProps) {
118
118
 
119
119
  const {
120
120
  busy,
121
+ paneBusy,
121
122
  message,
123
+ editError,
124
+ rowActivity,
122
125
  setBusy,
123
126
  setMessage,
127
+ setRowNote,
124
128
  startEdit,
129
+ cancelEdit,
125
130
  saveEdit,
126
131
  connectSelected,
132
+ enableSelected,
127
133
  syncSelected,
128
134
  selectedProfileActions,
129
135
  openProfileAction,
130
136
  removeSelected,
131
137
  } = useBrokerManagerActions({
138
+ rows,
132
139
  selectedRow,
133
140
  editDraft,
134
141
  setEditDraft,
@@ -143,7 +150,7 @@ export function BrokersPane({ focused, width, height }: PaneProps) {
143
150
  setEditDraft(null);
144
151
  setDetailOpen(false);
145
152
  }, [setDetailOpen, setSelectedId]);
146
- const addFlow = useBrokerAddFlow({ setBusy, setMessage, onProfileAdded: selectAddedProfile });
153
+ const addFlow = useBrokerAddFlow({ setBusy, setMessage, setRowNote, onProfileAdded: selectAddedProfile });
147
154
  const adding = addFlow.flow !== null;
148
155
  const { start: startAddFlow } = addFlow;
149
156
  const startAdd = useCallback(() => {
@@ -180,13 +187,14 @@ export function BrokersPane({ focused, width, height }: PaneProps) {
180
187
  const canUseSelectedBroker = selectedHasAdapter && !busy;
181
188
  const canOpenSelectedAction = selectedProfileActions.some((action) => !action.disabled && action.paneId);
182
189
  const canRemoveSelected = hasSelectedRow && !busy;
183
- const cancelEdit = useCallback(() => setEditDraft(null), []);
184
190
 
185
191
  useBrokerManagerFooter({
186
192
  busy,
193
+ paneBusy,
187
194
  message,
188
195
  actions: {
189
196
  connectSelected,
197
+ enableSelected,
190
198
  openProfileAction,
191
199
  removeSelected,
192
200
  saveEdit,
@@ -197,6 +205,7 @@ export function BrokersPane({ focused, width, height }: PaneProps) {
197
205
  canOpenSelectedAction,
198
206
  canRemoveSelected,
199
207
  canUseSelectedBroker,
208
+ disabledSelected: selectedRow?.instance.enabled === false ? selectedRow.brokerName : null,
200
209
  editing: !!editDraft || adding,
201
210
  });
202
211
 
@@ -231,22 +240,20 @@ export function BrokersPane({ focused, width, height }: PaneProps) {
231
240
  const columns = useMemo(() => buildBrokerColumns(tableWidth), [language, tableWidth]);
232
241
 
233
242
  const renderCell = useCallback(
234
- (row: BrokerProfileRow, column: BrokerColumn) => renderBrokerCell(row, column, desktop),
235
- [desktop],
243
+ (row: BrokerProfileRow, column: BrokerColumn) => renderBrokerCell(row, column, desktop, rowActivity(row)),
244
+ [desktop, rowActivity],
236
245
  );
237
246
 
238
247
  const openSelectedDetail = useCallback((_index: number, row: BrokerProfileRow) => {
239
248
  setSelectedId(row.id);
240
- setEditDraft(null);
249
+ cancelEdit();
241
250
  setDetailOpen(true);
242
- }, [setDetailOpen, setSelectedId]);
251
+ }, [cancelEdit, setDetailOpen, setSelectedId]);
243
252
 
244
253
  const selectBrokerRow = useCallback((_index: number, row: BrokerProfileRow) => {
245
254
  setSelectedId(row.id);
246
- if (selectedRow?.id !== row.id) {
247
- setEditDraft(null);
248
- }
249
- }, [selectedRow?.id, setSelectedId]);
255
+ if (selectedRow?.id !== row.id) cancelEdit();
256
+ }, [cancelEdit, selectedRow?.id, setSelectedId]);
250
257
 
251
258
  const updateDraftValue = useCallback((key: string, value: string) => {
252
259
  setEditDraft((current) => current
@@ -291,7 +298,8 @@ export function BrokersPane({ focused, width, height }: PaneProps) {
291
298
  activeEditKey={activeEditKey}
292
299
  editKeys={editKeys}
293
300
  busy={busy}
294
- message={message}
301
+ activity={selectedRow ? rowActivity(selectedRow) : {}}
302
+ editError={editError}
295
303
  width={detailContentWidth}
296
304
  editScope={editScope}
297
305
  paneFocused={focused}
@@ -312,7 +320,7 @@ export function BrokersPane({ focused, width, height }: PaneProps) {
312
320
  focused={focused}
313
321
  detailOpen={adding || (detailOpen && !!selectedRow)}
314
322
  onBack={adding ? addFlow.leave : () => {
315
- setEditDraft(null);
323
+ cancelEdit();
316
324
  setDetailOpen(false);
317
325
  }}
318
326
  detailContent={detailContent}
@@ -352,6 +360,7 @@ export const brokerManagerModule: PluginModule = {
352
360
  personalData: "account",
353
361
  icon: "B",
354
362
  component: BrokersPane,
363
+ reportFreshness: { status: "not-a-feed", basis: "broker connections" },
355
364
  defaultPosition: "right",
356
365
  defaultMode: "floating",
357
366
  defaultFloatingSize: { width: 92, height: 24 },
@@ -4,7 +4,7 @@ import type { BrokerEditKey } from "./detail";
4
4
 
5
5
  /**
6
6
  * The edit form's keys beside its field ring (the detail's useFieldRing walks
7
- * the fields). The list and detail actions (a, e, c, s, o, d) are footer
7
+ * the fields). The list and detail actions (a, e, c, s, b, o, d) are footer
8
8
  * hints, which bind their own keys, and the table opens a row on Enter, so
9
9
  * only editing needs keys of its own.
10
10
  *
@@ -10,6 +10,8 @@ export type BrokerDisplayState =
10
10
  | "disabled"
11
11
  | "unavailable"
12
12
  | "configured"
13
+ /** An error only a new sign-in clears. */
14
+ | "sign-in"
13
15
  | BrokerConnectionStatus["state"];
14
16
 
15
17
  export interface BrokerProfileRow {
@@ -78,7 +80,12 @@ function resolveState(
78
80
  status: BrokerConnectionStatus | null,
79
81
  ): { state: BrokerDisplayState; label: string; message: string; updatedAt: number } {
80
82
  if (instance.enabled === false) {
81
- return { state: "disabled", label: t("Disabled"), message: t("Profile is disabled"), updatedAt: 0 };
83
+ return {
84
+ state: "disabled",
85
+ label: t("Disabled"),
86
+ message: t("Gloom does not connect or sync this profile while it is disabled."),
87
+ updatedAt: 0,
88
+ };
82
89
  }
83
90
  if (!adapter) {
84
91
  return { state: "unavailable", label: t("Unavailable"), message: t("Broker plugin is not available"), updatedAt: 0 };
@@ -95,6 +102,9 @@ function resolveState(
95
102
  return { state: "configured", label: t("Configured"), message: t("Ready to test or sync"), updatedAt: 0 };
96
103
  }
97
104
 
105
+ if (status.state === "error" && status.needsSignIn) {
106
+ return { state: "sign-in", label: t("Sign-in needed"), message: status.message || "", updatedAt: status.updatedAt };
107
+ }
98
108
  const labels: Record<BrokerConnectionStatus["state"], string> = {
99
109
  disconnected: t("Disconnected"),
100
110
  connecting: t("Connecting"),
@@ -148,7 +158,7 @@ export function buildBrokerProfileRows(
148
158
  accountSummary: summarizeBrokerAccounts(accounts),
149
159
  accountIds: accounts.map((account) => account.accountId),
150
160
  // Say nothing next to a failure or a profile that does not connect.
151
- signInEndsAt: state.state === "error" || state.state === "disabled" || state.state === "unavailable"
161
+ signInEndsAt: state.state === "error" || state.state === "sign-in" || state.state === "disabled" || state.state === "unavailable"
152
162
  ? null
153
163
  : signInEnds.get(instance.id) ?? null,
154
164
  logo: brokerProfileLogo(instance, adapter, pluginLogo),