gloomberb 0.18.3 → 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 (886) 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/src/account/checkout-handoff.tsx +225 -0
  6. package/src/account/device-signin-dialog.tsx +2 -2
  7. package/src/account/device-signin.ts +2 -2
  8. package/src/account/upgrade-dialog.tsx +1 -1
  9. package/src/api-client/askg.ts +2 -2
  10. package/src/api-client/auth.ts +2 -2
  11. package/src/api-client/central-bank-rates.ts +6 -0
  12. package/src/api-client/collections.ts +5 -1
  13. package/src/api-client/cot.ts +2 -0
  14. package/src/api-client/crypto-etf-flows.ts +37 -0
  15. package/src/api-client/crypto-markets.ts +60 -0
  16. package/src/api-client/data.ts +84 -5
  17. package/src/api-client/doe.ts +15 -0
  18. package/src/api-client/equity-screener.ts +28 -0
  19. package/src/api-client/exchange-announcements.ts +38 -0
  20. package/src/api-client/fund-facts.ts +39 -0
  21. package/src/api-client/futures-curve.ts +9 -1
  22. package/src/api-client/hiring.ts +301 -0
  23. package/src/api-client/index.ts +22 -5
  24. package/src/api-client/market-discovery.ts +14 -0
  25. package/src/api-client/members.ts +6 -0
  26. package/src/api-client/mna.ts +6 -0
  27. package/src/api-client/paths.ts +18 -1
  28. package/src/api-client/request.ts +21 -4
  29. package/src/api-client/short-side-publications.ts +37 -0
  30. package/src/api-client/socket.ts +64 -4
  31. package/src/api-client/swap-curve.ts +35 -0
  32. package/src/api-client/themes.ts +7 -1
  33. package/src/api-client/types.ts +90 -2
  34. package/src/app/pane-runtime/plugin-bindings.ts +9 -2
  35. package/src/app/runtime/desktop-deeplink.ts +5 -5
  36. package/src/app/runtime/plugin-bindings.ts +2 -2
  37. package/src/app/runtime/startup.ts +13 -0
  38. package/src/app/star-prompt/status-line.tsx +2 -2
  39. package/src/architecture/core-builtin-allowlist.json +5 -2
  40. package/src/architecture/ui-literals-allowlist.json +3 -3
  41. package/src/architecture/ui-tokens-allowlist.json +1 -1
  42. package/src/brokers/broker-portfolio-sync.ts +37 -0
  43. package/src/brokers/directory.ts +11 -0
  44. package/src/brokers/logos.ts +3 -1
  45. package/src/brokers/signed-in/adapter.ts +304 -26
  46. package/src/brokers/signed-in/client.ts +14 -2
  47. package/src/brokers/signed-in/connect.ts +10 -2
  48. package/src/brokers/sync-broker-instance.ts +9 -1
  49. package/src/capabilities/chart-series.ts +22 -6
  50. package/src/cli/bank-section.ts +1 -1
  51. package/src/cli/base-converter.ts +23 -14
  52. package/src/cli/central-bank-events.ts +1 -1
  53. package/src/cli/command-options.ts +59 -4
  54. package/src/cli/commands/api.ts +9 -6
  55. package/src/cli/commands/broker.ts +2 -2
  56. package/src/cli/commands/command-utils.ts +2 -2
  57. package/src/cli/commands/crypto-hints.ts +7 -20
  58. package/src/cli/commands/fred-series.ts +4 -2
  59. package/src/cli/commands/keybindings.ts +2 -2
  60. package/src/cli/commands/market.ts +1117 -264
  61. package/src/cli/commands/news-hints.ts +2 -2
  62. package/src/cli/commands/news-search.ts +59 -6
  63. package/src/cli/commands/options-leaps.ts +41 -26
  64. package/src/cli/commands/overview.ts +121 -48
  65. package/src/cli/commands/plugins.ts +9 -9
  66. package/src/cli/commands/remote.ts +13 -10
  67. package/src/cli/commands/search.ts +64 -44
  68. package/src/cli/commands/system.ts +27 -19
  69. package/src/cli/commands/themes.ts +1 -1
  70. package/src/cli/commands/ticker.ts +192 -47
  71. package/src/cli/context.ts +3 -2
  72. package/src/cli/desktop-pane-shot-view.ts +2 -2
  73. package/src/cli/desktop-pane-shot.ts +1 -1
  74. package/src/cli/earnings-calendar.ts +4 -4
  75. package/src/cli/entry.ts +18 -1
  76. package/src/cli/errors.ts +20 -2
  77. package/src/cli/exit-codes.ts +1 -1
  78. package/src/cli/export-source.ts +10 -4
  79. package/src/cli/freshness.ts +2 -8
  80. package/src/cli/fx-forward.ts +130 -0
  81. package/src/cli/fx-pair.ts +10 -9
  82. package/src/cli/glossary.ts +64 -20
  83. package/src/cli/help.ts +19 -13
  84. package/src/cli/history-export.ts +126 -0
  85. package/src/cli/history-rows.ts +196 -43
  86. package/src/cli/index-roots.ts +5 -45
  87. package/src/cli/index.ts +24 -18
  88. package/src/cli/known-gaps.ts +118 -25
  89. package/src/cli/listing-arg.ts +300 -41
  90. package/src/cli/name-entries.ts +30 -18
  91. package/src/cli/native-smoke.ts +2 -0
  92. package/src/cli/not-a-ticker.ts +19 -9
  93. package/src/cli/opentui-libc.ts +5 -0
  94. package/src/cli/options.ts +12 -0
  95. package/src/cli/pane-functions/capabilities.ts +75 -20
  96. package/src/cli/pane-functions/catalog.ts +24 -23
  97. package/src/cli/pane-functions/discovery.ts +1 -1
  98. package/src/cli/pane-functions/dom.ts +10 -7
  99. package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
  100. package/src/cli/pane-functions/freshness.ts +174 -23
  101. package/src/cli/pane-functions/function-help.ts +66 -27
  102. package/src/cli/pane-functions/headless.ts +24 -11
  103. package/src/cli/pane-functions/index.ts +18 -16
  104. package/src/cli/pane-functions/options.ts +22 -2
  105. package/src/cli/pane-functions/report-notices.ts +12 -4
  106. package/src/cli/pane-functions/report.ts +5 -5
  107. package/src/cli/pane-functions/resolver.ts +47 -10
  108. package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
  109. package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
  110. package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
  111. package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
  112. package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
  113. package/src/cli/pane-functions/screenshot-payload.ts +453 -0
  114. package/src/cli/pane-functions/screenshot-render.ts +316 -0
  115. package/src/cli/pane-functions/screenshot-types.ts +162 -0
  116. package/src/cli/pane-functions/shot-options.ts +8 -3
  117. package/src/cli/peso-dollar-rates.ts +79 -0
  118. package/src/cli/quote-answer.ts +38 -3
  119. package/src/cli/report-tables.ts +61 -16
  120. package/src/cli/restore-plugins.ts +29 -14
  121. package/src/cli/result.ts +111 -22
  122. package/src/cli/series-search.ts +5 -5
  123. package/src/cli/statement-filings.ts +19 -0
  124. package/src/cli/suffixed-listing-rows.ts +49 -0
  125. package/src/cli/symbol-args.ts +50 -15
  126. package/src/cli/symbol-cells.ts +120 -0
  127. package/src/cli/symbol-list.ts +198 -68
  128. package/src/cli/symbol-rows.ts +131 -25
  129. package/src/cli/ticker-resolution.ts +108 -11
  130. package/src/cli/treasury-yields.ts +5 -5
  131. package/src/cli/types.ts +2 -0
  132. package/src/cli/uncovered-instrument.ts +3 -3
  133. package/src/cli/unknown-command.ts +6 -6
  134. package/src/components/chart/composite/chart-layout.ts +131 -0
  135. package/src/components/chart/composite/composite-chart.tsx +373 -16
  136. package/src/components/chart/composite/interactions.ts +7 -2
  137. package/src/components/chart/composite/legend.tsx +75 -3
  138. package/src/components/chart/composite/levels.ts +5 -0
  139. package/src/components/chart/composite/panel-gestures.ts +41 -0
  140. package/src/components/chart/composite/panel-labels.ts +2 -1
  141. package/src/components/chart/composite/panel-surface.tsx +305 -11
  142. package/src/components/chart/composite/price-axis-labels.tsx +27 -3
  143. package/src/components/chart/composite/rasterizer.ts +44 -19
  144. package/src/components/chart/composite/scene.ts +16 -4
  145. package/src/components/chart/composite/text-renderer.ts +48 -21
  146. package/src/components/chart/composite/toolbar.tsx +52 -5
  147. package/src/components/chart/composite/types.ts +13 -0
  148. package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
  149. package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
  150. package/src/components/chart/composite/use-composite-viewport.ts +12 -3
  151. package/src/components/chart/composite/value-scale.ts +149 -0
  152. package/src/components/chart/composite/volume-profile-paint.ts +6 -3
  153. package/src/components/chart/core/pointer.ts +2 -0
  154. package/src/components/chart-table/index.ts +2 -0
  155. package/src/components/chart-table/read.tsx +74 -0
  156. package/src/components/command-bar/commands/collection-list.ts +41 -19
  157. package/src/components/command-bar/commands/collection.ts +9 -3
  158. package/src/components/command-bar/commands/direct/index.ts +1 -1
  159. package/src/components/command-bar/commands/direct/runtime.ts +3 -2
  160. package/src/components/command-bar/pane-templates/items.ts +59 -6
  161. package/src/components/command-bar/pane-templates/workflow.ts +10 -1
  162. package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
  163. package/src/components/command-bar/routes/root/provider-search.ts +42 -11
  164. package/src/components/command-bar/routes/root/results.ts +18 -4
  165. package/src/components/command-bar/routes/root/runtime.ts +15 -3
  166. package/src/components/command-bar/routes/root/search-providers.ts +25 -2
  167. package/src/components/command-bar/routes/root/selection.ts +6 -1
  168. package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
  169. package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
  170. package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
  171. package/src/components/command-bar/selection-runtime.ts +50 -10
  172. package/src/components/command-bar/surface/index.tsx +24 -2
  173. package/src/components/command-bar/view-model.ts +7 -0
  174. package/src/components/command-bar/workflow/broker.ts +2 -2
  175. package/src/components/command-bar/workflow/collection-actions.ts +46 -7
  176. package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
  177. package/src/components/command-bar/workflow/fields.ts +8 -2
  178. package/src/components/command-bar/workflow/ops.ts +18 -4
  179. package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
  180. package/src/components/command-bar/workflow/submit.ts +3 -2
  181. package/src/components/command-bar/workflow/tickers.ts +5 -1
  182. package/src/components/company-logo.tsx +39 -0
  183. package/src/components/data-table/sections.ts +4 -2
  184. package/src/components/form-modal/confirm.tsx +2 -1
  185. package/src/components/form-modal/request.ts +5 -0
  186. package/src/components/form-modal/routes.ts +4 -1
  187. package/src/components/index.ts +12 -6
  188. package/src/components/layout/header.tsx +7 -6
  189. package/src/components/layout/market-summary.ts +9 -6
  190. package/src/components/layout/pane/capture-status.ts +1 -1
  191. package/src/components/layout/pane/footer/model.ts +11 -5
  192. package/src/components/layout/shell/chrome.ts +19 -6
  193. package/src/components/layout/shell/index.tsx +2 -1
  194. package/src/components/layout/shell/pane/layers.tsx +19 -1
  195. package/src/components/layout/status-bar.tsx +2 -2
  196. package/src/components/market-board/index.tsx +11 -3
  197. package/src/components/onboarding/onboarding-wizard.tsx +1 -0
  198. package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
  199. package/src/components/onboarding/wizard-broker-sync.ts +4 -1
  200. package/src/components/pane-settings-dialog/desktop.tsx +20 -7
  201. package/src/components/pane-settings-dialog/tui.tsx +17 -9
  202. package/src/components/pane-settings-dialog/value.ts +8 -1
  203. package/src/components/pane-settings-dialog.tsx +44 -13
  204. package/src/components/sign-in-code-panel.tsx +27 -19
  205. package/src/components/ui/column-grid.tsx +48 -4
  206. package/src/components/ui/country-flag-art.tsx +180 -0
  207. package/src/components/ui/country-flag.tsx +118 -12
  208. package/src/components/ui/data-table/opentui/index.tsx +61 -2
  209. package/src/components/ui/data-table/opentui/model.ts +109 -2
  210. package/src/components/ui/data-table/types.ts +1 -1
  211. package/src/components/ui/display.tsx +5 -1
  212. package/src/components/ui/index.ts +3 -1
  213. package/src/components/ui/logo-mark.tsx +11 -2
  214. package/src/components/ui/query-bar.tsx +1 -1
  215. package/src/components/ui/row-notes.ts +79 -0
  216. package/src/core/state/app/layout.ts +4 -4
  217. package/src/data/cached-query.ts +8 -1
  218. package/src/data/config/chart-settings.ts +3 -3
  219. package/src/data/config/home.ts +10 -2
  220. package/src/data/config/layout.ts +4 -1
  221. package/src/data/config/store/node.ts +4 -0
  222. package/src/data/config/store/normalize.ts +13 -3
  223. package/src/data/config/store/portfolio-as-of-column.ts +2 -2
  224. package/src/data/json-storage.ts +2 -0
  225. package/src/data/saved-copies.ts +84 -0
  226. package/src/docs/snapshot.json +65 -32
  227. package/src/i18n/es.ts +29 -12
  228. package/src/i18n/ja.ts +29 -12
  229. package/src/i18n/ko.ts +29 -12
  230. package/src/i18n/zh-cn.ts +29 -12
  231. package/src/i18n/zh-tw.ts +29 -12
  232. package/src/layout/desks.ts +1 -1
  233. package/src/layout/launch-layout.ts +1 -1
  234. package/src/layout/pane-manager/floating-actions.ts +5 -3
  235. package/src/layout/pane-manager/floating.ts +43 -1
  236. package/src/layout/pane-manager/index.ts +2 -0
  237. package/src/layout/selected-ticker.ts +74 -0
  238. package/src/market-data/depositary-pair.ts +251 -0
  239. package/src/market-data/futures-board.ts +1 -1
  240. package/src/market-data/futures-contract.ts +124 -40
  241. package/src/market-data/fx-closes.ts +17 -2
  242. package/src/market-data/hooks.tsx +19 -11
  243. package/src/market-data/market/change-basis.ts +49 -7
  244. package/src/market-data/market/freshness.ts +34 -5
  245. package/src/market-data/market/period-return.ts +163 -0
  246. package/src/market-data/market/trading-sessions.ts +13 -0
  247. package/src/market-data/market/year-to-date.ts +8 -13
  248. package/src/market-data/performance.ts +20 -14
  249. package/src/market-data/perpetual-premium.ts +32 -0
  250. package/src/market-data/published-apac-sessions.ts +2 -1
  251. package/src/market-data/published-futures-sessions.ts +69 -0
  252. package/src/market-data/quotes/contributions.ts +5 -1
  253. package/src/market-data/quotes/freshness.ts +42 -0
  254. package/src/market-data/quotes/intraday-bar.ts +37 -0
  255. package/src/market-data/quotes/regular-session-valuation.ts +13 -8
  256. package/src/market-data/quotes/resolution.ts +4 -2
  257. package/src/market-data/tax-equivalent.ts +1 -1
  258. package/src/market-data/ticker-price-returns.ts +3 -1
  259. package/src/news/aggregator.ts +5 -1
  260. package/src/news/news-model.ts +4 -0
  261. package/src/news/types.ts +11 -0
  262. package/src/notifications/app-notifier.ts +1 -1
  263. package/src/plugins/auto-update.ts +2 -2
  264. package/src/plugins/builtin/account-management/index.tsx +1 -0
  265. package/src/plugins/builtin/account-management/pane.tsx +9 -8
  266. package/src/plugins/builtin/alerts/alert-engine.ts +29 -19
  267. package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
  268. package/src/plugins/builtin/alerts/cli.ts +485 -76
  269. package/src/plugins/builtin/alerts/command.ts +5 -10
  270. package/src/plugins/builtin/alerts/event-rows.ts +9 -5
  271. package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
  272. package/src/plugins/builtin/alerts/events.ts +107 -5
  273. package/src/plugins/builtin/alerts/fired-log.ts +78 -0
  274. package/src/plugins/builtin/alerts/format.ts +2 -1
  275. package/src/plugins/builtin/alerts/headless.ts +100 -39
  276. package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
  277. package/src/plugins/builtin/alerts/history-rows.ts +89 -0
  278. package/src/plugins/builtin/alerts/index.tsx +45 -18
  279. package/src/plugins/builtin/alerts/iv-level.ts +365 -0
  280. package/src/plugins/builtin/alerts/levels.ts +3 -3
  281. package/src/plugins/builtin/alerts/pane.tsx +97 -29
  282. package/src/plugins/builtin/alerts/price.ts +35 -0
  283. package/src/plugins/builtin/alerts/quotes.ts +24 -0
  284. package/src/plugins/builtin/alerts/research-builder.ts +84 -11
  285. package/src/plugins/builtin/alerts/research-rules.ts +76 -3
  286. package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
  287. package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
  288. package/src/plugins/builtin/alerts/scheduled.ts +188 -29
  289. package/src/plugins/builtin/alerts/storage.ts +13 -10
  290. package/src/plugins/builtin/alerts/targets.ts +12 -3
  291. package/src/plugins/builtin/analytics/index.tsx +8 -2
  292. package/src/plugins/builtin/analytics/metrics.ts +1 -1
  293. package/src/plugins/builtin/analytics/risk-book.ts +215 -0
  294. package/src/plugins/builtin/analytics/risk-client.ts +13 -6
  295. package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
  296. package/src/plugins/builtin/analytics/risk-math.ts +6 -3
  297. package/src/plugins/builtin/analytics/risk-model.ts +297 -104
  298. package/src/plugins/builtin/analytics/risk-options.ts +17 -2
  299. package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
  300. package/src/plugins/builtin/attention/pane.tsx +6 -2
  301. package/src/plugins/builtin/awards/headless.ts +7 -3
  302. package/src/plugins/builtin/awards/model.ts +18 -0
  303. package/src/plugins/builtin/awards/pane.tsx +6 -3
  304. package/src/plugins/builtin/backtest/headless.ts +3 -3
  305. package/src/plugins/builtin/backtest/rules.ts +41 -5
  306. package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
  307. package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
  308. package/src/plugins/builtin/broker-manager/footer.ts +27 -11
  309. package/src/plugins/builtin/broker-manager/index.tsx +21 -12
  310. package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
  311. package/src/plugins/builtin/broker-manager/model.ts +12 -2
  312. package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
  313. package/src/plugins/builtin/broker-manager/table.ts +28 -12
  314. package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
  315. package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
  316. package/src/plugins/builtin/broker-trading/controller.ts +45 -13
  317. package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
  318. package/src/plugins/builtin/broker-trading/headless.ts +2 -1
  319. package/src/plugins/builtin/broker-trading/index.tsx +7 -1
  320. package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
  321. package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
  322. package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
  323. package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
  324. package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
  325. package/src/plugins/builtin/broker-trading/pane.tsx +110 -23
  326. package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
  327. package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
  328. package/src/plugins/builtin/buildout/cells.tsx +4 -0
  329. package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
  330. package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
  331. package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
  332. package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
  333. package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
  334. package/src/plugins/builtin/catalysts/detail.tsx +3 -2
  335. package/src/plugins/builtin/catalysts/index.tsx +1 -1
  336. package/src/plugins/builtin/catalysts/model.ts +49 -4
  337. package/src/plugins/builtin/catalysts/pane.tsx +6 -8
  338. package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
  339. package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
  340. package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
  341. package/src/plugins/builtin/changelog/index.tsx +1 -0
  342. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
  343. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
  344. package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
  345. package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
  346. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
  347. package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
  348. package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
  349. package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
  350. package/src/plugins/builtin/chart-composer/headless.ts +253 -35
  351. package/src/plugins/builtin/chart-composer/index.tsx +12 -2
  352. package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
  353. package/src/plugins/builtin/chart-composer/pane.tsx +127 -28
  354. package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
  355. package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
  356. package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
  357. package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
  358. package/src/plugins/builtin/chart-composer/settings.ts +31 -19
  359. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
  360. package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
  361. package/src/plugins/builtin/chat/attachments/model.ts +3 -1
  362. package/src/plugins/builtin/chat/content/index.tsx +1 -1
  363. package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
  364. package/src/plugins/builtin/chat/people.ts +1 -1
  365. package/src/plugins/builtin/clinical-trials/client.ts +5 -2
  366. package/src/plugins/builtin/clinical-trials/model.ts +13 -4
  367. package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
  368. package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
  369. package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
  370. package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
  371. package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
  372. package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
  373. package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
  374. package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
  375. package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
  376. package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
  377. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  378. package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
  379. package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
  380. package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
  381. package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
  382. package/src/plugins/builtin/company-attention/building-model.ts +222 -0
  383. package/src/plugins/builtin/company-attention/building.tsx +172 -0
  384. package/src/plugins/builtin/company-attention/client.ts +117 -1
  385. package/src/plugins/builtin/company-attention/evidence.ts +16 -3
  386. package/src/plugins/builtin/company-attention/headless.ts +101 -5
  387. package/src/plugins/builtin/company-attention/index.tsx +6 -3
  388. package/src/plugins/builtin/company-attention/model.ts +33 -7
  389. package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
  390. package/src/plugins/builtin/company-attention/moves.tsx +159 -0
  391. package/src/plugins/builtin/company-attention/pane.tsx +79 -23
  392. package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
  393. package/src/plugins/builtin/company-attention/signals.tsx +160 -0
  394. package/src/plugins/builtin/company-kpis/headless.ts +3 -2
  395. package/src/plugins/builtin/company-kpis/model.ts +2 -2
  396. package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
  397. package/src/plugins/builtin/composite-plugins.ts +2 -1
  398. package/src/plugins/builtin/congress-trades/headless.ts +1 -1
  399. package/src/plugins/builtin/connections/index.ts +1 -0
  400. package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
  401. package/src/plugins/builtin/correlation/headless.ts +5 -3
  402. package/src/plugins/builtin/cot/headless.ts +28 -6
  403. package/src/plugins/builtin/cot/model.ts +12 -0
  404. package/src/plugins/builtin/cot/pane.tsx +3 -2
  405. package/src/plugins/builtin/cpi/headless.ts +5 -1
  406. package/src/plugins/builtin/cpi/pane.tsx +11 -9
  407. package/src/plugins/builtin/credit-boards/model.ts +2 -0
  408. package/src/plugins/builtin/credit-documents/headless.ts +1 -1
  409. package/src/plugins/builtin/crypto-board/client.ts +86 -0
  410. package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
  411. package/src/plugins/builtin/crypto-board/defi.ts +239 -0
  412. package/src/plugins/builtin/crypto-board/headless.ts +117 -6
  413. package/src/plugins/builtin/crypto-board/index.tsx +8 -3
  414. package/src/plugins/builtin/crypto-board/model.ts +40 -8
  415. package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
  416. package/src/plugins/builtin/crypto-board/series.ts +19 -1
  417. package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
  418. package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
  419. package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
  420. package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
  421. package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
  422. package/src/plugins/builtin/debug/index.tsx +1 -0
  423. package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
  424. package/src/plugins/builtin/docs/index.tsx +1 -1
  425. package/src/plugins/builtin/docs/pane.tsx +2 -2
  426. package/src/plugins/builtin/docs/targets.ts +1 -1
  427. package/src/plugins/builtin/doe/client.ts +5 -1
  428. package/src/plugins/builtin/doe/headless.ts +12 -6
  429. package/src/plugins/builtin/doe/model.ts +43 -6
  430. package/src/plugins/builtin/doe/pane.tsx +18 -11
  431. package/src/plugins/builtin/earnings/board-model.ts +13 -6
  432. package/src/plugins/builtin/earnings/board-table.ts +4 -1
  433. package/src/plugins/builtin/earnings/board.tsx +253 -50
  434. package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
  435. package/src/plugins/builtin/earnings/calendar.tsx +338 -0
  436. package/src/plugins/builtin/earnings/client.ts +4 -3
  437. package/src/plugins/builtin/earnings/headless.ts +53 -15
  438. package/src/plugins/builtin/earnings/history-model.ts +53 -36
  439. package/src/plugins/builtin/earnings/index.tsx +15 -22
  440. package/src/plugins/builtin/earnings/model.ts +17 -12
  441. package/src/plugins/builtin/earnings/scope.ts +89 -0
  442. package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
  443. package/src/plugins/builtin/earnings-calls/data.ts +146 -2
  444. package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
  445. package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
  446. package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
  447. package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
  448. package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
  449. package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
  450. package/src/plugins/builtin/econ/calendar-model.ts +132 -20
  451. package/src/plugins/builtin/econ/detail-view.tsx +48 -10
  452. package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
  453. package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
  454. package/src/plugins/builtin/econ/index.tsx +112 -25
  455. package/src/plugins/builtin/econ/print-watch.ts +2 -1
  456. package/src/plugins/builtin/econ/types.ts +32 -1
  457. package/src/plugins/builtin/econ-statistics/client.ts +16 -3
  458. package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
  459. package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
  460. package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
  461. package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
  462. package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
  463. package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
  464. package/src/plugins/builtin/econ-statistics/view.ts +16 -1
  465. package/src/plugins/builtin/equity-screener/client.ts +21 -3
  466. package/src/plugins/builtin/equity-screener/headless.ts +68 -6
  467. package/src/plugins/builtin/equity-screener/live.ts +1 -1
  468. package/src/plugins/builtin/equity-screener/model.ts +6 -0
  469. package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
  470. package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
  471. package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
  472. package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
  473. package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
  474. package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
  475. package/src/plugins/builtin/exposure/headless.ts +51 -6
  476. package/src/plugins/builtin/exposure/index.tsx +28 -2
  477. package/src/plugins/builtin/exposure/model.ts +7 -0
  478. package/src/plugins/builtin/exposure/pane.tsx +6 -1
  479. package/src/plugins/builtin/fear-greed/index.tsx +1 -1
  480. package/src/plugins/builtin/filing-events/index.tsx +1 -1
  481. package/src/plugins/builtin/futures/model.ts +10 -9
  482. package/src/plugins/builtin/futures/returns.ts +8 -36
  483. package/src/plugins/builtin/futures/table.tsx +1 -1
  484. package/src/plugins/builtin/futures-curve/client.ts +40 -9
  485. package/src/plugins/builtin/futures-curve/headless.ts +39 -17
  486. package/src/plugins/builtin/futures-curve/model.ts +258 -69
  487. package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
  488. package/src/plugins/builtin/fx-matrix/client.ts +15 -8
  489. package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
  490. package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
  491. package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
  492. package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
  493. package/src/plugins/builtin/gpu/headless.ts +9 -4
  494. package/src/plugins/builtin/help/index.tsx +13 -3
  495. package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
  496. package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
  497. package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
  498. package/src/plugins/builtin/holders/client.ts +13 -1
  499. package/src/plugins/builtin/holders/format.ts +28 -17
  500. package/src/plugins/builtin/holders/headless.ts +46 -7
  501. package/src/plugins/builtin/holders/index-holders.ts +264 -0
  502. package/src/plugins/builtin/holders/pane.tsx +79 -15
  503. package/src/plugins/builtin/holders/report-rows.ts +35 -7
  504. package/src/plugins/builtin/holders/table-model.ts +2 -1
  505. package/src/plugins/builtin/holders/treemap.tsx +2 -2
  506. package/src/plugins/builtin/insider/headless.ts +1 -1
  507. package/src/plugins/builtin/insider/signals-client.ts +1 -1
  508. package/src/plugins/builtin/insider/signals.tsx +1 -1
  509. package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
  510. package/src/plugins/builtin/iv-history/client.ts +20 -0
  511. package/src/plugins/builtin/iv-history/headless.ts +4 -4
  512. package/src/plugins/builtin/iv-history/index.tsx +1 -1
  513. package/src/plugins/builtin/iv-history/model.ts +13 -4
  514. package/src/plugins/builtin/iv-history/series.ts +3 -1
  515. package/src/plugins/builtin/jobs/lock-note.ts +1 -1
  516. package/src/plugins/builtin/jobs/model.ts +4 -15
  517. package/src/plugins/builtin/jobs/pane.tsx +7 -5
  518. package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
  519. package/src/plugins/builtin/jodi/pane.tsx +10 -4
  520. package/src/plugins/builtin/layout-manager/index.tsx +1 -0
  521. package/src/plugins/builtin/macro-day/headless.ts +20 -7
  522. package/src/plugins/builtin/macro-day/index.tsx +3 -2
  523. package/src/plugins/builtin/macro-day/model.ts +29 -8
  524. package/src/plugins/builtin/macro-day/pane.tsx +46 -10
  525. package/src/plugins/builtin/macro-day/releases.ts +55 -13
  526. package/src/plugins/builtin/market-heatmap/data.ts +9 -2
  527. package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
  528. package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
  529. package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
  530. package/src/plugins/builtin/market-heatmap/model.ts +10 -7
  531. package/src/plugins/builtin/market-movers/client.ts +33 -19
  532. package/src/plugins/builtin/market-movers/headless.ts +8 -2
  533. package/src/plugins/builtin/market-movers/index.tsx +16 -10
  534. package/src/plugins/builtin/market-movers/screener.ts +29 -8
  535. package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
  536. package/src/plugins/builtin/market-movers/session-table.ts +4 -2
  537. package/src/plugins/builtin/market-movers/table.ts +4 -1
  538. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  539. package/src/plugins/builtin/market-valuation/view.ts +5 -0
  540. package/src/plugins/builtin/members/headless.ts +6 -5
  541. package/src/plugins/builtin/members/pane.tsx +11 -4
  542. package/src/plugins/builtin/mna/client.ts +1 -0
  543. package/src/plugins/builtin/mna/detail.tsx +20 -32
  544. package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
  545. package/src/plugins/builtin/mna/distress/model.ts +3 -2
  546. package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
  547. package/src/plugins/builtin/mna/headless.ts +6 -13
  548. package/src/plugins/builtin/mna/model.ts +93 -15
  549. package/src/plugins/builtin/mna/pane.tsx +5 -4
  550. package/src/plugins/builtin/news/headless.ts +12 -6
  551. package/src/plugins/builtin/news/index.tsx +10 -1
  552. package/src/plugins/builtin/news/wire/index.tsx +3 -2
  553. package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
  554. package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
  555. package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
  556. package/src/plugins/builtin/notes/cli.ts +49 -14
  557. package/src/plugins/builtin/openfda/pane.tsx +1 -1
  558. package/src/plugins/builtin/options/carry.ts +2 -2
  559. package/src/plugins/builtin/options/index.tsx +1 -1
  560. package/src/plugins/builtin/options/view.tsx +10 -10
  561. package/src/plugins/builtin/options-calculator/headless.ts +46 -7
  562. package/src/plugins/builtin/options-scenario/client.ts +123 -28
  563. package/src/plugins/builtin/options-scenario/collar.ts +8 -6
  564. package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
  565. package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
  566. package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
  567. package/src/plugins/builtin/options-scenario/csp.ts +101 -21
  568. package/src/plugins/builtin/options-scenario/headless.ts +36 -15
  569. package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
  570. package/src/plugins/builtin/options-scenario/index.tsx +28 -3
  571. package/src/plugins/builtin/options-scenario/model.ts +13 -0
  572. package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
  573. package/src/plugins/builtin/perps/equity-row.tsx +11 -3
  574. package/src/plugins/builtin/perps/freshness.ts +8 -5
  575. package/src/plugins/builtin/perps/headless.ts +3 -1
  576. package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
  577. package/src/plugins/builtin/perps/live-rows.ts +161 -0
  578. package/src/plugins/builtin/perps/markets-section.tsx +154 -0
  579. package/src/plugins/builtin/perps/pane.tsx +36 -17
  580. package/src/plugins/builtin/perps/venue-markets.ts +96 -0
  581. package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
  582. package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
  583. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
  584. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
  585. package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
  586. package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
  587. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
  588. package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
  589. package/src/plugins/builtin/portfolio-list/income.ts +13 -2
  590. package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
  591. package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
  592. package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
  593. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
  594. package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
  595. package/src/plugins/builtin/power/client.ts +4 -1
  596. package/src/plugins/builtin/power/evidence.ts +22 -7
  597. package/src/plugins/builtin/power/gas.tsx +5 -1
  598. package/src/plugins/builtin/power/pane.tsx +8 -1
  599. package/src/plugins/builtin/power/prices.tsx +10 -3
  600. package/src/plugins/builtin/research/analyst-headless.ts +25 -8
  601. package/src/plugins/builtin/research/analyst-model.ts +68 -3
  602. package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
  603. package/src/plugins/builtin/research/event-model.ts +3 -1
  604. package/src/plugins/builtin/research/event-sources.ts +12 -4
  605. package/src/plugins/builtin/research/index.tsx +2 -1
  606. package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
  607. package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
  608. package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
  609. package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
  610. package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
  611. package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
  612. package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
  613. package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
  614. package/src/plugins/builtin/risk-factors/index.tsx +2 -2
  615. package/src/plugins/builtin/scanner/lock-note.ts +1 -1
  616. package/src/plugins/builtin/sec/forms.ts +13 -0
  617. package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
  618. package/src/plugins/builtin/sec/fund-facts.ts +68 -8
  619. package/src/plugins/builtin/sec/headless.ts +85 -8
  620. package/src/plugins/builtin/sec/index.tsx +58 -12
  621. package/src/plugins/builtin/sectors/client.ts +2 -1
  622. package/src/plugins/builtin/sectors/sector-model.ts +11 -15
  623. package/src/plugins/builtin/series-inventory.ts +2 -0
  624. package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
  625. package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
  626. package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
  627. package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
  628. package/src/plugins/builtin/shared/earnings-report.ts +3 -3
  629. package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
  630. package/src/plugins/builtin/shared/job-posting.ts +129 -0
  631. package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
  632. package/src/plugins/builtin/shared/report-freshness.ts +3 -0
  633. package/src/plugins/builtin/shared/research-trading.tsx +21 -0
  634. package/src/plugins/builtin/shared/series-cache.ts +2 -0
  635. package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
  636. package/src/plugins/builtin/short-interest/client.ts +2 -0
  637. package/src/plugins/builtin/short-interest/headless.ts +41 -12
  638. package/src/plugins/builtin/short-interest/index.tsx +23 -1
  639. package/src/plugins/builtin/short-interest/model.ts +70 -19
  640. package/src/plugins/builtin/short-interest/pane.tsx +19 -2
  641. package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
  642. package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
  643. package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
  644. package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
  645. package/src/plugins/builtin/short-interest/schedule.ts +35 -2
  646. package/src/plugins/builtin/short-interest/surface.tsx +11 -4
  647. package/src/plugins/builtin/short-interest/types.ts +9 -0
  648. package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
  649. package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
  650. package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
  651. package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
  652. package/src/plugins/builtin/supply-chain/model.ts +51 -3
  653. package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
  654. package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
  655. package/src/plugins/builtin/themes/headless.ts +8 -5
  656. package/src/plugins/builtin/themes/model.ts +14 -4
  657. package/src/plugins/builtin/themes/pane.tsx +24 -5
  658. package/src/plugins/builtin/thirteenf/headless.ts +5 -5
  659. package/src/plugins/builtin/thirteenf/signals.ts +3 -1
  660. package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
  661. package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
  662. package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
  663. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
  664. package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
  665. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
  666. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
  667. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
  668. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
  669. package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
  670. package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
  671. package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
  672. package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
  673. package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
  674. package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
  675. package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
  676. package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
  677. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
  678. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
  679. package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
  680. package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
  681. package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
  682. package/src/plugins/builtin/vol-surface/client.ts +5 -4
  683. package/src/plugins/builtin/vol-surface/headless.ts +12 -3
  684. package/src/plugins/builtin/vol-surface/model.ts +4 -2
  685. package/src/plugins/builtin/volatility/model.ts +5 -10
  686. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
  687. package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
  688. package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
  689. package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
  690. package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
  691. package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
  692. package/src/plugins/builtin/world-venue-map/index.ts +3 -26
  693. package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
  694. package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
  695. package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
  696. package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
  697. package/src/plugins/builtin/yield-curve/client.ts +25 -0
  698. package/src/plugins/builtin/yield-curve/curves.ts +7 -4
  699. package/src/plugins/builtin/yield-curve/headless.ts +38 -4
  700. package/src/plugins/builtin/yield-curve/history.ts +4 -3
  701. package/src/plugins/builtin/yield-curve/index.tsx +12 -6
  702. package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
  703. package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
  704. package/src/plugins/bundle.ts +1 -1
  705. package/src/plugins/catalog-browser.ts +2 -1
  706. package/src/plugins/compat.ts +3 -3
  707. package/src/plugins/dependencies.ts +75 -14
  708. package/src/plugins/extracted-plugins.ts +132 -34
  709. package/src/plugins/host-link.ts +149 -34
  710. package/src/plugins/installer.ts +35 -10
  711. package/src/plugins/loader.ts +206 -38
  712. package/src/plugins/manager-node.ts +2 -2
  713. package/src/plugins/marketplace/deactivation.ts +22 -0
  714. package/src/plugins/marketplace/model.ts +2 -2
  715. package/src/plugins/marketplace/packs.ts +1 -1
  716. package/src/plugins/ownership.ts +1 -1
  717. package/src/plugins/peer-retry.ts +155 -0
  718. package/src/plugins/registry/contributions.ts +3 -1
  719. package/src/plugins/registry/index.ts +4 -3
  720. package/src/plugins/registry/plugin-state.ts +3 -0
  721. package/src/plugins/seed-notice.ts +20 -0
  722. package/src/plugins/shortcut-argument.ts +39 -0
  723. package/src/portfolio/allocation.ts +1 -1
  724. package/src/portfolio/collection-name.ts +31 -0
  725. package/src/portfolio/column-values.ts +10 -8
  726. package/src/portfolio/cost-fx.ts +296 -19
  727. package/src/portfolio/manual-lots.ts +75 -0
  728. package/src/portfolio/mutations.ts +60 -22
  729. package/src/portfolio/suffixed-listings.ts +209 -0
  730. package/src/portfolio/totals-currency.ts +24 -0
  731. package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
  732. package/src/public/time-series.ts +11 -8
  733. package/src/remote/schema.ts +1 -1
  734. package/src/renderers/browser/config-host.ts +3 -0
  735. package/src/renderers/browser/main.tsx +23 -3
  736. package/src/renderers/dom/boot-frame-page.ts +187 -0
  737. package/src/renderers/dom/boot-frame.ts +237 -0
  738. package/src/renderers/dom/build-assets.ts +46 -8
  739. package/src/renderers/dom/dom-ui-host.tsx +4 -29
  740. package/src/renderers/dom/host/ascii-text.ts +16 -2
  741. package/src/renderers/dom/host/box.tsx +43 -2
  742. package/src/renderers/dom/host/chart-surface.tsx +2 -0
  743. package/src/renderers/dom/host/hls.chunk.ts +3 -0
  744. package/src/renderers/dom/host/image-surface.tsx +49 -0
  745. package/src/renderers/dom/host/media-surface.tsx +24 -18
  746. package/src/renderers/dom/host/mouse.ts +30 -0
  747. package/src/renderers/dom/host/size-observer.ts +1 -1
  748. package/src/renderers/dom/host/style.ts +1 -1
  749. package/src/renderers/dom/styles.css +76 -0
  750. package/src/renderers/dom/test-utils.tsx +2 -1
  751. package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
  752. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
  753. package/src/renderers/electrobun/bun/desktop/backend.ts +46 -3
  754. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
  755. package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
  756. package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
  757. package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
  758. package/src/renderers/electrobun/bun/index.ts +11 -1
  759. package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
  760. package/src/renderers/electrobun/bun/window/create.ts +4 -1
  761. package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
  762. package/src/renderers/electrobun/shared/protocol.ts +6 -1
  763. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
  764. package/src/renderers/electrobun/view/config-host.ts +3 -0
  765. package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
  766. package/src/renderers/electrobun/view/main.tsx +30 -4
  767. package/src/renderers/electrobun/view/news-source.ts +5 -5
  768. package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
  769. package/src/renderers/electrobun/view/ui-host.tsx +1 -1
  770. package/src/renderers/opentui/browser-open.ts +88 -0
  771. package/src/renderers/opentui/host.tsx +5 -14
  772. package/src/renderers/opentui/image/loader.ts +3 -2
  773. package/src/renderers/opentui/native-smoke.ts +10 -1
  774. package/src/renderers/opentui/pane-image/index.ts +2 -1
  775. package/src/renderers/opentui/render-lib.ts +253 -0
  776. package/src/renderers/opentui/render-timing-smoke.ts +1 -1
  777. package/src/renderers/opentui/start.tsx +1 -1
  778. package/src/renderers/share/layout-view.tsx +2 -2
  779. package/src/renderers/share/main.tsx +4 -4
  780. package/src/renderers/share/view.tsx +1 -1
  781. package/src/series/resolve.ts +22 -6
  782. package/src/series/standalone.ts +30 -2
  783. package/src/series/types.ts +8 -1
  784. package/src/shares/api.ts +4 -1
  785. package/src/shares/pane.ts +1 -1
  786. package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
  787. package/src/sources/gloomberb-cloud/index.ts +32 -16
  788. package/src/sources/gloomberb-cloud/news.ts +39 -0
  789. package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
  790. package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
  791. package/src/sources/listing-symbols.ts +37 -0
  792. package/src/sources/provider-errors.ts +16 -2
  793. package/src/sources/provider-router/financial-routes.ts +21 -3
  794. package/src/sources/provider-router/financials.ts +15 -2
  795. package/src/sources/provider-router/history.ts +30 -8
  796. package/src/sources/provider-router/primary.ts +1 -1
  797. package/src/state/app/bootstrap.ts +23 -0
  798. package/src/state/hooks/inline-tickers.ts +30 -5
  799. package/src/sync/controller.ts +1 -1
  800. package/src/sync/core-contributors.ts +46 -14
  801. package/src/team/collections-sync.ts +2 -1
  802. package/src/team/collections.ts +178 -17
  803. package/src/telemetry/crash-reports.ts +17 -4
  804. package/src/test-support/builtin-panes.ts +1 -1
  805. package/src/theme/colors.ts +3 -30
  806. package/src/theme/ui-tokens.ts +37 -1
  807. package/src/tickers/company-name-listing.ts +210 -33
  808. package/src/tickers/index-roots.ts +47 -0
  809. package/src/tickers/instrument-label.ts +5 -1
  810. package/src/tickers/metadata.ts +10 -0
  811. package/src/tickers/perpetual-listing.ts +5 -2
  812. package/src/tickers/search/home-listing.ts +75 -0
  813. package/src/tickers/search/index.ts +76 -27
  814. package/src/tickers/search/ranking.ts +54 -4
  815. package/src/tickers/search/upsert.ts +29 -0
  816. package/src/tickers/terminal-codes.ts +416 -40
  817. package/src/time-series/bar-aggregation.ts +243 -0
  818. package/src/time-series/base-series.ts +307 -0
  819. package/src/time-series/chart-bounds.ts +349 -0
  820. package/src/time-series/chart-seed.ts +142 -0
  821. package/src/time-series/economic.ts +5 -0
  822. package/src/time-series/fundamentals.ts +18 -3
  823. package/src/time-series/history-acquisition.ts +499 -0
  824. package/src/time-series/leverage.ts +100 -0
  825. package/src/time-series/market-resolution.ts +4 -2
  826. package/src/time-series/market.ts +2 -1
  827. package/src/time-series/price-comparison.ts +175 -30
  828. package/src/time-series/range.ts +9 -1
  829. package/src/time-series/resolution.ts +174 -16
  830. package/src/time-series/resolve-context.ts +157 -0
  831. package/src/time-series/resolve.ts +126 -1577
  832. package/src/time-series/series-name.ts +38 -0
  833. package/src/time-series/series-presentation.ts +208 -0
  834. package/src/time-series/spec.ts +11 -6
  835. package/src/time-series/studies.ts +109 -12
  836. package/src/time-series/tail-reconcile.ts +121 -0
  837. package/src/time-series/types.ts +29 -2
  838. package/src/time-series/use-chart-resolution.ts +4 -5
  839. package/src/types/broker.ts +10 -0
  840. package/src/types/config.ts +14 -0
  841. package/src/types/data-provider.ts +14 -0
  842. package/src/types/exchange-rate.ts +6 -0
  843. package/src/types/financials.ts +104 -7
  844. package/src/types/headless.ts +76 -6
  845. package/src/types/instrument.ts +3 -0
  846. package/src/types/plugin.ts +65 -8
  847. package/src/types/price-history.ts +2 -0
  848. package/src/types/ticker.ts +13 -0
  849. package/src/types/trading.ts +59 -1
  850. package/src/ui/ascii-font.ts +13 -1
  851. package/src/ui/host.tsx +6 -1
  852. package/src/updater/command-names.ts +175 -0
  853. package/src/updater/index.ts +10 -5
  854. package/src/utils/calendar-date.ts +32 -15
  855. package/src/utils/cash-runway.ts +241 -0
  856. package/src/utils/central-banks.ts +42 -0
  857. package/src/utils/cli-output.ts +259 -80
  858. package/src/utils/contract-month.ts +16 -0
  859. package/src/utils/crypto-pair.ts +61 -3
  860. package/src/utils/currency-units.ts +29 -0
  861. package/src/utils/datetime-format.ts +10 -0
  862. package/src/utils/debug-log.ts +1 -1
  863. package/src/utils/decimal-comma.ts +39 -6
  864. package/src/utils/exchange-announcements.ts +71 -0
  865. package/src/utils/exchange-rate-snapshot.ts +10 -0
  866. package/src/utils/financial-statements.ts +83 -4
  867. package/src/utils/format.ts +34 -16
  868. package/src/utils/fundamentals.ts +150 -34
  869. package/src/utils/fx-market-hours.ts +10 -1
  870. package/src/utils/latest-financial-period.ts +8 -0
  871. package/src/utils/linux-libc.ts +54 -0
  872. package/src/utils/market-capitalization.ts +111 -15
  873. package/src/utils/max-drawdown.ts +64 -0
  874. package/src/utils/network-failure.ts +83 -0
  875. package/src/utils/option-expiry.ts +139 -7
  876. package/src/utils/price-earnings.ts +11 -5
  877. package/src/utils/price-history.ts +18 -8
  878. package/src/utils/price-window.ts +131 -0
  879. package/src/utils/release-date.ts +47 -0
  880. package/src/utils/sec.ts +3 -0
  881. package/src/utils/throttled-fetch.ts +11 -4
  882. package/src/utils/trailing-eps.ts +67 -0
  883. package/src/utils/typed-text.ts +21 -0
  884. package/src/utils/utc-time.ts +24 -1
  885. package/src/version.ts +6 -0
  886. package/src/cli/pane-functions/screenshot.ts +0 -2122
@@ -57,6 +57,12 @@ export interface CliReportColumn<Row = Record<string, unknown>> {
57
57
  format?: (value: unknown, row: Row) => string;
58
58
  /** The row field naming the unit of a number in this column; the number then exports as it is, with that unit. */
59
59
  unitKey?: string;
60
+ /**
61
+ * With `unitKey`: the unit always goes to a `<header> unit` column beside
62
+ * the figures, never into the header, so the header is the same whichever
63
+ * rows loaded (a market cap in one currency for some peers, in another for others).
64
+ */
65
+ unitColumn?: boolean;
60
66
  }
61
67
 
62
68
  /** A label/value line of a report. `unit` names the unit of a numeric `value` when `formatted` cannot say it. */
@@ -83,6 +89,8 @@ interface ResolvedColumn {
83
89
  cells: ResolvedCell[];
84
90
  /** The unit the column draws its numbers in, for a table with no rows to say it. */
85
91
  unit?: string;
92
+ /** The unit always has a column of its own (`unitColumn`). */
93
+ unitColumn?: boolean;
86
94
  }
87
95
 
88
96
  const BLANK = { kind: "blank" } as const;
@@ -318,7 +326,7 @@ function rowUnits(columns: readonly ResolvedColumn[], mixed: readonly boolean[],
318
326
  */
319
327
  function assembleTable(title: string, columns: readonly ResolvedColumn[], rowCount: number, status?: StatusColumn): CliReportTable {
320
328
  const units = columns.map((column) => rowCount === 0 && column.unit != null ? new Set([column.unit]) : numberUnits(column.cells));
321
- const mixed = units.map((columnUnits) => columnUnits.size > 1);
329
+ const mixed = units.map((columnUnits, index) => columnUnits.size > 1 || columns[index]!.unitColumn === true);
322
330
  const byRow = mixed.some(Boolean) ? rowUnits(columns, mixed, rowCount) : null;
323
331
  const layout = columns.flatMap((column, index) => {
324
332
  const columnUnits = units[index]!;
@@ -381,7 +389,9 @@ const EMPTY_ROW: unknown = (() => {
381
389
  * plain figure), read from what its format draws for one; null when it draws
382
390
  * no figure for one, passes the value through as it is, or throws.
383
391
  */
384
- function drawnUnit<Row>(column: CliReportColumn<Row>, row: Row): string | null {
392
+ function drawnUnit<Row>(column: CliReportColumn<Row>, row: Row, rowUnitKey?: string): string | null {
393
+ // A figure in the row's own unit is bare: the row's `currency_or_unit` names it.
394
+ if (rowUnitKey && column.unitKey === rowUnitKey) return "";
385
395
  const unit = column.unitKey ? (row as Record<string, unknown> | undefined)?.[column.unitKey] : undefined;
386
396
  if (typeof unit === "string" && unit) return unit;
387
397
  if (!column.format) return null;
@@ -438,29 +448,36 @@ const IDENTIFIER_KEY = /^(?:id|cik|code|cusip|figi|isin|symbol|ticker)$|(?:Id|Ci
438
448
  * when one of its columns draws figures through a format, read from the
439
449
  * columns alone so it is there with or without rows, and a table of text has
440
450
  * none; beside a column of its own named Status it is `value_status`.
451
+ * `rowUnitKey` is the row field its `currency_or_unit` cell is read from: a
452
+ * column whose `unitKey` is that field exports its figures bare under its own
453
+ * header (`Last`, never `Last ($)` beside a franc), each row's unit named there.
441
454
  */
442
455
  export function exportRowsTable<Row extends Record<string, unknown>>(
443
456
  title: string,
444
457
  columns: readonly CliReportColumn<Row>[],
445
458
  rows: readonly Row[],
446
- { status = false }: { status?: boolean } = {},
459
+ { status = false, rowUnitKey }: { status?: boolean; rowUnitKey?: string } = {},
447
460
  ): CliReportTable {
448
461
  const reasons = rows.map((): Array<{ header: string; text: string }> => []);
449
462
  const units = columns.map(columnUnit);
450
463
  // Decided by the columns alone, so a table has the column, or not, whatever rows it has.
451
464
  const withStatus = status && units.some((unit) => unit != null);
452
465
  const resolved = columns.map((column, columnIndex): ResolvedColumn => {
453
- const rowUnits = rows.map((row) => drawnUnit(column, row));
466
+ const rowUnits = rows.map((row) => drawnUnit(column, row, rowUnitKey));
454
467
  const values = rows.map((row) => (row as Record<string, unknown> | undefined)?.[column.key]);
468
+ const inRowUnit = !!rowUnitKey && column.unitKey === rowUnitKey;
455
469
  const { header, cells } = resolveColumn(
456
470
  column.header,
457
471
  rows.map((row, index): Cell => {
458
472
  const value = values[index];
459
473
  const unit = column.unitKey ? (row as Record<string, unknown> | undefined)?.[column.unitKey] : undefined;
460
- if (typeof unit === "string" && unit && typeof value === "number" && Number.isFinite(value)) {
461
- return { kind: "number", value: exportNumber(value), unit };
474
+ const drawn = column.format ? column.format(value, row) : null;
475
+ // A figure the text leaves out of this row (another session's print) is not one of its figures.
476
+ const left = drawn != null && readDisplay(drawn) === BLANK_DISPLAY;
477
+ if (!left && typeof value === "number" && Number.isFinite(value) && (inRowUnit || (typeof unit === "string" && unit))) {
478
+ return { kind: "number", value: exportNumber(value), unit: inRowUnit ? "" : unit as string };
462
479
  }
463
- return exportCell(value, column.format ? column.format(value, row) : null, column.key);
480
+ return exportCell(value, drawn, column.key);
464
481
  }),
465
482
  !IDENTIFIER_KEY.test(column.key),
466
483
  );
@@ -478,7 +495,8 @@ export function exportRowsTable<Row extends Record<string, unknown>>(
478
495
  }),
479
496
  };
480
497
  const unit = units[columnIndex];
481
- return unit == null ? table : { ...table, unit };
498
+ const withUnit = unit == null ? table : { ...table, unit };
499
+ return column.unitColumn && column.unitKey && !inRowUnit ? { ...withUnit, unitColumn: true } : withUnit;
482
500
  });
483
501
  const statusColumn = withStatus ? {
484
502
  header: columns.some((column) => column.header.trim().toLowerCase() === "status") ? "value_status" : "status",
@@ -552,18 +570,33 @@ function sectionList(tables: readonly CliReportTable[]): string {
552
570
  }
553
571
 
554
572
  /**
555
- * `--section`: one table, by its title (any case) or its 1-based position.
556
- * Without a selector the report keeps every table.
573
+ * The table `--section` names by title, in any case: the one titled so, else
574
+ * the one whose title starts with it, as a title that carries its date does
575
+ * (`Strikes` for `Strikes · Oct 30 '26`). A start several titles share picks
576
+ * none.
577
+ */
578
+ function sectionByTitle(tables: readonly CliReportTable[], wanted: string): CliReportTable | undefined {
579
+ const name = wanted.toLowerCase();
580
+ const titles = tables.map((table) => table.title.trim().toLowerCase());
581
+ const exact = titles.indexOf(name);
582
+ if (exact >= 0) return tables[exact];
583
+ const starting = tables.filter((_, index) => titles[index]!.startsWith(name));
584
+ if (starting.length > 1) {
585
+ throw new Error(`"${wanted}" starts more than one section: ${starting.map((table) => table.title).join(", ")}. Give more of the title, or its number.`);
586
+ }
587
+ return starting[0];
588
+ }
589
+
590
+ /**
591
+ * `--section`: one table, by its title or the start of it (any case), or its
592
+ * 1-based position. Without a selector the report keeps every table.
557
593
  */
558
594
  export function selectReportTables(report: CliReportTables, selector: string | true | undefined): CliReportTables {
559
595
  if (selector === undefined) return report;
560
596
  if (selector === true || !selector.trim()) throw new Error("--section needs a section title or number.");
561
597
  const wanted = selector.trim();
562
598
  if (report.tables.length === 0) throw new Error(`No section "${wanted}": this report has no tables.`);
563
- const index = /^\d+$/.test(wanted)
564
- ? Number(wanted) - 1
565
- : report.tables.findIndex((table) => table.title.trim().toLowerCase() === wanted.toLowerCase());
566
- const table = report.tables[index];
599
+ const table = /^\d+$/.test(wanted) ? report.tables[Number(wanted) - 1] : sectionByTitle(report.tables, wanted);
567
600
  if (!table) throw new Error(`No section "${wanted}". Sections: ${sectionList(report.tables)}.`);
568
601
  return { ...report, tables: [table] };
569
602
  }
@@ -582,7 +615,10 @@ function csvLine(row: readonly unknown[]): string {
582
615
 
583
616
  /**
584
617
  * A table with the fixed columns after its own, every row naming what it is
585
- * and the source and as-of the footer cites. A table without columns stays empty.
618
+ * and the source and as-of the footer cites. A fixed column the table already
619
+ * has under the same name is left out, so its own per-row values stay the
620
+ * only ones (CBR's `source` and `as_of`) and a reader keyed by name finds one
621
+ * column. A table without columns stays empty.
586
622
  */
587
623
  function identifiedTable(table: CliReportTable, report: CliReportTables, freshness: ReportFreshness | undefined): CliReportTable {
588
624
  if (!freshness || table.columns.length === 0) return table;
@@ -592,7 +628,16 @@ function identifiedTable(table: CliReportTable, report: CliReportTables, freshne
592
628
  const own = table.rowIdentities?.[index];
593
629
  return own ? exportIdentityCells(freshness, { ...identity, ...own }) : cells;
594
630
  };
595
- return { ...table, columns: [...table.columns, ...EXPORT_IDENTITY_COLUMNS], rows: table.rows.map((row, index) => [...row, ...rowCells(index)]) };
631
+ const added = EXPORT_IDENTITY_COLUMNS.flatMap((column, index) => table.columns.includes(column) ? [] : [index]);
632
+ if (added.length === 0) return table;
633
+ return {
634
+ ...table,
635
+ columns: [...table.columns, ...added.map((index) => EXPORT_IDENTITY_COLUMNS[index]!)],
636
+ rows: table.rows.map((row, index) => {
637
+ const identityCells = rowCells(index);
638
+ return [...row, ...added.map((column) => identityCells[column]!)];
639
+ }),
640
+ };
596
641
  }
597
642
 
598
643
  /**
@@ -1,8 +1,10 @@
1
1
  import { saveConfig } from "../data/config/store";
2
2
  import { loadCliConfigIfAvailable } from "./context";
3
3
  import { getPluginsDir } from "../plugins/loader";
4
- import { seedExtractedPlugins } from "../plugins/extracted-plugins";
4
+ import { pluginSeedFailure, pluginSeedNotice, samePluginSeedFailure, seedExtractedPlugins } from "../plugins/extracted-plugins";
5
+ import { setPluginSeedNotice } from "../plugins/seed-notice";
5
6
  import { debugLog } from "../utils/debug-log";
7
+ import type { AppConfig } from "../types/config";
6
8
 
7
9
  const log = debugLog.createLogger("plugin-seed");
8
10
 
@@ -10,39 +12,52 @@ const log = debugLog.createLogger("plugin-seed");
10
12
  * Reinstalls plugins that moved out of this repository into their own.
11
13
  *
12
14
  * Runs before the plugin catalog is read so a restored plugin is available in
13
- * the same session, and stays quiet on failure: an offline launch should start
14
- * normally and try again next time, not block on a network request.
15
+ * the same session, and never blocks or prints: an offline launch should
16
+ * start normally and try again next time. What it could not install becomes
17
+ * one notice the app shows once it is up (`setPluginSeedNotice`), saying why
18
+ * when git is missing, and `doctor` names the plugins.
15
19
  *
16
- * Returns the seeded ids so a caller that already holds the config in memory
17
- * can adopt them. The desktop loads its config before restoring, and without
18
- * this it would keep an object whose `seededPlugins` is one launch stale and
19
- * overwrite the record on the next save.
20
+ * Returns what it recorded (the seeded ids, and what failed) so a caller that
21
+ * already holds the config in memory can adopt it. The desktop loads its
22
+ * config before restoring, and without this it would keep an object one
23
+ * launch stale and overwrite the record on the next save.
20
24
  */
21
- export async function restoreExtractedPlugins(): Promise<string[] | null> {
25
+ export async function restoreExtractedPlugins(): Promise<Pick<AppConfig, "seededPlugins" | "pluginSeedFailure"> | null> {
22
26
  try {
23
27
  const config = await loadCliConfigIfAvailable();
24
28
  // No data directory yet means a first run: there is nothing to restore.
25
29
  if (!config) return null;
26
- // Through the registry like `gloomberb install`: the reviewed commit, and
30
+ // Through the registry like `gloom install`: the reviewed commit, and
27
31
  // nothing on a Gloomberb too old for it. That failure is retried at the
28
32
  // next launch, by when this Gloomberb has usually updated itself. The
29
33
  // registry is read once, and only when something is left to install.
30
- const { installListedPlugin, loadRegistryListings } = await import("../plugins/installer");
34
+ // Quiet: the terminal app is about to own the screen, and git's or bun's
35
+ // output would be left behind in the scrollback.
36
+ const { gitInstalled, installListedPlugin, loadRegistryListings } = await import("../plugins/installer");
31
37
  let listings: ReturnType<typeof loadRegistryListings> | undefined;
38
+ let gitMissing: boolean | undefined;
32
39
  const result = await seedExtractedPlugins(config, async (repo) => {
40
+ // Without git every clone fails the same way: no registry read, no attempt.
41
+ gitMissing ??= !gitInstalled();
42
+ if (gitMissing) throw new Error("git is not installed");
33
43
  listings ??= loadRegistryListings();
34
- return installListedPlugin(repo, {}, await listings);
44
+ return installListedPlugin(repo, { quiet: true }, await listings);
35
45
  });
46
+ // Recorded, so doctor knows a launch tried, and a failure the next launch
47
+ // retries is not announced again while it lasts.
48
+ const failure = pluginSeedFailure(result.failed, gitMissing === true);
49
+ setPluginSeedNotice(pluginSeedNotice(failure, config.pluginSeedFailure));
36
50
 
37
51
  const seeded = [...new Set(result.seeded)].sort();
38
52
  const existing = [...new Set(config.seededPlugins ?? [])].sort();
39
- if (seeded.join() === existing.join()) return seeded;
53
+ const record = { seededPlugins: seeded, pluginSeedFailure: failure };
54
+ if (seeded.join() === existing.join() && samePluginSeedFailure(failure, config.pluginSeedFailure)) return record;
40
55
 
41
- await saveConfig({ ...config, seededPlugins: seeded });
56
+ await saveConfig({ ...config, ...record });
42
57
  if (result.installed.length > 0) {
43
58
  log.info(`Restored ${result.installed.join(", ")} into ${getPluginsDir()}`);
44
59
  }
45
- return seeded;
60
+ return record;
46
61
  } catch (error) {
47
62
  log.error(`Plugin restore skipped: ${error}`);
48
63
  return null;
package/src/cli/result.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { CliGlobalOptions } from "./options";
2
2
  import {
3
+ cliPlainEnabled,
3
4
  cliStyles,
4
5
  cliTerminalWidth,
5
6
  renderStats,
@@ -13,7 +14,7 @@ import {
13
14
  } from "../utils/cli-output";
14
15
  import { serializeCsv } from "../utils/csv";
15
16
  import { formatUtcTime, isEpochMilliseconds, isZonedIsoDateTime } from "../utils/utc-time";
16
- import { formatFreshnessLine, type ReportFreshness } from "./pane-functions/freshness";
17
+ import { formatFreshnessLine, withSavedCopy, type ReportFreshness } from "./pane-functions/freshness";
17
18
  import { withSearchHints, type FredSeriesCheck } from "./not-a-ticker";
18
19
  import { renderReportCsv, renderReportNdjson, withCsvFooter, type CliReportTables } from "./report-tables";
19
20
  import {
@@ -98,6 +99,11 @@ export interface CliResultRenderOptions<T = unknown, Row = Record<string, unknow
98
99
  * `metadata.rows` in JSON.
99
100
  */
100
101
  dateKey?: string;
102
+ /**
103
+ * The row key that splits the rows into series of their own, each windowed
104
+ * apart: with `symbol`, `--tail 5` keeps every symbol's newest five rows.
105
+ */
106
+ seriesKey?: string;
101
107
  /** How many rows to show when neither `--limit` nor `--tail` is given; every row when absent. */
102
108
  defaultLimit?: number;
103
109
  /**
@@ -114,6 +120,15 @@ export interface CliResultRenderOptions<T = unknown, Row = Record<string, unknow
114
120
  exportIdentity?: ExportIdentity | ((row: Row) => ExportIdentity);
115
121
  /** What CSV says after the source lines as `# note:` lines: what the rows do not show, such as where a series begins. */
116
122
  exportNotes?: readonly string[];
123
+ /**
124
+ * Why a row's figures are empty (`Not a ticker: ZZZZQQ.`, `Chg%: no previous
125
+ * close`), for the `status` column CSV writes after the row's own columns and
126
+ * the `status` field of an NDJSON row; empty for a whole row. The column is
127
+ * there whenever this is, with rows or without, so the header never depends
128
+ * on what loaded. A figure that is no number (NaN) is written empty and,
129
+ * without a reason here, named as `<header>: not available`.
130
+ */
131
+ exportStatus?: (row: Row) => string | null | undefined;
117
132
  }
118
133
 
119
134
  interface CliResultJsonEnvelope<T> extends Omit<CliResult<T>, "freshness" | "exportFreshness" | "failure"> {
@@ -149,11 +164,28 @@ function rowWindowOptions(options: CliGlobalOptions, renderOptions: Pick<CliResu
149
164
  function windowed<Row>(
150
165
  rows: readonly Row[],
151
166
  options: CliGlobalOptions,
152
- renderOptions: Pick<CliResultRenderOptions, "dateKey" | "defaultLimit">,
167
+ renderOptions: Pick<CliResultRenderOptions, "dateKey" | "defaultLimit" | "seriesKey">,
153
168
  ): RowWindow<Row> {
154
- const { dateKey } = renderOptions;
169
+ const { dateKey, seriesKey } = renderOptions;
155
170
  const dateOf = dateKey ? (row: Row) => (isPlainObject(row) ? row[dateKey] : undefined) : undefined;
156
- return windowRows(rows, rowWindowOptions(options, renderOptions), dateOf);
171
+ const windowOptions = rowWindowOptions(options, renderOptions);
172
+ if (!seriesKey) return windowRows(rows, windowOptions, dateOf);
173
+ const series = new Map<unknown, Row[]>();
174
+ for (const row of rows) {
175
+ const key = isPlainObject(row) ? row[seriesKey] : undefined;
176
+ const group = series.get(key);
177
+ if (group) group.push(row);
178
+ else series.set(key, [row]);
179
+ }
180
+ const windows = [...series.values()].map((group) => windowRows(group, windowOptions, dateOf));
181
+ const count = windowOptions.tail ?? windowOptions.limit;
182
+ return {
183
+ rows: windows.flatMap((window) => window.rows),
184
+ total: rows.length,
185
+ kept: windows.find((window) => window.kept)?.kept ?? null,
186
+ note: windows.some((window) => window.note)
187
+ ? `showing the oldest ${count} ${count === 1 ? "row" : "rows"} of each ${seriesKey}; --tail ${count} for the latest` : null,
188
+ };
157
189
  }
158
190
 
159
191
  function asRows<T, Row>(data: T, rows?: (data: T) => Row[]): Row[] {
@@ -206,7 +238,7 @@ function formatTextValue(
206
238
  depth = 0,
207
239
  width: number | null = null,
208
240
  ): string {
209
- const missing = context === "record" ? cliStyles.muted("-") : "";
241
+ const missing = context === "record" ? cliPlainEnabled() ? "—" : cliStyles.muted("-") : "";
210
242
  if (value == null || value === "") return missing;
211
243
  // Times print in UTC with the zone named, never in the host's zone; JSON and CSV keep the raw value.
212
244
  if (value instanceof Date) return formatUtcTime(value);
@@ -291,23 +323,69 @@ function serializeColumns<Row>(columns?: CliResultColumn<Row>[]) {
291
323
  }));
292
324
  }
293
325
 
326
+ /** A number a spreadsheet cannot read: NaN or an infinity, which exports write empty, never as the word. */
327
+ function isNonFiniteNumber(value: unknown): boolean {
328
+ return typeof value === "number" && !Number.isFinite(value);
329
+ }
330
+
331
+ /**
332
+ * What a row's status cell says: the command's reason, else the figures
333
+ * written empty for being no number. Empty when nothing is missing.
334
+ */
335
+ function exportStatusText(reason: string | null | undefined, blanked: readonly string[]): string {
336
+ const own = reason?.trim();
337
+ if (own) return own;
338
+ return blanked.length > 0 ? `${blanked.join(", ")}: not available` : "";
339
+ }
340
+
341
+ /** `status`, or `value_status` beside a column of the table's own named Status. */
342
+ function statusHeader(headers: readonly string[]): string {
343
+ return headers.some((header) => header.trim().toLowerCase() === "status") ? "value_status" : "status";
344
+ }
345
+
294
346
  function renderCsv<Row extends Record<string, unknown>>(
295
347
  rows: Row[],
296
348
  columns?: CliResultColumn<Row>[],
297
349
  identity?: (row: Row) => string[],
350
+ status?: (row: Row) => string | null | undefined,
298
351
  ): string {
299
352
  const resolvedColumns = columns && columns.length > 0
300
353
  ? columns
301
354
  : inferColumns(rows as Record<string, unknown>[]) as CliResultColumn<Row>[];
355
+ const headers = resolvedColumns.map((column) => column.header);
302
356
  return serializeCsv([
303
- [...resolvedColumns.map((column) => column.header), ...identity ? EXPORT_IDENTITY_COLUMNS : []],
304
- ...rows.map((row) => [
305
- ...resolvedColumns.map((column) => (column.value ? column.value(row) : row[column.key])),
306
- ...identity?.(row) ?? [],
307
- ]),
357
+ [...headers, ...status ? [statusHeader(headers)] : [], ...identity ? EXPORT_IDENTITY_COLUMNS : []],
358
+ ...rows.map((row) => {
359
+ const values = resolvedColumns.map((column) => (column.value ? column.value(row) : row[column.key]));
360
+ const blanked = resolvedColumns.flatMap((column, index) => isNonFiniteNumber(values[index]) ? [column.header] : []);
361
+ return [
362
+ ...values.map((value) => isNonFiniteNumber(value) ? "" : value),
363
+ ...status ? [exportStatusText(status(row), blanked)] : [],
364
+ ...identity?.(row) ?? [],
365
+ ];
366
+ }),
308
367
  ]);
309
368
  }
310
369
 
370
+ /**
371
+ * The key an NDJSON row says why its figures are empty under: `status`, or
372
+ * `value_status` beside a field of the row's own that the export writes under
373
+ * that name (an order's status), as CSV's header does.
374
+ */
375
+ function ndjsonStatusKey(rows: readonly unknown[], columns?: readonly CliResultColumn<never>[]): string {
376
+ const own = columns && columns.length > 0
377
+ ? columns.some((column) => column.key === "status")
378
+ : rows.some((row) => isPlainObject(row) && "status" in row);
379
+ return own ? "value_status" : "status";
380
+ }
381
+
382
+ /** An NDJSON row: a figure that is no number is null, and the row says why its figures are empty when the command does. */
383
+ function ndjsonRow<Row extends Record<string, unknown>>(row: Row, status: ((row: Row) => string | null | undefined) | undefined, statusKey: string): Record<string, unknown> {
384
+ const blanked = Object.entries(row).flatMap(([key, value]) => isNonFiniteNumber(value) ? [key] : []);
385
+ const own = blanked.length > 0 ? { ...row, ...Object.fromEntries(blanked.map((key) => [key, null])) } : row;
386
+ return status ? { ...own, [statusKey]: exportStatusText(status(row), blanked) || null } : own;
387
+ }
388
+
311
389
  function stringField(row: Record<string, unknown>, key: string): string | null {
312
390
  const value = row?.[key];
313
391
  return typeof value === "string" && value.trim() ? value : null;
@@ -348,10 +426,11 @@ function renderTextTable<Row extends Record<string, unknown>>(
348
426
  ): string {
349
427
  const resolvedColumns = textColumns(rows, columns);
350
428
  const cells = rows.map((row) => resolvedColumns.map((column) => formatTextCell(column, row, "table")));
351
- // A column no row fills is noise in a table; exports keep it.
429
+ // A column no row fills is noise in a table; exports keep it, and so does plain output, whose
430
+ // tables keep one shape from query to query with "—" in the empty cells.
352
431
  const filled = resolvedColumns
353
432
  .map((column, index) => ({ column, index }))
354
- .filter(({ column, index }) => column.width != null || cells.some((row) => row[index] !== ""));
433
+ .filter(({ column, index }) => cliPlainEnabled() || column.width != null || cells.some((row) => row[index] !== ""));
355
434
  const shown = filled.length > 0 ? filled : resolvedColumns.map((column, index) => ({ column, index }));
356
435
  return renderTable(
357
436
  shown.map(({ column }) => ({
@@ -395,9 +474,13 @@ function overflowsTerminal<Row extends Record<string, unknown>>(rows: Row[]): bo
395
474
  return width > terminalWidth;
396
475
  }
397
476
 
398
- /** The closing source, as-of and status line of a text result, for output printed without `printResult`. */
399
- export function cliFreshnessFooter(freshness: ReportFreshness): string {
400
- return cliStyles.muted(wrapToTerminal(formatFreshnessLine(freshness)));
477
+ /**
478
+ * The closing source, as-of and status line of a text result, for output
479
+ * printed without `printResult`; `shown` is the data the line is drawn from,
480
+ * which says whether it came from a saved copy.
481
+ */
482
+ export function cliFreshnessFooter(freshness: ReportFreshness, shown?: unknown): string {
483
+ return cliStyles.muted(wrapToTerminal(formatFreshnessLine(withSavedCopy(freshness, shown))));
401
484
  }
402
485
 
403
486
  export function serializeCliResult<T, Row extends Record<string, unknown> = Record<string, unknown>>(
@@ -405,8 +488,10 @@ export function serializeCliResult<T, Row extends Record<string, unknown> = Reco
405
488
  options: CliGlobalOptions,
406
489
  renderOptions: CliResultRenderOptions<T, Row> = {},
407
490
  ): string {
408
- const { freshness, exportFreshness, failure, ...rest } = result;
409
- const cited = freshness ?? exportFreshness;
491
+ const { freshness: reported, exportFreshness, failure, ...rest } = result;
492
+ // Rows shown from a saved copy, its refresh having failed, say so in place of live or delayed.
493
+ const freshness = reported && withSavedCopy(reported, result.data);
494
+ const cited = freshness ?? (exportFreshness && withSavedCopy(exportFreshness, result.data));
410
495
  if (options.format === "json") {
411
496
  const columns = serializeColumns(renderOptions.columns);
412
497
  const window = Array.isArray(result.data) ? windowed(result.data as unknown[], options, renderOptions) : null;
@@ -443,14 +528,18 @@ function serializeCliRows<T, Row extends Record<string, unknown>>(
443
528
  }
444
529
  const window = windowed(asRows(result.data, renderOptions.rows), options, renderOptions);
445
530
  const rows = window.rows;
531
+ const status = renderOptions.exportStatus;
446
532
  if (options.format === "ndjson") {
447
- return rows.map((row) => JSON.stringify(cited && isPlainObject(row)
448
- ? { ...row, ...exportIdentityFields(cited, rowIdentity(row as Row, renderOptions.exportIdentity)) }
449
- : row)).join("\n");
533
+ const statusKey = ndjsonStatusKey(rows, renderOptions.columns as readonly CliResultColumn<never>[] | undefined);
534
+ return rows.map((row) => {
535
+ if (!isPlainObject(row)) return JSON.stringify(row);
536
+ const fields = ndjsonRow(row as Row, status, statusKey);
537
+ return JSON.stringify(cited ? { ...fields, ...exportIdentityFields(cited, rowIdentity(row as Row, renderOptions.exportIdentity)) } : fields);
538
+ }).join("\n");
450
539
  }
451
540
  if (options.format === "csv") {
452
- if (!cited) return renderCsv(rows as Row[], renderOptions.columns);
453
- const csv = renderCsv(rows as Row[], renderOptions.columns, (row) => exportIdentityCells(cited, rowIdentity(row, renderOptions.exportIdentity)));
541
+ if (!cited) return renderCsv(rows as Row[], renderOptions.columns, undefined, status);
542
+ const csv = renderCsv(rows as Row[], renderOptions.columns, (row) => exportIdentityCells(cited, rowIdentity(row, renderOptions.exportIdentity)), status);
454
543
  return withCsvFooter(csv, [...exportSourceLines(cited), ...(renderOptions.exportNotes ?? []).map((note) => `note: ${note}`)]);
455
544
  }
456
545
  if (renderOptions.text) {
@@ -27,7 +27,7 @@ function fredSeriesIdOf(expression: string): string | null {
27
27
  return /^FRED:([A-Z0-9]+)$/i.exec(expression)?.[1]?.toUpperCase() ?? null;
28
28
  }
29
29
 
30
- /** The FRED series the plugins' catalog charts, as `gloomberb fred` takes them: DFEDTARU, ECBDFR. */
30
+ /** The FRED series the plugins' catalog charts, as `gloom fred` takes them: DFEDTARU, ECBDFR. */
31
31
  export function catalogFredSeriesIds(plugins: readonly SeriesSource[]): Set<string> {
32
32
  return new Set(plugins.flatMap((plugin) => plugin.series ?? [])
33
33
  .flatMap((definition) => definition.expression ? [fredSeriesIdOf(definition.expression)] : [])
@@ -96,14 +96,14 @@ export function renderSeriesMatches(
96
96
  const shown = matches.slice(0, limit);
97
97
  const count = shown.length < matches.length ? `${shown.length} of ${matches.length}` : String(matches.length);
98
98
  const quoted = `"${query.replace(/"/g, "")}"`;
99
- // A FRED series named by its id is also one `gloomberb fred` prints.
99
+ // A FRED series named by its id is also one `gloom fred` prints.
100
100
  const asked = query.trim().toUpperCase().replace(/^FRED:/, "");
101
101
  const fred = matches.find((match) => match.exact && fredSeriesIdOf(match.expression) === asked);
102
102
  const hint = fred
103
- ? `Print it with gloomberb fred ${asked}; chart it with gloomberb fn G ${fred.expression}.`
103
+ ? `Print it with gloom fred ${asked}; chart it with gloom fn G ${fred.expression}.`
104
104
  : shown.length < matches.length
105
- ? `Chart one with gloomberb fn G <chart>; gloomberb ${rest === "catalog" ? `catalog ${quoted}` : `shot CAT ${quoted}`} lists all ${matches.length}.`
106
- : "Chart one with gloomberb fn G <chart>.";
105
+ ? `Chart one with gloom fn G <chart>; gloom ${rest === "catalog" ? `catalog ${quoted}` : `shot CAT ${quoted}`} lists all ${matches.length}.`
106
+ : "Chart one with gloom fn G <chart>.";
107
107
  return [
108
108
  `${renderSection(`Series for "${query}"`)} ${cliStyles.muted(`(${count})`)}`,
109
109
  renderTable(
@@ -1,6 +1,7 @@
1
1
  import { apiClient } from "../api-client";
2
2
  import type { BankFiguresPayload } from "../api-client/bank-figures";
3
3
  import type { FinancialStatement } from "../types/financials";
4
+ import { fetchOfferingFilings, type OfferingFiling } from "../utils/cash-runway";
4
5
  import { logFailure } from "../utils/log-failure";
5
6
  import { nonUsSecListingVenue } from "../utils/sec";
6
7
 
@@ -42,6 +43,8 @@ export interface StatementReportSources {
42
43
  /** The company's 10-K, 10-Q, 8-K, 20-F and 40-F filings, newest first. */
43
44
  statementFilings(symbol: string): Promise<PeriodicFiling[]>;
44
45
  bankFigures(symbol: string): Promise<BankFiguresPayload>;
46
+ /** The company's latest offering prospectuses (424B5, 424B4), newest first. */
47
+ offeringFilings?(symbol: string): Promise<OfferingFiling[]>;
45
48
  }
46
49
 
47
50
  export const cloudStatementReportSources: StatementReportSources = {
@@ -62,8 +65,24 @@ export const cloudStatementReportSources: StatementReportSources = {
62
65
  });
63
66
  },
64
67
  bankFigures: (symbol) => apiClient.getCloudBankFigures(symbol),
68
+ offeringFilings: (symbol) => fetchOfferingFilings(apiClient, symbol),
65
69
  };
66
70
 
71
+ /**
72
+ * A US listing's latest offering prospectuses, for the note that its cash
73
+ * predates one; nothing (and no request) for any other listing, or when
74
+ * `wanted` is false. A failed read leaves the note out.
75
+ */
76
+ export async function loadOfferingFilings(
77
+ sources: StatementReportSources | undefined,
78
+ listing: { symbol: string; exchange?: string },
79
+ wanted: boolean,
80
+ ): Promise<OfferingFiling[]> {
81
+ if (!wanted || !sources?.offeringFilings || nonUsSecListingVenue(listing.symbol, listing.exchange)) return [];
82
+ return sources.offeringFilings(listing.symbol)
83
+ .catch(logFailure("cli.statement-filings", "Reading the offering filings failed", [] as OfferingFiling[]));
84
+ }
85
+
67
86
  /** The filing a statement row's period was read from: its form when the filing list names it, and its filed date. */
68
87
  export interface StatementFiling {
69
88
  /** 10-Q, 10-K, 20-F or 40-F; null when the filing is not among those listed. */
@@ -0,0 +1,49 @@
1
+ import { saveConfig } from "../data/config/store";
2
+ import { mergeSavedSuffixedListings } from "../portfolio/suffixed-listings";
3
+ import type { CliCommandContext } from "../types/plugin";
4
+ import { debugLog } from "../utils/debug-log";
5
+ import { logFailure } from "../utils/log-failure";
6
+ import { withConfigData, withMarketData } from "./scoped-context";
7
+ import type { ConfigContext, MarketContext } from "./types";
8
+
9
+ const log = debugLog.createLogger("cli.suffixed-listings");
10
+
11
+ /**
12
+ * The profile with the rows a collection holds under a vendor's suffixed key
13
+ * (GARAN.IS) merged into their listing's row (`mergeSuffixedListings`), as
14
+ * the app does at launch, for a command about to change a portfolio or
15
+ * watchlist: what it reads is then what it saves over. A dry run writes
16
+ * nothing and reads the profile as it is. A merge that fails leaves the rows
17
+ * as they were.
18
+ */
19
+ async function mergedForWrite<TContext extends ConfigContext>(ctx: Pick<CliCommandContext, "cliOptions">, context: TContext): Promise<TContext> {
20
+ if (ctx.cliOptions.dryRun) return context;
21
+ try {
22
+ const merged = await mergeSavedSuffixedListings(await context.store.loadAllTickers(), context.config, {
23
+ config: saveConfig,
24
+ tickers: (rows) => context.store.saveTickers(rows),
25
+ });
26
+ // In place: a market context's provider reads the config through this object.
27
+ if (merged) context.config = merged.config;
28
+ for (const kept of merged?.keptCustom ?? []) log.info("custom fields kept on the suffixed row", kept);
29
+ } catch (error) {
30
+ logFailure("cli.suffixed-listings", "Merging suffixed listing rows failed")(error);
31
+ }
32
+ return context;
33
+ }
34
+
35
+ /** `withConfigData` for a command that changes a portfolio or watchlist (`mergedForWrite`). Commands that only read use `withConfigData`. */
36
+ export function withCollectionConfigData<TResult>(
37
+ ctx: Pick<CliCommandContext, "initConfigData" | "cliOptions">,
38
+ operation: (context: ConfigContext) => TResult | Promise<TResult>,
39
+ ): Promise<TResult> {
40
+ return withConfigData(async () => mergedForWrite(ctx, await ctx.initConfigData()), operation);
41
+ }
42
+
43
+ /** `withMarketData` for a command that changes a portfolio or watchlist (`mergedForWrite`). */
44
+ export function withCollectionMarketData<TResult>(
45
+ ctx: Pick<CliCommandContext, "initMarketData" | "cliOptions">,
46
+ operation: (context: MarketContext) => TResult | Promise<TResult>,
47
+ ): Promise<TResult> {
48
+ return withMarketData(async () => mergedForWrite(ctx, await ctx.initMarketData()), operation);
49
+ }