gloomberb 0.16.3 → 0.16.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 (820) hide show
  1. package/README.md +14 -91
  2. package/package.json +7 -1
  3. package/src/{plugins/builtin/cloud → account}/auth-form.tsx +9 -9
  4. package/src/{plugins/builtin/cloud → account}/auth-model.ts +4 -4
  5. package/src/account/billing.ts +57 -0
  6. package/src/{plugins/builtin/cloud → account}/device-signin-dialog.tsx +18 -12
  7. package/src/{plugins/builtin/cloud → account}/device-signin.ts +2 -2
  8. package/src/{plugins/builtin/cloud → account}/email-auth-attempt.ts +2 -2
  9. package/src/account/session.ts +16 -0
  10. package/src/{plugins/builtin/cloud → account}/upgrade-dialog.tsx +42 -17
  11. package/src/account/upgrade-personalization.ts +57 -0
  12. package/src/account/upgrade-tickers.ts +124 -0
  13. package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
  14. package/src/api-client/askg.ts +43 -0
  15. package/src/api-client/auth.ts +15 -0
  16. package/src/api-client/beneficial-owners.ts +4 -0
  17. package/src/api-client/chat.ts +19 -0
  18. package/src/api-client/company-kpis.ts +14 -2
  19. package/src/api-client/data.ts +58 -18
  20. package/src/api-client/earnings.ts +6 -0
  21. package/src/api-client/futures-curve.ts +56 -0
  22. package/src/api-client/index.ts +16 -1
  23. package/src/api-client/market-discovery.ts +10 -1
  24. package/src/api-client/normalizers.ts +27 -0
  25. package/src/api-client/paths.ts +95 -23
  26. package/src/api-client/request.ts +2 -1
  27. package/src/api-client/research-activity.ts +46 -10
  28. package/src/api-client/socket.ts +39 -8
  29. package/src/api-client/types.ts +74 -2
  30. package/src/api-client/upgrade-experiment.ts +90 -0
  31. package/src/api-client/yield-curves.ts +8 -0
  32. package/src/app/global-shortcuts.ts +26 -2
  33. package/src/app/keybindings/actions.ts +10 -0
  34. package/src/app/pane-runtime/index.tsx +8 -0
  35. package/src/app/pane-runtime/pane-template-runtime.ts +5 -0
  36. package/src/app/pane-runtime/plugin-bindings.ts +65 -25
  37. package/src/app/pane-runtime/ticker-inspector-runtime.ts +12 -0
  38. package/src/app/pane-runtime/ticker-open-runtime.ts +25 -4
  39. package/src/app/runtime/desktop-deeplink.ts +5 -0
  40. package/src/app/star-prompt/model.ts +98 -0
  41. package/src/app/star-prompt/runtime.ts +41 -0
  42. package/src/app/star-prompt/status-line.tsx +190 -0
  43. package/src/app.tsx +13 -7
  44. package/src/architecture/core-builtin-allowlist.json +61 -0
  45. package/src/brokers/signed-in/adapter.ts +33 -2
  46. package/src/brokers/signed-in/client.ts +10 -0
  47. package/src/brokers/signed-in/sign-in-dialog.tsx +34 -14
  48. package/src/brokers/signed-in/sign-in.ts +62 -5
  49. package/src/capabilities/chart-series.ts +11 -1
  50. package/src/capabilities/registry.ts +8 -1
  51. package/src/capabilities/types.ts +2 -0
  52. package/src/cli/commands/crypto-hints.ts +19 -4
  53. package/src/cli/commands/fred-series.ts +61 -0
  54. package/src/cli/commands/market.ts +744 -181
  55. package/src/cli/commands/news-hints.ts +62 -0
  56. package/src/cli/commands/news-search.ts +53 -0
  57. package/src/cli/commands/options-chain.ts +172 -0
  58. package/src/cli/commands/options-leaps.ts +425 -0
  59. package/src/cli/commands/overview.ts +251 -40
  60. package/src/cli/commands/remote.ts +2 -1
  61. package/src/cli/commands/search.ts +109 -15
  62. package/src/cli/commands/system.ts +151 -24
  63. package/src/cli/commands/themes.ts +64 -0
  64. package/src/cli/commands/ticker.ts +149 -40
  65. package/src/cli/context.ts +45 -14
  66. package/src/cli/desktop-pane-shot.ts +150 -17
  67. package/src/cli/earnings-calendar.ts +71 -0
  68. package/src/cli/errors.ts +25 -2
  69. package/src/cli/freshness.ts +22 -8
  70. package/src/cli/fx-pair.ts +57 -0
  71. package/src/cli/glossary.ts +429 -0
  72. package/src/cli/help.ts +14 -1
  73. package/src/cli/history-rows.ts +48 -7
  74. package/src/cli/index-roots.ts +58 -0
  75. package/src/cli/index.ts +29 -12
  76. package/src/cli/known-gaps.ts +27 -0
  77. package/src/cli/listing-arg.ts +595 -26
  78. package/src/cli/not-a-ticker.ts +44 -0
  79. package/src/cli/options.ts +50 -6
  80. package/src/cli/pane-functions/access-gate.ts +5 -0
  81. package/src/cli/pane-functions/capabilities.ts +11 -4
  82. package/src/cli/pane-functions/catalog.ts +48 -7
  83. package/src/cli/pane-functions/data.ts +48 -13
  84. package/src/cli/pane-functions/discovery.ts +1 -0
  85. package/src/cli/pane-functions/dom.ts +41 -19
  86. package/src/cli/pane-functions/freshness.ts +531 -32
  87. package/src/cli/pane-functions/function-help.ts +77 -25
  88. package/src/cli/pane-functions/headless.ts +50 -21
  89. package/src/cli/pane-functions/index.ts +66 -10
  90. package/src/cli/pane-functions/market-session.ts +147 -0
  91. package/src/cli/pane-functions/options.ts +77 -25
  92. package/src/cli/pane-functions/report-notices.ts +81 -0
  93. package/src/cli/pane-functions/report.ts +19 -8
  94. package/src/cli/pane-functions/resolver.ts +53 -18
  95. package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
  96. package/src/cli/pane-functions/screenshot.ts +199 -30
  97. package/src/cli/registry.ts +2 -1
  98. package/src/cli/report-tables.ts +3 -0
  99. package/src/cli/result.ts +53 -13
  100. package/src/cli/row-window.ts +76 -0
  101. package/src/cli/scroll-truncation.ts +34 -0
  102. package/src/cli/staged-tickers.ts +52 -0
  103. package/src/cli/symbol-args.ts +9 -0
  104. package/src/cli/symbol-list.ts +172 -0
  105. package/src/cli/ticker-resolution.ts +223 -30
  106. package/src/cli/types.ts +5 -0
  107. package/src/components/chart/composite/axis-overlays.tsx +6 -2
  108. package/src/components/chart/composite/composite-chart.tsx +83 -10
  109. package/src/components/chart/composite/legend.tsx +88 -8
  110. package/src/components/chart/composite/panel-surface.tsx +44 -17
  111. package/src/components/chart/composite/price-axis-labels.tsx +3 -1
  112. package/src/components/chart/composite/rasterizer.ts +64 -4
  113. package/src/components/chart/composite/series-cues.ts +71 -0
  114. package/src/components/chart/composite/text-renderer.ts +16 -8
  115. package/src/components/chart/composite/types.ts +3 -0
  116. package/src/components/command-bar/commands/direct/index.ts +9 -1
  117. package/src/components/command-bar/commands/plugin/items.ts +3 -1
  118. package/src/components/command-bar/commands/registry.ts +7 -0
  119. package/src/components/command-bar/layout-items/focused-pane.ts +38 -0
  120. package/src/components/command-bar/pane-templates/workflow.ts +5 -0
  121. package/src/components/command-bar/panel/index.tsx +11 -3
  122. package/src/components/command-bar/panel/runtime.ts +3 -0
  123. package/src/components/command-bar/panel/types.ts +2 -0
  124. package/src/components/command-bar/routes/root/command-items.ts +2 -0
  125. package/src/components/command-bar/routes/root/plugin-turn-on.ts +92 -0
  126. package/src/components/command-bar/routes/root/provider-search.ts +4 -3
  127. package/src/components/command-bar/routes/root/results.ts +40 -10
  128. package/src/components/command-bar/routes/root/runtime.ts +8 -0
  129. package/src/components/command-bar/routes/root/search-providers.ts +97 -14
  130. package/src/components/command-bar/routes/ticker-search/results.ts +12 -11
  131. package/src/components/command-bar/routes/ticker-search/route.ts +4 -3
  132. package/src/components/command-bar/surface/index.tsx +18 -4
  133. package/src/components/command-bar/theme-picker.tsx +48 -13
  134. package/src/components/command-bar/workflow/ops.ts +5 -3
  135. package/src/components/command-bar/workflow/tickers.ts +23 -4
  136. package/src/components/data-table/view.tsx +28 -9
  137. package/src/components/layout/detached-pane-shell.tsx +9 -0
  138. package/src/components/layout/floating-pane.tsx +9 -2
  139. package/src/components/layout/header.tsx +20 -5
  140. package/src/components/layout/market-summary.ts +23 -9
  141. package/src/components/layout/pane/content.tsx +40 -29
  142. package/src/components/layout/pane/cycle-order.ts +2 -11
  143. package/src/components/layout/pane/footer/index.tsx +6 -2
  144. package/src/components/layout/pane/footer/model.ts +35 -1
  145. package/src/components/layout/pane/header.tsx +26 -2
  146. package/src/components/layout/pane/index.tsx +12 -2
  147. package/src/components/layout/pane/sidebar.tsx +78 -10
  148. package/src/components/layout/pane/title.ts +1 -1
  149. package/src/components/layout/presentation.ts +22 -0
  150. package/src/components/layout/shell/active-drag.ts +21 -5
  151. package/src/components/layout/shell/drag/index.ts +43 -9
  152. package/src/components/layout/shell/drag/live.ts +87 -6
  153. package/src/components/layout/shell/drag/runtime.ts +62 -20
  154. package/src/components/layout/shell/index.tsx +71 -12
  155. package/src/components/layout/shell/layout-state.ts +5 -11
  156. package/src/components/layout/shell/menu.ts +33 -1
  157. package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
  158. package/src/components/layout/shell/pane/actions.ts +2 -1
  159. package/src/components/layout/shell/pane/layers.tsx +216 -28
  160. package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
  161. package/src/components/layout/shell/pane/new-layout.ts +116 -0
  162. package/src/components/layout/shell/shortcuts.ts +5 -2
  163. package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
  164. package/src/components/layout/shell/visible-layout.ts +44 -1
  165. package/src/components/layout/status-bar.tsx +4 -1
  166. package/src/components/markdown-text.tsx +69 -23
  167. package/src/components/metric-treemap/heat-surface.tsx +37 -9
  168. package/src/components/metric-treemap/heat-tiles.ts +48 -17
  169. package/src/components/onboarding/account-step/form-panel.tsx +1 -1
  170. package/src/components/onboarding/account-step/index.tsx +1 -1
  171. package/src/components/onboarding/account-step/qr-panel.tsx +1 -1
  172. package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
  173. package/src/components/onboarding/onboarding-frame.tsx +33 -10
  174. package/src/components/onboarding/onboarding-keyboard.ts +1 -1
  175. package/src/components/onboarding/onboarding-wizard.tsx +50 -41
  176. package/src/components/onboarding/portfolio-step/positions-panel.tsx +5 -2
  177. package/src/components/onboarding/pro-step-layout.ts +86 -0
  178. package/src/components/onboarding/use-onboarding-upgrade.ts +8 -4
  179. package/src/components/onboarding/wizard-account.ts +2 -2
  180. package/src/components/pane-template-wizard.tsx +9 -1
  181. package/src/components/price-selector-dialog.tsx +11 -2
  182. package/src/components/sign-in-gate.tsx +3 -3
  183. package/src/components/ticker/list-table-view.tsx +24 -1
  184. package/src/components/ui/action-row.tsx +2 -1
  185. package/src/components/ui/button.tsx +17 -1
  186. package/src/components/ui/choice-dialog.tsx +6 -4
  187. package/src/components/ui/confirm-dialog.tsx +28 -18
  188. package/src/components/ui/data-table/index.tsx +49 -0
  189. package/src/components/ui/data-table/opentui/index.tsx +37 -6
  190. package/src/components/ui/data-table/types.ts +20 -1
  191. package/src/components/ui/data-table/visible-range.ts +2 -0
  192. package/src/components/ui/dialog-actions.tsx +64 -0
  193. package/src/components/ui/display.tsx +17 -3
  194. package/src/components/ui/frame.tsx +35 -2
  195. package/src/components/ui/icon.tsx +13 -2
  196. package/src/components/ui/index.ts +1 -1
  197. package/src/components/ui/text-prompt-dialog.tsx +11 -9
  198. package/src/core/connection-health.ts +1 -1
  199. package/src/core/state/app/layout-reducer.ts +89 -3
  200. package/src/core/state/app/state.ts +8 -5
  201. package/src/core/state/app/types.ts +13 -2
  202. package/src/data/cached-query.ts +2 -0
  203. package/src/data/config/layout.ts +55 -21
  204. package/src/data/config/store/fold-panes.ts +149 -0
  205. package/src/data/config/store/migrations.ts +7 -0
  206. package/src/data/config/store/node.ts +27 -6
  207. package/src/data/config/store/normalize.ts +44 -5
  208. package/src/data/ticker-repository.ts +5 -0
  209. package/src/data/ticker-store.ts +15 -0
  210. package/src/docs/content.ts +215 -0
  211. package/src/docs/load.ts +139 -0
  212. package/src/docs/requests.ts +39 -0
  213. package/src/docs/snapshot.chunk.ts +8 -0
  214. package/src/docs/snapshot.json +7416 -0
  215. package/src/docs/topics.ts +216 -0
  216. package/src/i18n/es.ts +75 -5
  217. package/src/i18n/ja.ts +75 -5
  218. package/src/i18n/ko.ts +75 -5
  219. package/src/i18n/zh-cn.ts +75 -5
  220. package/src/i18n/zh-tw.ts +75 -5
  221. package/src/layout/desks.ts +2 -3
  222. package/src/layout/pane-layout-move.ts +264 -0
  223. package/src/layout/pane-manager/dock-tree.ts +18 -0
  224. package/src/layout/pane-manager/hidden-panes.ts +160 -0
  225. package/src/layout/pane-manager/index.ts +2 -0
  226. package/src/market-data/coordinator/chart.ts +10 -4
  227. package/src/market-data/coordinator/entries.ts +7 -1
  228. package/src/market-data/coordinator/index.ts +6 -3
  229. package/src/market-data/coordinator/quotes.ts +2 -2
  230. package/src/{plugins/builtin/futures/contracts.ts → market-data/futures-board.ts} +81 -28
  231. package/src/market-data/futures-contract.ts +151 -0
  232. package/src/market-data/hooks.tsx +10 -2
  233. package/src/market-data/market/format.ts +39 -21
  234. package/src/market-data/market/freshness.ts +193 -30
  235. package/src/market-data/market/status.ts +59 -23
  236. package/src/market-data/options-alternatives.ts +69 -0
  237. package/src/market-data/published-apac-sessions.ts +23 -1
  238. package/src/market-data/quotes/contributions.ts +22 -2
  239. package/src/market-data/quotes/metadata.ts +8 -9
  240. package/src/market-data/quotes/resolution.ts +2 -0
  241. package/src/market-data/quotes/screener-live-quotes.ts +61 -9
  242. package/src/market-data/result-types.ts +2 -0
  243. package/src/plugins/builtin/account-management/keyboard.ts +3 -0
  244. package/src/plugins/builtin/account-management/model.ts +2 -56
  245. package/src/plugins/builtin/account-management/navigation.ts +1 -1
  246. package/src/plugins/builtin/account-management/pane.tsx +37 -8
  247. package/src/plugins/builtin/account-management/password-dialog.tsx +1 -1
  248. package/src/plugins/builtin/alerts/cli.ts +313 -47
  249. package/src/plugins/builtin/alerts/events-pane.tsx +45 -7
  250. package/src/plugins/builtin/alerts/events.ts +23 -2
  251. package/src/plugins/builtin/alerts/history-pane.tsx +7 -2
  252. package/src/plugins/builtin/alerts/history.ts +2 -0
  253. package/src/plugins/builtin/alerts/index.tsx +41 -9
  254. package/src/plugins/builtin/alerts/pane.tsx +8 -0
  255. package/src/plugins/builtin/alerts/quotes.ts +3 -0
  256. package/src/plugins/builtin/alerts/research-builder.ts +8 -3
  257. package/src/plugins/builtin/alerts/research-rules.ts +18 -2
  258. package/src/plugins/builtin/alerts/scheduled-check.ts +122 -0
  259. package/src/plugins/builtin/alerts/scheduled-sources.ts +25 -0
  260. package/src/plugins/builtin/alerts/scheduled.ts +254 -0
  261. package/src/plugins/builtin/alerts/targets.ts +92 -0
  262. package/src/plugins/builtin/analytics/index.tsx +4 -2
  263. package/src/plugins/builtin/analytics/risk-headless.ts +33 -13
  264. package/src/plugins/builtin/analytics/risk-math.ts +91 -27
  265. package/src/plugins/builtin/analytics/risk-model.ts +71 -12
  266. package/src/plugins/builtin/analytics/risk-pane.tsx +23 -12
  267. package/src/plugins/builtin/attention/index.tsx +2 -0
  268. package/src/plugins/builtin/attention/pane.tsx +3 -1
  269. package/src/plugins/builtin/attention/series.ts +26 -0
  270. package/src/plugins/builtin/awards/index.tsx +2 -0
  271. package/src/plugins/builtin/awards/pane.tsx +3 -1
  272. package/src/plugins/builtin/awards/series.ts +29 -0
  273. package/src/plugins/builtin/backtest/pane.tsx +1 -1
  274. package/src/plugins/builtin/bond-calculator/model.ts +2 -1
  275. package/src/plugins/builtin/broker-manager/detail.tsx +4 -0
  276. package/src/plugins/builtin/broker-manager/index.tsx +7 -3
  277. package/src/plugins/builtin/broker-manager/model.ts +8 -0
  278. package/src/plugins/builtin/broker-manager/pane-actions.tsx +8 -2
  279. package/src/plugins/builtin/broker-manager/sign-in-end.ts +82 -0
  280. package/src/plugins/builtin/broker-manager/table.ts +5 -0
  281. package/src/plugins/builtin/builtin-plugin-meta.ts +121 -11
  282. package/src/plugins/builtin/catalysts/pane.tsx +3 -1
  283. package/src/plugins/builtin/cds/client.ts +70 -13
  284. package/src/plugins/builtin/cds/headless.ts +116 -19
  285. package/src/plugins/builtin/cds/index.tsx +3 -1
  286. package/src/plugins/builtin/cds/model.ts +193 -31
  287. package/src/plugins/builtin/cds/pane.tsx +56 -14
  288. package/src/plugins/builtin/cds/series.ts +19 -0
  289. package/src/plugins/builtin/central-bank-rates/index.tsx +2 -0
  290. package/src/plugins/builtin/central-bank-rates/series.ts +42 -0
  291. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +192 -255
  292. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +84 -46
  293. package/src/plugins/builtin/chart-composer/editor.tsx +5 -4
  294. package/src/plugins/builtin/chart-composer/field-series.ts +40 -0
  295. package/src/plugins/builtin/chart-composer/headless.ts +8 -3
  296. package/src/plugins/builtin/chart-composer/index.tsx +9 -2
  297. package/src/plugins/builtin/chart-composer/pane.tsx +1 -1
  298. package/src/plugins/builtin/chart-composer/series-catalog.ts +58 -50
  299. package/src/plugins/builtin/chart-composer/series-expression.ts +18 -10
  300. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +59 -3
  301. package/src/plugins/builtin/chart-composer/user-series.ts +84 -0
  302. package/src/plugins/builtin/chat/channels.ts +34 -36
  303. package/src/plugins/builtin/chat/command-bar.ts +138 -0
  304. package/src/plugins/builtin/chat/composer-commands.ts +21 -1
  305. package/src/plugins/builtin/chat/content/composer-runtime.ts +11 -1
  306. package/src/plugins/builtin/chat/content/footer.tsx +5 -3
  307. package/src/plugins/builtin/chat/content/index.tsx +21 -1
  308. package/src/plugins/builtin/chat/content/mentions.ts +2 -1
  309. package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
  310. package/src/plugins/builtin/chat/content/user-map.ts +3 -1
  311. package/src/plugins/builtin/chat/controller/index.ts +50 -0
  312. package/src/plugins/builtin/chat/conversations.ts +256 -0
  313. package/src/plugins/builtin/chat/discord-command.ts +91 -0
  314. package/src/plugins/builtin/chat/edit-window.ts +12 -6
  315. package/src/plugins/builtin/chat/ghost-user.ts +14 -0
  316. package/src/plugins/builtin/chat/index.tsx +40 -2
  317. package/src/plugins/builtin/chat/layout.ts +2 -0
  318. package/src/plugins/builtin/chat/message/desktop.tsx +2 -1
  319. package/src/plugins/builtin/chat/message/header.tsx +24 -15
  320. package/src/plugins/builtin/chat/message/profile-popover.tsx +2 -1
  321. package/src/plugins/builtin/chat/message/render-state.ts +3 -0
  322. package/src/plugins/builtin/chat/pane-requests.ts +60 -0
  323. package/src/plugins/builtin/chat/pane-state.ts +32 -2
  324. package/src/plugins/builtin/chat/pane.tsx +8 -0
  325. package/src/plugins/builtin/cloud/askg/controller.ts +223 -23
  326. package/src/plugins/builtin/cloud/askg/conversation-store.ts +21 -0
  327. package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
  328. package/src/plugins/builtin/cloud/askg/manifest.ts +33 -7
  329. package/src/plugins/builtin/cloud/askg/model.ts +156 -78
  330. package/src/plugins/builtin/cloud/askg/pane.tsx +772 -377
  331. package/src/plugins/builtin/cloud/askg/protocol.ts +50 -3
  332. package/src/plugins/builtin/cloud/askg/tool-display.ts +440 -0
  333. package/src/plugins/builtin/cloud/askg/tool-timeline.tsx +403 -0
  334. package/src/plugins/builtin/cloud/askg/undo.ts +2 -0
  335. package/src/plugins/builtin/cloud/auth-actions.tsx +1 -1
  336. package/src/plugins/builtin/cloud/auth-commands.ts +1 -1
  337. package/src/plugins/builtin/cloud/auth-dialog.tsx +3 -3
  338. package/src/plugins/builtin/cloud/company-picker.tsx +1 -9
  339. package/src/plugins/builtin/cloud/mcp-connect/command.ts +24 -0
  340. package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +363 -0
  341. package/src/plugins/builtin/cloud/mcp-connect/model.ts +135 -0
  342. package/src/plugins/builtin/cloud/mcp-connect/sections.ts +62 -0
  343. package/src/plugins/builtin/cloud/plugin.tsx +36 -1
  344. package/src/plugins/builtin/cloud/terminal-relay/acm-tab.tsx +89 -0
  345. package/src/plugins/builtin/cloud/terminal-relay/client.ts +97 -0
  346. package/src/plugins/builtin/cloud/terminal-relay/connect-section.tsx +57 -0
  347. package/src/plugins/builtin/cloud/terminal-relay/engine.ts +734 -0
  348. package/src/plugins/builtin/cloud/terminal-relay/grants.ts +137 -0
  349. package/src/plugins/builtin/cloud/terminal-relay/host.tsx +81 -0
  350. package/src/plugins/builtin/cloud/terminal-relay/indicator.tsx +82 -0
  351. package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +239 -0
  352. package/src/plugins/builtin/cloud/terminal-relay/policy.ts +162 -0
  353. package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +192 -0
  354. package/src/plugins/builtin/cloud/terminal-relay/redact.ts +73 -0
  355. package/src/plugins/builtin/cloud/terminal-relay/summary.ts +62 -0
  356. package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
  357. package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
  358. package/src/plugins/builtin/comment-letters/client.ts +1 -3
  359. package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
  360. package/src/plugins/builtin/company-attention/headless.ts +19 -5
  361. package/src/plugins/builtin/company-attention/index.tsx +2 -0
  362. package/src/plugins/builtin/company-attention/model.ts +26 -7
  363. package/src/plugins/builtin/company-attention/pane.tsx +12 -9
  364. package/src/plugins/builtin/company-attention/series.ts +52 -0
  365. package/src/plugins/builtin/company-kpis/client.ts +23 -8
  366. package/src/plugins/builtin/company-kpis/headless.ts +3 -1
  367. package/src/plugins/builtin/company-kpis/pane.tsx +19 -9
  368. package/src/plugins/builtin/company-kpis/screenshot-evidence.ts +10 -3
  369. package/src/plugins/builtin/composite-plugins.ts +116 -67
  370. package/src/plugins/builtin/cot/index.tsx +3 -1
  371. package/src/plugins/builtin/cot/model.ts +40 -11
  372. package/src/plugins/builtin/cot/series.ts +27 -0
  373. package/src/plugins/builtin/credit-boards/cdx-pane.tsx +4 -4
  374. package/src/plugins/builtin/credit-boards/index.tsx +23 -21
  375. package/src/plugins/builtin/credit-boards/model.ts +0 -1
  376. package/src/plugins/builtin/credit-boards/pane.tsx +30 -0
  377. package/src/plugins/builtin/credit-boards/series.ts +66 -0
  378. package/src/plugins/builtin/credit-boards/sovr-pane.tsx +4 -4
  379. package/src/plugins/builtin/credit-conditions/index.tsx +2 -0
  380. package/src/plugins/builtin/credit-conditions/series.ts +26 -0
  381. package/src/plugins/builtin/credit-documents/headless.ts +31 -1
  382. package/src/plugins/builtin/credit-documents/pane.tsx +3 -1
  383. package/src/plugins/builtin/crypto-board/headless.ts +2 -3
  384. package/src/plugins/builtin/crypto-board/index.tsx +2 -0
  385. package/src/plugins/builtin/crypto-board/model.ts +12 -0
  386. package/src/plugins/builtin/crypto-board/pane.tsx +19 -12
  387. package/src/plugins/builtin/crypto-board/series.ts +48 -0
  388. package/src/plugins/builtin/custom-view/live-quotes.ts +2 -2
  389. package/src/plugins/builtin/debt-maturities/client.ts +37 -9
  390. package/src/plugins/builtin/debt-maturities/headless.ts +3 -1
  391. package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
  392. package/src/plugins/builtin/debt-maturities/pane.tsx +5 -4
  393. package/src/plugins/builtin/debt-maturities/series.ts +45 -0
  394. package/src/plugins/builtin/dividend-yield/headless.ts +2 -2
  395. package/src/plugins/builtin/dividend-yield/index.tsx +3 -1
  396. package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
  397. package/src/plugins/builtin/dividend-yield/series.ts +20 -0
  398. package/src/plugins/builtin/docs/blocks.tsx +181 -0
  399. package/src/plugins/builtin/docs/index.tsx +68 -0
  400. package/src/plugins/builtin/docs/pane.tsx +426 -0
  401. package/src/plugins/builtin/docs/targets.ts +72 -0
  402. package/src/plugins/builtin/docs/use-docs.ts +60 -0
  403. package/src/plugins/builtin/doe/index.tsx +2 -0
  404. package/src/plugins/builtin/doe/series.ts +62 -0
  405. package/src/plugins/builtin/earnings/client.ts +3 -2
  406. package/src/plugins/builtin/earnings/format.ts +1 -5
  407. package/src/plugins/builtin/earnings/headless.ts +58 -6
  408. package/src/plugins/builtin/earnings/history-model.ts +15 -1
  409. package/src/plugins/builtin/earnings/history-table.ts +13 -2
  410. package/src/plugins/builtin/earnings/history.tsx +7 -3
  411. package/src/plugins/builtin/earnings-calls/data.ts +28 -7
  412. package/src/plugins/builtin/earnings-calls/headless.ts +3 -2
  413. package/src/plugins/builtin/earnings-calls/pane.tsx +10 -5
  414. package/src/plugins/builtin/econ/calendar-model.ts +42 -17
  415. package/src/plugins/builtin/econ/detail-view.tsx +2 -2
  416. package/src/plugins/builtin/econ/fred-catalog.ts +189 -0
  417. package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
  418. package/src/plugins/builtin/econ/index.tsx +70 -22
  419. package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
  420. package/src/plugins/builtin/econ-statistics/headless.ts +30 -5
  421. package/src/plugins/builtin/econ-statistics/pane.tsx +1 -1
  422. package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
  423. package/src/plugins/builtin/econ-statistics/view.ts +17 -0
  424. package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
  425. package/src/plugins/builtin/executives/data.ts +17 -6
  426. package/src/plugins/builtin/executives/pane.tsx +16 -7
  427. package/src/plugins/builtin/exposure/holdings.ts +1 -1
  428. package/src/plugins/builtin/exposure/pane.tsx +3 -1
  429. package/src/plugins/builtin/fear-greed/index.tsx +4 -0
  430. package/src/plugins/builtin/fear-greed/series.ts +52 -0
  431. package/src/plugins/builtin/filing-events/pane.tsx +22 -5
  432. package/src/plugins/builtin/futures/index.tsx +43 -3
  433. package/src/plugins/builtin/futures/model.ts +1 -1
  434. package/src/plugins/builtin/futures/returns.ts +1 -1
  435. package/src/plugins/builtin/futures/series.ts +13 -0
  436. package/src/plugins/builtin/futures/table.tsx +1 -1
  437. package/src/plugins/builtin/futures/use-front-returns.ts +1 -1
  438. package/src/plugins/builtin/futures-curve/client.ts +12 -3
  439. package/src/plugins/builtin/futures-curve/headless.ts +70 -9
  440. package/src/plugins/builtin/futures-curve/index.tsx +1 -1
  441. package/src/plugins/builtin/futures-curve/model.ts +66 -11
  442. package/src/plugins/builtin/futures-curve/pane.tsx +52 -18
  443. package/src/plugins/builtin/fx-matrix/index.tsx +22 -1
  444. package/src/plugins/builtin/fx-matrix/pairs.ts +1 -1
  445. package/src/plugins/builtin/fx-matrix/settings.ts +42 -2
  446. package/src/plugins/builtin/gpu/board.tsx +13 -10
  447. package/src/plugins/builtin/gpu/changes.tsx +4 -4
  448. package/src/plugins/builtin/gpu/client.ts +19 -1
  449. package/src/plugins/builtin/gpu/equities.tsx +14 -10
  450. package/src/plugins/builtin/gpu/headless.ts +64 -27
  451. package/src/plugins/builtin/gpu/history.tsx +3 -3
  452. package/src/plugins/builtin/gpu/index.tsx +2 -0
  453. package/src/plugins/builtin/gpu/model.ts +114 -20
  454. package/src/plugins/builtin/gpu/pane.tsx +28 -12
  455. package/src/plugins/builtin/gpu/series.ts +38 -0
  456. package/src/plugins/builtin/help/function-card.tsx +25 -6
  457. package/src/plugins/builtin/help/index.tsx +18 -8
  458. package/src/plugins/builtin/holders/beneficial-client.ts +29 -7
  459. package/src/plugins/builtin/holders/beneficial-model.ts +90 -3
  460. package/src/plugins/builtin/holders/beneficial-report.ts +57 -5
  461. package/src/plugins/builtin/holders/beneficial-view.tsx +62 -14
  462. package/src/plugins/builtin/holders/client.ts +22 -3
  463. package/src/plugins/builtin/holders/format.ts +18 -3
  464. package/src/plugins/builtin/holders/headless.ts +42 -134
  465. package/src/plugins/builtin/holders/pane.tsx +14 -4
  466. package/src/plugins/builtin/holders/report-header.ts +40 -5
  467. package/src/plugins/builtin/holders/report-rows.ts +240 -0
  468. package/src/plugins/builtin/insider/client.ts +35 -20
  469. package/src/plugins/builtin/insider/headless.ts +41 -11
  470. package/src/plugins/builtin/insider/index.tsx +27 -10
  471. package/src/plugins/builtin/insider/insider-data.ts +10 -0
  472. package/src/plugins/builtin/insider/issuer.ts +49 -0
  473. package/src/plugins/builtin/insider/model.ts +3 -0
  474. package/src/plugins/builtin/iv-history/charts.tsx +21 -7
  475. package/src/plugins/builtin/iv-history/client.ts +26 -6
  476. package/src/plugins/builtin/iv-history/format.ts +33 -2
  477. package/src/plugins/builtin/iv-history/headless.ts +27 -12
  478. package/src/plugins/builtin/iv-history/index.tsx +5 -3
  479. package/src/plugins/builtin/iv-history/model.ts +172 -20
  480. package/src/plugins/builtin/iv-history/pane.tsx +11 -3
  481. package/src/plugins/builtin/iv-history/screen-pane.tsx +45 -25
  482. package/src/plugins/builtin/iv-history/series.ts +29 -0
  483. package/src/plugins/builtin/jobs/headless.ts +28 -3
  484. package/src/plugins/builtin/jobs/index.tsx +3 -1
  485. package/src/plugins/builtin/jobs/pane.tsx +1 -1
  486. package/src/plugins/builtin/jobs/series.ts +19 -0
  487. package/src/plugins/builtin/kelly-sizer/headless.ts +149 -0
  488. package/src/plugins/builtin/kelly-sizer/history.ts +80 -0
  489. package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
  490. package/src/plugins/builtin/kelly-sizer/pane.tsx +111 -40
  491. package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
  492. package/src/plugins/builtin/kelly-sizer/sections.tsx +14 -0
  493. package/src/plugins/builtin/kelly-sizer/types.ts +9 -1
  494. package/src/plugins/builtin/layout-manager/index.tsx +9 -1
  495. package/src/plugins/builtin/macro-day/client.ts +68 -3
  496. package/src/plugins/builtin/macro-day/headless.ts +18 -12
  497. package/src/plugins/builtin/macro-day/index.tsx +3 -0
  498. package/src/plugins/builtin/macro-day/model.ts +66 -15
  499. package/src/plugins/builtin/macro-day/pane.tsx +34 -20
  500. package/src/plugins/builtin/macro-day/release-table.ts +40 -0
  501. package/src/plugins/builtin/macro-day/releases.ts +62 -44
  502. package/src/plugins/builtin/market-heatmap/data.ts +25 -5
  503. package/src/plugins/builtin/market-heatmap/evidence.ts +90 -0
  504. package/src/plugins/builtin/market-heatmap/index.tsx +144 -63
  505. package/src/plugins/builtin/market-heatmap/model.ts +102 -3
  506. package/src/plugins/builtin/market-heatmap/portfolio.ts +12 -2
  507. package/src/plugins/builtin/market-movers/client.ts +7 -5
  508. package/src/plugins/builtin/market-movers/headless.ts +31 -4
  509. package/src/plugins/builtin/market-movers/index.tsx +11 -3
  510. package/src/plugins/builtin/market-movers/model.ts +101 -17
  511. package/src/plugins/builtin/market-movers/screener.ts +31 -0
  512. package/src/plugins/builtin/market-movers/table.ts +50 -23
  513. package/src/plugins/builtin/market-valuation/chart-series.ts +29 -69
  514. package/src/plugins/builtin/market-valuation/index.tsx +3 -3
  515. package/src/plugins/builtin/market-valuation/indicators.ts +0 -5
  516. package/src/plugins/builtin/members/headless.ts +7 -2
  517. package/src/plugins/builtin/members/model.ts +31 -3
  518. package/src/plugins/builtin/members/pane.tsx +3 -6
  519. package/src/plugins/builtin/mna/headless.ts +15 -3
  520. package/src/plugins/builtin/money-markets/index.tsx +2 -0
  521. package/src/plugins/builtin/money-markets/series.ts +41 -0
  522. package/src/plugins/builtin/news/headless.ts +9 -2
  523. package/src/plugins/builtin/news/wire/news/footer.ts +10 -0
  524. package/src/plugins/builtin/notes/cli.ts +12 -7
  525. package/src/plugins/builtin/openfda/client.ts +1 -1
  526. package/src/plugins/builtin/options/carry.ts +95 -0
  527. package/src/plugins/builtin/options/index.tsx +58 -5
  528. package/src/plugins/builtin/options/strike-window.ts +183 -0
  529. package/src/plugins/builtin/options/table.ts +55 -3
  530. package/src/plugins/builtin/options/types.ts +8 -1
  531. package/src/plugins/builtin/options/view.tsx +162 -13
  532. package/src/plugins/builtin/options-calculator/inputs.ts +2 -1
  533. package/src/plugins/builtin/options-positioning/client.ts +7 -3
  534. package/src/plugins/builtin/options-positioning/headless.ts +5 -2
  535. package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
  536. package/src/plugins/builtin/options-scenario/charts.tsx +2 -2
  537. package/src/plugins/builtin/options-scenario/client.ts +75 -18
  538. package/src/plugins/builtin/options-scenario/headless.ts +72 -24
  539. package/src/plugins/builtin/options-scenario/hedge.ts +285 -0
  540. package/src/plugins/builtin/options-scenario/index.tsx +9 -2
  541. package/src/plugins/builtin/options-scenario/model.ts +33 -0
  542. package/src/plugins/builtin/options-scenario/pane.tsx +40 -16
  543. package/src/plugins/builtin/pe-band/model.ts +2 -2
  544. package/src/plugins/builtin/pe-band/report-dates.ts +11 -7
  545. package/src/plugins/builtin/perps/client.ts +40 -6
  546. package/src/plugins/builtin/perps/equity-row.tsx +33 -8
  547. package/src/plugins/builtin/perps/freshness.ts +66 -0
  548. package/src/plugins/builtin/perps/headless.ts +45 -30
  549. package/src/plugins/builtin/perps/index.tsx +18 -1
  550. package/src/plugins/builtin/perps/model.ts +32 -6
  551. package/src/plugins/builtin/perps/pane.tsx +76 -20
  552. package/src/plugins/builtin/perps/series.ts +76 -0
  553. package/src/plugins/builtin/plugin-marketplace/model.ts +64 -21
  554. package/src/plugins/builtin/plugin-marketplace/packs.ts +118 -0
  555. package/src/plugins/builtin/plugin-marketplace/pane.tsx +357 -39
  556. package/src/plugins/builtin/plugin-marketplace/store.ts +7 -1
  557. package/src/plugins/builtin/plugin-module.ts +90 -4
  558. package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
  559. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +273 -0
  560. package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
  561. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +400 -99
  562. package/src/plugins/builtin/portfolio-list/cli/render.ts +281 -43
  563. package/src/plugins/builtin/portfolio-list/cli/shared.ts +26 -16
  564. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +120 -47
  565. package/src/plugins/builtin/portfolio-list/column-values.ts +1 -1
  566. package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
  567. package/src/plugins/builtin/portfolio-list/headless.ts +70 -9
  568. package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
  569. package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
  570. package/src/plugins/builtin/portfolio-list/pane/index.tsx +6 -1
  571. package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +17 -1
  572. package/src/plugins/builtin/portfolio-list/summary/totals.ts +1 -1
  573. package/src/plugins/builtin/portfolio-list/table.tsx +7 -1
  574. package/src/plugins/builtin/power/client.ts +16 -0
  575. package/src/plugins/builtin/power/evidence.ts +6 -2
  576. package/src/plugins/builtin/power/headless.ts +71 -7
  577. package/src/plugins/builtin/power/index.tsx +4 -1
  578. package/src/plugins/builtin/power/model.ts +72 -1
  579. package/src/plugins/builtin/power/pane.tsx +32 -9
  580. package/src/plugins/builtin/rate-path/headless.ts +11 -3
  581. package/src/plugins/builtin/realized-vol/headless.ts +8 -0
  582. package/src/plugins/builtin/realized-vol/pane.tsx +1 -1
  583. package/src/plugins/builtin/research/corporate-actions-pane.tsx +7 -4
  584. package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +1 -1
  585. package/src/plugins/builtin/research/event-model.ts +68 -24
  586. package/src/plugins/builtin/research/events-headless.ts +2 -1
  587. package/src/plugins/builtin/research/headless.ts +2 -1
  588. package/src/plugins/builtin/revenue-breakdown/client.ts +13 -6
  589. package/src/plugins/builtin/revenue-breakdown/headless.ts +4 -1
  590. package/src/plugins/builtin/revenue-breakdown/pane.tsx +7 -4
  591. package/src/plugins/builtin/reverse-dcf/headless.ts +5 -1
  592. package/src/plugins/builtin/reverse-dcf/pane.tsx +1 -1
  593. package/src/plugins/builtin/risk-factors/data.ts +23 -9
  594. package/src/plugins/builtin/risk-factors/headless.ts +5 -2
  595. package/src/plugins/builtin/risk-factors/pane.tsx +6 -5
  596. package/src/plugins/builtin/seasonality/client.ts +15 -7
  597. package/src/plugins/builtin/seasonality/headless.ts +36 -12
  598. package/src/plugins/builtin/seasonality/index.tsx +2 -2
  599. package/src/plugins/builtin/seasonality/model.ts +119 -0
  600. package/src/plugins/builtin/seasonality/pane.tsx +108 -37
  601. package/src/plugins/builtin/sec/index.tsx +5 -5
  602. package/src/plugins/builtin/sectors/client.ts +10 -2
  603. package/src/plugins/builtin/sectors/headless.ts +35 -6
  604. package/src/plugins/builtin/sectors/index.tsx +18 -1
  605. package/src/plugins/builtin/sectors/sector-model.ts +150 -41
  606. package/src/plugins/builtin/series-inventory.ts +91 -0
  607. package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
  608. package/src/plugins/builtin/shared/command-tab.ts +69 -0
  609. package/src/plugins/builtin/shared/earnings-report.ts +55 -0
  610. package/src/plugins/builtin/shared/fred-points.ts +20 -0
  611. package/src/plugins/builtin/shared/fx-rate-freshness.ts +101 -0
  612. package/src/plugins/builtin/shared/headless-market-data.ts +33 -1
  613. package/src/plugins/builtin/shared/members-menu.tsx +4 -4
  614. package/src/plugins/builtin/shared/open-description.ts +29 -0
  615. package/src/plugins/builtin/shared/report-freshness.ts +59 -2
  616. package/src/plugins/builtin/shared/series-warning.ts +5 -0
  617. package/src/plugins/builtin/shared/ticker-request.ts +25 -1
  618. package/src/plugins/builtin/shared/use-quote-board.ts +25 -5
  619. package/src/plugins/builtin/shared/volatility/options.ts +1 -46
  620. package/src/plugins/builtin/short-interest/headless.ts +1 -0
  621. package/src/plugins/builtin/short-interest/index.tsx +21 -4
  622. package/src/plugins/builtin/short-interest/series.ts +36 -0
  623. package/src/plugins/builtin/short-interest/surface.tsx +4 -4
  624. package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
  625. package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
  626. package/src/plugins/builtin/short-volume/headless.ts +1 -0
  627. package/src/plugins/builtin/short-volume/index.tsx +3 -10
  628. package/src/plugins/builtin/short-volume/series.ts +23 -0
  629. package/src/plugins/builtin/social-mentions/index.tsx +2 -0
  630. package/src/plugins/builtin/social-mentions/series.ts +23 -0
  631. package/src/plugins/builtin/supply-chain/graph-pane.tsx +3 -2
  632. package/src/plugins/builtin/supply-chain/model.ts +1 -1
  633. package/src/plugins/builtin/supply-chain/pane.tsx +3 -1
  634. package/src/plugins/builtin/thirteenf/api.ts +1 -0
  635. package/src/plugins/builtin/thirteenf/data.ts +6 -4
  636. package/src/plugins/builtin/thirteenf/headless.ts +217 -36
  637. package/src/plugins/builtin/thirteenf/model.ts +39 -1
  638. package/src/plugins/builtin/thirteenf/overlap.ts +75 -0
  639. package/src/plugins/builtin/thirteenf/pane.tsx +10 -1
  640. package/src/plugins/builtin/thirteenf/report-notes.ts +103 -1
  641. package/src/plugins/builtin/thirteenf/types.ts +2 -0
  642. package/src/plugins/builtin/ticker-detail/headless.ts +43 -21
  643. package/src/plugins/builtin/ticker-detail/index.tsx +3 -0
  644. package/src/plugins/builtin/ticker-detail/overview/components.tsx +1 -1
  645. package/src/plugins/builtin/ticker-detail/overview/futures-contract.ts +31 -0
  646. package/src/plugins/builtin/ticker-detail/overview/model.ts +3 -3
  647. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +2 -1
  648. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +48 -4
  649. package/src/plugins/builtin/ticker-detail/pane.tsx +4 -5
  650. package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +94 -6
  651. package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
  652. package/src/plugins/builtin/time-sales/headless.ts +1 -0
  653. package/src/plugins/builtin/treasury-auctions/cache.ts +5 -2
  654. package/src/plugins/builtin/treasury-auctions/client.ts +22 -8
  655. package/src/plugins/builtin/treasury-auctions/headless.ts +56 -6
  656. package/src/plugins/builtin/treasury-auctions/index.tsx +12 -9
  657. package/src/plugins/builtin/treasury-auctions/model.ts +205 -30
  658. package/src/plugins/builtin/treasury-auctions/pane.tsx +35 -11
  659. package/src/plugins/builtin/treasury-auctions/types.ts +11 -1
  660. package/src/plugins/builtin/vol-surface/charts.tsx +1 -3
  661. package/src/plugins/builtin/vol-surface/client.ts +6 -2
  662. package/src/plugins/builtin/vol-surface/evidence.ts +11 -6
  663. package/src/plugins/builtin/vol-surface/headless.ts +125 -20
  664. package/src/plugins/builtin/vol-surface/model.ts +23 -11
  665. package/src/plugins/builtin/vol-surface/pane.tsx +38 -27
  666. package/src/plugins/builtin/vol-surface/tables.ts +124 -0
  667. package/src/plugins/builtin/volatility/index.tsx +2 -0
  668. package/src/plugins/builtin/volatility/series.ts +84 -0
  669. package/src/plugins/builtin/world-indices/client.ts +22 -4
  670. package/src/plugins/builtin/world-indices/headless.ts +54 -27
  671. package/src/plugins/builtin/world-indices/model.ts +4 -2
  672. package/src/plugins/builtin/world-indices/table.tsx +13 -2
  673. package/src/plugins/builtin/world-venue-map/geo-series.ts +27 -2
  674. package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
  675. package/src/plugins/builtin/world-venue-map/index.ts +3 -2
  676. package/src/plugins/builtin/world-venue-map/layered-pane.tsx +8 -4
  677. package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
  678. package/src/plugins/builtin/yield-curve/chart.ts +2 -2
  679. package/src/plugins/builtin/yield-curve/curves.ts +21 -8
  680. package/src/plugins/builtin/yield-curve/headless.ts +71 -18
  681. package/src/plugins/builtin/yield-curve/index.tsx +4 -2
  682. package/src/plugins/builtin/yield-curve/series.ts +86 -0
  683. package/src/plugins/builtin-editorial.ts +126 -0
  684. package/src/plugins/catalog-backend.ts +16 -9
  685. package/src/plugins/catalog-browser.ts +129 -64
  686. package/src/plugins/catalog-manifest.ts +73 -40
  687. package/src/plugins/catalog-ui.ts +26 -6
  688. package/src/plugins/extracted-plugins.ts +7 -1
  689. package/src/plugins/ownership.ts +150 -7
  690. package/src/plugins/plugin-functions.ts +54 -0
  691. package/src/plugins/plugin-off.ts +36 -0
  692. package/src/plugins/registry/host-actions.ts +16 -0
  693. package/src/plugins/registry/index.ts +173 -28
  694. package/src/plugins/registry/plugin-state.ts +25 -1
  695. package/src/plugins/runtime/context.tsx +29 -0
  696. package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
  697. package/src/portfolio/position-value.ts +40 -0
  698. package/src/public/__snapshots__/public-api.test.ts.snap +7 -0
  699. package/src/public/time-series.ts +17 -0
  700. package/src/react/auto-refresh.ts +13 -3
  701. package/src/react/input.ts +48 -1
  702. package/src/remote/app-host.tsx +25 -4
  703. package/src/remote/confirm-change.tsx +85 -0
  704. package/src/remote/controller-utils.ts +8 -1
  705. package/src/remote/controller.ts +126 -59
  706. package/src/remote/matching.ts +69 -0
  707. package/src/remote/pane-screenshot.ts +47 -0
  708. package/src/remote/schema.ts +63 -1
  709. package/src/remote/semantic-tree.tsx +14 -0
  710. package/src/remote/types.ts +32 -0
  711. package/src/remote/watchlist.ts +306 -0
  712. package/src/renderers/browser/main.tsx +3 -2
  713. package/src/renderers/cloudflare/worker.ts +1 -1
  714. package/src/renderers/dom/data-table/frozen-column.ts +3 -1
  715. package/src/renderers/dom/data-table/index.tsx +33 -6
  716. package/src/renderers/dom/data-table/row.tsx +27 -1
  717. package/src/renderers/dom/desktop/control-styles.ts +63 -1
  718. package/src/renderers/dom/desktop/controls.tsx +30 -23
  719. package/src/renderers/dom/desktop/dialog-actions.tsx +170 -0
  720. package/src/renderers/dom/desktop/icons.tsx +21 -0
  721. package/src/renderers/dom/desktop/query-bar.tsx +59 -32
  722. package/src/renderers/dom/dom-ui-host.tsx +3 -0
  723. package/src/renderers/dom/host/box.tsx +4 -1
  724. package/src/renderers/dom/host/chart-surface.tsx +6 -2
  725. package/src/renderers/dom/host/drag-shield.ts +17 -6
  726. package/src/renderers/dom/host/live-frame.ts +14 -2
  727. package/src/renderers/dom/host/overflow-fade.ts +14 -1
  728. package/src/renderers/dom/host/size-observer.ts +26 -0
  729. package/src/renderers/dom/host/surface-3d.tsx +7 -2
  730. package/src/renderers/dom/host/text.tsx +1 -1
  731. package/src/renderers/dom/input-host.tsx +6 -1
  732. package/src/renderers/dom/styles.css +74 -0
  733. package/src/renderers/electrobun/bun/desktop/backend.ts +5 -1
  734. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +12 -1
  735. package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -1
  736. package/src/renderers/electrobun/shared/protocol.ts +2 -0
  737. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +18 -3
  738. package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +109 -5
  739. package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
  740. package/src/renderers/electrobun/view/main.tsx +6 -1
  741. package/src/renderers/opentui/input-host.tsx +6 -1
  742. package/src/renderers/opentui/start.tsx +9 -0
  743. package/src/series/capability.ts +75 -0
  744. package/src/series/csv.ts +160 -0
  745. package/src/series/files.ts +107 -0
  746. package/src/series/registry.ts +198 -0
  747. package/src/series/resolve.ts +107 -0
  748. package/src/series/standalone.ts +48 -0
  749. package/src/series/types.ts +145 -0
  750. package/src/series/validate.ts +171 -0
  751. package/src/shares/portable-layout.ts +16 -6
  752. package/src/sources/gloomberb-cloud/index.ts +26 -17
  753. package/src/sources/gloomberb-cloud/normalizers.ts +5 -1
  754. package/src/sources/history-result.ts +1 -0
  755. package/src/sources/listing-symbols.ts +14 -5
  756. package/src/sources/provider-errors.ts +88 -3
  757. package/src/sources/provider-router/batches.ts +4 -1
  758. package/src/sources/provider-router/cache.ts +4 -2
  759. package/src/sources/provider-router/cached-routes.ts +9 -5
  760. package/src/sources/provider-router/financial-routes.ts +12 -5
  761. package/src/sources/provider-router/financials.ts +55 -15
  762. package/src/sources/provider-router/history.ts +68 -34
  763. package/src/sources/provider-router/index.ts +1 -1
  764. package/src/sources/provider-router/primary.ts +23 -5
  765. package/src/sources/provider-router/search.ts +1 -0
  766. package/src/sources/sec-edgar.ts +68 -8
  767. package/src/sync/core-contributors.ts +5 -3
  768. package/src/test-support/cli-context.ts +2 -1
  769. package/src/test-support/data-provider.ts +34 -0
  770. package/src/test-support/shell-pane-keys.tsx +1 -0
  771. package/src/theme/series-colors.ts +46 -0
  772. package/src/theme/themes.ts +149 -0
  773. package/src/tickers/company-name.ts +75 -0
  774. package/src/tickers/instrument-kind.ts +25 -0
  775. package/src/tickers/open-target.ts +3 -2
  776. package/src/tickers/search/index.ts +67 -9
  777. package/src/tickers/search/ranking.ts +78 -18
  778. package/src/tickers/search/types.ts +10 -2
  779. package/src/tickers/starter-symbols.ts +8 -0
  780. package/src/tickers/us-listing.ts +34 -0
  781. package/src/time-series/hooks.ts +9 -0
  782. package/src/time-series/resolve.ts +96 -30
  783. package/src/time-series/types.ts +4 -2
  784. package/src/time-series/use-chart-resolution.ts +32 -0
  785. package/src/types/config.ts +67 -1
  786. package/src/types/data-provider.ts +5 -0
  787. package/src/types/financials.ts +52 -1
  788. package/src/types/headless.ts +72 -0
  789. package/src/types/instrument.ts +8 -0
  790. package/src/types/plugin.ts +68 -3
  791. package/src/types/price-history.ts +7 -0
  792. package/src/types/ticker.ts +14 -0
  793. package/src/ui/host.tsx +26 -4
  794. package/src/ui/index.tsx +2 -0
  795. package/src/ui/live-resize.ts +81 -0
  796. package/src/ui/live-stretch.ts +121 -0
  797. package/src/ui/measured-cells.ts +58 -0
  798. package/src/ui/pane-fill.ts +11 -0
  799. package/src/utils/basis-points.ts +17 -0
  800. package/src/utils/cli-output.ts +21 -2
  801. package/src/utils/concurrency.ts +25 -0
  802. package/src/utils/crypto-pair.ts +20 -0
  803. package/src/utils/currency-pair.ts +19 -0
  804. package/src/utils/decimal-comma.ts +19 -0
  805. package/src/utils/dom-screenshot-css.ts +265 -0
  806. package/src/utils/dom-screenshot-rasters.ts +276 -0
  807. package/src/utils/dom-screenshot.ts +437 -52
  808. package/src/utils/exchange-rate-snapshot.ts +6 -2
  809. package/src/utils/exchanges.ts +120 -1
  810. package/src/utils/format.ts +17 -3
  811. package/src/utils/fundamentals.ts +66 -0
  812. package/src/utils/futures-generic.ts +6 -12
  813. package/src/utils/fx-market-hours.ts +44 -0
  814. package/src/utils/option-expiry.ts +126 -0
  815. package/src/utils/price-history.ts +130 -40
  816. package/src/utils/rpc-timeout-error.ts +6 -2
  817. package/src/utils/sec-eps-basis.ts +178 -36
  818. package/src/utils/sec.ts +98 -40
  819. package/src/utils/throttled-fetch.ts +51 -22
  820. package/src/utils/utc-time.ts +51 -4
@@ -1,6 +1,8 @@
1
1
  import { useRef } from "react";
2
2
  import { Box, Text, useUiCapabilities, type BoxRenderable } from "../../../../ui";
3
3
  import { t } from "../../../../i18n";
4
+ import { displayWidth } from "../../../../utils/format";
5
+ import { chatAuthorName, isDiscordGhost } from "../ghost-user";
4
6
  import { Button } from "../../../../components/ui";
5
7
  import { MESSAGE_ACTION_WIDTH } from "../layout";
6
8
  import type { ChatMessageRenderState } from "./render-state";
@@ -82,7 +84,9 @@ export function ChatMessageHeader({
82
84
  /** The terminal sizes the author cell to its label. */
83
85
  fitAuthorWidth?: boolean;
84
86
  }) {
85
- const authorLabel = msg.user.username ?? "anon";
87
+ const authorLabel = chatAuthorName(msg.user);
88
+ // A Discord ghost has no Gloom profile to open and no one to message.
89
+ const hasProfile = !isDiscordGhost(msg.user);
86
90
  const { nativeContextMenu } = useUiCapabilities();
87
91
  // The card opens beside the name the pointer is on.
88
92
  const nameRef = useRef<BoxRenderable | null>(null);
@@ -90,26 +94,31 @@ export function ChatMessageHeader({
90
94
  <Box {...rowProps} flexDirection="row" height={1} paddingLeft={1}>
91
95
  <Box
92
96
  ref={nameRef}
93
- width={fitAuthorWidth ? authorLabel.length : undefined}
97
+ width={fitAuthorWidth ? displayWidth(authorLabel) : undefined}
94
98
  height={1}
95
- onMouseOver={() => onUserHover(msg.user, nameRef.current)}
96
- onMouseMove={() => onUserHover(msg.user, nameRef.current)}
97
- onMouseOut={onUserHoverEnd}
98
- data-gloom-context-menu-surface="true"
99
- onMouseDown={(event: { button?: number; preventDefault?: () => void; stopPropagation?: () => void }) => {
100
- event.preventDefault?.();
101
- event.stopPropagation?.();
102
- // A native menu opens on the right-click's contextmenu event instead.
103
- if (event.button === 2 && nativeContextMenu === true) return;
104
- onUserActivate?.(msg.user, nameRef.current);
105
- }}
106
- onContextMenu={(event: { preventDefault?: () => void; stopPropagation?: () => void }) => onUserContextMenu?.(msg.user, event, nameRef.current)}
107
- style={{ cursor: "pointer" }}
99
+ {...(hasProfile
100
+ ? {
101
+ onMouseOver: () => onUserHover(msg.user, nameRef.current),
102
+ onMouseMove: () => onUserHover(msg.user, nameRef.current),
103
+ onMouseOut: onUserHoverEnd,
104
+ "data-gloom-context-menu-surface": "true",
105
+ onMouseDown: (event: { button?: number; preventDefault?: () => void; stopPropagation?: () => void }) => {
106
+ event.preventDefault?.();
107
+ event.stopPropagation?.();
108
+ // A native menu opens on the right-click's contextmenu event instead.
109
+ if (event.button === 2 && nativeContextMenu === true) return;
110
+ onUserActivate?.(msg.user, nameRef.current);
111
+ },
112
+ onContextMenu: (event: { preventDefault?: () => void; stopPropagation?: () => void }) => onUserContextMenu?.(msg.user, event, nameRef.current),
113
+ style: { cursor: "pointer" },
114
+ }
115
+ : {})}
108
116
  >
109
117
  <Text fg={state.authorColor} attributes={state.authorAttributes}>
110
118
  {authorLabel}
111
119
  </Text>
112
120
  </Box>
121
+ {msg.origin === "discord" && <Text fg={state.originTagColor}> Discord</Text>}
113
122
  <Text fg={state.headerStatusColor}> {state.headerStatus}</Text>
114
123
  {(state.showReplyAction || (state.showRetryAction && actionProps.retryMessage)) && <Text fg={state.headerStatusColor}> </Text>}
115
124
  <ChatMessageActions state={state} {...actionProps} />
@@ -5,6 +5,7 @@ import { colors } from "../../../../theme/colors";
5
5
  import type { ChatUserSummary, PublicPortfolioAnalytics } from "../../../../api-client";
6
6
  import { displayWidth, formatNumber, truncateToDisplayWidth } from "../../../../utils/format";
7
7
  import { truncateWithEllipsis } from "../../../../utils/text-wrap";
8
+ import { isDiscordGhost } from "../ghost-user";
8
9
  import type { ChatUserAnchor } from "./types";
9
10
 
10
11
  /**
@@ -24,7 +25,7 @@ function hasPortfolioAnalytics(analytics: PublicPortfolioAnalytics | null | unde
24
25
  }
25
26
 
26
27
  export function hasPublicChatProfileInfo(user: ChatUserSummary): boolean {
27
- if (user.profilePublic === false) return false;
28
+ if (user.profilePublic === false || isDiscordGhost(user)) return false;
28
29
  return Boolean(user.bio?.trim() || user.title?.trim() || user.company?.trim() || hasPortfolioAnalytics(user.portfolioAnalytics));
29
30
  }
30
31
 
@@ -20,6 +20,8 @@ export interface ChatMessageRenderState {
20
20
  replyAuthorColor: string;
21
21
  headerStatus: string;
22
22
  headerStatusColor: string;
23
+ /** The dim "Discord" tag beside the author of a message that came from Discord. */
24
+ originTagColor: string;
23
25
  authorColor: string;
24
26
  authorAttributes: number;
25
27
  bodyColor: string;
@@ -82,6 +84,7 @@ export function getChatMessageRenderState({
82
84
  : hasFailed
83
85
  ? colors.negative
84
86
  : colors.textMuted,
87
+ originTagColor: isSelected ? selectedTextColor : colors.textDim,
85
88
  authorColor: isSelected ? selectedTextColor : hasFailed ? colors.negative : colors.positive,
86
89
  authorAttributes: (isSending ? TextAttributes.DIM : 0) | TextAttributes.BOLD,
87
90
  bodyColor: isSelected ? selectedTextColor : hasFailed ? colors.negative : isSending ? colors.textDim : colors.text,
@@ -0,0 +1,60 @@
1
+ import { useSyncExternalStore } from "react";
2
+
3
+ /**
4
+ * Something a Chat pane should do once it has the keyboard, asked for from
5
+ * outside it: the command bar opens a conversation to write in, or the New DM
6
+ * dialog. The pane that is focused on that conversation takes it.
7
+ */
8
+ export type ChatPaneRequest =
9
+ | { action: "compose"; channelId: string }
10
+ | { action: "new-dm" };
11
+
12
+ interface PendingChatPaneRequest {
13
+ request: ChatPaneRequest;
14
+ at: number;
15
+ }
16
+
17
+ /** A request no pane took by then (the pane never opened) must not fire later. */
18
+ const REQUEST_TTL_MS = 10_000;
19
+
20
+ let pending: PendingChatPaneRequest | null = null;
21
+ const listeners = new Set<() => void>();
22
+
23
+ function emit(): void {
24
+ for (const listener of listeners) listener();
25
+ }
26
+
27
+ export function requestChatPaneAction(request: ChatPaneRequest, now = Date.now()): void {
28
+ pending = { request, at: now };
29
+ emit();
30
+ }
31
+
32
+ /**
33
+ * Hands the request to the pane on `channelId` and clears it. Null when there
34
+ * is none for that pane or it went stale.
35
+ */
36
+ export function takeChatPaneRequest(channelId: string, now = Date.now()): ChatPaneRequest | null {
37
+ if (!pending) return null;
38
+ const { request, at } = pending;
39
+ if (now - at > REQUEST_TTL_MS) {
40
+ pending = null;
41
+ emit();
42
+ return null;
43
+ }
44
+ if (request.action === "compose" && request.channelId !== channelId) return null;
45
+ pending = null;
46
+ emit();
47
+ return request;
48
+ }
49
+
50
+ function subscribe(listener: () => void): () => void {
51
+ listeners.add(listener);
52
+ return () => {
53
+ listeners.delete(listener);
54
+ };
55
+ }
56
+
57
+ /** The request waiting for a pane, so a pane can take it once it has the keyboard. */
58
+ export function usePendingChatPaneRequest(): ChatPaneRequest | null {
59
+ return useSyncExternalStore(subscribe, () => pending?.request ?? null);
60
+ }
@@ -1,6 +1,6 @@
1
1
  import { updatePaneInstance } from "../../../pane-settings";
2
- import { removePane } from "../../../layout/pane-manager";
3
- import type { AppConfig } from "../../../types/config";
2
+ import { isPaneInLayout, removePane } from "../../../layout/pane-manager";
3
+ import type { AppConfig, LayoutConfig, PaneInstanceConfig } from "../../../types/config";
4
4
  import { LAST_VISITED_CHAT_CHANNEL_KEY, normalizeChannelId } from "./channels";
5
5
 
6
6
  type ChatPaneSettings = Record<string, unknown>;
@@ -32,6 +32,36 @@ export function clearChatPaneTargetMessage(
32
32
  return nextSettings;
33
33
  }
34
34
 
35
+ function paneChannelId(instance: PaneInstanceConfig): string | null {
36
+ return typeof instance.settings?.channelId === "string" ? normalizeChannelId(instance.settings.channelId) : null;
37
+ }
38
+
39
+ /**
40
+ * The Chat pane the command bar shows a conversation in: the one already on
41
+ * it, else the focused one, else the one in front. Null when none is open, so
42
+ * the caller opens one.
43
+ */
44
+ export function pickChatPaneToReuse(
45
+ layout: LayoutConfig,
46
+ focusedPaneId: string | null,
47
+ channelId: string | null,
48
+ ): PaneInstanceConfig | null {
49
+ const chatPanes = layout.instances.filter((instance) => (
50
+ instance.paneId === "chat" && isPaneInLayout(layout, instance.instanceId)
51
+ ));
52
+ if (chatPanes.length === 0) return null;
53
+ const onChannel = channelId ? chatPanes.find((instance) => paneChannelId(instance) === channelId) : undefined;
54
+ if (onChannel) return onChannel;
55
+ const focused = chatPanes.find((instance) => instance.instanceId === focusedPaneId);
56
+ if (focused) return focused;
57
+ // A floating pane without a stacking order sits at the default of 50; docked panes sit below every one.
58
+ const zIndexOf = (instance: PaneInstanceConfig) => {
59
+ const entry = layout.floating.find((floating) => floating.instanceId === instance.instanceId);
60
+ return entry ? entry.zIndex ?? 50 : -1;
61
+ };
62
+ return [...chatPanes].sort((left, right) => zIndexOf(right) - zIndexOf(left))[0] ?? null;
63
+ }
64
+
35
65
  function setChatPaneJump(
36
66
  settings: ChatPaneSettings | undefined,
37
67
  channelId: string,
@@ -77,6 +77,14 @@ export function ChatPane({ focused, width, height }: PaneProps) {
77
77
  }, [dispatch, paneId, stateRef]);
78
78
  const [channelId, setLocalChannelId] = useState(initialChannelIdRef.current);
79
79
  const pendingChannelIdRef = useRef<string | null>(null);
80
+ // A channel set from outside the pane (the command bar, the unread list)
81
+ // usually arrives with focus. Taking it in the same render keeps the pane
82
+ // from showing the old channel focused for a frame, which marks it read.
83
+ const [followedChannelId, setFollowedChannelId] = useState(persistedChannelId);
84
+ if (followedChannelId !== persistedChannelId) {
85
+ setFollowedChannelId(persistedChannelId);
86
+ if (!pendingChannelIdRef.current && channelId !== persistedChannelId) setLocalChannelId(persistedChannelId);
87
+ }
80
88
 
81
89
  useEffect(() => {
82
90
  if (rawPaneChannelId) return;
@@ -4,22 +4,28 @@ import {
4
4
  type ASKGToolResultOutcome,
5
5
  type ASKGTransport,
6
6
  } from "../../../../api-client/askg";
7
- import type { ASKGToolExecutor } from "./executor";
7
+ import { toolCallRemainingMs, type ASKGToolExecutor, type ASKGToolPreview } from "./executor";
8
8
  import {
9
9
  activeTurn,
10
10
  askgReducer,
11
+ canRateTurn,
11
12
  EMPTY_ASKG_CONVERSATION,
12
13
  isTurnRunning,
14
+ NOT_APPROVED_IN_TIME_NOTE,
13
15
  requiresLocalConfirmation,
14
16
  type ASKGAction,
15
17
  type ASKGConversationState,
16
18
  type ASKGErrorState,
19
+ type ASKGTurnFeedback,
17
20
  } from "./model";
18
21
  import {
19
22
  ASKG_CLIENT_CAPABILITIES,
20
23
  ASKG_PROTOCOL_VERSION,
21
24
  type ASKGCapabilities,
22
25
  type ASKGClientDescriptor,
26
+ type ASKGFeedbackRating,
27
+ type ASKGFeedbackReason,
28
+ type ASKGFeedbackRequest,
23
29
  type ASKGSessionContext,
24
30
  type ASKGSessionStartResponse,
25
31
  type ASKGSseEvent,
@@ -37,6 +43,18 @@ const MAX_HISTORY_TURNS = 8;
37
43
  const DEFAULT_TURN_WALL_CLOCK_MS = 120_000;
38
44
  /** Sessions are renegotiated a little before they expire. */
39
45
  const SESSION_EXPIRY_GRACE_MS = 5_000;
46
+ /**
47
+ * A confirmation prompt closes this long before the server stops waiting for
48
+ * its call, so an approval still leaves time for the write and its result.
49
+ */
50
+ export const CONFIRMATION_CLOSE_MARGIN_MS = 2_000;
51
+
52
+ /**
53
+ * How a confirmation prompt ended. `expired` is this app's own deadline for
54
+ * the call; `abandoned` is the turn giving up on it (the call timed out on the
55
+ * server, the turn ended, was cancelled or lost its stream).
56
+ */
57
+ type ConfirmationAnswer = "approved" | "declined" | "expired" | "abandoned";
40
58
 
41
59
  export interface ASKGControllerManifest {
42
60
  tools: ClientToolManifest[];
@@ -104,6 +122,16 @@ function turnCapabilities(session: ASKGSessionStartResponse): ASKGCapabilities |
104
122
  return session.capabilities?.scripts === 1 ? { scripts: 1 } : null;
105
123
  }
106
124
 
125
+ /**
126
+ * Refusals that say ratings cannot work from here at all: signed out, no plan
127
+ * that reaches Ask Gloom, or a protocol this build does not speak. The control
128
+ * goes away rather than failing on every click.
129
+ */
130
+ function feedbackUnavailable(error: unknown): boolean {
131
+ return error instanceof ASKGTransportError
132
+ && (error.code === "unauthorized" || error.code === "tier_required" || error.code === "protocol");
133
+ }
134
+
107
135
  function errorState(error: unknown): ASKGErrorState {
108
136
  if (error instanceof ASKGTransportError) {
109
137
  return {
@@ -131,11 +159,13 @@ export class ASKGSessionController {
131
159
  private session: ASKGSessionStartResponse | null = null;
132
160
  private sessionRequest: Promise<ASKGSessionStartResponse> | null = null;
133
161
  private manifest: ASKGControllerManifest | null = null;
134
- private readonly confirmations = new Map<string, (approved: boolean) => void>();
135
- /** Calls whose turn ended while they were still waiting to be approved. */
136
- private readonly abandonedCalls = new Set<string>();
162
+ private readonly confirmations = new Map<string, (answer: ConfirmationAnswer) => void>();
137
163
  private readonly toolTasks = new Set<Promise<void>>();
138
164
  private turnAbort: AbortController | null = null;
165
+ /** Ratings of one answer go out in the order they were made. */
166
+ private readonly feedbackQueues = new Map<string, Promise<void>>();
167
+ /** The latest rating request per answer; an older answer never wins. */
168
+ private readonly feedbackVersions = new Map<string, number>();
139
169
  private disposed = false;
140
170
  private readonly now: () => number;
141
171
  private readonly createId: () => string;
@@ -188,6 +218,7 @@ export class ASKGSessionController {
188
218
  model: session.model,
189
219
  limits: session.limits,
190
220
  acceptedTools: session.acceptedTools,
221
+ feedback: session.capabilities?.feedback === 1,
191
222
  });
192
223
  return session;
193
224
  })();
@@ -266,6 +297,8 @@ export class ASKGSessionController {
266
297
  signal: abort.signal,
267
298
  onEvent: (event) => this.handleEvent(event),
268
299
  });
300
+ // The stream is over, so no approval can reach this turn any more.
301
+ this.abandonPendingConfirmations();
269
302
  // Tool calls delivered late in the stream may still be running.
270
303
  await Promise.allSettled([...this.toolTasks]);
271
304
  } catch (error) {
@@ -311,14 +344,14 @@ export class ASKGSessionController {
311
344
  }
312
345
 
313
346
  /**
314
- * Asks a failed question again. The failed turn is dropped rather than kept
315
- * above the retry, so a transcript reads as the conversation the user had
316
- * rather than as a list of attempts.
347
+ * Asks a failed or stopped question again. The attempt is dropped rather
348
+ * than kept above the retry, so a transcript reads as the conversation the
349
+ * user had rather than as a list of attempts.
317
350
  */
318
351
  async retryTurn(turnId: string): Promise<void> {
319
352
  if (this.disposed || isTurnRunning(this.state)) return;
320
353
  const turn = this.state.turns.find((entry) => entry.id === turnId);
321
- if (!turn || turn.status !== "error") return;
354
+ if (!turn || (turn.status !== "error" && turn.status !== "cancelled")) return;
322
355
  this.dispatch({ type: "drop-turn", turnId });
323
356
  await this.ask(turn.prompt);
324
357
  }
@@ -330,6 +363,13 @@ export class ASKGSessionController {
330
363
  this.abandonPendingConfirmations();
331
364
  return;
332
365
  }
366
+ // The server reports a delegated call it gave up on (timed out, or its
367
+ // script ended) like one it got a result for. A prompt still open for it
368
+ // closes: an approval could no longer reach the turn.
369
+ if (event.type === "tool-executed") {
370
+ this.settleConfirmation(event.toolCallId, "abandoned");
371
+ return;
372
+ }
333
373
  if (event.type !== "tool-call") return;
334
374
  const task = this.runToolCall(event).finally(() => {
335
375
  this.toolTasks.delete(task);
@@ -364,12 +404,43 @@ export class ASKGSessionController {
364
404
 
365
405
  try {
366
406
  let confirmed = false;
407
+ let confirmedChange: string | undefined;
367
408
  if (requiresLocalConfirmation(call)) {
368
- this.dispatch({ type: "tool-awaiting-confirmation", toolCallId: call.toolCallId });
369
- confirmed = await new Promise<boolean>((resolve) => {
370
- this.confirmations.set(call.toolCallId, resolve);
371
- });
372
- if (this.abandonedCalls.delete(call.toolCallId)) return;
409
+ const preview = await this.previewCall(call, signal);
410
+ // The turn ended or moved on while the app looked.
411
+ if (signal?.aborted || this.toolRowStatus(call.toolCallId) !== "pending") return;
412
+ if (preview?.kind === "refusal") {
413
+ await this.deliver(failure(preview.message));
414
+ return;
415
+ }
416
+ if (preview?.kind === "change") confirmedChange = preview.confirmKey;
417
+ // Nothing to approve: the operation re-checks and asks in the app itself if that changed.
418
+ if (preview?.kind === "no-change") {
419
+ confirmed = true;
420
+ } else {
421
+ this.dispatch({
422
+ type: "tool-awaiting-confirmation",
423
+ toolCallId: call.toolCallId,
424
+ ...(preview?.kind === "change" ? { preview: preview.summary } : {}),
425
+ });
426
+ const answer = await this.awaitConfirmation(
427
+ call.toolCallId,
428
+ startedAt + toolCallRemainingMs(call, startedAt),
429
+ );
430
+ if (answer === "abandoned") return;
431
+ if (answer === "expired") {
432
+ await this.deliver({
433
+ turnId: call.turnId,
434
+ toolCallId: call.toolCallId,
435
+ status: "timeout",
436
+ truncated: false,
437
+ elapsedMs: Math.max(0, this.now() - startedAt),
438
+ note: NOT_APPROVED_IN_TIME_NOTE,
439
+ });
440
+ return;
441
+ }
442
+ confirmed = answer === "approved";
443
+ }
373
444
  if (!confirmed) {
374
445
  await this.deliver({
375
446
  turnId: call.turnId,
@@ -393,6 +464,7 @@ export class ASKGSessionController {
393
464
  }
394
465
  const payload = await executor.execute(call, {
395
466
  confirmed: confirmed || !requiresLocalConfirmation(call),
467
+ ...(confirmedChange ? { confirmedChange } : {}),
396
468
  ...(signal ? { signal } : {}),
397
469
  });
398
470
  await this.deliver(payload);
@@ -405,6 +477,28 @@ export class ASKGSessionController {
405
477
  }
406
478
  }
407
479
 
480
+ /**
481
+ * The operation's own account of a call that needs approval, when it has
482
+ * one. Null keeps the server's description.
483
+ */
484
+ private async previewCall(call: ASKGToolCallEvent, signal?: AbortSignal): Promise<ASKGToolPreview | null> {
485
+ try {
486
+ const manifest = this.manifest ?? await this.options.loadManifest();
487
+ this.manifest = manifest;
488
+ return await this.options.getExecutor(manifest)?.preview?.(call, signal) ?? null;
489
+ } catch {
490
+ return null;
491
+ }
492
+ }
493
+
494
+ private toolRowStatus(toolCallId: string): string | undefined {
495
+ for (const turn of this.state.turns) {
496
+ const row = turn.tools.find((entry) => entry.toolCallId === toolCallId);
497
+ if (row) return row.status;
498
+ }
499
+ return undefined;
500
+ }
501
+
408
502
  /** Records a tool result locally, then posts it to the turn loop. */
409
503
  private async deliver(payload: ToolResultPayload): Promise<void> {
410
504
  this.dispatch({ type: "tool-result", payload });
@@ -424,25 +518,131 @@ export class ASKGSessionController {
424
518
  }
425
519
  }
426
520
 
427
- /** Answers a `user-data` or `broker` confirmation prompt. */
428
- resolveConfirmation(toolCallId: string, approved: boolean): void {
521
+ /**
522
+ * Waits for the person's answer to one call. The prompt closes on its own
523
+ * a little before the server stops waiting (`deadlineAt`, by this clock),
524
+ * so an approval always has time to land; an older server that waits less
525
+ * than the call declared says so in the frame, and is honoured the same way.
526
+ */
527
+ private awaitConfirmation(toolCallId: string, deadlineAt: number): Promise<ConfirmationAnswer> {
528
+ return new Promise<ConfirmationAnswer>((resolve) => {
529
+ const timer = setTimeout(
530
+ () => this.settleConfirmation(toolCallId, "expired"),
531
+ Math.max(0, deadlineAt - CONFIRMATION_CLOSE_MARGIN_MS - this.now()),
532
+ );
533
+ this.confirmations.set(toolCallId, (answer) => {
534
+ clearTimeout(timer);
535
+ resolve(answer);
536
+ });
537
+ });
538
+ }
539
+
540
+ /** Ends one prompt. Only the first answer counts; a later one does nothing. */
541
+ private settleConfirmation(toolCallId: string, answer: ConfirmationAnswer): void {
429
542
  const resolve = this.confirmations.get(toolCallId);
430
543
  if (!resolve) return;
431
544
  this.confirmations.delete(toolCallId);
432
- resolve(approved);
545
+ resolve(answer);
433
546
  }
434
547
 
435
- private rejectPendingConfirmations(): void {
436
- for (const [toolCallId, resolve] of [...this.confirmations]) {
437
- this.confirmations.delete(toolCallId);
438
- resolve(false);
439
- }
548
+ /** Answers a `user-data` or `broker` confirmation prompt. */
549
+ resolveConfirmation(toolCallId: string, approved: boolean): void {
550
+ this.settleConfirmation(toolCallId, approved ? "approved" : "declined");
440
551
  }
441
552
 
442
553
  /** Drops confirmations whose answer can no longer reach the turn. */
443
554
  private abandonPendingConfirmations(): void {
444
- for (const toolCallId of this.confirmations.keys()) this.abandonedCalls.add(toolCallId);
445
- this.rejectPendingConfirmations();
555
+ for (const toolCallId of [...this.confirmations.keys()]) {
556
+ this.settleConfirmation(toolCallId, "abandoned");
557
+ }
558
+ }
559
+
560
+ /**
561
+ * Rates one answer. The control shows the choice at once; a refusal puts the
562
+ * previous one back without a word, because a rating is not worth an error.
563
+ * A thumbs down keeps the reason it already had, a thumbs up drops it.
564
+ */
565
+ rateAnswer(turnId: string, rating: ASKGFeedbackRating): Promise<void> {
566
+ const current = this.state.turns.find((turn) => turn.id === turnId)?.feedback;
567
+ const reason = rating === "down" && current?.rating === "down" ? current.reason : null;
568
+ return this.sendFeedback(turnId, { rating, reason }, {
569
+ rating,
570
+ reason,
571
+ shared: current?.shared ?? false,
572
+ pending: "rating",
573
+ });
574
+ }
575
+
576
+ /** Says why an answer got a thumbs down. */
577
+ chooseFeedbackReason(turnId: string, reason: ASKGFeedbackReason): Promise<void> {
578
+ const current = this.state.turns.find((turn) => turn.id === turnId)?.feedback;
579
+ return this.sendFeedback(turnId, { rating: "down", reason }, {
580
+ rating: "down",
581
+ reason,
582
+ shared: current?.shared ?? false,
583
+ pending: "rating",
584
+ });
585
+ }
586
+
587
+ /**
588
+ * Sends one answer to Gloom with its rating. Only the consent travels: the
589
+ * platform copies the question, the answer and which tools ran from its own
590
+ * transcript, so nothing else on this machine can go with it.
591
+ */
592
+ shareAnswer(turnId: string): Promise<void> {
593
+ const current = this.state.turns.find((turn) => turn.id === turnId)?.feedback;
594
+ if (!current?.rating || current.shared) return Promise.resolve();
595
+ return this.sendFeedback(
596
+ turnId,
597
+ { rating: current.rating, reason: current.reason, share: true },
598
+ { rating: current.rating, reason: current.reason, shared: false, pending: "share" },
599
+ );
600
+ }
601
+
602
+ private sendFeedback(
603
+ turnId: string,
604
+ request: ASKGFeedbackRequest,
605
+ optimistic: ASKGTurnFeedback,
606
+ ): Promise<void> {
607
+ const turn = this.state.turns.find((entry) => entry.id === turnId);
608
+ if (this.disposed || !turn || !canRateTurn(this.state, turn) || !turn.remoteTurnId) {
609
+ return Promise.resolve();
610
+ }
611
+ const remoteTurnId = turn.remoteTurnId;
612
+ const previous = turn.feedback ? { ...turn.feedback, pending: null } : null;
613
+ const version = (this.feedbackVersions.get(turnId) ?? 0) + 1;
614
+ this.feedbackVersions.set(turnId, version);
615
+ this.dispatch({ type: "feedback", turnId, feedback: optimistic });
616
+
617
+ const send = async () => {
618
+ const latest = () => this.feedbackVersions.get(turnId) === version;
619
+ try {
620
+ const stored = await this.options.transport.sendFeedback(remoteTurnId, request);
621
+ if (!latest()) return;
622
+ if (!stored) {
623
+ // No answer of this person's under that id: nothing here can rate it.
624
+ this.dispatch({ type: "feedback", turnId, feedback: previous });
625
+ this.dispatch({ type: "feedback-unavailable" });
626
+ return;
627
+ }
628
+ this.dispatch({
629
+ type: "feedback",
630
+ turnId,
631
+ feedback: {
632
+ ...stored,
633
+ pending: null,
634
+ ...(request.share && !stored.shared ? { shareFailed: true } : {}),
635
+ },
636
+ });
637
+ } catch (error) {
638
+ if (!latest()) return;
639
+ this.dispatch({ type: "feedback", turnId, feedback: previous });
640
+ if (feedbackUnavailable(error)) this.dispatch({ type: "feedback-unavailable" });
641
+ }
642
+ };
643
+ const queued = (this.feedbackQueues.get(turnId) ?? Promise.resolve()).then(send);
644
+ this.feedbackQueues.set(turnId, queued);
645
+ return queued;
446
646
  }
447
647
 
448
648
  setExpanded(toolCallId: string, expanded: boolean): void {
@@ -46,6 +46,7 @@ export class ASKGConversationListStore {
46
46
  private persistence: PluginPersistence | null = null;
47
47
  private transport: ASKGTransport | null = null;
48
48
  private inFlight: Promise<void> | null = null;
49
+ private openConversationId: string | null = null;
49
50
 
50
51
  getSnapshot(): ASKGConversationListSnapshot {
51
52
  return this.snapshot;
@@ -126,6 +127,7 @@ export class ASKGConversationListStore {
126
127
  async delete(id: string): Promise<void> {
127
128
  const transport = this.transport;
128
129
  if (!transport) return;
130
+ if (this.openConversationId === id) this.openConversationId = null;
129
131
  const previous = this.snapshot.conversations;
130
132
  this.remove(id);
131
133
  try {
@@ -178,11 +180,30 @@ export class ASKGConversationListStore {
178
180
  this.persistence?.setState(WIDTH_STATE_KEY, width);
179
181
  }
180
182
 
183
+ /**
184
+ * The conversation an Ask Gloom pane last showed. Closing the pane (Esc Esc
185
+ * is two keys) must not lose the answer on screen, so the next pane this
186
+ * app session opens picks it up again. Kept in memory only: a fresh launch
187
+ * starts a fresh conversation, and every older one is in the list.
188
+ */
189
+ rememberOpen(id: string | null): void {
190
+ this.openConversationId = id;
191
+ }
192
+
193
+ rememberedOpen(): string | null {
194
+ const id = this.openConversationId;
195
+ if (!id) return null;
196
+ // A conversation deleted since is not brought back.
197
+ if (this.snapshot.loaded && !this.snapshot.conversations.some((conversation) => conversation.id === id)) return null;
198
+ return id;
199
+ }
200
+
181
201
  /** Test hook: drops the persisted handle, the transport and the rows. */
182
202
  reset(): void {
183
203
  this.persistence = null;
184
204
  this.transport = null;
185
205
  this.inFlight = null;
206
+ this.openConversationId = null;
186
207
  this.snapshot = EMPTY;
187
208
  }
188
209