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
@@ -1,6 +1,9 @@
1
1
  import type { MnaDeal, MnaStatus, MnaTerms } from "../../../api-client/mna";
2
2
  import type { Quote } from "../../../types/financials";
3
+ import { getListingSymbol } from "../../../sources/listing-symbols";
4
+ import { parsePublicTickerKey } from "../../../utils/exchanges";
3
5
  import { formatCompact } from "../../../utils/format";
6
+ import { nonUsSecListingVenue } from "../../../utils/sec";
4
7
 
5
8
  export const MNA_PANE_ID = "mna";
6
9
  export const MISSING = "--";
@@ -33,6 +36,28 @@ function ratioLabel(ratio: number, symbol: string | null): string {
33
36
  return symbol ? `${shares} ${symbol}` : `${shares} sh`;
34
37
  }
35
38
 
39
+ /**
40
+ * The symbol a company's deals are filed under, from the ticker a pane is
41
+ * linked to. A deal carries its companies' quote symbols: plain for a US
42
+ * listing, suffixed by the venue elsewhere (ATH.TO, SHEL.L, 9984.T). A
43
+ * listing abroad therefore asks by that quote symbol: its bare symbol is
44
+ * another company's US ticker (ATH is Athene in New York, Athabasca in
45
+ * Toronto). A US listing, a symbol with no venue and a symbol already
46
+ * suffixed go as they are, so a US ticker is asked for exactly as before.
47
+ * `savedExchange` is the venue the saved ticker names, for a key with none.
48
+ */
49
+ export function dealsSymbol(key: string | null | undefined, savedExchange = ""): string {
50
+ const value = key?.trim();
51
+ if (!value) return "";
52
+ if (nonUsSecListingVenue(value, savedExchange)) return getListingSymbol(value, savedExchange).toUpperCase();
53
+ return parsePublicTickerKey(value).symbol;
54
+ }
55
+
56
+ /** Each holder gets the cash or the shares, not both. Older servers never say so. */
57
+ export function isElection(terms: MnaTerms): boolean {
58
+ return terms.election === true && terms.cashPerShare != null && terms.exchangeRatio != null;
59
+ }
60
+
36
61
  /** What one target share gets, in as few characters as the terms allow. */
37
62
  export function termsLabel(terms: MnaTerms): string {
38
63
  const parts: string[] = [];
@@ -48,7 +73,7 @@ export function termsLabel(terms: MnaTerms): string {
48
73
  : terms.consideration === "mixed" ? "Cash and stock"
49
74
  : MISSING);
50
75
  }
51
- let label = parts.join(" + ");
76
+ let label = parts.join(isElection(terms) ? " or " : " + ");
52
77
  if (terms.cvr) label += " + CVR";
53
78
  if (terms.partial) label += ", partial";
54
79
  return label;
@@ -75,7 +100,7 @@ const PENCE = new Set(["GBp", "GBX"]);
75
100
  * London quotes arrive in pounds while UK offers are often in pence, so the
76
101
  * two compare after scaling; any other currency mismatch has no price.
77
102
  */
78
- function inQuoteCurrency(amount: number, from: string | null, quoteCurrency: string | undefined): number | null {
103
+ export function inQuoteCurrency(amount: number, from: string | null, quoteCurrency: string | undefined): number | null {
79
104
  const offer = from ?? "USD";
80
105
  const quote = quoteCurrency ?? "USD";
81
106
  if (offer === quote) return amount;
@@ -85,28 +110,81 @@ function inQuoteCurrency(amount: number, from: string | null, quoteCurrency: str
85
110
  return offer.toUpperCase() === quote.toUpperCase() ? amount : null;
86
111
  }
87
112
 
113
+ function cashLeg(terms: MnaTerms, targetQuote: Quote | null): number | null {
114
+ return terms.cashPerShare == null ? null : inQuoteCurrency(terms.cashPerShare, terms.currency, targetQuote?.currency);
115
+ }
116
+
117
+ function stockLeg(terms: MnaTerms, targetQuote: Quote | null, ratioQuote: Quote | null): number | null {
118
+ const price = ratioQuote?.price;
119
+ if (terms.exchangeRatio == null || !terms.ratioSymbol || price == null || !Number.isFinite(price) || price <= 0) return null;
120
+ const leg = inQuoteCurrency(price, ratioQuote?.currency ?? null, targetQuote?.currency);
121
+ return leg == null ? null : terms.exchangeRatio * leg;
122
+ }
123
+
124
+ /**
125
+ * The leg an election is priced at. It pays each holder the cash or the
126
+ * shares, never both, so it is priced at its cash leg: the legs are set about
127
+ * equal at signing, proration means a holder cannot count on getting the
128
+ * stock, and the cash does not move. The stock leg stands in only when the
129
+ * cash cannot be compared with the target's quote. Without a quote, the cash.
130
+ */
131
+ export function electionLeg(terms: MnaTerms, targetQuote: Quote | null): "cash" | "stock" {
132
+ return !targetQuote || cashLeg(terms, targetQuote) != null ? "cash" : "stock";
133
+ }
134
+
88
135
  /**
89
136
  * What the terms pay per target share at the latest prices, in the target
90
137
  * quote's currency. Null when a leg cannot be priced: no terms, a ratio
91
- * without its listing, or cash in another currency.
138
+ * without its listing, or cash in another currency. An election is one leg,
139
+ * the one {@link electionLeg} picks.
92
140
  */
93
141
  function offerValue(deal: MnaDeal, targetQuote: Quote | null, ratioQuote: Quote | null): number | null {
94
142
  const { terms } = deal;
95
143
  if (terms.cashPerShare == null && terms.exchangeRatio == null) return null;
96
- let total = 0;
97
- if (terms.cashPerShare != null) {
98
- const cash = inQuoteCurrency(terms.cashPerShare, terms.currency, targetQuote?.currency);
99
- if (cash == null) return null;
100
- total += cash;
144
+ let total: number | null;
145
+ if (isElection(terms)) {
146
+ total = electionLeg(terms, targetQuote) === "cash"
147
+ ? cashLeg(terms, targetQuote)
148
+ : stockLeg(terms, targetQuote, ratioQuote);
149
+ } else {
150
+ const cash = terms.cashPerShare == null ? 0 : cashLeg(terms, targetQuote);
151
+ const stock = terms.exchangeRatio == null ? 0 : stockLeg(terms, targetQuote, ratioQuote);
152
+ total = cash == null || stock == null ? null : cash + stock;
101
153
  }
102
- if (terms.exchangeRatio != null) {
103
- const price = ratioQuote?.price;
104
- if (!terms.ratioSymbol || price == null || !Number.isFinite(price) || price <= 0) return null;
105
- const leg = inQuoteCurrency(price, ratioQuote?.currency ?? null, targetQuote?.currency);
106
- if (leg == null) return null;
107
- total += terms.exchangeRatio * leg;
154
+ return total != null && total > 0 ? total : null;
155
+ }
156
+
157
+ /**
158
+ * What the terms were worth each day since the announcement: flat for cash,
159
+ * the ratio times the paying listing's close for stock. An election draws
160
+ * the one leg its Offer is priced at (`leg`, from {@link electionLeg}), its
161
+ * stock leg in the target quote's currency as the Offer converts it.
162
+ */
163
+ export function offerSeries(
164
+ deal: MnaDeal,
165
+ ratioCloses: readonly { date: Date; close: number }[],
166
+ days: readonly string[],
167
+ leg: "cash" | "stock" | null,
168
+ toQuote: (close: number) => number | null = (close) => close,
169
+ ): Array<{ day: string; value: number }> {
170
+ const { cashPerShare, exchangeRatio, currency } = deal.terms;
171
+ if (cashPerShare == null && exchangeRatio == null) return [];
172
+ const pence = currency === "GBp" || currency === "GBX";
173
+ const cash = cashPerShare == null || leg === "stock" ? 0 : pence ? cashPerShare / 100 : cashPerShare;
174
+ const ratioByDay = new Map(ratioCloses.map((point) => [point.date.toISOString().slice(0, 10), point.close]));
175
+ const out: Array<{ day: string; value: number }> = [];
176
+ let lastRatio: number | null = null;
177
+ for (const day of days) {
178
+ if (day < deal.announced) continue;
179
+ if (exchangeRatio == null || leg === "cash") {
180
+ out.push({ day, value: cash });
181
+ continue;
182
+ }
183
+ const close = ratioByDay.get(day);
184
+ lastRatio = close == null ? lastRatio : toQuote(close) ?? lastRatio;
185
+ if (lastRatio != null) out.push({ day, value: cash + exchangeRatio * lastRatio });
108
186
  }
109
- return total > 0 ? total : null;
187
+ return out;
110
188
  }
111
189
 
112
190
  export interface DealSpread {
@@ -26,7 +26,6 @@ import { usePlanAccess } from "../../../api-client/plan-access";
26
26
  import { useAsyncResource, useAutoRefresh, usePaneSettingValue, usePluginPaneState, useShortcut } from "../../../public/react";
27
27
  import { usePaneInstance } from "../../../state/app/context";
28
28
  import { usePaneTickerIdentity } from "../../../state/hooks/pane-ticker";
29
- import { listingIdentity } from "../shared/ticker-request";
30
29
  import { blendHex } from "../../../theme/colors";
31
30
  import { useThemeColors } from "../../../theme/theme-context";
32
31
  import type { PaneProps, TickerResearchTabProps } from "../../../types/plugin";
@@ -42,6 +41,7 @@ import { MnaDealDetail, mnaDealTitle } from "./detail";
42
41
  import { DistressBoard } from "./distress/pane";
43
42
  import {
44
43
  dealSpread,
44
+ dealsSymbol,
45
45
  expectedCloseDate,
46
46
  formatDealValue,
47
47
  formatExpectedClose,
@@ -133,10 +133,11 @@ const MNA_TABS: { label: string; value: MnaTab }[] = [
133
133
 
134
134
  /** `MA`, or `MA ACVA`. A link supplies the ticker; an older pane still has it in settings. */
135
135
  export function MnaPane(props: PaneProps) {
136
- const { symbol: bound } = usePaneTickerIdentity();
136
+ const { symbol: bound, ticker: boundTicker } = usePaneTickerIdentity();
137
137
  const [ticker] = usePaneSettingValue("ticker", "");
138
138
  const fromSettings = typeof ticker === "string" ? ticker.trim().toUpperCase() : "";
139
- const symbol = listingIdentity(bound)?.symbol || fromSettings;
139
+ // Deals are filed under a listing's quote symbol (ATH.TO), not its bare symbol (ATH:TSX is not ATH).
140
+ const symbol = dealsSymbol(bound, boundTicker?.metadata.exchange) || fromSettings;
140
141
  // One company's deals have no market-wide distress tab beside them.
141
142
  if (symbol) return <MnaDealsView key={symbol} focused={props.focused} width={props.width} height={props.height} symbol={symbol} />;
142
143
  return <MnaBoard focused={props.focused} width={props.width} height={props.height} />;
@@ -172,7 +173,7 @@ function MnaBoard({ focused, width, height }: { focused: boolean; width: number;
172
173
 
173
174
  export function MnaTickerTab({ focused, width, height }: TickerResearchTabProps) {
174
175
  const { ticker } = usePaneTickerIdentity();
175
- const symbol = ticker?.metadata.ticker;
176
+ const symbol = dealsSymbol(ticker?.metadata.ticker, ticker?.metadata.exchange);
176
177
  if (!symbol) return <EmptyState title="Select a ticker." />;
177
178
  return <MnaDealsView key={symbol} focused={focused} width={width} height={height} symbol={symbol} />;
178
179
  }
@@ -1,4 +1,3 @@
1
- import type { CloudNewsListResponse } from "../../../api-client";
2
1
  import type {
3
2
  HeadlessPaneContext,
4
3
  HeadlessPaneDefinition,
@@ -7,8 +6,10 @@ import type {
7
6
  } from "../../../types/plugin";
8
7
  import type { NewsArticle, NewsQuery } from "../../../news/types";
9
8
  import {
10
- cloudNewsParams,
9
+ coinNewsFallbackNotice,
11
10
  mapCloudNewsArticle,
11
+ readCloudNews,
12
+ type CloudNewsRead,
12
13
  } from "../../../sources/gloomberb-cloud/news";
13
14
  import { parsePublicTickerKey } from "../../../utils/exchanges";
14
15
  import { formatUtcSeconds } from "../../../utils/utc-time";
@@ -29,14 +30,14 @@ export interface NewsHeadlessDependencies {
29
30
  loadNews(
30
31
  query: NewsQuery,
31
32
  context: HeadlessPaneContext,
32
- ): Promise<CloudNewsListResponse>;
33
+ ): Promise<CloudNewsRead>;
33
34
  now(): Date;
34
35
  /** Whether the session has real-time news; without it the stories are held back. */
35
36
  realtimeAccess?(): Promise<boolean | null>;
36
37
  }
37
38
 
38
39
  const defaultDependencies: NewsHeadlessDependencies = {
39
- loadNews: (query, context) => context.apiClient.getCloudNews(cloudNewsParams(query)),
40
+ loadNews: (query, context) => readCloudNews(context.apiClient, query),
40
41
  now: () => new Date(),
41
42
  realtimeAccess: cloudRealtimeAccess,
42
43
  };
@@ -71,7 +72,7 @@ function selectedSentiment(args: HeadlessPaneLoadArgs): string {
71
72
  }
72
73
 
73
74
  function projectNewsHeadless(
74
- response: CloudNewsListResponse,
75
+ response: CloudNewsRead,
75
76
  args: HeadlessPaneLoadArgs,
76
77
  now: Date,
77
78
  realtime: boolean | null,
@@ -80,7 +81,7 @@ function projectNewsHeadless(
80
81
  const minImportance = Number(args.options.minImportance ?? 0);
81
82
  const limit = Number(args.options.limit ?? 50);
82
83
  const matching = response.items
83
- .map((item) => mapCloudNewsArticle(item, args.symbols[0]))
84
+ .map((item) => mapCloudNewsArticle(item, response.searchedFor ? undefined : args.symbols[0]))
84
85
  .filter((article) => sentiment === "any" || article.sentiment === sentiment)
85
86
  .filter((article) => article.importance >= minImportance)
86
87
  .sort((left, right) => right.publishedAt.getTime() - left.publishedAt.getTime());
@@ -91,6 +92,10 @@ function projectNewsHeadless(
91
92
  items,
92
93
  // Dated by the newest story, held back for an account without real-time news.
93
94
  freshness: cloudNewsFreshness(realtime),
95
+ // A coin pair no story is filed under shows the stories that mention the coin, and says so.
96
+ ...(response.searchedFor && args.symbols[0]
97
+ ? { notes: [coinNewsFallbackNotice(parsePublicTickerKey(args.symbols[0]).symbol, response.searchedFor)] }
98
+ : {}),
94
99
  metadata: {
95
100
  nextCursor: response.nextCursor,
96
101
  sentiment,
@@ -98,6 +103,7 @@ function projectNewsHeadless(
98
103
  total: matching.length,
99
104
  returned: items.length,
100
105
  truncated: items.length < matching.length || response.nextCursor != null,
106
+ ...(response.searchedFor ? { searchedFor: response.searchedFor } : {}),
101
107
  },
102
108
  };
103
109
  }
@@ -5,7 +5,8 @@ import { useArticleSummary, useResolvedEntryValue } from "../../../market-data/h
5
5
  import { instrumentFromTicker } from "../../../market-data/request-types";
6
6
  import { useCallback } from "react";
7
7
  import { useDebouncedPluginPaneState, usePluginPaneState } from "../../runtime";
8
- import { EmptyState, PaneStatusBody, QueryBar } from "../../../components";
8
+ import { EmptyState, PaneStatusBody, QueryBar, usePaneNoticeFooter } from "../../../components";
9
+ import { coinNewsFallbackNotice } from "../../../sources/gloomberb-cloud/news";
9
10
  import { newsMuteSettingsDef, newsMutesApplyToFeed, useNewsMuteFilter } from "./wire/mutes";
10
11
  import { newsListEmptyCopy } from "./wire/filter-articles";
11
12
  import { NEWS_LIST_SEARCH_PLACEHOLDER, useNewsListSearch, useNewsListSearchHint } from "./wire/news/list-search";
@@ -45,6 +46,7 @@ function TickerNewsView({ width, height, focused }: { width: number; height: num
45
46
  exchange: instrument.exchange,
46
47
  tickerTier: "primary" as const,
47
48
  limit: NEWS_ITEM_LIMIT,
49
+ ...(ticker?.metadata.name ? { listingName: ticker.metadata.name } : {}),
48
50
  } : null;
49
51
  const newsState = useNewsArticles(newsQuery);
50
52
  const loaded = usePersistedNewsArticles(
@@ -91,6 +93,13 @@ function TickerNewsView({ width, height, focused }: { width: number; height: num
91
93
  }, [markArticleRead, popOutArticle, readableArticle]);
92
94
 
93
95
  useNewsListSearchHint("ticker-news", focused && !detailOpen, search.focusSearch);
96
+ // A coin pair no story is filed under lists the stories that mention the coin; the footer says so.
97
+ const searchedFor = loaded[0]?.searchedFor;
98
+ usePaneNoticeFooter({
99
+ registrationId: "ticker-news-notices",
100
+ notices: searchedFor && instrument ? [coinNewsFallbackNotice(instrument.symbol, searchedFor)] : [],
101
+ focused,
102
+ });
94
103
  useNewsArticleFooter({
95
104
  registrationId: "news",
96
105
  focused: listFocused,
@@ -92,6 +92,7 @@ const newsWirePanes: PluginModule["panes"] = [
92
92
  {
93
93
  id: NEWS_STORY_PANE_ID,
94
94
  reportFreshness: NEWS_REPORT_FRESHNESS,
95
+ reportArgument: { kind: "free-text", placeholder: "story id", description: "The id of the story to open." },
95
96
  name: "Story",
96
97
  icon: "A",
97
98
  component: NewsStoryPane,
@@ -147,8 +148,8 @@ const newsWirePaneTemplates: PluginModule["paneTemplates"] = [
147
148
  id: "news-industry-pane",
148
149
  paneId: "news-industry",
149
150
  label: TOPIC_NEWS_TITLE,
150
- description: "Market news by topic code (MNA, CB, ENERGY, REG, CRYPTO, EARN, IPO) or sector, and public fund letters (LTR)",
151
- keywords: ["news", "industry", "sector", "topic", "ni", "mna", "central banks", "crypto", "ipo", "earnings", "regulation", "letters", "ltr", "fund letters", "investor letters"],
151
+ description: "Market news by topic code (MNA, CB, ENERGY, METALS, REG, CRYPTO, EARN, IPO) or sector, and public fund letters (LTR)",
152
+ keywords: ["news", "industry", "sector", "topic", "ni", "mna", "central banks", "metals", "precious metals", "crypto", "ipo", "earnings", "regulation", "letters", "ltr", "fund letters", "investor letters"],
152
153
  shortcut: {
153
154
  prefix: "NI",
154
155
  argPlaceholder: "code",
@@ -7,6 +7,7 @@ import type {
7
7
  CommandBarSearchProvider,
8
8
  GloomPluginContext,
9
9
  } from "../../../../../types/plugin";
10
+ import { abortable, settleWithin } from "../../../../../utils/async-deadline";
10
11
  import { formatFeedTime } from "../../../../../utils/datetime-format";
11
12
  import { logFailure } from "../../../../../utils/log-failure";
12
13
  import { openNewsStoryPane } from "./pop-out";
@@ -54,10 +55,19 @@ export function matchLoadedStories(
54
55
  .slice(0, limit);
55
56
  }
56
57
 
58
+ /**
59
+ * How long a lookup waits for the feed to load before it answers with the
60
+ * stories the app already holds. The feed waits on its slowest source, so one
61
+ * feed that is down must not keep the command bar searching.
62
+ */
63
+ const WARM_TIMEOUT_MS = 3_000;
64
+
57
65
  interface StorySearchDeps {
58
66
  getService(): NewsService | null;
59
67
  isSignedIn(): boolean;
60
68
  now(): number;
69
+ /** How long to wait for the feed to load. Default 3000. */
70
+ warmTimeoutMs?: number;
61
71
  }
62
72
 
63
73
  const defaultDeps: StorySearchDeps = {
@@ -66,22 +76,28 @@ const defaultDeps: StorySearchDeps = {
66
76
  now: Date.now,
67
77
  };
68
78
 
69
- let warming: Promise<unknown> | null = null;
79
+ const warming = new WeakMap<NewsService, Promise<unknown>>();
70
80
 
71
81
  /**
72
82
  * Unless News Feed is open, the app may hold few stories or none, so a lookup
73
83
  * first loads the latest feed News Feed reads (the same request, delayed when
74
84
  * the account has no live news). The service keeps it for a while after, so
75
- * later lookups reuse it instead of asking again.
85
+ * later lookups reuse it instead of asking again. The wait ends when the
86
+ * feed has loaded, the lookup is abandoned, or `timeoutMs` passes; a load
87
+ * still running then carries on for the next lookup.
76
88
  */
77
- async function warmLatestStories(service: NewsService): Promise<void> {
89
+ async function warmLatestStories(service: NewsService, signal: AbortSignal, timeoutMs: number): Promise<void> {
78
90
  if (service.getQueryState(NEWS_QUERY_PRESETS.feed).articles.length > 0) return;
79
- warming ??= service.load(NEWS_QUERY_PRESETS.feed)
80
- .catch(logFailure("news.command-bar-search", "Load news for command bar search failed", null))
81
- .finally(() => {
82
- warming = null;
83
- });
84
- await warming;
91
+ let loading = warming.get(service);
92
+ if (!loading) {
93
+ loading = service.load(NEWS_QUERY_PRESETS.feed)
94
+ .catch(logFailure("news.command-bar-search", "Load news for command bar search failed", null))
95
+ .finally(() => {
96
+ warming.delete(service);
97
+ });
98
+ warming.set(service, loading);
99
+ }
100
+ await settleWithin(abortable(loading, signal, "News lookup abandoned"), timeoutMs);
85
101
  }
86
102
 
87
103
  /**
@@ -104,7 +120,7 @@ export function createLoadedStorySearchProvider(
104
120
  if (deps.isSignedIn()) return [];
105
121
  const service = deps.getService();
106
122
  if (!service) return [];
107
- await warmLatestStories(service);
123
+ await warmLatestStories(service, signal, deps.warmTimeoutMs ?? WARM_TIMEOUT_MS);
108
124
  if (signal.aborted) return [];
109
125
  const now = deps.now();
110
126
  return matchLoadedStories(service.listArticles(), query).map((article) => ({
@@ -17,8 +17,9 @@ export type SectorNewsSelection = "all" | typeof SECTOR_NEWS_SECTORS[number];
17
17
 
18
18
  /**
19
19
  * NI codes, Bloomberg style: topics the service tags from a story's text and
20
- * source (`NI MNA`), and the sectors NI always had (`NI TECH`). ENERGY is a
21
- * topic, so it takes energy news from every sector. `LTR` is the one code that
20
+ * source (`NI MNA`), and the sectors NI always had (`NI TECH`). ENERGY and
21
+ * METALS are topics, so they take their market's news from every sector:
22
+ * METALS is metal prices, futures and bullion, not a miner's releases. `LTR` is the one code that
22
23
  * lists no stories: public fund and investor letters, as links.
23
24
  */
24
25
  export interface NewsIndustryCode {
@@ -34,6 +35,7 @@ export const NEWS_INDUSTRY_CODES: readonly NewsIndustryCode[] = [
34
35
  { code: "MNA", label: "M&A", topic: "mna" },
35
36
  { code: "CB", label: "Central banks", topic: "cb" },
36
37
  { code: "ENERGY", label: "Energy", topic: "energy" },
38
+ { code: "METALS", label: "Metals", topic: "metals" },
37
39
  { code: "REG", label: "Regulation", topic: "reg" },
38
40
  { code: "CRYPTO", label: "Crypto", topic: "crypto" },
39
41
  { code: "EARN", label: "Earnings", topic: "earn" },
@@ -58,6 +60,8 @@ const INDUSTRY_CODE_ALIASES: Record<string, string> = {
58
60
  earnings: "EARN",
59
61
  ipos: "IPO",
60
62
  regulation: "REG",
63
+ metal: "METALS",
64
+ precious_metals: "METALS",
61
65
  };
62
66
 
63
67
  function industryKey(value: string): string {
@@ -14,10 +14,10 @@ export const rssCliCommand: CliCommandDef = {
14
14
  },
15
15
  execute: async (args, ctx) => {
16
16
  const action = args[0] ?? "fetch";
17
- if (action !== "fetch") ctx.fail("Usage: gloomberb rss fetch <url> [--name <label>]");
17
+ if (action !== "fetch") ctx.fail("Usage: gloom rss fetch <url> [--name <label>]");
18
18
  const rawArgs = args.slice(1);
19
19
  const name = takeOption(rawArgs, "--name") ?? "RSS";
20
- const url = requireArg(rawArgs[0], "Usage: gloomberb rss fetch <url> [--name <label>]", ctx);
20
+ const url = requireArg(rawArgs[0], "Usage: gloom rss fetch <url> [--name <label>]", ctx);
21
21
  const capability = createRssNewsCapability([{
22
22
  id: "cli-feed",
23
23
  url,
@@ -37,7 +37,7 @@ export const rssCliCommand: CliCommandDef = {
37
37
  })) }, {
38
38
  textColumns: [
39
39
  { key: "publishedAt", header: "Published" },
40
- { key: "source", header: "Source", maxWidth: 20 },
40
+ { key: "source", header: "Source" },
41
41
  { key: "title", header: "Title" },
42
42
  { key: "url", header: "URL", optional: true },
43
43
  { key: "summary", header: "Summary", optional: true },
@@ -1,12 +1,14 @@
1
1
  import { apiClient } from "../../../api-client";
2
- import { withCliServices, withConfigData } from "../../../cli/scoped-context";
2
+ import { withCliServices, withConfigData, withMarketData } from "../../../cli/scoped-context";
3
3
  import type { CliServicesContext } from "../../../cli/types";
4
4
  import { CLI_COMMAND_GROUPS } from "../../../cli/help";
5
5
  import { dryRunNote } from "../../../cli/helpers";
6
6
  import { requireArg, takeOption } from "../../../cli/commands/command-utils";
7
7
  import { EXCHANGE_OPTION, listingReadNotes, requireListingArg } from "../../../cli/listing-arg";
8
+ import { isNotATickerMessage } from "../../../cli/not-a-ticker";
9
+ import { requireQuotedListing } from "../../../cli/quote-answer";
8
10
  import { createPluginPersistence } from "../../plugin-persistence";
9
- import type { CliCommandDef } from "../../../types/plugin";
11
+ import type { BuiltinCliCommandDef } from "../../../cli/command-options";
10
12
  import { cliStyles } from "../../../utils/cli-output";
11
13
  import { errorMessage } from "../../../utils/errors";
12
14
  import { logFailure } from "../../../utils/log-failure";
@@ -15,9 +17,11 @@ import { describeExportSkip, exportNotesToDirectory, type NotesExportSource } fr
15
17
  import { NotesFiles } from "./files";
16
18
  import { CloudNotesStore } from "./store";
17
19
 
18
- export const notesCliCommand: CliCommandDef = {
20
+ export const notesCliCommand: BuiltinCliCommandDef = {
19
21
  name: "notes",
20
22
  description: "Read, write, or export ticker notes",
23
+ // A note's text is saved as typed, and an export's folder is a path; the symbol is read as any other.
24
+ keepsArgAsTyped: ([action], index) => (action === "set" && index >= 2) || (action === "export" && index >= 1),
21
25
  help: {
22
26
  group: CLI_COMMAND_GROUPS.portfolios,
23
27
  usage: ["notes show <symbol>", "notes set <symbol> <text...>", "notes delete <symbol>", "notes quick list", "notes export [dir]"],
@@ -28,13 +32,43 @@ export const notesCliCommand: CliCommandDef = {
28
32
  const args = [...rawArgs];
29
33
  const exchange = takeOption(args, "--exchange");
30
34
  // A note belongs to one listing: SAN:EPA, or SAN with --exchange EPA.
31
- // What a typed listing was read as (7203:TSE as 7203:JPX) is said beside the note.
35
+ // What a typed listing was read as (7203:TSE as 7203:JPX, Apple as AAPL) is said beside the note.
32
36
  let read: { warnings?: string[] } = {};
33
- const noteSymbol = async (usage: string) => {
34
- const listing = await requireListingArg(requireArg(args[1], usage, ctx), exchange, ctx);
35
- const notes = listingReadNotes(listing);
36
- if (notes.length > 0) read = { warnings: notes };
37
- return listing.key;
37
+ const said = (warnings: string[]) => {
38
+ if (warnings.length > 0) read = { warnings };
39
+ };
40
+ /**
41
+ * The file a note of the symbol typed is kept in, the same for show, set
42
+ * and delete. A note already kept under what was typed is the one, so a
43
+ * note written before names were read (APPLE.md) or for a symbol that
44
+ * stopped trading stays reachable. Otherwise the symbol is read as
45
+ * `quote` reads it (`requireQuotedListing`): a company's name is its
46
+ * listing (`Apple` is AAPL, under the bare symbol as the app keeps a
47
+ * ticker it was not given a venue for), and a pair its listing
48
+ * (USDNGN=X). With `refuse`, a definite "Not a ticker" fails the command
49
+ * with `quote`'s search hint, so no note is written for a symbol that
50
+ * does not exist. Any other failure (offline, the data service down, a
51
+ * symbol with no quote) keeps what was typed, as does `lookUp: false`,
52
+ * which opens no data source.
53
+ */
54
+ const noteSymbol = async (usage: string, notes: NotesFiles, options: { refuse?: boolean; lookUp?: boolean } = {}) => {
55
+ const raw = requireArg(args[1], usage, ctx);
56
+ const typed = await requireListingArg(raw, exchange, ctx);
57
+ const asTyped = () => {
58
+ said(listingReadNotes(typed));
59
+ return typed.key;
60
+ };
61
+ if ((await notes.load(typed.key).catch(logFailure("notes.cli", "Read the note kept under a typed symbol failed", ""))).trim()) return asTyped();
62
+ if (options.lookUp === false) return asTyped();
63
+ try {
64
+ const quoted = await withMarketData(ctx, (market) => requireQuotedListing(raw, exchange, market, ctx, `notes ${args[0] ?? "show"}`));
65
+ said(quoted.notes);
66
+ return typed.exchange ? quoted.listing.key : quoted.listing.symbol;
67
+ } catch (error) {
68
+ if (!isNotATickerMessage(errorMessage(error))) logFailure("notes.cli", "Read a note's symbol as quote does failed")(error);
69
+ else if (options.refuse) throw error;
70
+ return asTyped();
71
+ }
38
72
  };
39
73
  await withConfigData(ctx, async (config) => {
40
74
  const notes = new NotesFiles(config.dataDir);
@@ -80,7 +114,7 @@ export const notesCliCommand: CliCommandDef = {
80
114
  });
81
115
  return;
82
116
  }
83
- warnings.push(...result.skipped.map(describeExportSkip));
117
+ warnings.push(...(result.warnings ?? []), ...result.skipped.map(describeExportSkip));
84
118
  ctx.printResult({
85
119
  data: {
86
120
  dir: result.dir,
@@ -96,20 +130,21 @@ export const notesCliCommand: CliCommandDef = {
96
130
  }
97
131
  if (action === "quick") {
98
132
  const subaction = args[1] ?? "list";
99
- if (subaction !== "list") ctx.fail("Usage: gloomberb notes quick list");
133
+ if (subaction !== "list") ctx.fail("Usage: gloom notes quick list");
100
134
  const entries = await notes.loadQuickNotesIndex();
101
135
  ctx.printResult({ data: entries }, { empty: "No quick notes." });
102
136
  return;
103
137
  }
104
138
  if (action === "show") {
105
- const symbol = await noteSymbol("Usage: gloomberb notes show <symbol>");
139
+ const symbol = await noteSymbol("Usage: gloom notes show <symbol>", notes);
106
140
  ctx.printResult({ data: { symbol, text: await notes.load(symbol) }, ...read }, {
107
141
  text: (data) => data.text?.trim() ? data.text.trimEnd() : cliStyles.muted(`No note for ${symbol}.`),
108
142
  });
109
143
  return;
110
144
  }
111
145
  if (action === "set") {
112
- const symbol = await noteSymbol("Usage: gloomberb notes set <symbol> <text...>");
146
+ // A dry run looks nothing up: it says the note it would write under the symbol as typed.
147
+ const symbol = await noteSymbol("Usage: gloom notes set <symbol> <text...>", notes, { refuse: true, lookUp: !ctx.cliOptions.dryRun });
113
148
  const text = args.slice(2).join(" ");
114
149
  if (!ctx.cliOptions.dryRun) await notes.save(symbol, text);
115
150
  ctx.printResult({ data: { changed: !ctx.cliOptions.dryRun, dryRun: ctx.cliOptions.dryRun, symbol, bytes: text.length }, ...read }, {
@@ -118,7 +153,7 @@ export const notesCliCommand: CliCommandDef = {
118
153
  return;
119
154
  }
120
155
  if (action === "delete" || action === "rm") {
121
- const symbol = await noteSymbol("Usage: gloomberb notes delete <symbol>");
156
+ const symbol = await noteSymbol("Usage: gloom notes delete <symbol>", notes);
122
157
  const existed = await notes.load(symbol).then((text) => !!text?.trim(), () => {
123
158
  // Intentional ignore: an unreadable note is still deleted, so the message says it existed.
124
159
  return true;
@@ -131,7 +166,7 @@ export const notesCliCommand: CliCommandDef = {
131
166
  });
132
167
  return;
133
168
  }
134
- ctx.fail("Usage: gloomberb notes show|set|delete|quick|export");
169
+ ctx.fail("Usage: gloom notes show|set|delete|quick|export");
135
170
  });
136
171
  },
137
172
  };
@@ -1,4 +1,5 @@
1
1
  import { errorMessage } from "../../../utils/errors";
2
+ import { logFailure } from "../../../utils/log-failure";
2
3
  import type { NoteFileEntry, QuickNoteEntry } from "./files";
3
4
  import type { NotesStore } from "./store";
4
5
  import { noteOwnerKey, splitNoteKey } from "./store";
@@ -25,6 +26,8 @@ export interface NotesExportResult {
25
26
  /** The sources whose notes were written, in the order given. */
26
27
  exported: string[];
27
28
  skipped: NotesExportSkip[];
29
+ /** Notes were written, but some descriptive metadata could not be read. */
30
+ warnings?: string[];
28
31
  }
29
32
 
30
33
  function safeFileName(value: string): string {
@@ -46,15 +49,21 @@ export async function exportNotesToDirectory(
46
49
  let files = 0;
47
50
  const exported: string[] = [];
48
51
  const skipped: NotesExportResult["skipped"] = [];
52
+ const warnings: string[] = [];
49
53
  for (const source of sources) {
50
54
  const folder = sources.length > 1 ? `${dir}/${safeFileName(source.label)}` : dir;
51
55
  let entries: NoteFileEntry[];
52
56
  let quick: QuickNoteEntry[];
57
+ let titlesWarning: string | null = null;
53
58
  const unreadable: Array<{ key: string; error: unknown }> = [];
54
59
  try {
55
60
  [entries, quick] = await Promise.all([
56
61
  source.store.list({ strict: true, skipped: (key, error) => unreadable.push({ key, error }) }),
57
- source.store.loadQuickNotesIndex(),
62
+ source.store.loadQuickNotesIndex({ strict: true }).catch((error) => {
63
+ logFailure("notes.export", "Read quick note titles for export failed")(error);
64
+ titlesWarning = `Quick notes from ${source.label} were exported using ids because their titles could not be read (${errorMessage(error)}).`;
65
+ return [];
66
+ }),
58
67
  ]);
59
68
  } catch (error) {
60
69
  skipped.push({ label: source.label, reason: errorMessage(error) });
@@ -74,9 +83,10 @@ export async function exportNotesToDirectory(
74
83
  await writeFile(path, entry.text, "utf-8");
75
84
  files += 1;
76
85
  }
86
+ if (titlesWarning && entries.some((entry) => splitNoteKey(entry.key).kind === "quick")) warnings.push(titlesWarning);
77
87
  exported.push(source.label);
78
88
  }
79
- return { dir, files, exported, skipped };
89
+ return { dir, files, exported, skipped, ...(warnings.length > 0 ? { warnings } : {}) };
80
90
  }
81
91
 
82
92
  /** One line per skip, as `notes export` warns and the Export Notes command reports. */
@@ -86,12 +96,13 @@ export function describeExportSkip(skip: NotesExportSkip): string {
86
96
  : `Skipped the ${skip.label} note ${skip.note}: it could not be read (${skip.reason}).`;
87
97
  }
88
98
 
89
- /** The Export Notes command's notice: the count, then what was skipped. */
99
+ /** The Export Notes command's notice: the count, then warnings and what was skipped. */
90
100
  export function exportNotice(result: NotesExportResult): { body: string; type: "success" | "error" } {
91
101
  const exported = `Exported ${result.files} ${result.files === 1 ? "note" : "notes"} to ${result.dir}`;
92
- if (result.skipped.length === 0) return { body: exported, type: "success" };
93
- const shown = result.skipped.slice(0, 3).map(describeExportSkip);
94
- const more = result.skipped.length - shown.length;
102
+ const issues = [...(result.warnings ?? []), ...result.skipped.map(describeExportSkip)];
103
+ if (issues.length === 0) return { body: exported, type: "success" };
104
+ const shown = issues.slice(0, 3);
105
+ const more = issues.length - shown.length;
95
106
  return {
96
107
  body: [`${exported}.`, ...shown, ...(more > 0 ? [`${more} more could not be read.`] : [])].join(" "),
97
108
  type: "error",