gloomberb 0.18.3 → 0.18.5

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 (1018) 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 +32 -1
  6. package/src/account/auth-model.ts +7 -3
  7. package/src/account/checkout-handoff.tsx +225 -0
  8. package/src/account/device-signin-dialog.tsx +2 -2
  9. package/src/account/device-signin.ts +2 -2
  10. package/src/account/upgrade-dialog.tsx +1 -1
  11. package/src/api-client/askg.ts +2 -2
  12. package/src/api-client/auth.ts +11 -6
  13. package/src/api-client/catalysts.ts +2 -1
  14. package/src/api-client/central-bank-rates.ts +6 -0
  15. package/src/api-client/collections.ts +5 -1
  16. package/src/api-client/cot.ts +2 -0
  17. package/src/api-client/crypto-etf-flows.ts +37 -0
  18. package/src/api-client/crypto-markets.ts +60 -0
  19. package/src/api-client/data.ts +98 -5
  20. package/src/api-client/doe.ts +15 -0
  21. package/src/api-client/equity-screener.ts +28 -0
  22. package/src/api-client/exchange-announcements.ts +38 -0
  23. package/src/api-client/fund-facts.ts +39 -0
  24. package/src/api-client/futures-curve.ts +9 -1
  25. package/src/api-client/hiring.ts +301 -0
  26. package/src/api-client/index.ts +182 -16
  27. package/src/api-client/live-scan.ts +91 -0
  28. package/src/api-client/market-discovery.ts +14 -0
  29. package/src/api-client/members.ts +18 -0
  30. package/src/api-client/mna.ts +6 -0
  31. package/src/api-client/paths.ts +18 -1
  32. package/src/api-client/request.ts +224 -26
  33. package/src/api-client/research-activity.ts +3 -10
  34. package/src/api-client/short-side-publications.ts +37 -0
  35. package/src/api-client/socket.ts +64 -4
  36. package/src/api-client/swap-curve.ts +35 -0
  37. package/src/api-client/themes.ts +7 -1
  38. package/src/api-client/types.ts +96 -2
  39. package/src/app/keybindings/index.ts +3 -0
  40. package/src/app/keybindings/labels.ts +18 -1
  41. package/src/app/keybindings/resolve.ts +14 -0
  42. package/src/app/pane-runtime/plugin-bindings.ts +9 -2
  43. package/src/app/runtime/broker-import.ts +43 -26
  44. package/src/app/runtime/desktop-deeplink.ts +5 -5
  45. package/src/app/runtime/plugin-bindings.ts +2 -2
  46. package/src/app/runtime/startup.ts +13 -0
  47. package/src/app/star-prompt/status-line.tsx +2 -2
  48. package/src/architecture/core-builtin-allowlist.json +5 -2
  49. package/src/architecture/ui-literals-allowlist.json +3 -3
  50. package/src/architecture/ui-tokens-allowlist.json +1 -1
  51. package/src/brokers/broker-portfolio-sync.ts +37 -0
  52. package/src/brokers/directory.ts +11 -0
  53. package/src/brokers/logos.ts +3 -1
  54. package/src/brokers/signed-in/adapter.ts +304 -26
  55. package/src/brokers/signed-in/client.ts +14 -2
  56. package/src/brokers/signed-in/connect.ts +10 -2
  57. package/src/brokers/sync-broker-instance.ts +9 -1
  58. package/src/capabilities/chart-series.ts +22 -6
  59. package/src/cli/bank-section.ts +1 -1
  60. package/src/cli/base-converter.ts +23 -14
  61. package/src/cli/central-bank-events.ts +1 -1
  62. package/src/cli/command-options.ts +59 -4
  63. package/src/cli/commands/api.ts +9 -6
  64. package/src/cli/commands/broker.ts +2 -2
  65. package/src/cli/commands/command-utils.ts +2 -2
  66. package/src/cli/commands/crypto-hints.ts +7 -20
  67. package/src/cli/commands/fred-series.ts +9 -2
  68. package/src/cli/commands/keybindings.ts +25 -2
  69. package/src/cli/commands/market.ts +1177 -278
  70. package/src/cli/commands/news-hints.ts +2 -2
  71. package/src/cli/commands/news-search.ts +59 -6
  72. package/src/cli/commands/options-chain.ts +59 -3
  73. package/src/cli/commands/options-leaps.ts +41 -26
  74. package/src/cli/commands/overview.ts +222 -61
  75. package/src/cli/commands/plugins.ts +9 -9
  76. package/src/cli/commands/remote.ts +13 -10
  77. package/src/cli/commands/search.ts +82 -46
  78. package/src/cli/commands/system.ts +27 -19
  79. package/src/cli/commands/themes.ts +1 -1
  80. package/src/cli/commands/ticker.ts +194 -48
  81. package/src/cli/context.ts +3 -2
  82. package/src/cli/desktop-pane-shot-view.ts +2 -2
  83. package/src/cli/desktop-pane-shot.ts +1 -1
  84. package/src/cli/earnings-calendar.ts +4 -4
  85. package/src/cli/entry.ts +18 -1
  86. package/src/cli/errors.ts +21 -3
  87. package/src/cli/exit-codes.ts +1 -1
  88. package/src/cli/export-source.ts +38 -4
  89. package/src/cli/freshness.ts +2 -8
  90. package/src/cli/fx-forward.ts +130 -0
  91. package/src/cli/fx-pair.ts +10 -9
  92. package/src/cli/glossary.ts +113 -20
  93. package/src/cli/help.ts +19 -13
  94. package/src/cli/history-export.ts +126 -0
  95. package/src/cli/history-rows.ts +226 -50
  96. package/src/cli/index-roots.ts +5 -45
  97. package/src/cli/index.ts +24 -18
  98. package/src/cli/known-gaps.ts +123 -27
  99. package/src/cli/listing-arg.ts +316 -46
  100. package/src/cli/name-entries.ts +30 -18
  101. package/src/cli/native-smoke.ts +2 -0
  102. package/src/cli/not-a-ticker.ts +19 -9
  103. package/src/cli/opentui-libc.ts +5 -0
  104. package/src/cli/options.ts +12 -0
  105. package/src/cli/pane-functions/capabilities.ts +75 -20
  106. package/src/cli/pane-functions/catalog.ts +24 -23
  107. package/src/cli/pane-functions/discovery.ts +1 -1
  108. package/src/cli/pane-functions/dom.ts +10 -7
  109. package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
  110. package/src/cli/pane-functions/freshness.ts +193 -30
  111. package/src/cli/pane-functions/function-help.ts +76 -30
  112. package/src/cli/pane-functions/headless.ts +59 -12
  113. package/src/cli/pane-functions/index.ts +28 -19
  114. package/src/cli/pane-functions/market-session.ts +15 -5
  115. package/src/cli/pane-functions/options.ts +22 -2
  116. package/src/cli/pane-functions/report-notices.ts +12 -4
  117. package/src/cli/pane-functions/report.ts +10 -6
  118. package/src/cli/pane-functions/resolver.ts +64 -11
  119. package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
  120. package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
  121. package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
  122. package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
  123. package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
  124. package/src/cli/pane-functions/screenshot-payload.ts +453 -0
  125. package/src/cli/pane-functions/screenshot-render.ts +316 -0
  126. package/src/cli/pane-functions/screenshot-types.ts +162 -0
  127. package/src/cli/pane-functions/shot-options.ts +8 -3
  128. package/src/cli/peso-dollar-rates.ts +79 -0
  129. package/src/cli/quote-answer.ts +45 -4
  130. package/src/cli/report-tables.ts +75 -19
  131. package/src/cli/restore-plugins.ts +42 -15
  132. package/src/cli/result.ts +164 -23
  133. package/src/cli/series-search.ts +5 -5
  134. package/src/cli/statement-filings.ts +19 -0
  135. package/src/cli/suffixed-listing-rows.ts +49 -0
  136. package/src/cli/symbol-args.ts +50 -15
  137. package/src/cli/symbol-cells.ts +120 -0
  138. package/src/cli/symbol-list.ts +198 -68
  139. package/src/cli/symbol-rows.ts +131 -25
  140. package/src/cli/ticker-resolution.ts +108 -11
  141. package/src/cli/treasury-yields.ts +5 -5
  142. package/src/cli/types.ts +2 -0
  143. package/src/cli/uncovered-instrument.ts +3 -3
  144. package/src/cli/unknown-command.ts +6 -6
  145. package/src/components/chart/composite/chart-layout.ts +131 -0
  146. package/src/components/chart/composite/composite-chart.tsx +395 -20
  147. package/src/components/chart/composite/format.ts +27 -0
  148. package/src/components/chart/composite/interactions.ts +7 -2
  149. package/src/components/chart/composite/legend.tsx +75 -3
  150. package/src/components/chart/composite/levels.ts +7 -0
  151. package/src/components/chart/composite/panel-gestures.ts +41 -0
  152. package/src/components/chart/composite/panel-labels.ts +2 -1
  153. package/src/components/chart/composite/panel-series.ts +1 -0
  154. package/src/components/chart/composite/panel-surface.tsx +314 -13
  155. package/src/components/chart/composite/price-axis-labels.tsx +27 -3
  156. package/src/components/chart/composite/range-statistics.ts +62 -0
  157. package/src/components/chart/composite/rasterizer.ts +44 -19
  158. package/src/components/chart/composite/scene.ts +20 -4
  159. package/src/components/chart/composite/series-axis-tags.tsx +16 -9
  160. package/src/components/chart/composite/text-renderer.ts +48 -21
  161. package/src/components/chart/composite/toolbar.tsx +52 -5
  162. package/src/components/chart/composite/types.ts +17 -0
  163. package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
  164. package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
  165. package/src/components/chart/composite/use-composite-viewport.ts +12 -3
  166. package/src/components/chart/composite/value-scale.ts +149 -0
  167. package/src/components/chart/composite/volume-profile-paint.ts +6 -3
  168. package/src/components/chart/core/pointer.ts +2 -0
  169. package/src/components/chart-table/index.ts +2 -0
  170. package/src/components/chart-table/read.tsx +74 -0
  171. package/src/components/command-bar/commands/collection-list.ts +41 -19
  172. package/src/components/command-bar/commands/collection.ts +9 -3
  173. package/src/components/command-bar/commands/direct/index.ts +1 -1
  174. package/src/components/command-bar/commands/direct/runtime.ts +3 -2
  175. package/src/components/command-bar/pane-templates/items.ts +59 -6
  176. package/src/components/command-bar/pane-templates/workflow.ts +10 -1
  177. package/src/components/command-bar/panel/prompt-binding.ts +0 -8
  178. package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
  179. package/src/components/command-bar/routes/root/provider-search.ts +42 -11
  180. package/src/components/command-bar/routes/root/results.ts +18 -4
  181. package/src/components/command-bar/routes/root/runtime.ts +15 -3
  182. package/src/components/command-bar/routes/root/search-providers.ts +25 -2
  183. package/src/components/command-bar/routes/root/selection.ts +6 -1
  184. package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
  185. package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
  186. package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
  187. package/src/components/command-bar/selection-runtime.ts +50 -10
  188. package/src/components/command-bar/surface/index.tsx +24 -2
  189. package/src/components/command-bar/view-model.ts +7 -0
  190. package/src/components/command-bar/workflow/alert.ts +1 -1
  191. package/src/components/command-bar/workflow/broker.ts +2 -2
  192. package/src/components/command-bar/workflow/collection-actions.ts +46 -7
  193. package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
  194. package/src/components/command-bar/workflow/fields.ts +8 -2
  195. package/src/components/command-bar/workflow/ops.ts +18 -4
  196. package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
  197. package/src/components/command-bar/workflow/submit.ts +3 -2
  198. package/src/components/command-bar/workflow/tickers.ts +5 -1
  199. package/src/components/company-logo.tsx +39 -0
  200. package/src/components/data-table/sections.ts +4 -2
  201. package/src/components/form-modal/confirm.tsx +2 -1
  202. package/src/components/form-modal/request.ts +5 -0
  203. package/src/components/form-modal/routes.ts +4 -1
  204. package/src/components/index.ts +12 -6
  205. package/src/components/layout/header.tsx +33 -46
  206. package/src/components/layout/market-summary.ts +9 -6
  207. package/src/components/layout/pane/capture-status.ts +1 -1
  208. package/src/components/layout/pane/footer/index.tsx +1 -0
  209. package/src/components/layout/pane/footer/model.ts +38 -5
  210. package/src/components/layout/shell/chrome.ts +19 -6
  211. package/src/components/layout/shell/index.tsx +2 -1
  212. package/src/components/layout/shell/pane/layers.tsx +19 -1
  213. package/src/components/layout/status-bar.tsx +2 -2
  214. package/src/components/market-board/index.tsx +11 -3
  215. package/src/components/onboarding/onboarding-frame.tsx +1 -1
  216. package/src/components/onboarding/onboarding-wizard.tsx +1 -0
  217. package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
  218. package/src/components/onboarding/portfolio-step/positions-panel.tsx +2 -2
  219. package/src/components/onboarding/wizard-broker-sync.ts +4 -1
  220. package/src/components/pane-settings-dialog/desktop.tsx +20 -7
  221. package/src/components/pane-settings-dialog/tui.tsx +17 -9
  222. package/src/components/pane-settings-dialog/value.ts +8 -1
  223. package/src/components/pane-settings-dialog.tsx +44 -13
  224. package/src/components/sign-in-code-panel.tsx +27 -19
  225. package/src/components/ui/column-grid.tsx +48 -4
  226. package/src/components/ui/country-flag-art.tsx +180 -0
  227. package/src/components/ui/country-flag.tsx +118 -12
  228. package/src/components/ui/data-table/opentui/index.tsx +61 -2
  229. package/src/components/ui/data-table/opentui/model.ts +109 -2
  230. package/src/components/ui/data-table/types.ts +1 -1
  231. package/src/components/ui/display.tsx +10 -2
  232. package/src/components/ui/index.ts +3 -1
  233. package/src/components/ui/logo-mark.tsx +11 -2
  234. package/src/components/ui/query-bar.tsx +1 -1
  235. package/src/components/ui/row-notes.ts +79 -0
  236. package/src/core/state/app/layout.ts +6 -4
  237. package/src/core/state/app/state.ts +9 -0
  238. package/src/core/state/app/types.ts +3 -0
  239. package/src/data/cached-query.ts +8 -1
  240. package/src/data/config/chart-settings.ts +3 -3
  241. package/src/data/config/home.ts +10 -2
  242. package/src/data/config/layout.ts +4 -1
  243. package/src/data/config/store/node.ts +4 -0
  244. package/src/data/config/store/normalize.ts +13 -3
  245. package/src/data/config/store/portfolio-as-of-column.ts +2 -2
  246. package/src/data/json-storage.ts +2 -0
  247. package/src/data/saved-copies.ts +123 -0
  248. package/src/docs/snapshot.json +422 -112
  249. package/src/i18n/es.ts +30 -13
  250. package/src/i18n/ja.ts +30 -13
  251. package/src/i18n/ko.ts +30 -13
  252. package/src/i18n/zh-cn.ts +30 -13
  253. package/src/i18n/zh-tw.ts +30 -13
  254. package/src/layout/desks.ts +1 -1
  255. package/src/layout/launch-layout.ts +1 -1
  256. package/src/layout/pane-manager/floating-actions.ts +5 -3
  257. package/src/layout/pane-manager/floating.ts +43 -1
  258. package/src/layout/pane-manager/index.ts +2 -0
  259. package/src/layout/selected-ticker.ts +74 -0
  260. package/src/market-data/coordinator/financials.ts +10 -2
  261. package/src/market-data/coordinator/index.ts +3 -1
  262. package/src/market-data/coordinator/quotes.ts +4 -2
  263. package/src/market-data/depositary-pair.ts +251 -0
  264. package/src/market-data/futures-board.ts +1 -1
  265. package/src/market-data/futures-contract.ts +124 -40
  266. package/src/market-data/fx-closes.ts +17 -2
  267. package/src/market-data/hooks.tsx +19 -11
  268. package/src/market-data/market/change-basis.ts +81 -11
  269. package/src/market-data/market/dated-previous-close.ts +203 -0
  270. package/src/market-data/market/freshness.ts +34 -5
  271. package/src/market-data/market/futures-week.ts +68 -0
  272. package/src/market-data/market/period-return.ts +163 -0
  273. package/src/market-data/market/status.ts +16 -4
  274. package/src/market-data/market/trading-sessions.ts +13 -0
  275. package/src/market-data/market/year-to-date.ts +8 -13
  276. package/src/market-data/options-alternatives.ts +60 -0
  277. package/src/market-data/performance.ts +20 -14
  278. package/src/market-data/perpetual-premium.ts +32 -0
  279. package/src/market-data/published-apac-sessions.ts +2 -1
  280. package/src/market-data/published-futures-sessions.ts +69 -0
  281. package/src/market-data/quotes/contributions.ts +25 -3
  282. package/src/market-data/quotes/freshness.ts +42 -0
  283. package/src/market-data/quotes/intraday-bar.ts +37 -0
  284. package/src/market-data/quotes/regular-session-valuation.ts +13 -8
  285. package/src/market-data/quotes/resolution.ts +7 -2
  286. package/src/market-data/selectors.ts +3 -0
  287. package/src/market-data/tax-equivalent.ts +1 -1
  288. package/src/market-data/ticker-price-returns.ts +3 -1
  289. package/src/news/aggregator.ts +5 -1
  290. package/src/news/news-model.ts +4 -0
  291. package/src/news/types.ts +11 -0
  292. package/src/notifications/app-notifier.ts +1 -1
  293. package/src/notifications/notification-log.ts +6 -4
  294. package/src/plugins/auto-update.ts +2 -2
  295. package/src/plugins/builtin/account-management/index.tsx +1 -0
  296. package/src/plugins/builtin/account-management/pane.tsx +9 -8
  297. package/src/plugins/builtin/alerts/alert-engine.ts +34 -20
  298. package/src/plugins/builtin/alerts/calendar-events.ts +429 -0
  299. package/src/plugins/builtin/alerts/cli.ts +533 -85
  300. package/src/plugins/builtin/alerts/command.ts +12 -10
  301. package/src/plugins/builtin/alerts/constants.ts +1 -1
  302. package/src/plugins/builtin/alerts/event-rows.ts +9 -5
  303. package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
  304. package/src/plugins/builtin/alerts/events.ts +107 -5
  305. package/src/plugins/builtin/alerts/fired-log.ts +119 -0
  306. package/src/plugins/builtin/alerts/format.ts +10 -3
  307. package/src/plugins/builtin/alerts/headless.ts +107 -41
  308. package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
  309. package/src/plugins/builtin/alerts/history-rows.ts +92 -0
  310. package/src/plugins/builtin/alerts/history.ts +2 -0
  311. package/src/plugins/builtin/alerts/index.tsx +107 -30
  312. package/src/plugins/builtin/alerts/iv-level.ts +365 -0
  313. package/src/plugins/builtin/alerts/levels.ts +3 -3
  314. package/src/plugins/builtin/alerts/live.ts +3 -3
  315. package/src/plugins/builtin/alerts/metric-command.ts +61 -0
  316. package/src/plugins/builtin/alerts/metric-data.ts +70 -0
  317. package/src/plugins/builtin/alerts/metric-model.ts +175 -0
  318. package/src/plugins/builtin/alerts/metric-parity-fixture.json +725 -0
  319. package/src/plugins/builtin/alerts/pane.tsx +130 -49
  320. package/src/plugins/builtin/alerts/price.ts +35 -0
  321. package/src/plugins/builtin/alerts/quotes.ts +24 -0
  322. package/src/plugins/builtin/alerts/research-builder.ts +84 -11
  323. package/src/plugins/builtin/alerts/research-rules.ts +76 -3
  324. package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
  325. package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
  326. package/src/plugins/builtin/alerts/scheduled.ts +188 -29
  327. package/src/plugins/builtin/alerts/storage.ts +38 -12
  328. package/src/plugins/builtin/alerts/targets.ts +12 -3
  329. package/src/plugins/builtin/alerts/types.ts +3 -0
  330. package/src/plugins/builtin/analytics/index.tsx +8 -2
  331. package/src/plugins/builtin/analytics/metrics.ts +1 -1
  332. package/src/plugins/builtin/analytics/risk-book.ts +215 -0
  333. package/src/plugins/builtin/analytics/risk-client.ts +13 -6
  334. package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
  335. package/src/plugins/builtin/analytics/risk-math.ts +6 -3
  336. package/src/plugins/builtin/analytics/risk-model.ts +297 -104
  337. package/src/plugins/builtin/analytics/risk-options.ts +17 -2
  338. package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
  339. package/src/plugins/builtin/attention/pane.tsx +6 -2
  340. package/src/plugins/builtin/awards/headless.ts +7 -3
  341. package/src/plugins/builtin/awards/model.ts +18 -0
  342. package/src/plugins/builtin/awards/pane.tsx +6 -3
  343. package/src/plugins/builtin/backtest/headless.ts +13 -8
  344. package/src/plugins/builtin/backtest/pane.tsx +9 -4
  345. package/src/plugins/builtin/backtest/presets.ts +29 -3
  346. package/src/plugins/builtin/backtest/rules.ts +41 -5
  347. package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
  348. package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
  349. package/src/plugins/builtin/broker-manager/footer.ts +27 -11
  350. package/src/plugins/builtin/broker-manager/index.tsx +24 -14
  351. package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
  352. package/src/plugins/builtin/broker-manager/model.ts +18 -3
  353. package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
  354. package/src/plugins/builtin/broker-manager/table.ts +28 -12
  355. package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
  356. package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
  357. package/src/plugins/builtin/broker-trading/controller.ts +66 -24
  358. package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
  359. package/src/plugins/builtin/broker-trading/headless.ts +2 -1
  360. package/src/plugins/builtin/broker-trading/index.tsx +19 -1
  361. package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
  362. package/src/plugins/builtin/broker-trading/order-feed.ts +83 -10
  363. package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
  364. package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
  365. package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
  366. package/src/plugins/builtin/broker-trading/pane.tsx +111 -24
  367. package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
  368. package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
  369. package/src/plugins/builtin/buildout/cells.tsx +4 -0
  370. package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
  371. package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
  372. package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
  373. package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
  374. package/src/plugins/builtin/builtin-plugin-meta.ts +2 -2
  375. package/src/plugins/builtin/catalysts/detail.tsx +3 -2
  376. package/src/plugins/builtin/catalysts/index.tsx +1 -1
  377. package/src/plugins/builtin/catalysts/model.ts +51 -5
  378. package/src/plugins/builtin/catalysts/pane.tsx +6 -8
  379. package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
  380. package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
  381. package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
  382. package/src/plugins/builtin/changelog/index.tsx +1 -0
  383. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +4 -1
  384. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +3 -2
  385. package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
  386. package/src/plugins/builtin/chart-composer/cli-options.ts +7 -10
  387. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +7 -3
  388. package/src/plugins/builtin/chart-composer/editor/controller.ts +4 -0
  389. package/src/plugins/builtin/chart-composer/editor/model.ts +2 -0
  390. package/src/plugins/builtin/chart-composer/editor.tsx +9 -4
  391. package/src/plugins/builtin/chart-composer/formula.ts +71 -18
  392. package/src/plugins/builtin/chart-composer/headless-schema.ts +42 -29
  393. package/src/plugins/builtin/chart-composer/headless.ts +266 -37
  394. package/src/plugins/builtin/chart-composer/index.tsx +12 -2
  395. package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
  396. package/src/plugins/builtin/chart-composer/pane.tsx +144 -30
  397. package/src/plugins/builtin/chart-composer/presets.ts +50 -15
  398. package/src/plugins/builtin/chart-composer/quick-add.tsx +40 -25
  399. package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
  400. package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
  401. package/src/plugins/builtin/chart-composer/session-history.ts +31 -28
  402. package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
  403. package/src/plugins/builtin/chart-composer/settings.ts +31 -19
  404. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +44 -31
  405. package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
  406. package/src/plugins/builtin/chat/attachments/model.ts +3 -1
  407. package/src/plugins/builtin/chat/content/command-suggestions.ts +92 -0
  408. package/src/plugins/builtin/chat/content/composer.tsx +13 -6
  409. package/src/plugins/builtin/chat/content/footer.tsx +6 -3
  410. package/src/plugins/builtin/chat/content/index.tsx +51 -22
  411. package/src/plugins/builtin/chat/content/open-targets.ts +14 -3
  412. package/src/plugins/builtin/chat/controller/session-runtime.ts +4 -2
  413. package/src/plugins/builtin/chat/index.tsx +23 -0
  414. package/src/plugins/builtin/chat/message/desktop.tsx +1 -0
  415. package/src/plugins/builtin/chat/message/inline-tokens.tsx +23 -0
  416. package/src/plugins/builtin/chat/message/pane-chip.tsx +50 -20
  417. package/src/plugins/builtin/chat/pane-links/commands.ts +265 -0
  418. package/src/plugins/builtin/chat/pane-links/model.ts +12 -3
  419. package/src/plugins/builtin/chat/pane-links/open.ts +9 -2
  420. package/src/plugins/builtin/chat/people.ts +1 -1
  421. package/src/plugins/builtin/chat/unread-inbox-pane.tsx +10 -1
  422. package/src/plugins/builtin/clinical-trials/client.ts +5 -2
  423. package/src/plugins/builtin/clinical-trials/model.ts +13 -4
  424. package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
  425. package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
  426. package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
  427. package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
  428. package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
  429. package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
  430. package/src/plugins/builtin/cloud/plugin.tsx +1 -1
  431. package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
  432. package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
  433. package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
  434. package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
  435. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  436. package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
  437. package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
  438. package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
  439. package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
  440. package/src/plugins/builtin/company-attention/building-model.ts +222 -0
  441. package/src/plugins/builtin/company-attention/building.tsx +172 -0
  442. package/src/plugins/builtin/company-attention/client.ts +117 -1
  443. package/src/plugins/builtin/company-attention/evidence.ts +16 -3
  444. package/src/plugins/builtin/company-attention/headless.ts +101 -5
  445. package/src/plugins/builtin/company-attention/index.tsx +6 -3
  446. package/src/plugins/builtin/company-attention/model.ts +33 -7
  447. package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
  448. package/src/plugins/builtin/company-attention/moves.tsx +159 -0
  449. package/src/plugins/builtin/company-attention/pane.tsx +79 -23
  450. package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
  451. package/src/plugins/builtin/company-attention/signals.tsx +160 -0
  452. package/src/plugins/builtin/company-kpis/headless.ts +3 -2
  453. package/src/plugins/builtin/company-kpis/model.ts +2 -2
  454. package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
  455. package/src/plugins/builtin/composite-plugins.ts +2 -1
  456. package/src/plugins/builtin/congress-trades/headless.ts +1 -1
  457. package/src/plugins/builtin/connections/index.ts +1 -0
  458. package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
  459. package/src/plugins/builtin/correlation/headless.ts +5 -3
  460. package/src/plugins/builtin/cot/headless.ts +28 -6
  461. package/src/plugins/builtin/cot/model.ts +12 -0
  462. package/src/plugins/builtin/cot/pane.tsx +3 -2
  463. package/src/plugins/builtin/cpi/headless.ts +5 -1
  464. package/src/plugins/builtin/cpi/pane.tsx +11 -9
  465. package/src/plugins/builtin/credit-boards/model.ts +2 -0
  466. package/src/plugins/builtin/credit-documents/headless.ts +1 -1
  467. package/src/plugins/builtin/crypto-board/client.ts +86 -0
  468. package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
  469. package/src/plugins/builtin/crypto-board/defi.ts +239 -0
  470. package/src/plugins/builtin/crypto-board/headless.ts +117 -6
  471. package/src/plugins/builtin/crypto-board/index.tsx +8 -3
  472. package/src/plugins/builtin/crypto-board/model.ts +40 -8
  473. package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
  474. package/src/plugins/builtin/crypto-board/series.ts +19 -1
  475. package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
  476. package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
  477. package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
  478. package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
  479. package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
  480. package/src/plugins/builtin/debug/index.tsx +1 -0
  481. package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
  482. package/src/plugins/builtin/docs/index.tsx +1 -1
  483. package/src/plugins/builtin/docs/pane.tsx +2 -2
  484. package/src/plugins/builtin/docs/targets.ts +1 -1
  485. package/src/plugins/builtin/doe/client.ts +5 -1
  486. package/src/plugins/builtin/doe/headless.ts +12 -6
  487. package/src/plugins/builtin/doe/model.ts +43 -6
  488. package/src/plugins/builtin/doe/pane.tsx +18 -11
  489. package/src/plugins/builtin/earnings/board-model.ts +13 -6
  490. package/src/plugins/builtin/earnings/board-table.ts +4 -1
  491. package/src/plugins/builtin/earnings/board.tsx +253 -50
  492. package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
  493. package/src/plugins/builtin/earnings/calendar.tsx +338 -0
  494. package/src/plugins/builtin/earnings/client.ts +4 -3
  495. package/src/plugins/builtin/earnings/headless.ts +53 -15
  496. package/src/plugins/builtin/earnings/history-model.ts +53 -36
  497. package/src/plugins/builtin/earnings/index.tsx +15 -22
  498. package/src/plugins/builtin/earnings/model.ts +17 -12
  499. package/src/plugins/builtin/earnings/scope.ts +89 -0
  500. package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
  501. package/src/plugins/builtin/earnings-calls/data.ts +146 -2
  502. package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
  503. package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
  504. package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
  505. package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
  506. package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
  507. package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
  508. package/src/plugins/builtin/econ/calendar-model.ts +144 -27
  509. package/src/plugins/builtin/econ/detail-view.tsx +48 -10
  510. package/src/plugins/builtin/econ/figures.ts +72 -0
  511. package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
  512. package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
  513. package/src/plugins/builtin/econ/index.tsx +144 -27
  514. package/src/plugins/builtin/econ/print-watch.ts +2 -1
  515. package/src/plugins/builtin/econ/types.ts +34 -1
  516. package/src/plugins/builtin/econ-statistics/client.ts +16 -3
  517. package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
  518. package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
  519. package/src/plugins/builtin/econ-statistics/headless.ts +87 -28
  520. package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
  521. package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
  522. package/src/plugins/builtin/econ-statistics/stats.ts +104 -0
  523. package/src/plugins/builtin/econ-statistics/view.ts +19 -1
  524. package/src/plugins/builtin/equity-screener/client.ts +21 -3
  525. package/src/plugins/builtin/equity-screener/headless.ts +68 -6
  526. package/src/plugins/builtin/equity-screener/live.ts +1 -1
  527. package/src/plugins/builtin/equity-screener/model.ts +6 -0
  528. package/src/plugins/builtin/equity-screener/pane.tsx +47 -12
  529. package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
  530. package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
  531. package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
  532. package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
  533. package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
  534. package/src/plugins/builtin/exposure/charts.tsx +2 -2
  535. package/src/plugins/builtin/exposure/headless.ts +51 -6
  536. package/src/plugins/builtin/exposure/index.tsx +28 -2
  537. package/src/plugins/builtin/exposure/model.ts +20 -1
  538. package/src/plugins/builtin/exposure/pane.tsx +10 -5
  539. package/src/plugins/builtin/fear-greed/index.tsx +1 -1
  540. package/src/plugins/builtin/filing-events/index.tsx +1 -1
  541. package/src/plugins/builtin/futures/index.tsx +1 -0
  542. package/src/plugins/builtin/futures/model.ts +12 -10
  543. package/src/plugins/builtin/futures/returns.ts +8 -36
  544. package/src/plugins/builtin/futures/table.tsx +3 -3
  545. package/src/plugins/builtin/futures-curve/client.ts +40 -9
  546. package/src/plugins/builtin/futures-curve/headless.ts +39 -17
  547. package/src/plugins/builtin/futures-curve/model.ts +258 -69
  548. package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
  549. package/src/plugins/builtin/fx-matrix/client.ts +20 -8
  550. package/src/plugins/builtin/fx-matrix/headless.ts +37 -16
  551. package/src/plugins/builtin/fx-matrix/index.tsx +25 -13
  552. package/src/plugins/builtin/fx-matrix/live-legs.ts +34 -0
  553. package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
  554. package/src/plugins/builtin/gpu/headless.ts +9 -4
  555. package/src/plugins/builtin/help/index.tsx +13 -3
  556. package/src/plugins/builtin/help/keybindings-editor.tsx +18 -14
  557. package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
  558. package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
  559. package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
  560. package/src/plugins/builtin/holders/client.ts +13 -1
  561. package/src/plugins/builtin/holders/format.ts +28 -17
  562. package/src/plugins/builtin/holders/headless.ts +46 -7
  563. package/src/plugins/builtin/holders/index-holders.ts +264 -0
  564. package/src/plugins/builtin/holders/pane.tsx +79 -15
  565. package/src/plugins/builtin/holders/report-rows.ts +35 -7
  566. package/src/plugins/builtin/holders/table-model.ts +2 -1
  567. package/src/plugins/builtin/holders/treemap.tsx +2 -2
  568. package/src/plugins/builtin/insider/headless.ts +1 -1
  569. package/src/plugins/builtin/insider/signals-client.ts +1 -1
  570. package/src/plugins/builtin/insider/signals.tsx +1 -1
  571. package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
  572. package/src/plugins/builtin/iv-history/client.ts +20 -0
  573. package/src/plugins/builtin/iv-history/headless.ts +7 -4
  574. package/src/plugins/builtin/iv-history/index.tsx +1 -1
  575. package/src/plugins/builtin/iv-history/model.ts +13 -4
  576. package/src/plugins/builtin/iv-history/series.ts +3 -1
  577. package/src/plugins/builtin/jobs/lock-note.ts +1 -1
  578. package/src/plugins/builtin/jobs/model.ts +4 -15
  579. package/src/plugins/builtin/jobs/pane.tsx +7 -5
  580. package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
  581. package/src/plugins/builtin/jodi/pane.tsx +10 -4
  582. package/src/plugins/builtin/layout-manager/index.tsx +1 -0
  583. package/src/plugins/builtin/macro-day/headless.ts +20 -7
  584. package/src/plugins/builtin/macro-day/index.tsx +3 -2
  585. package/src/plugins/builtin/macro-day/model.ts +29 -8
  586. package/src/plugins/builtin/macro-day/pane.tsx +51 -13
  587. package/src/plugins/builtin/macro-day/releases.ts +55 -13
  588. package/src/plugins/builtin/market-heatmap/data.ts +9 -2
  589. package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
  590. package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
  591. package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
  592. package/src/plugins/builtin/market-heatmap/model.ts +10 -7
  593. package/src/plugins/builtin/market-movers/client.ts +33 -19
  594. package/src/plugins/builtin/market-movers/footer.ts +2 -2
  595. package/src/plugins/builtin/market-movers/headless.ts +8 -2
  596. package/src/plugins/builtin/market-movers/index.tsx +16 -10
  597. package/src/plugins/builtin/market-movers/screener.ts +29 -8
  598. package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
  599. package/src/plugins/builtin/market-movers/session-table.ts +4 -2
  600. package/src/plugins/builtin/market-movers/table.ts +4 -1
  601. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  602. package/src/plugins/builtin/market-valuation/view.ts +5 -0
  603. package/src/plugins/builtin/members/breadth-pane.tsx +81 -0
  604. package/src/plugins/builtin/members/client.ts +19 -4
  605. package/src/plugins/builtin/members/headless.ts +24 -10
  606. package/src/plugins/builtin/members/index.tsx +9 -9
  607. package/src/plugins/builtin/members/model.ts +23 -4
  608. package/src/plugins/builtin/members/pane.tsx +31 -14
  609. package/src/plugins/builtin/mna/client.ts +1 -0
  610. package/src/plugins/builtin/mna/detail.tsx +20 -32
  611. package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
  612. package/src/plugins/builtin/mna/distress/model.ts +3 -2
  613. package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
  614. package/src/plugins/builtin/mna/headless.ts +6 -13
  615. package/src/plugins/builtin/mna/model.ts +93 -15
  616. package/src/plugins/builtin/mna/pane.tsx +5 -4
  617. package/src/plugins/builtin/news/headless.ts +12 -6
  618. package/src/plugins/builtin/news/index.tsx +10 -1
  619. package/src/plugins/builtin/news/wire/index.tsx +3 -2
  620. package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
  621. package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
  622. package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
  623. package/src/plugins/builtin/notes/cli.ts +49 -14
  624. package/src/plugins/builtin/openfda/pane.tsx +1 -1
  625. package/src/plugins/builtin/options/analytics.ts +26 -2
  626. package/src/plugins/builtin/options/carry.ts +2 -2
  627. package/src/plugins/builtin/options/index.tsx +1 -1
  628. package/src/plugins/builtin/options/model-spot.ts +5 -2
  629. package/src/plugins/builtin/options/strike-window.ts +2 -1
  630. package/src/plugins/builtin/options/table.ts +1 -7
  631. package/src/plugins/builtin/options/view.tsx +30 -13
  632. package/src/plugins/builtin/options-calculator/headless.ts +46 -7
  633. package/src/plugins/builtin/options-positioning/client.ts +19 -0
  634. package/src/plugins/builtin/options-positioning/headless.ts +54 -14
  635. package/src/plugins/builtin/options-positioning/index.tsx +3 -3
  636. package/src/plugins/builtin/options-positioning/model.ts +47 -8
  637. package/src/plugins/builtin/options-positioning/pane.tsx +68 -38
  638. package/src/plugins/builtin/options-scenario/client.ts +123 -28
  639. package/src/plugins/builtin/options-scenario/collar.ts +8 -6
  640. package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
  641. package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
  642. package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
  643. package/src/plugins/builtin/options-scenario/csp.ts +101 -21
  644. package/src/plugins/builtin/options-scenario/headless.ts +36 -15
  645. package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
  646. package/src/plugins/builtin/options-scenario/index.tsx +28 -3
  647. package/src/plugins/builtin/options-scenario/model.ts +13 -0
  648. package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
  649. package/src/plugins/builtin/perps/equity-row.tsx +11 -3
  650. package/src/plugins/builtin/perps/freshness.ts +14 -9
  651. package/src/plugins/builtin/perps/headless.ts +3 -1
  652. package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
  653. package/src/plugins/builtin/perps/live-rows.ts +168 -0
  654. package/src/plugins/builtin/perps/markets-section.tsx +154 -0
  655. package/src/plugins/builtin/perps/pane.tsx +49 -26
  656. package/src/plugins/builtin/perps/venue-markets.ts +96 -0
  657. package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
  658. package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
  659. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
  660. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
  661. package/src/plugins/builtin/portfolio-list/cli/render.ts +54 -22
  662. package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
  663. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
  664. package/src/plugins/builtin/portfolio-list/headless.ts +7 -4
  665. package/src/plugins/builtin/portfolio-list/income.ts +13 -2
  666. package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
  667. package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
  668. package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
  669. package/src/plugins/builtin/portfolio-list/summary/index.tsx +11 -8
  670. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
  671. package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
  672. package/src/plugins/builtin/power/client.ts +4 -1
  673. package/src/plugins/builtin/power/evidence.ts +22 -7
  674. package/src/plugins/builtin/power/gas.tsx +5 -1
  675. package/src/plugins/builtin/power/pane.tsx +8 -1
  676. package/src/plugins/builtin/power/prices.tsx +10 -3
  677. package/src/plugins/builtin/rate-path/pane.tsx +2 -2
  678. package/src/plugins/builtin/research/analyst-headless.ts +25 -8
  679. package/src/plugins/builtin/research/analyst-model.ts +68 -3
  680. package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
  681. package/src/plugins/builtin/research/event-model.ts +3 -1
  682. package/src/plugins/builtin/research/event-sources.ts +12 -4
  683. package/src/plugins/builtin/research/index.tsx +2 -1
  684. package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
  685. package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
  686. package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
  687. package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
  688. package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
  689. package/src/plugins/builtin/research/relative-valuation-pane.tsx +80 -13
  690. package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
  691. package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
  692. package/src/plugins/builtin/risk-factors/index.tsx +2 -2
  693. package/src/plugins/builtin/scanner/feed.ts +2 -2
  694. package/src/plugins/builtin/scanner/index.ts +24 -1
  695. package/src/plugins/builtin/scanner/live-condition-editor.tsx +222 -0
  696. package/src/plugins/builtin/scanner/live-feed.ts +168 -0
  697. package/src/plugins/builtin/scanner/live-headless.ts +114 -0
  698. package/src/plugins/builtin/scanner/live-model.ts +351 -0
  699. package/src/plugins/builtin/scanner/live-pane.tsx +677 -0
  700. package/src/plugins/builtin/scanner/live-track.ts +186 -0
  701. package/src/plugins/builtin/scanner/lock-note.ts +1 -1
  702. package/src/plugins/builtin/sec/forms.ts +13 -0
  703. package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
  704. package/src/plugins/builtin/sec/fund-facts.ts +68 -8
  705. package/src/plugins/builtin/sec/headless.ts +85 -8
  706. package/src/plugins/builtin/sec/index.tsx +58 -12
  707. package/src/plugins/builtin/sectors/client.ts +2 -1
  708. package/src/plugins/builtin/sectors/sector-model.ts +11 -15
  709. package/src/plugins/builtin/series-inventory.ts +3 -0
  710. package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
  711. package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
  712. package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
  713. package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
  714. package/src/plugins/builtin/shared/earnings-report.ts +3 -3
  715. package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
  716. package/src/plugins/builtin/shared/job-posting.ts +129 -0
  717. package/src/plugins/builtin/shared/macro-releases.ts +65 -0
  718. package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
  719. package/src/plugins/builtin/shared/report-freshness.ts +3 -0
  720. package/src/plugins/builtin/shared/research-trading.tsx +21 -0
  721. package/src/plugins/builtin/shared/scanner-capture.ts +3 -0
  722. package/src/plugins/builtin/shared/series-cache.ts +2 -0
  723. package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
  724. package/src/plugins/builtin/shared/use-quote-board.ts +8 -2
  725. package/src/plugins/builtin/shared/volatility/pricing.ts +7 -1
  726. package/src/plugins/builtin/short-interest/client.ts +2 -0
  727. package/src/plugins/builtin/short-interest/headless.ts +41 -12
  728. package/src/plugins/builtin/short-interest/index.tsx +23 -1
  729. package/src/plugins/builtin/short-interest/model.ts +70 -19
  730. package/src/plugins/builtin/short-interest/pane.tsx +19 -2
  731. package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
  732. package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
  733. package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
  734. package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
  735. package/src/plugins/builtin/short-interest/schedule.ts +35 -2
  736. package/src/plugins/builtin/short-interest/surface.tsx +11 -4
  737. package/src/plugins/builtin/short-interest/types.ts +9 -0
  738. package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
  739. package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
  740. package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
  741. package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
  742. package/src/plugins/builtin/supply-chain/model.ts +51 -3
  743. package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
  744. package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
  745. package/src/plugins/builtin/themes/headless.ts +11 -6
  746. package/src/plugins/builtin/themes/model.ts +15 -5
  747. package/src/plugins/builtin/themes/pane.tsx +27 -8
  748. package/src/plugins/builtin/thirteenf/headless.ts +5 -5
  749. package/src/plugins/builtin/thirteenf/signals.ts +3 -1
  750. package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
  751. package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
  752. package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
  753. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
  754. package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
  755. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
  756. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
  757. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
  758. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
  759. package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
  760. package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
  761. package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
  762. package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
  763. package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
  764. package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
  765. package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
  766. package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
  767. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
  768. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
  769. package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
  770. package/src/plugins/builtin/ticker-detail/quote-footer.ts +14 -4
  771. package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
  772. package/src/plugins/builtin/vol-surface/charts.tsx +9 -4
  773. package/src/plugins/builtin/vol-surface/client.ts +7 -4
  774. package/src/plugins/builtin/vol-surface/headless.ts +71 -13
  775. package/src/plugins/builtin/vol-surface/index.tsx +2 -2
  776. package/src/plugins/builtin/vol-surface/model.ts +26 -9
  777. package/src/plugins/builtin/vol-surface/pane.tsx +44 -7
  778. package/src/plugins/builtin/vol-surface/tables.ts +31 -3
  779. package/src/plugins/builtin/volatility/dvol.ts +46 -0
  780. package/src/plugins/builtin/volatility/model.ts +5 -10
  781. package/src/plugins/builtin/volatility/pane.tsx +2 -2
  782. package/src/plugins/builtin/volatility/series.ts +26 -0
  783. package/src/plugins/builtin/world-indices/footer.ts +1 -1
  784. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
  785. package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
  786. package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
  787. package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
  788. package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
  789. package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
  790. package/src/plugins/builtin/world-venue-map/index.ts +3 -26
  791. package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
  792. package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
  793. package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
  794. package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
  795. package/src/plugins/builtin/yield-curve/client.ts +25 -0
  796. package/src/plugins/builtin/yield-curve/curves.ts +7 -4
  797. package/src/plugins/builtin/yield-curve/headless.ts +38 -4
  798. package/src/plugins/builtin/yield-curve/history.ts +4 -3
  799. package/src/plugins/builtin/yield-curve/index.tsx +12 -6
  800. package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
  801. package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
  802. package/src/plugins/bundle.ts +1 -1
  803. package/src/plugins/catalog-browser.ts +15 -9
  804. package/src/plugins/compat.ts +3 -3
  805. package/src/plugins/dependencies.ts +75 -14
  806. package/src/plugins/extracted-plugins.ts +132 -34
  807. package/src/plugins/host-link.ts +149 -34
  808. package/src/plugins/installer.ts +35 -10
  809. package/src/plugins/loader.ts +206 -38
  810. package/src/plugins/manager-node.ts +2 -2
  811. package/src/plugins/marketplace/deactivation.ts +22 -0
  812. package/src/plugins/marketplace/model.ts +2 -2
  813. package/src/plugins/marketplace/packs.ts +1 -1
  814. package/src/plugins/ownership.ts +1 -1
  815. package/src/plugins/peer-retry.ts +155 -0
  816. package/src/plugins/registry/contributions.ts +3 -1
  817. package/src/plugins/registry/index.ts +4 -3
  818. package/src/plugins/registry/plugin-state.ts +3 -0
  819. package/src/plugins/seed-notice.ts +20 -0
  820. package/src/plugins/shortcut-argument.ts +39 -0
  821. package/src/portfolio/allocation.ts +1 -1
  822. package/src/portfolio/collection-name.ts +31 -0
  823. package/src/portfolio/column-values.ts +15 -13
  824. package/src/portfolio/cost-fx.ts +296 -19
  825. package/src/portfolio/manual-lots.ts +75 -0
  826. package/src/portfolio/mutations.ts +60 -22
  827. package/src/portfolio/suffixed-listings.ts +209 -0
  828. package/src/portfolio/totals-currency.ts +24 -0
  829. package/src/public/__snapshots__/public-api.test.ts.snap +15 -0
  830. package/src/public/time-series.ts +11 -8
  831. package/src/remote/schema.ts +1 -1
  832. package/src/renderers/browser/app-services.ts +1 -7
  833. package/src/renderers/browser/config-host.ts +5 -55
  834. package/src/renderers/browser/main.tsx +30 -60
  835. package/src/renderers/dom/boot-frame-page.ts +187 -0
  836. package/src/renderers/dom/boot-frame.ts +237 -0
  837. package/src/renderers/dom/build-assets.ts +46 -8
  838. package/src/renderers/dom/dom-ui-host.tsx +4 -29
  839. package/src/renderers/dom/host/ascii-text.ts +16 -2
  840. package/src/renderers/dom/host/box.tsx +43 -2
  841. package/src/renderers/dom/host/chart-surface.tsx +2 -0
  842. package/src/renderers/dom/host/hls.chunk.ts +3 -0
  843. package/src/renderers/dom/host/image-surface.tsx +49 -0
  844. package/src/renderers/dom/host/media-surface.tsx +24 -18
  845. package/src/renderers/dom/host/mouse.ts +30 -0
  846. package/src/renderers/dom/host/size-observer.ts +1 -1
  847. package/src/renderers/dom/host/style.ts +1 -1
  848. package/src/renderers/dom/styles.css +76 -0
  849. package/src/renderers/dom/test-utils.tsx +2 -1
  850. package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
  851. package/src/renderers/electrobun/bun/desktop/app-name.ts +222 -0
  852. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
  853. package/src/renderers/electrobun/bun/desktop/backend.ts +56 -3
  854. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
  855. package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
  856. package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
  857. package/src/renderers/electrobun/bun/desktop/relaunch.ts +74 -25
  858. package/src/renderers/electrobun/bun/desktop/state-broadcaster.ts +1 -0
  859. package/src/renderers/electrobun/bun/desktop/update.ts +70 -3
  860. package/src/renderers/electrobun/bun/desktop/workspace/index.ts +2 -0
  861. package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
  862. package/src/renderers/electrobun/bun/index.ts +36 -2
  863. package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
  864. package/src/renderers/electrobun/bun/window/create.ts +4 -1
  865. package/src/renderers/electrobun/shared/app-name.ts +17 -0
  866. package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
  867. package/src/renderers/electrobun/shared/protocol.ts +6 -1
  868. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
  869. package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +3 -3
  870. package/src/renderers/electrobun/view/config-host.ts +3 -0
  871. package/src/renderers/electrobun/view/desktop/window/snapshot.ts +1 -0
  872. package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
  873. package/src/renderers/electrobun/view/main.tsx +30 -4
  874. package/src/renderers/electrobun/view/news-source.ts +5 -5
  875. package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
  876. package/src/renderers/electrobun/view/ui-host.tsx +1 -1
  877. package/src/renderers/opentui/browser-open.ts +88 -0
  878. package/src/renderers/opentui/host.tsx +5 -14
  879. package/src/renderers/opentui/image/loader.ts +3 -2
  880. package/src/renderers/opentui/native-smoke.ts +10 -1
  881. package/src/renderers/opentui/pane-image/index.ts +2 -1
  882. package/src/renderers/opentui/render-lib.ts +253 -0
  883. package/src/renderers/opentui/render-timing-smoke.ts +1 -1
  884. package/src/renderers/opentui/start.tsx +1 -1
  885. package/src/renderers/opentui/toast-host.tsx +71 -43
  886. package/src/renderers/share/layout-view.tsx +2 -2
  887. package/src/renderers/share/main.tsx +4 -4
  888. package/src/renderers/share/view.tsx +1 -1
  889. package/src/series/resolve.ts +22 -6
  890. package/src/series/standalone.ts +30 -2
  891. package/src/series/types.ts +8 -1
  892. package/src/shares/api.ts +4 -1
  893. package/src/shares/pane.ts +1 -1
  894. package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
  895. package/src/sources/gloomberb-cloud/index.ts +32 -16
  896. package/src/sources/gloomberb-cloud/news.ts +39 -0
  897. package/src/sources/gloomberb-cloud/normalizers.ts +16 -1
  898. package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
  899. package/src/sources/listing-symbols.ts +37 -0
  900. package/src/sources/provider-errors.ts +16 -2
  901. package/src/sources/provider-router/batches.ts +10 -2
  902. package/src/sources/provider-router/financial-routes.ts +21 -3
  903. package/src/sources/provider-router/financials.ts +15 -2
  904. package/src/sources/provider-router/history.ts +58 -15
  905. package/src/sources/provider-router/index.ts +146 -10
  906. package/src/sources/provider-router/primary.ts +1 -1
  907. package/src/sources/provider-router/search.ts +13 -2
  908. package/src/state/app/bootstrap.ts +23 -0
  909. package/src/state/app/context/index.tsx +3 -0
  910. package/src/state/hooks/inline-tickers.ts +30 -5
  911. package/src/sync/auth-transition.ts +19 -9
  912. package/src/sync/baseline.ts +10 -4
  913. package/src/sync/controller.ts +67 -17
  914. package/src/sync/core-contributors.ts +46 -14
  915. package/src/sync/react.ts +4 -1
  916. package/src/sync/types.ts +3 -0
  917. package/src/team/collections-sync.ts +2 -1
  918. package/src/team/collections.ts +178 -17
  919. package/src/telemetry/crash-reports.ts +17 -4
  920. package/src/telemetry/usage-counts.ts +0 -18
  921. package/src/test-support/builtin-panes.ts +1 -1
  922. package/src/theme/colors.ts +11 -30
  923. package/src/theme/ui-tokens.ts +37 -1
  924. package/src/tickers/company-name-listing.ts +210 -33
  925. package/src/tickers/company-name.ts +59 -0
  926. package/src/tickers/index-roots.ts +47 -0
  927. package/src/tickers/instrument-label.ts +5 -1
  928. package/src/tickers/listing-venues.ts +23 -0
  929. package/src/tickers/metadata.ts +10 -0
  930. package/src/tickers/perpetual-listing.ts +5 -2
  931. package/src/tickers/search/bare-symbol.ts +36 -0
  932. package/src/tickers/search/home-listing.ts +75 -0
  933. package/src/tickers/search/index.ts +111 -33
  934. package/src/tickers/search/ranking.ts +64 -5
  935. package/src/tickers/search/types.ts +5 -0
  936. package/src/tickers/search/upsert.ts +29 -0
  937. package/src/tickers/terminal-codes.ts +416 -40
  938. package/src/time-series/bar-aggregation.ts +243 -0
  939. package/src/time-series/base-series.ts +315 -0
  940. package/src/time-series/chart-bounds.ts +349 -0
  941. package/src/time-series/chart-seed.ts +142 -0
  942. package/src/time-series/daily-valuation.ts +62 -0
  943. package/src/time-series/economic.ts +5 -0
  944. package/src/time-series/field-catalog.ts +1 -3
  945. package/src/time-series/forward-valuation.ts +32 -0
  946. package/src/time-series/fundamentals.ts +173 -10
  947. package/src/time-series/history-acquisition.ts +499 -0
  948. package/src/time-series/hooks.ts +1 -0
  949. package/src/time-series/leverage.ts +100 -0
  950. package/src/time-series/market-resolution.ts +4 -2
  951. package/src/time-series/market.ts +2 -1
  952. package/src/time-series/price-comparison.ts +175 -30
  953. package/src/time-series/price-units.ts +72 -2
  954. package/src/time-series/range.ts +9 -1
  955. package/src/time-series/resolution.ts +174 -16
  956. package/src/time-series/resolve-context.ts +161 -0
  957. package/src/time-series/resolve.ts +185 -1587
  958. package/src/time-series/series-name.ts +38 -0
  959. package/src/time-series/series-presentation.ts +242 -0
  960. package/src/time-series/spec.ts +13 -7
  961. package/src/time-series/studies.ts +377 -82
  962. package/src/time-series/tail-reconcile.ts +121 -0
  963. package/src/time-series/transforms.ts +1 -0
  964. package/src/time-series/types.ts +34 -2
  965. package/src/time-series/use-chart-resolution.ts +4 -5
  966. package/src/time-series/valuation-releases.ts +39 -0
  967. package/src/types/broker.ts +10 -0
  968. package/src/types/config.ts +14 -0
  969. package/src/types/data-provider.ts +23 -1
  970. package/src/types/desktop-window.ts +2 -0
  971. package/src/types/exchange-rate.ts +6 -0
  972. package/src/types/financials.ts +145 -8
  973. package/src/types/headless.ts +117 -9
  974. package/src/types/instrument.ts +6 -0
  975. package/src/types/plugin.ts +66 -9
  976. package/src/types/price-history.ts +2 -0
  977. package/src/types/ticker.ts +13 -0
  978. package/src/types/trading.ts +59 -1
  979. package/src/ui/ascii-font.ts +13 -1
  980. package/src/ui/host.tsx +6 -1
  981. package/src/updater/command-names.ts +180 -0
  982. package/src/updater/index.ts +10 -5
  983. package/src/utils/calendar-date.ts +32 -15
  984. package/src/utils/cash-runway.ts +241 -0
  985. package/src/utils/central-banks.ts +42 -0
  986. package/src/utils/cli-output.ts +259 -80
  987. package/src/utils/contract-month.ts +16 -0
  988. package/src/utils/crypto-pair.ts +61 -3
  989. package/src/utils/currency-units.ts +29 -0
  990. package/src/utils/datetime-format.ts +10 -0
  991. package/src/utils/debug-log.ts +1 -1
  992. package/src/utils/decimal-comma.ts +39 -6
  993. package/src/utils/exchange-announcements.ts +71 -0
  994. package/src/utils/exchange-rate-snapshot.ts +10 -0
  995. package/src/utils/financial-statements.ts +89 -5
  996. package/src/utils/format.ts +34 -16
  997. package/src/utils/fundamentals.ts +150 -34
  998. package/src/utils/fx-market-hours.ts +10 -1
  999. package/src/utils/latest-financial-period.ts +8 -0
  1000. package/src/utils/linux-libc.ts +54 -0
  1001. package/src/utils/market-capitalization.ts +111 -15
  1002. package/src/utils/max-drawdown.ts +64 -0
  1003. package/src/utils/network-failure.ts +86 -0
  1004. package/src/utils/option-expiry.ts +186 -7
  1005. package/src/utils/options.ts +10 -0
  1006. package/src/utils/plugin-proxy-hosts.json +1 -0
  1007. package/src/utils/price-earnings.ts +11 -5
  1008. package/src/utils/price-history.ts +23 -8
  1009. package/src/utils/price-window.ts +131 -0
  1010. package/src/utils/release-date.ts +47 -0
  1011. package/src/utils/sec.ts +3 -0
  1012. package/src/utils/throttled-fetch.ts +11 -4
  1013. package/src/utils/trailing-eps.ts +67 -0
  1014. package/src/utils/typed-text.ts +21 -0
  1015. package/src/utils/utc-time.ts +24 -1
  1016. package/src/version.ts +6 -0
  1017. package/src/cli/pane-functions/screenshot.ts +0 -2122
  1018. package/src/renderers/browser/first-screen.ts +0 -193
@@ -1,11 +1,13 @@
1
- import { useEffect, useMemo, useState, useSyncExternalStore } from "react";
1
+ import { useAsyncResource } from "../../../react/async-resource";
2
+ import { logFailure } from "../../../utils/log-failure";
3
+ import { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from "react";
2
4
  import {
3
5
  buildTickerSearchCandidates,
4
6
  searchTickerCandidates,
5
7
  } from "../../../tickers/search";
6
8
  import { useOptionalAppSelector } from "../../../state/app/context";
7
9
  import type { TickerRecord } from "../../../types/ticker";
8
- import { searchChartSeriesCapabilities } from "../../../capabilities";
10
+ import { searchChartSeriesCatalogs } from "../../../capabilities/chart-series";
9
11
  import { SERIES_CATALOG_CAPABILITY_ID } from "../../../series/capability";
10
12
  import type { SeriesCatalogEntry } from "../../../series/types";
11
13
  import { getSharedRegistry } from "../../registry";
@@ -83,7 +85,7 @@ function candidateToInstrument(candidate: {
83
85
  * folder) are asked for once and listed after the rest; elsewhere, sources
84
86
  * that change while the app runs catch up when the catalog opens.
85
87
  */
86
- export function useRegisteredSeries(): readonly SeriesCatalogEntry[] {
88
+ export function useRegisteredSeries() {
87
89
  const registry = getSharedRegistry();
88
90
  const series = registry?.series;
89
91
  const version = useSyncExternalStore(
@@ -92,31 +94,32 @@ export function useRegisteredSeries(): readonly SeriesCatalogEntry[] {
92
94
  () => 0,
93
95
  );
94
96
  const disabledPlugins = useOptionalAppSelector((state) => state.config.disabledPlugins, EMPTY_PLUGINS);
95
- const [remote, setRemote] = useState<readonly SeriesCatalogEntry[] | null>(null);
97
+ const remoteLoader = useMemo(() => registry?.usesRemoteCapabilities && series ? async () => {
98
+ try {
99
+ const result = await registry.invokeCapability<{ entries: SeriesCatalogEntry[] }>(SERIES_CATALOG_CAPABILITY_ID, "list", {});
100
+ if (!Array.isArray(result?.entries)) throw new Error("Invalid series catalog response");
101
+ return result.entries;
102
+ } catch (error) {
103
+ logFailure("chart-composer.use-series-catalog", "Load remote chart series catalog failed")(error);
104
+ throw new Error("Series catalog unavailable.");
105
+ }
106
+ } : null, [registry, series]);
107
+ const remote = useAsyncResource(remoteLoader);
96
108
 
97
109
  useEffect(() => {
98
- if (!registry || !series) return;
99
- if (!registry.usesRemoteCapabilities) {
100
- void series.refresh();
101
- return;
102
- }
103
- let cancelled = false;
104
- void registry.invokeCapability<{ entries: SeriesCatalogEntry[] }>(SERIES_CATALOG_CAPABILITY_ID, "list", {})
105
- .then((result) => {
106
- if (!cancelled && Array.isArray(result?.entries)) setRemote(result.entries);
107
- })
108
- .catch(() => {
109
- // The view's own series still list; only the Bun process's extras are missing.
110
- });
111
- return () => { cancelled = true; };
110
+ if (registry && series && !registry.usesRemoteCapabilities) void series.refresh();
112
111
  }, [registry, series]);
112
+ const retry = useCallback(async () => {
113
+ if (remoteLoader) await remote.reload();
114
+ else await series?.refresh();
115
+ }, [remoteLoader, remote.reload, series]);
113
116
 
114
- return useMemo(() => {
117
+ const entries = useMemo(() => {
115
118
  const local = series?.catalog() ?? EMPTY_ENTRIES;
116
119
  let entries = local;
117
- if (remote?.length) {
120
+ if (remote.data?.length) {
118
121
  const known = new Set(local.map((entry) => entry.id));
119
- const extra = remote.filter((entry) => !known.has(entry.id));
122
+ const extra = remote.data.filter((entry) => !known.has(entry.id));
120
123
  if (extra.length) entries = [...local, ...extra];
121
124
  }
122
125
  if (disabledPlugins.length === 0) return entries;
@@ -124,7 +127,8 @@ export function useRegisteredSeries(): readonly SeriesCatalogEntry[] {
124
127
  return entries.some((entry) => disabled.has(entry.pluginId))
125
128
  ? entries.filter((entry) => !disabled.has(entry.pluginId))
126
129
  : entries;
127
- }, [disabledPlugins, remote, series, version]);
130
+ }, [disabledPlugins, remote.data, series, version]);
131
+ return { entries, loading: remote.loading, error: remote.error, retry };
128
132
  }
129
133
 
130
134
  export function useCatalogUniverse(query: string): {
@@ -231,6 +235,7 @@ export interface SeriesCatalogSearchResult {
231
235
  loading: boolean;
232
236
  /** Set when a lookup failed, so an outage is never reported as zero matches. */
233
237
  error: string | null;
238
+ retry: () => Promise<void>;
234
239
  }
235
240
 
236
241
  function searchFailureMessage(error: unknown): string {
@@ -249,6 +254,11 @@ export function useSeriesCatalogSuggestions({
249
254
  }): SeriesCatalogSearchResult {
250
255
  const tickers = useOptionalAppSelector((state) => state.tickers, EMPTY_TICKERS);
251
256
  const registered = useRegisteredSeries();
257
+ const [attempt, setAttempt] = useState(0);
258
+ const retry = useCallback(async () => {
259
+ setAttempt((value) => value + 1);
260
+ await registered.retry();
261
+ }, [registered.retry]);
252
262
  const analysis = useMemo(() => analyzeSeriesSearchQuery(query), [query]);
253
263
  const [providerSearch, setProviderSearch] = useState<{
254
264
  query: string;
@@ -274,12 +284,12 @@ export function useSeriesCatalogSuggestions({
274
284
  const controller = new AbortController();
275
285
  setProviderSearch({ query: normalizedQuery, suggestions: [], loading: true, error: null });
276
286
  const timer = setTimeout(() => {
277
- void searchChartSeriesCapabilities(registry, normalizedQuery, MAX_SERIES_SUGGESTIONS, controller.signal).then((items) => {
287
+ void searchChartSeriesCatalogs(registry, normalizedQuery, MAX_SERIES_SUGGESTIONS, controller.signal).then(({ items, errors }) => {
278
288
  if (!cancelled) setProviderSearch({
279
289
  query: normalizedQuery,
280
290
  suggestions: buildCapabilitySeriesSuggestions(items),
281
291
  loading: false,
282
- error: null,
292
+ error: errors.join(" ") || null,
283
293
  });
284
294
  }).catch((error: unknown) => {
285
295
  if (controller.signal.aborted || cancelled) return;
@@ -296,7 +306,7 @@ export function useSeriesCatalogSuggestions({
296
306
  controller.abort();
297
307
  clearTimeout(timer);
298
308
  };
299
- }, [enabled, query]);
309
+ }, [attempt, enabled, query]);
300
310
 
301
311
  useEffect(() => {
302
312
  const instrumentQuery = analysis.instrumentQuery.trim();
@@ -345,7 +355,7 @@ export function useSeriesCatalogSuggestions({
345
355
  cancelled = true;
346
356
  clearTimeout(timer);
347
357
  };
348
- }, [analysis.directInstrument, analysis.instrumentQuery, enabled, tickers]);
358
+ }, [analysis.directInstrument, analysis.instrumentQuery, attempt, enabled, tickers]);
349
359
 
350
360
  const instruments = search.query === analysis.instrumentQuery
351
361
  ? search.instruments
@@ -354,18 +364,21 @@ export function useSeriesCatalogSuggestions({
354
364
  // and they arrive well before plugin catalogs (which can take seconds), so
355
365
  // late plugin results append below instead of pushing the list around.
356
366
  const suggestions = useMemo(() => {
357
- const builtIn = buildSeriesCatalogSuggestions(query, defaultInstrument, instruments, MAX_SERIES_SUGGESTIONS, registered);
367
+ const builtIn = buildSeriesCatalogSuggestions(query, defaultInstrument, instruments, MAX_SERIES_SUGGESTIONS, registered.entries);
358
368
  const provider = providerSearch.query === query.trim() ? providerSearch.suggestions : [];
359
369
  return [...builtIn, ...provider.filter((entry) => !builtIn.some((candidate) => candidate.id === entry.id))]
360
370
  .slice(0, MAX_SERIES_SUGGESTIONS);
361
- }, [defaultInstrument, instruments, providerSearch, query, registered]);
371
+ }, [defaultInstrument, instruments, providerSearch, query, registered.entries]);
362
372
 
363
373
  return {
364
374
  suggestions,
365
375
  instruments,
366
- loading: (search.loading && search.query === analysis.instrumentQuery)
376
+ retry,
377
+ loading: registered.loading || (search.loading && search.query === analysis.instrumentQuery)
367
378
  || (providerSearch.loading && providerSearch.query === query.trim()),
368
- error: (search.query === analysis.instrumentQuery ? search.error : null)
369
- ?? (providerSearch.query === query.trim() ? providerSearch.error : null),
379
+ error: [registered.error,
380
+ search.query === analysis.instrumentQuery ? search.error : null,
381
+ providerSearch.query === query.trim() ? providerSearch.error : null,
382
+ ].filter(Boolean).join(" ") || null,
370
383
  };
371
384
  }
@@ -1,6 +1,7 @@
1
1
  import type { ChartResolution } from "../../../components/chart/core/types";
2
+ import { chartBarSizeParts, isManualChartResolution, type ManualChartResolution } from "../../../time-series/resolution";
2
3
 
3
- const RESOLUTION_LABELS: Record<ChartResolution, string> = {
4
+ const RESOLUTION_LABELS: Record<ManualChartResolution | "auto", string> = {
4
5
  auto: "Auto",
5
6
  "1m": "1m",
6
7
  "5m": "5m",
@@ -13,7 +14,7 @@ const RESOLUTION_LABELS: Record<ChartResolution, string> = {
13
14
  "1mo": "M",
14
15
  };
15
16
 
16
- const RESOLUTION_NAMES: Record<Exclude<ChartResolution, "auto">, string> = {
17
+ const RESOLUTION_NAMES: Record<ManualChartResolution, string> = {
17
18
  "1m": "1-minute",
18
19
  "5m": "5-minute",
19
20
  "15m": "15-minute",
@@ -25,19 +26,27 @@ const RESOLUTION_NAMES: Record<Exclude<ChartResolution, "auto">, string> = {
25
26
  "1mo": "monthly",
26
27
  };
27
28
 
29
+ // Months take MO beyond one (3MO), as 3M and 6M are ranges in the same bar.
30
+ const BUILT_UNIT_LABELS = { m: "m", h: "h", d: "D", wk: "W", mo: "MO" } as const;
31
+ const BUILT_UNIT_NAMES = { m: "minute", h: "hour", d: "day", wk: "week", mo: "month" } as const;
32
+
28
33
  /**
29
34
  * The one way chart intervals are labelled. Intraday reads in lowercase units
30
- * (1m, 1h) and daily and longer as D W M, so an interval never collides with
31
- * a range such as 1M (one month) in the same bar.
35
+ * (1m, 1h, 4h) and daily and longer as D W M, with a count when there are
36
+ * several (2D, 2W), so an interval never collides with a range such as 1M
37
+ * (one month) in the same bar.
32
38
  */
33
39
  export function formatChartResolution(resolution: ChartResolution): string {
34
- return RESOLUTION_LABELS[resolution] ?? resolution;
40
+ if (resolution === "auto" || isManualChartResolution(resolution)) return RESOLUTION_LABELS[resolution];
41
+ const parts = chartBarSizeParts(resolution);
42
+ return parts ? `${parts.count}${BUILT_UNIT_LABELS[parts.unit]}` : resolution;
35
43
  }
36
44
 
37
45
  export function describeChartResolution(resolution: ChartResolution): string {
38
- return resolution === "auto"
39
- ? "Choose an interval automatically for the active range."
40
- : `Use ${RESOLUTION_NAMES[resolution] ?? resolution} observations.`;
46
+ if (resolution === "auto") return "Choose an interval automatically for the active range.";
47
+ if (isManualChartResolution(resolution)) return `Use ${RESOLUTION_NAMES[resolution]} observations.`;
48
+ const parts = chartBarSizeParts(resolution);
49
+ return parts ? `Use ${parts.count}-${BUILT_UNIT_NAMES[parts.unit]} observations.` : `Use ${resolution} observations.`;
41
50
  }
42
51
 
43
52
  function calendarParts(date: Date, timeZone: string): { key: string; year: number; label: string } {
@@ -72,6 +81,7 @@ export function formatChartDateWindow(
72
81
  try {
73
82
  new Intl.DateTimeFormat("en-US", { timeZone: zone });
74
83
  } catch {
84
+ // Intentional ignore: unsupported exchange time zones use UTC so the date label remains readable.
75
85
  zone = "UTC";
76
86
  }
77
87
  const first = calendarParts(start, zone);
@@ -1,6 +1,7 @@
1
1
  import { ApiRequestError } from "../../../../api-client/errors";
2
2
  import type { ChatAttachment, ChatMessage } from "../../../../api-client";
3
3
  import { chatPlainText } from "../markdown";
4
+ import { isNetworkFailure } from "../../../../utils/network-failure";
4
5
 
5
6
  /** What the server takes: four images a message, each up to 5 MB, as PNG, JPEG, WebP or GIF. */
6
7
  export const MAX_CHAT_IMAGES = 4;
@@ -152,7 +153,8 @@ export function describeChatImageError(error: unknown, fallback = "The image cou
152
153
  if (error.status === 429) return UPLOAD_ERROR_SENTENCES.upload_rate_limited!;
153
154
  return fallback;
154
155
  }
155
- if (error instanceof TypeError) return `${fallback.replace(/\.$/, "")}. Check your connection and try again.`;
156
+ // No answer at all: a browser's TypeError, or the Cloud client's own word for it.
157
+ if (error instanceof TypeError || isNetworkFailure(error)) return `${fallback.replace(/\.$/, "")}. Check your connection and try again.`;
156
158
  if (error instanceof Error && error.message.trim()) return error.message.trim();
157
159
  return fallback;
158
160
  }
@@ -0,0 +1,92 @@
1
+ import type { ChatFunction } from "../pane-links/commands";
2
+
3
+ /** A function offered after a backtick: its code and what it is called. */
4
+ export interface ChatCommandSuggestion {
5
+ code: string;
6
+ name: string;
7
+ takesArg: boolean;
8
+ }
9
+
10
+ interface ChatCommandTrigger {
11
+ /** Where the opening backtick is. */
12
+ start: number;
13
+ end: number;
14
+ query: string;
15
+ }
16
+
17
+ // An opening backtick after a space or punctuation (not inside a word, not a
18
+ // second tick of a fence), then the start of a code.
19
+ const COMMAND_TRIGGER_RE = /(^|[\s([{<,.;:!?"'])`([A-Za-z][A-Za-z0-9+-]{0,11})$/;
20
+ const FENCE_RE = /^\s{0,3}```/;
21
+ const MAX_COMMAND_SUGGESTIONS = 5;
22
+
23
+ /**
24
+ * The code being typed after an opening backtick, up to the cursor. A
25
+ * backtick that closes a span already open on the line, or one inside a
26
+ * fenced code block, starts no code.
27
+ */
28
+ export function detectChatCommandTrigger(draft: string, cursorOffset: number): ChatCommandTrigger | null {
29
+ const cursor = Math.max(0, Math.min(cursorOffset, draft.length));
30
+ const beforeCursor = draft.slice(0, cursor);
31
+ const match = beforeCursor.match(COMMAND_TRIGGER_RE);
32
+ if (!match) return null;
33
+ const query = match[2]!;
34
+ const start = cursor - query.length - 1;
35
+ const lines = draft.slice(0, start).split("\n");
36
+ const line = lines[lines.length - 1]!;
37
+ if ((line.match(/`/g)?.length ?? 0) % 2 === 1) return null;
38
+ if (lines.slice(0, -1).filter((previous) => FENCE_RE.test(previous)).length % 2 === 1) return null;
39
+ return { start, end: cursor, query };
40
+ }
41
+
42
+ /**
43
+ * The functions whose code starts with the query, the exact one and the
44
+ * shortest first, then those with a word of their name that does, as people
45
+ * are found by their handle or their name.
46
+ */
47
+ export function filterCommandSuggestions(
48
+ functions: ReadonlyMap<string, ChatFunction>,
49
+ query: string,
50
+ limit = MAX_COMMAND_SUGGESTIONS,
51
+ ): ChatCommandSuggestion[] {
52
+ const upper = query.trim().toUpperCase();
53
+ if (!upper) return [];
54
+ const lower = upper.toLowerCase();
55
+ const byCode: ChatFunction[] = [];
56
+ const byName: ChatFunction[] = [];
57
+ for (const fn of new Set(functions.values())) {
58
+ if (fn.code.startsWith(upper) || fn.aliases.includes(upper)) byCode.push(fn);
59
+ else if (fn.name.toLowerCase().split(/[\s/&()-]+/).some((word) => word.startsWith(lower))) byName.push(fn);
60
+ }
61
+ const rank = (fn: ChatFunction) => (fn.code === upper || fn.aliases.includes(upper) ? 0 : 1);
62
+ byCode.sort((a, b) => rank(a) - rank(b) || a.code.length - b.code.length || a.code.localeCompare(b.code));
63
+ byName.sort((a, b) => a.code.localeCompare(b.code));
64
+ return [...byCode, ...byName].slice(0, Math.min(limit, MAX_COMMAND_SUGGESTIONS))
65
+ .map(({ code, name, arg }) => ({ code, name, takesArg: arg !== "none" }));
66
+ }
67
+
68
+ /**
69
+ * The code in place of what was typed, with the closing backtick. A function
70
+ * that takes an argument leaves the cursor before it, after a space, for the
71
+ * ticker or topic; any other leaves it after the span and a space.
72
+ */
73
+ export function applyCommandSuggestion(
74
+ draft: string,
75
+ trigger: ChatCommandTrigger,
76
+ suggestion: ChatCommandSuggestion,
77
+ ): { draft: string; cursorOffset: number } {
78
+ const before = draft.slice(0, trigger.start);
79
+ let after = draft.slice(trigger.end);
80
+ // A closing backtick already there is the one this span ends with.
81
+ if (after.startsWith("`")) after = after.slice(1);
82
+ const code = `\`${suggestion.code}`;
83
+ if (suggestion.takesArg) {
84
+ return { draft: `${before}${code} \`${after}`, cursorOffset: before.length + code.length + 1 };
85
+ }
86
+ // A space to go on writing after, unless the text there already goes on.
87
+ const suffix = /^[\s.,;:!?)\]]/.test(after) ? "" : " ";
88
+ return {
89
+ draft: `${before}${code}\`${suffix}${after}`,
90
+ cursorOffset: before.length + code.length + 1 + suffix.length,
91
+ };
92
+ }
@@ -10,7 +10,6 @@ import { Button, ListView } from "../../../../components/ui";
10
10
  import { COMPOSER_ACTION_WIDTH } from "../layout";
11
11
  import { isManagedBot } from "../ghost-user";
12
12
  import { ChatBotIcon } from "../message/person-icons";
13
- import type { ChatMentionSuggestion } from "./mentions";
14
13
  import type { ChatDraftAttachment } from "../controller/attachments";
15
14
  import { DesktopChatAttachButton, DesktopChatAttachmentStrip } from "../attachments/desktop";
16
15
  import { TerminalChatAttachmentRows } from "../attachments/terminal";
@@ -48,7 +47,8 @@ interface ChatComposerAreaProps {
48
47
  replyPreview: string;
49
48
  replyTo: ChatMessage | null;
50
49
  sendMessage: () => void;
51
- mentionSuggestions: ChatMentionSuggestion[];
50
+ /** People after @, or functions after a backtick: one list at a time. */
51
+ suggestions: ChatComposerSuggestion[];
52
52
  mentionSelectedIndex: number;
53
53
  onMentionCursorChange: () => void;
54
54
  onMentionSelect: (index?: number) => boolean;
@@ -69,6 +69,13 @@ interface ChatComposerAreaProps {
69
69
  attachPickerRef: { current: (() => void) | null };
70
70
  }
71
71
 
72
+ /** A row of the list over the composer: a handle, or a function's code with its name at the end. */
73
+ interface ChatComposerSuggestion {
74
+ id: string;
75
+ label: string;
76
+ detail?: string;
77
+ }
78
+
72
79
  function ChatMentionSuggestions({
73
80
  contentWidth,
74
81
  onSelect,
@@ -78,14 +85,14 @@ function ChatMentionSuggestions({
78
85
  contentWidth: number;
79
86
  onSelect: (index?: number) => boolean;
80
87
  selectedIndex: number;
81
- suggestions: ChatMentionSuggestion[];
88
+ suggestions: ChatComposerSuggestion[];
82
89
  }) {
83
90
  if (suggestions.length === 0) return null;
84
91
  const width = Math.max(18, Math.min(contentWidth, 44));
85
92
  return (
86
93
  <Box width={width}>
87
94
  <ListView
88
- items={suggestions.map((suggestion) => ({ id: suggestion.username, label: `@${suggestion.username}` }))}
95
+ items={suggestions}
89
96
  selectedIndex={selectedIndex}
90
97
  height={suggestions.length}
91
98
  rowGap={0}
@@ -119,7 +126,7 @@ export function ChatComposerArea({
119
126
  replyPreview,
120
127
  replyTo,
121
128
  sendMessage,
122
- mentionSuggestions,
129
+ suggestions,
123
130
  mentionSelectedIndex,
124
131
  onMentionCursorChange,
125
132
  onMentionSelect,
@@ -211,7 +218,7 @@ export function ChatComposerArea({
211
218
  contentWidth={contentWidth}
212
219
  onSelect={onMentionSelect}
213
220
  selectedIndex={mentionSelectedIndex}
214
- suggestions={mentionSuggestions}
221
+ suggestions={suggestions}
215
222
  />
216
223
 
217
224
  {!editingMessage && draftAttachments.length > 0 && (nativePaneChrome ? (
@@ -9,6 +9,7 @@ import { useOptionalDialog, type PromptContext } from "../../../../ui/dialog";
9
9
  import { chatAuthorName, isDiscordGhost } from "../ghost-user";
10
10
  import { chatMessageOpenTargets, type ChatOpenTarget } from "./open-targets";
11
11
  import { chatMessagePaneLinks, type ChatMessagePaneLink } from "../pane-links/model";
12
+ import { useChatFunctions } from "../pane-links/commands";
12
13
  import { openChatImageViewer } from "../attachments/desktop";
13
14
  import { canReactToMessage } from "../reactions";
14
15
 
@@ -102,11 +103,13 @@ export function useChatFooter({
102
103
  const rendererHost = useRendererHost();
103
104
  const { links: paneLinks, content } = chatMessagePaneLinks(selectedMessage);
104
105
  const attachments = selectedMessage?.attachments;
106
+ const { nativePaneChrome } = useUiCapabilities();
107
+ const functions = useChatFunctions();
108
+ // The desktop and the web draw functions written in a message as chips, so Open offers them too.
105
109
  const openTargets = useMemo(
106
- () => chatMessageOpenTargets(content, catalog, attachments, paneLinks),
107
- [attachments, catalog, content, paneLinks],
110
+ () => chatMessageOpenTargets(content, catalog, attachments, paneLinks, nativePaneChrome ? functions : undefined),
111
+ [attachments, catalog, content, functions, nativePaneChrome, paneLinks],
108
112
  );
109
- const { nativePaneChrome } = useUiCapabilities();
110
113
 
111
114
  const openTarget = useCallback((target: ChatOpenTarget) => {
112
115
  if (target.kind === "pane") {
@@ -57,6 +57,7 @@ import type { ContextMenuItem } from "../../../../types/context-menu";
57
57
  import { usePluginAppActions } from "../../../runtime";
58
58
  import { openTeamPane } from "../../../../team/pane-request";
59
59
  import { openChatPaneLink } from "../pane-links/open";
60
+ import { runChatCommand, useChatFunctions } from "../pane-links/commands";
60
61
  import type { ChatMessagePaneLink } from "../pane-links/model";
61
62
  import { splitComposerDraft, type ComposerShareLink } from "../pane-links/composer";
62
63
  import { teamStore } from "../../../../team/store";
@@ -71,6 +72,7 @@ import {
71
72
  detectChatMentionTrigger,
72
73
  filterMentionSuggestions,
73
74
  } from "./mentions";
75
+ import { applyCommandSuggestion, detectChatCommandTrigger, filterCommandSuggestions } from "./command-suggestions";
74
76
  import { getComposerCursorOffset } from "./composer-cursor";
75
77
  import { ChatHandlePrompt, chatHandlePromptRows, handleSavedMessage, useChatHandlePrompt } from "./handle-prompt";
76
78
 
@@ -321,12 +323,31 @@ export function ChatContent({
321
323
  if (!mentionTrigger || mentionTriggerKey === dismissedMentionKey) return [];
322
324
  return filterMentionSuggestions(recentMentionSuggestions, mentionTrigger.query);
323
325
  }, [dismissedMentionKey, mentionTrigger, mentionTriggerKey, recentMentionSuggestions]);
324
- const mentionSelectedIndexSafe = mentionSuggestions.length > 0
325
- ? Math.min(mentionSelectedIndex, mentionSuggestions.length - 1)
326
+ // Desktop and web: after a backtick the same list offers functions, which a message draws as chips there.
327
+ const commandTrigger = useMemo(() => (
328
+ nativePaneChrome && !mentionTrigger ? detectChatCommandTrigger(composerDraft, composerCursorOffset) : null
329
+ ), [composerCursorOffset, composerDraft, mentionTrigger, nativePaneChrome]);
330
+ const commandTriggerKey = commandTrigger
331
+ ? `${channelId}:code:${commandTrigger.start}:${commandTrigger.end}:${commandTrigger.query}`
332
+ : null;
333
+ const functions = useChatFunctions();
334
+ const commandSuggestions = useMemo(() => {
335
+ if (!commandTrigger || commandTriggerKey === dismissedMentionKey) return [];
336
+ return filterCommandSuggestions(functions, commandTrigger.query);
337
+ }, [commandTrigger, commandTriggerKey, dismissedMentionKey, functions]);
338
+ // One list at a time: people after @, functions after a backtick.
339
+ const suggestionTriggerKey = mentionTriggerKey ?? commandTriggerKey;
340
+ const suggestionCount = mentionSuggestions.length + commandSuggestions.length;
341
+ const composerSuggestions = useMemo(() => mentionSuggestions.length > 0
342
+ ? mentionSuggestions.map((suggestion) => ({ id: suggestion.username, label: `@${suggestion.username}` }))
343
+ : commandSuggestions.map((suggestion) => ({ id: suggestion.code, label: suggestion.code, detail: suggestion.name })),
344
+ [commandSuggestions, mentionSuggestions]);
345
+ const mentionSelectedIndexSafe = suggestionCount > 0
346
+ ? Math.min(mentionSelectedIndex, suggestionCount - 1)
326
347
  : 0;
327
348
  useEffect(() => {
328
349
  setMentionSelectedIndex(0);
329
- }, [mentionTriggerKey]);
350
+ }, [suggestionTriggerKey]);
330
351
  const {
331
352
  composerHeight,
332
353
  messageAreaHeight,
@@ -335,7 +356,7 @@ export function ChatContent({
335
356
  composerRows,
336
357
  editingMessage,
337
358
  height,
338
- mentionSuggestionCount: mentionSuggestions.length,
359
+ mentionSuggestionCount: suggestionCount,
339
360
  nativePaneChrome,
340
361
  replyTo,
341
362
  stackHeader: stackedNav && !channelListOpen,
@@ -568,17 +589,18 @@ export function ChatContent({
568
589
  if (controller.attachToChannel(channelIdRef.current, files.map(uploadFromTransferFile)) > 0) focusInput();
569
590
  }, [canAttach, controller, focusInput, imagesAvailable, notify]);
570
591
 
571
- // A chip under a message: the shared pane, or the story or calendar a Wire post names.
592
+ // A chip: the shared pane, the story or calendar a Wire post names, or a function written in a message.
572
593
  const openPaneLink = useCallback((link: ChatMessagePaneLink) => {
573
594
  openChatPaneLink(link, {
574
595
  createPaneFromTemplate,
575
596
  notify,
576
597
  openExternal: (url) => { void rendererHost.openExternal(url); },
598
+ runCommand: runChatCommand,
577
599
  });
578
600
  }, [createPaneFromTemplate, notify, rendererHost]);
579
601
 
580
602
  const handleDiscordCommand = useCallback((command: DiscordComposerCommand) => {
581
- void runDiscordCommand(command, { openUrl: (url) => rendererHost.openExternal(url) }).then(notify);
603
+ void runDiscordCommand(command, { openUrl: async (url) => { await rendererHost.openExternal(url); } }).then(notify);
582
604
  }, [notify, rendererHost]);
583
605
 
584
606
  // The terminal: a pasted or dropped path to an image file attaches the file
@@ -821,41 +843,48 @@ export function ChatContent({
821
843
  }, [directMessageContext, messageUser, selectedMessageAuthor]);
822
844
 
823
845
  const moveMentionSelection = useCallback((direction: "up" | "down") => {
824
- if (mentionSuggestions.length === 0) return false;
846
+ if (suggestionCount === 0) return false;
825
847
  setMentionSelectedIndex((current) => {
826
- const safeCurrent = Math.max(0, Math.min(current, mentionSuggestions.length - 1));
848
+ const safeCurrent = Math.max(0, Math.min(current, suggestionCount - 1));
827
849
  if (direction === "up") {
828
- return safeCurrent <= 0 ? mentionSuggestions.length - 1 : safeCurrent - 1;
850
+ return safeCurrent <= 0 ? suggestionCount - 1 : safeCurrent - 1;
829
851
  }
830
- return safeCurrent >= mentionSuggestions.length - 1 ? 0 : safeCurrent + 1;
852
+ return safeCurrent >= suggestionCount - 1 ? 0 : safeCurrent + 1;
831
853
  });
832
854
  return true;
833
- }, [mentionSuggestions.length]);
855
+ }, [suggestionCount]);
834
856
 
835
857
  const dismissMentionSuggestions = useCallback(() => {
836
- if (!mentionTriggerKey || mentionSuggestions.length === 0) return false;
837
- setDismissedMentionKey(mentionTriggerKey);
858
+ if (!suggestionTriggerKey || suggestionCount === 0) return false;
859
+ setDismissedMentionKey(suggestionTriggerKey);
838
860
  return true;
839
- }, [mentionSuggestions.length, mentionTriggerKey]);
861
+ }, [suggestionCount, suggestionTriggerKey]);
840
862
 
841
863
  const commitMentionSelection = useCallback((index = mentionSelectedIndexSafe) => {
842
- if (!mentionTrigger || mentionSuggestions.length === 0) return false;
843
- const suggestion = mentionSuggestions[index] ?? mentionSuggestions[0];
844
- if (!suggestion) return false;
845
- const replacement = applyMentionSuggestion(composerDraft, mentionTrigger, suggestion);
864
+ let replacement: { draft: string; cursorOffset: number } | null = null;
865
+ if (mentionTrigger && mentionSuggestions.length > 0) {
866
+ const suggestion = mentionSuggestions[index] ?? mentionSuggestions[0]!;
867
+ replacement = applyMentionSuggestion(composerDraft, mentionTrigger, suggestion);
868
+ } else if (commandTrigger && commandSuggestions.length > 0) {
869
+ const suggestion = commandSuggestions[index] ?? commandSuggestions[0]!;
870
+ replacement = applyCommandSuggestion(composerDraft, commandTrigger, suggestion);
871
+ }
872
+ if (!replacement) return false;
846
873
  replaceComposerDraft(replacement.draft, replacement.cursorOffset);
847
874
  setMentionSelectedIndex(0);
848
- setDismissedMentionKey(mentionTriggerKey);
875
+ setDismissedMentionKey(suggestionTriggerKey);
849
876
  queueMicrotask(() => focusInput());
850
877
  return true;
851
878
  }, [
879
+ commandSuggestions,
880
+ commandTrigger,
852
881
  composerDraft,
853
882
  focusInput,
854
883
  mentionSelectedIndexSafe,
855
884
  mentionSuggestions,
856
885
  mentionTrigger,
857
- mentionTriggerKey,
858
886
  replaceComposerDraft,
887
+ suggestionTriggerKey,
859
888
  ]);
860
889
 
861
890
  const {
@@ -941,7 +970,7 @@ export function ChatContent({
941
970
  inputValueRef,
942
971
  loadingOlderMessages,
943
972
  messages,
944
- mentionMenuOpen: mentionSuggestions.length > 0,
973
+ mentionMenuOpen: suggestionCount > 0,
945
974
  moveMentionSelection,
946
975
  dismissMentionSuggestions,
947
976
  commitMentionSelection,
@@ -1193,7 +1222,7 @@ export function ChatContent({
1193
1222
  replyPreview={replyPreview}
1194
1223
  replyTo={replyTo}
1195
1224
  sendMessage={sendMessage}
1196
- mentionSuggestions={mentionSuggestions}
1225
+ suggestions={composerSuggestions}
1197
1226
  mentionSelectedIndex={mentionSelectedIndexSafe}
1198
1227
  onMentionCursorChange={syncComposerCursor}
1199
1228
  onMentionSelect={commitMentionSelection}
@@ -4,6 +4,7 @@ import { chatMessageTokens } from "../markdown";
4
4
  import { chatImageLabel } from "../attachments/model";
5
5
  import { wirePaneTarget, type ChatMessagePaneLink } from "../pane-links/model";
6
6
  import { chatPaneLinkPane, peekSharePreview } from "../pane-links/previews";
7
+ import { resolveChatCommand, type ChatFunction } from "../pane-links/commands";
7
8
 
8
9
  export type ChatOpenTarget =
9
10
  | { kind: "pane"; link: ChatMessagePaneLink; label: string }
@@ -11,8 +12,9 @@ export type ChatOpenTarget =
11
12
  | { kind: "link"; url: string; label: string }
12
13
  | { kind: "image"; index: number; url: string; label: string };
13
14
 
14
- /** What the Open list calls a chip: the share's title once read, else its link; a Wire post's pane. */
15
+ /** What the Open list calls a chip: the share's title once read, else its link; a Wire post's pane; a function as written. */
15
16
  function paneLinkLabel(link: ChatMessagePaneLink): string {
17
+ if (link.kind === "command") return link.query;
16
18
  if (link.kind === "share") {
17
19
  const preview = peekSharePreview(link.id);
18
20
  return preview.status === "ready" ? preview.title : link.url;
@@ -27,13 +29,16 @@ function paneLinkLabel(link: ChatMessagePaneLink): string {
27
29
  * share links and Wire link open), the ticker badges its text draws (a symbol
28
30
  * the catalog does not know stays plain text), its links, then its images.
29
31
  * `content` is the text the message draws, without the links its chips stand
30
- * for. Code is text, so nothing in it is offered.
32
+ * for. Code is text, so nothing in it is offered, except where `functions` is
33
+ * given (the desktop and the web): there a function written in backticks is a
34
+ * chip, offered where the text names it.
31
35
  */
32
36
  export function chatMessageOpenTargets(
33
37
  content: string,
34
38
  catalog: Record<string, InlineTickerCatalogEntry>,
35
39
  attachments: readonly ChatAttachment[] = [],
36
40
  paneLinks: readonly ChatMessagePaneLink[] = [],
41
+ functions?: ReadonlyMap<string, ChatFunction>,
37
42
  ): ChatOpenTarget[] {
38
43
  const targets: ChatOpenTarget[] = paneLinks.map((link) => ({ kind: "pane", link, label: paneLinkLabel(link) }));
39
44
  const seen = new Set<string>();
@@ -45,7 +50,13 @@ export function chatMessageOpenTargets(
45
50
  continue;
46
51
  }
47
52
  open = null;
48
- if (token.kind === "ticker") {
53
+ const command = functions && token.kind === "text" && token.style?.code ? resolveChatCommand(token.value, functions) : null;
54
+ if (command) {
55
+ if (seen.has(`command:${command.query}`)) continue;
56
+ seen.add(`command:${command.query}`);
57
+ const link = { kind: "command", query: command.query, name: command.fn.name } as const;
58
+ targets.push({ kind: "pane", link, label: paneLinkLabel(link) });
59
+ } else if (token.kind === "ticker") {
49
60
  const entry = catalog[token.symbol];
50
61
  if (!entry || entry.status === "missing" || seen.has(`ticker:${token.symbol}`)) continue;
51
62
  seen.add(`ticker:${token.symbol}`);
@@ -121,7 +121,7 @@ export async function refreshChatControllerSession({
121
121
  stopVerificationPolling,
122
122
  syncVerificationPolling,
123
123
  }: RefreshChatControllerSessionOptions): Promise<void> {
124
- session.sessionToken = apiClient.getSessionToken();
124
+ const cachedToken = session.sessionToken;
125
125
  const apiSession = await apiClient.getSession(isCurrent);
126
126
  if (!isCurrent()) return;
127
127
  if (!apiSession) {
@@ -133,7 +133,9 @@ export async function refreshChatControllerSession({
133
133
  // startup from signing the user out.
134
134
  if (persistedToken) {
135
135
  session.sessionToken = persistedToken;
136
- session.user = session.user ?? normalizeSessionUser(apiClient.getCurrentUser());
136
+ // A failed sign-in can install another token before its user arrives.
137
+ // Only the credential stored with a cached user can restore that user.
138
+ session.user = (cachedToken === persistedToken ? session.user : null) ?? normalizeSessionUser(apiClient.getCurrentUser());
137
139
  // getSession() clears the API client's cached user when the endpoint
138
140
  // answers null. Keep both session views aligned while the protected
139
141
  // request validates the preserved native credential.