gloomberb 0.11.2 → 0.12.0

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 (531) hide show
  1. package/README.md +7 -4
  2. package/README.zh-CN.md +4 -2
  3. package/package.json +28 -1
  4. package/src/api-client/auth.ts +10 -0
  5. package/src/api-client/data.ts +108 -1
  6. package/src/api-client/index.test.ts +127 -0
  7. package/src/api-client/index.ts +134 -1
  8. package/src/api-client/normalizers.ts +39 -0
  9. package/src/api-client/paths.ts +85 -1
  10. package/src/api-client/types.ts +220 -0
  11. package/src/app/pane-runtime/index.tsx +15 -12
  12. package/src/app/pane-runtime/layout-placement.test.ts +27 -0
  13. package/src/app/pane-runtime/layout-placement.ts +13 -0
  14. package/src/app/pane-runtime/plugin-bindings.ts +62 -0
  15. package/src/app.tsx +60 -18
  16. package/src/architecture/browser-entry-graph.test.ts +96 -0
  17. package/src/brokers/profile-form.test.ts +25 -27
  18. package/src/brokers/test-broker.ts +68 -0
  19. package/src/capabilities/chart-series.ts +3 -2
  20. package/src/cli/commands/market.ts +2 -2
  21. package/src/cli/commands/plugins.ts +39 -11
  22. package/src/cli/desktop-pane-shot.ts +285 -16
  23. package/src/cli/index.ts +1 -1
  24. package/src/cli/pane-functions/capabilities.ts +61 -31
  25. package/src/cli/pane-functions/catalog.ts +16 -4
  26. package/src/cli/pane-functions/discovery.ts +1 -0
  27. package/src/cli/pane-functions/headless.test.ts +247 -0
  28. package/src/cli/pane-functions/headless.ts +423 -0
  29. package/src/cli/pane-functions/index.test.ts +9 -0
  30. package/src/cli/pane-functions/index.ts +6 -2
  31. package/src/cli/pane-functions/options.ts +27 -2
  32. package/src/cli/pane-functions/report.ts +4 -0
  33. package/src/cli/pane-functions/resolver.ts +26 -8
  34. package/src/cli/pane-functions/screenshot.test.ts +76 -0
  35. package/src/cli/pane-functions/screenshot.ts +236 -20
  36. package/src/cli/registry.ts +0 -22
  37. package/src/cli/restore-plugins.ts +34 -0
  38. package/src/cli/result.ts +7 -10
  39. package/src/components/chart/{static/chart → composite}/axis-overlays.test.tsx +3 -3
  40. package/src/components/chart/{static/chart → composite}/axis-overlays.tsx +6 -11
  41. package/src/components/chart/{static/chart → composite}/bitmap.ts +17 -3
  42. package/src/components/chart/composite/composite-chart.test.tsx +68 -20
  43. package/src/components/chart/composite/composite-chart.tsx +301 -204
  44. package/src/components/chart/composite/format.ts +8 -2
  45. package/src/components/chart/composite/interactions.test.ts +68 -102
  46. package/src/components/chart/composite/interactions.ts +214 -264
  47. package/src/components/chart/composite/price-axis-labels.test.ts +21 -0
  48. package/src/components/chart/{price-axis-labels.tsx → composite/price-axis-labels.tsx} +9 -4
  49. package/src/components/chart/composite/scene.ts +57 -3
  50. package/src/components/chart/composite/text-renderer.ts +3 -2
  51. package/src/components/chart/composite/time-scale.ts +138 -57
  52. package/src/components/chart/composite/types.ts +25 -1
  53. package/src/components/chart/core/data.ts +9 -13
  54. package/src/components/chart/core/date-window.ts +7 -1
  55. package/src/components/chart/core/pointer.ts +3 -0
  56. package/src/components/chart/core/types.ts +0 -45
  57. package/src/components/chart/native/chart-rasterizer.ts +0 -1
  58. package/src/components/chart/native/kitty/index.test.ts +0 -188
  59. package/src/components/chart/native/raster/crosshair.ts +6 -5
  60. package/src/components/chart/native/raster/primitives.ts +0 -23
  61. package/src/components/chart/native/renderer-selection.ts +81 -31
  62. package/src/components/chart/static/{chart/surface.test.tsx → chart-surface.test.tsx} +28 -80
  63. package/src/components/chart/static/chart-surface.tsx +150 -0
  64. package/src/components/chart/static/index.ts +8 -0
  65. package/src/components/chart/static/multi-line-chart-surface.tsx +51 -166
  66. package/src/components/chart/static/scatter-chart-surface.test.ts +30 -0
  67. package/src/components/chart/static/scatter-chart-surface.tsx +135 -34
  68. package/src/components/chart/static/series.ts +49 -0
  69. package/src/components/command-bar/action-runtime.ts +1 -3
  70. package/src/components/command-bar/assist/model.test.ts +17 -2
  71. package/src/components/command-bar/assist/model.ts +40 -9
  72. package/src/components/command-bar/commands/direct/index.ts +1 -1
  73. package/src/components/command-bar/commands/direct/runtime.ts +1 -1
  74. package/src/components/command-bar/commands/registry.ts +0 -11
  75. package/src/components/command-bar/helpers.test.ts +2 -2
  76. package/src/components/command-bar/helpers.ts +2 -6
  77. package/src/components/command-bar/keyboard-shortcuts.ts +0 -11
  78. package/src/components/command-bar/list/badge.test.ts +54 -0
  79. package/src/components/command-bar/list/badge.ts +62 -0
  80. package/src/components/command-bar/list/model.test.ts +103 -0
  81. package/src/components/command-bar/list/model.ts +61 -4
  82. package/src/components/command-bar/list/view.test.tsx +113 -0
  83. package/src/components/command-bar/list/view.tsx +147 -131
  84. package/src/components/command-bar/pane-templates/workflow.ts +1 -1
  85. package/src/components/command-bar/panel/body.tsx +51 -65
  86. package/src/components/command-bar/panel/index.tsx +48 -13
  87. package/src/components/command-bar/panel/layout.test.ts +139 -0
  88. package/src/components/command-bar/panel/layout.ts +65 -28
  89. package/src/components/command-bar/panel/native-surface.ts +24 -0
  90. package/src/components/command-bar/panel/prompt-binding.ts +54 -0
  91. package/src/components/command-bar/panel/runtime.ts +6 -3
  92. package/src/components/command-bar/panel/state.ts +41 -7
  93. package/src/components/command-bar/panel/types.ts +7 -1
  94. package/src/components/command-bar/routes/root/provider-search.ts +34 -15
  95. package/src/components/command-bar/routes/root/results.test.ts +161 -0
  96. package/src/components/command-bar/routes/root/results.ts +30 -28
  97. package/src/components/command-bar/routes/root/runtime.ts +37 -20
  98. package/src/components/command-bar/routes/root/search-providers.test.tsx +224 -0
  99. package/src/components/command-bar/routes/root/search-providers.ts +205 -0
  100. package/src/components/command-bar/routes/root/selection.ts +1 -12
  101. package/src/components/command-bar/routes/root/shortcuts.test.ts +8 -8
  102. package/src/components/command-bar/routes/ticker-search/actions.ts +10 -9
  103. package/src/components/command-bar/routes/ticker-search/results.test.ts +54 -1
  104. package/src/components/command-bar/routes/ticker-search/results.ts +60 -19
  105. package/src/components/command-bar/routes/ticker-search/route.ts +1 -0
  106. package/src/components/command-bar/routing/actions.ts +1 -81
  107. package/src/components/command-bar/routing/launch-request.ts +1 -1
  108. package/src/components/command-bar/routing/list-state.ts +6 -21
  109. package/src/components/command-bar/selection-runtime.ts +1 -1
  110. package/src/components/command-bar/surface/assist.test.tsx +14 -10
  111. package/src/components/command-bar/surface/environment.ts +8 -1
  112. package/src/components/command-bar/surface/index.test.tsx +84 -68
  113. package/src/components/command-bar/surface/index.tsx +33 -36
  114. package/src/components/command-bar/surface/test-harness.tsx +15 -3
  115. package/src/components/command-bar/theme-picker.tsx +43 -15
  116. package/src/components/command-bar/view-model.test.ts +53 -8
  117. package/src/components/command-bar/view-model.ts +43 -14
  118. package/src/components/command-bar/workflow/tickers.ts +1 -0
  119. package/src/components/command-bar/workflow/types.ts +1 -1
  120. package/src/components/data-table/export.test.ts +21 -0
  121. package/src/components/data-table/export.ts +21 -0
  122. package/src/components/data-table/view.test.tsx +45 -6
  123. package/src/components/data-table/view.tsx +55 -9
  124. package/src/components/index.ts +10 -2
  125. package/src/components/input-search-bar.test.tsx +36 -2
  126. package/src/components/input-search-bar.tsx +18 -1
  127. package/src/components/layout/header.test.tsx +57 -10
  128. package/src/components/layout/header.tsx +292 -149
  129. package/src/components/layout/market-summary.test.ts +81 -0
  130. package/src/components/layout/market-summary.ts +109 -0
  131. package/src/components/layout/shell/chrome.ts +96 -1
  132. package/src/components/layout/shell/index.tsx +11 -3
  133. package/src/components/layout/shell/menu.ts +9 -0
  134. package/src/components/layout/shell/pane/actions.ts +29 -0
  135. package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
  136. package/src/components/layout/shell/shortcuts.ts +3 -0
  137. package/src/components/layout/status-bar.test.tsx +9 -8
  138. package/src/components/layout/status-bar.tsx +85 -54
  139. package/src/components/onboarding/onboarding-frame.tsx +2 -26
  140. package/src/components/price-sparkline/index.ts +61 -34
  141. package/src/components/price-sparkline/view.tsx +1 -1
  142. package/src/components/sign-in-gate.test.tsx +128 -0
  143. package/src/components/sign-in-gate.tsx +149 -0
  144. package/src/components/speedometer-gauge/desktop.tsx +2 -12
  145. package/src/components/ticker/badge/list.tsx +17 -3
  146. package/src/components/ticker/list-table-view.tsx +6 -3
  147. package/src/components/ui/data-table/index.tsx +22 -4
  148. package/src/components/ui/data-table/opentui/index.tsx +165 -120
  149. package/src/components/ui/frame.tsx +28 -0
  150. package/src/components/ui/index.ts +3 -0
  151. package/src/components/ui/native-select.tsx +20 -10
  152. package/src/components/ui/select-button.tsx +138 -0
  153. package/src/components/ui/status.tsx +2 -2
  154. package/src/components/ui/table-layout.ts +1 -1
  155. package/src/components/use-double-click-activation.ts +7 -3
  156. package/src/core/app-services.ts +3 -3
  157. package/src/data/config/chart-settings.ts +4 -4
  158. package/src/data/config/layout.ts +12 -6
  159. package/src/data/config/store/index.test.ts +97 -0
  160. package/src/data/config/store/migrations.ts +41 -0
  161. package/src/data/config/store/normalize.ts +5 -3
  162. package/src/i18n/es.ts +6 -2
  163. package/src/i18n/ja.ts +6 -2
  164. package/src/i18n/ko.ts +6 -2
  165. package/src/i18n/zh-cn.ts +6 -2
  166. package/src/i18n/zh-tw.ts +6 -2
  167. package/src/layout-marketplace/gallery-terminal.tsx +126 -96
  168. package/src/layout-marketplace/gallery.test.tsx +65 -1
  169. package/src/layout-marketplace/pane-imagery.ts +1 -0
  170. package/src/layout-marketplace/payload.test.ts +17 -0
  171. package/src/layout-marketplace/payload.ts +40 -5
  172. package/src/market-data/coordinator/index.ts +3 -2
  173. package/src/market-data/coordinator/quotes.ts +173 -66
  174. package/src/market-data/coordinator/subscriptions.test.ts +215 -37
  175. package/src/pane-settings.ts +1 -1
  176. package/src/plugins/builtin/analytics/pane-model.ts +1 -1
  177. package/src/plugins/builtin/analytics/view.tsx +1 -1
  178. package/src/plugins/builtin/broker-manager/index.test.tsx +3 -2
  179. package/src/plugins/builtin/broker-manager/model.test.ts +2 -2
  180. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +16 -2
  181. package/src/plugins/builtin/chart-composer/cli-options.ts +12 -9
  182. package/src/plugins/builtin/chart-composer/pane.tsx +22 -8
  183. package/src/plugins/builtin/chart-composer/settings.ts +2 -13
  184. package/src/plugins/builtin/chat/content/composer.tsx +8 -4
  185. package/src/plugins/builtin/cloud/auth-dialog.tsx +14 -228
  186. package/src/plugins/builtin/cloud/auth-form.tsx +277 -0
  187. package/src/plugins/builtin/cloud/plugin.tsx +1 -0
  188. package/src/plugins/builtin/composite-plugins.ts +16 -1
  189. package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
  190. package/src/plugins/builtin/correlation/relationship/pane.tsx +2 -6
  191. package/src/plugins/builtin/correlation/relationship/view-model.ts +2 -2
  192. package/src/plugins/builtin/credit-conditions/index.test.tsx +12 -6
  193. package/src/plugins/builtin/credit-conditions/index.tsx +2 -21
  194. package/src/plugins/builtin/dividend-yield/index.tsx +1 -0
  195. package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
  196. package/src/plugins/builtin/earnings/index.tsx +1 -0
  197. package/src/plugins/builtin/earnings-calls/data.ts +223 -0
  198. package/src/plugins/builtin/earnings-calls/format.ts +49 -0
  199. package/src/plugins/builtin/earnings-calls/index.tsx +69 -0
  200. package/src/plugins/builtin/earnings-calls/pane.tsx +756 -0
  201. package/src/plugins/builtin/earnings-calls/prose.test.ts +36 -0
  202. package/src/plugins/builtin/earnings-calls/prose.ts +59 -0
  203. package/src/plugins/builtin/earnings-calls/transcript-view.tsx +334 -0
  204. package/src/plugins/builtin/econ/detail-view.tsx +1 -2
  205. package/src/plugins/builtin/econ/fred-series-map.ts +16 -1
  206. package/src/plugins/builtin/econ/index.tsx +3 -1
  207. package/src/plugins/builtin/econ-statistics/cache.ts +4 -0
  208. package/src/plugins/builtin/econ-statistics/client.ts +92 -0
  209. package/src/plugins/builtin/econ-statistics/defs.ts +66 -0
  210. package/src/plugins/builtin/econ-statistics/detail.tsx +154 -0
  211. package/src/plugins/builtin/econ-statistics/headless.test.ts +54 -0
  212. package/src/plugins/builtin/econ-statistics/headless.ts +171 -0
  213. package/src/plugins/builtin/econ-statistics/index.tsx +54 -0
  214. package/src/plugins/builtin/econ-statistics/pane.tsx +356 -0
  215. package/src/plugins/builtin/econ-statistics/stats.ts +522 -0
  216. package/src/plugins/builtin/econ-statistics/transform.test.ts +86 -0
  217. package/src/plugins/builtin/econ-statistics/transform.ts +85 -0
  218. package/src/plugins/builtin/econ-statistics/trend.ts +57 -0
  219. package/src/plugins/builtin/econ-statistics/view.ts +90 -0
  220. package/src/plugins/builtin/fear-greed/charts.tsx +7 -18
  221. package/src/plugins/builtin/fear-greed/data.ts +6 -1
  222. package/src/plugins/builtin/futures/index.tsx +1 -0
  223. package/src/plugins/builtin/fx-matrix/index.tsx +1 -0
  224. package/src/plugins/builtin/help/index.tsx +4 -0
  225. package/src/plugins/builtin/holders/index.tsx +1 -0
  226. package/src/plugins/builtin/insider/index.tsx +1 -0
  227. package/src/plugins/builtin/ipo-calendar/index.tsx +1 -0
  228. package/src/plugins/builtin/kelly-sizer/pane.tsx +1 -1
  229. package/src/plugins/builtin/kelly-sizer/sections.tsx +2 -3
  230. package/src/plugins/builtin/market-halts/index.tsx +1 -0
  231. package/src/plugins/builtin/market-movers/index.tsx +1 -0
  232. package/src/plugins/builtin/market-valuation/align.ts +122 -0
  233. package/src/plugins/builtin/market-valuation/cache.ts +32 -0
  234. package/src/plugins/builtin/market-valuation/chart-projection.ts +217 -0
  235. package/src/plugins/builtin/market-valuation/chart-series.ts +89 -0
  236. package/src/plugins/builtin/market-valuation/client.test.ts +141 -0
  237. package/src/plugins/builtin/market-valuation/client.ts +116 -0
  238. package/src/plugins/builtin/market-valuation/defs.ts +251 -0
  239. package/src/plugins/builtin/market-valuation/detail.tsx +159 -0
  240. package/src/plugins/builtin/market-valuation/headless.test.ts +58 -0
  241. package/src/plugins/builtin/market-valuation/headless.ts +170 -0
  242. package/src/plugins/builtin/market-valuation/index.tsx +64 -0
  243. package/src/plugins/builtin/market-valuation/indicators.ts +422 -0
  244. package/src/plugins/builtin/market-valuation/model.test.ts +350 -0
  245. package/src/plugins/builtin/market-valuation/model.ts +8 -0
  246. package/src/plugins/builtin/market-valuation/pane.test.tsx +247 -0
  247. package/src/plugins/builtin/market-valuation/pane.tsx +344 -0
  248. package/src/plugins/builtin/market-valuation/series.ts +12 -0
  249. package/src/plugins/builtin/market-valuation/settings.ts +38 -0
  250. package/src/plugins/builtin/market-valuation/sources.ts +130 -0
  251. package/src/plugins/builtin/market-valuation/trend.ts +89 -0
  252. package/src/plugins/builtin/market-valuation/view.ts +137 -0
  253. package/src/plugins/builtin/market-valuation/zone-scale/desktop.tsx +123 -0
  254. package/src/plugins/builtin/market-valuation/zone-scale/index.tsx +12 -0
  255. package/src/plugins/builtin/market-valuation/zone-scale/model.ts +60 -0
  256. package/src/plugins/builtin/market-valuation/zone-scale/terminal.tsx +94 -0
  257. package/src/plugins/builtin/news/wire/breaking/filters.test.ts +99 -0
  258. package/src/plugins/builtin/news/wire/breaking/filters.ts +110 -0
  259. package/src/plugins/builtin/news/wire/breaking/notifications.test.ts +157 -53
  260. package/src/plugins/builtin/news/wire/breaking/notifications.ts +91 -25
  261. package/src/plugins/builtin/news/wire/index.tsx +31 -44
  262. package/src/plugins/builtin/options/analytics.test.ts +83 -0
  263. package/src/plugins/builtin/options/analytics.ts +110 -0
  264. package/src/plugins/builtin/options/index.tsx +18 -2
  265. package/src/plugins/builtin/options/table.ts +121 -51
  266. package/src/plugins/builtin/options/types.ts +22 -15
  267. package/src/plugins/builtin/options/view.test.tsx +53 -1
  268. package/src/plugins/builtin/options/view.tsx +92 -41
  269. package/src/plugins/builtin/plugin-marketplace/feed.ts +80 -0
  270. package/src/plugins/builtin/plugin-marketplace/index.tsx +31 -0
  271. package/src/plugins/builtin/plugin-marketplace/model.test.ts +200 -0
  272. package/src/plugins/builtin/plugin-marketplace/model.ts +204 -0
  273. package/src/plugins/builtin/plugin-marketplace/pane.tsx +385 -0
  274. package/src/plugins/builtin/plugin-marketplace/store.ts +46 -0
  275. package/src/plugins/builtin/plugin-module.test.ts +2 -4
  276. package/src/plugins/builtin/plugin-module.ts +9 -8
  277. package/src/plugins/builtin/portfolio-list/index.tsx +1 -0
  278. package/src/plugins/builtin/research/index.tsx +4 -0
  279. package/src/plugins/builtin/research-search/command-bar-search.test.ts +81 -0
  280. package/src/plugins/builtin/research-search/command-bar-search.ts +175 -0
  281. package/src/plugins/builtin/research-search/data.ts +109 -0
  282. package/src/plugins/builtin/research-search/document-view.test.tsx +75 -0
  283. package/src/plugins/builtin/research-search/document-view.tsx +254 -0
  284. package/src/plugins/builtin/research-search/filter-bar.tsx +62 -0
  285. package/src/plugins/builtin/research-search/focus-handoff.ts +47 -0
  286. package/src/plugins/builtin/research-search/index.tsx +85 -0
  287. package/src/plugins/builtin/research-search/model.test.ts +40 -0
  288. package/src/plugins/builtin/research-search/model.ts +291 -0
  289. package/src/plugins/builtin/research-search/pane.test.tsx +241 -0
  290. package/src/plugins/builtin/research-search/pane.tsx +678 -0
  291. package/src/plugins/builtin/research-search/saved-view.tsx +171 -0
  292. package/src/plugins/builtin/research-search/snippet-text.tsx +35 -0
  293. package/src/plugins/builtin/research-search/snippet.test.ts +78 -0
  294. package/src/plugins/builtin/research-search/snippet.ts +134 -0
  295. package/src/plugins/builtin/scanner/flow-model.test.ts +11 -1
  296. package/src/plugins/builtin/scanner/flow-model.ts +29 -1
  297. package/src/plugins/builtin/scanner/flow-pane.tsx +78 -22
  298. package/src/plugins/builtin/scanner/index.ts +2 -0
  299. package/src/plugins/builtin/sec/index.tsx +1 -0
  300. package/src/plugins/builtin/sectors/index.tsx +1 -0
  301. package/src/plugins/builtin/shared/series-cache.ts +93 -0
  302. package/src/plugins/builtin/short-interest/index.tsx +1 -0
  303. package/src/plugins/builtin/short-interest/pane.tsx +1 -1
  304. package/src/plugins/builtin/thirteenf/index.tsx +1 -0
  305. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +3 -5
  306. package/src/plugins/builtin/ticker-detail/index.tsx +2 -14
  307. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +1 -1
  308. package/src/plugins/builtin/treasury-auctions/index.tsx +1 -0
  309. package/src/plugins/builtin/volatility/index.tsx +1 -1
  310. package/src/plugins/builtin/world-indices/index.tsx +1 -0
  311. package/src/plugins/builtin/world-venue-map/index.ts +27 -0
  312. package/src/plugins/builtin/world-venue-map/map.desktop.test.tsx +106 -0
  313. package/src/plugins/builtin/world-venue-map/map.tsx +481 -0
  314. package/src/plugins/builtin/world-venue-map/model.test.ts +85 -0
  315. package/src/plugins/builtin/world-venue-map/model.ts +268 -0
  316. package/src/plugins/builtin/world-venue-map/pane.tsx +300 -0
  317. package/src/plugins/builtin/world-venue-map/world-outlines.ts +2 -0
  318. package/src/plugins/builtin/yield-curve/index.tsx +1 -1
  319. package/src/plugins/bundle.test.ts +109 -0
  320. package/src/plugins/bundle.ts +139 -0
  321. package/src/plugins/catalog-backend.ts +6 -44
  322. package/src/plugins/catalog-browser.test.ts +1 -0
  323. package/src/plugins/catalog-browser.ts +12 -0
  324. package/src/plugins/catalog-manifest.test.ts +43 -0
  325. package/src/plugins/catalog-manifest.ts +92 -0
  326. package/src/plugins/catalog-ui.ts +20 -4
  327. package/src/plugins/catalog.ts +9 -2
  328. package/src/plugins/current-target.ts +28 -0
  329. package/src/plugins/host-contract.ts +37 -0
  330. package/src/plugins/host-link.ts +158 -0
  331. package/src/plugins/host-modules.ts +61 -0
  332. package/src/plugins/loader.ts +41 -22
  333. package/src/plugins/ownership.ts +1 -0
  334. package/src/plugins/prediction-markets/index.tsx +1 -0
  335. package/src/plugins/registry/context.ts +3 -0
  336. package/src/plugins/registry/contributions.ts +27 -0
  337. package/src/plugins/registry/index.test.ts +25 -0
  338. package/src/plugins/registry/index.ts +8 -0
  339. package/src/plugins/registry/pane-settings.test.ts +53 -0
  340. package/src/plugins/registry/pane-settings.ts +29 -3
  341. package/src/plugins/seed.test.ts +83 -0
  342. package/src/plugins/seed.ts +80 -0
  343. package/src/public/broker.ts +31 -0
  344. package/src/public/market-data.ts +9 -0
  345. package/src/public/pane-hooks.ts +57 -0
  346. package/src/public/public-api.test.ts +285 -0
  347. package/src/public/react.ts +62 -0
  348. package/src/public/test-support.ts +23 -0
  349. package/src/public/time-series.ts +8 -0
  350. package/src/public/utils.ts +77 -0
  351. package/src/remote/layout-helpers.ts +6 -8
  352. package/src/remote/resources.ts +2 -0
  353. package/src/remote/schema.ts +1 -0
  354. package/src/remote/semantic-tree.test.tsx +105 -0
  355. package/src/remote/semantic-tree.tsx +53 -35
  356. package/src/renderers/browser/main.tsx +6 -0
  357. package/src/renderers/browser/ui-host.tsx +11 -0
  358. package/src/renderers/cloudflare/worker.test.ts +19 -0
  359. package/src/renderers/cloudflare/worker.ts +1 -1
  360. package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -2
  361. package/src/renderers/electrobun/bun/external-plugins.ts +140 -0
  362. package/src/renderers/electrobun/bun/index.ts +6 -2
  363. package/src/renderers/electrobun/shared/protocol.ts +25 -0
  364. package/src/renderers/electrobun/view/build-assets.ts +0 -1
  365. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +51 -1
  366. package/src/renderers/electrobun/view/external-plugins.test.ts +45 -0
  367. package/src/renderers/electrobun/view/external-plugins.ts +63 -0
  368. package/src/renderers/electrobun/view/host/ascii-text.test.ts +48 -0
  369. package/src/renderers/electrobun/view/host/ascii-text.ts +11 -1
  370. package/src/renderers/electrobun/view/host/chart-surface.tsx +38 -32
  371. package/src/renderers/electrobun/view/host/mouse.ts +16 -2
  372. package/src/renderers/electrobun/view/main.tsx +27 -2
  373. package/src/renderers/electrobun/view/styles.css +5 -0
  374. package/src/renderers/electrobun/view/toast-host.tsx +18 -0
  375. package/src/renderers/electrobun/view/ui-host.tsx +3 -0
  376. package/src/renderers/opentui/chart-surface.tsx +5 -1
  377. package/src/renderers/opentui/host.tsx +20 -2
  378. package/src/renderers/opentui/interaction-performance.test.ts +79 -0
  379. package/src/renderers/opentui/interaction-performance.ts +188 -0
  380. package/src/renderers/opentui/start.tsx +26 -1
  381. package/src/renderers/opentui/test-utils.tsx +13 -0
  382. package/src/renderers/opentui/toast-host.tsx +26 -2
  383. package/src/renderers/opentui/ui-host.tsx +1 -0
  384. package/src/sources/provider-router/search.test.ts +191 -0
  385. package/src/sources/provider-router/search.ts +92 -39
  386. package/src/state/app/context/index.tsx +2 -0
  387. package/src/state/app/context/selector.test.tsx +33 -1
  388. package/src/state/hooks/quote-streaming.test.tsx +93 -0
  389. package/src/state/hooks/quote-streaming.ts +106 -30
  390. package/src/state/pane-table-export-registry.ts +50 -0
  391. package/src/theme/color-utils.ts +1 -1
  392. package/src/theme/colors.ts +50 -0
  393. package/src/theme/themes.test.ts +15 -2
  394. package/src/theme/themes.ts +19 -1
  395. package/src/tickers/search/index.test.ts +26 -0
  396. package/src/tickers/search/index.ts +42 -17
  397. package/src/tickers/search/ranking.ts +14 -0
  398. package/src/time-series/chart-data.test.ts +216 -0
  399. package/src/time-series/range.ts +12 -0
  400. package/src/time-series/resolution.test.ts +25 -26
  401. package/src/time-series/resolution.ts +44 -25
  402. package/src/time-series/resolve.ts +7 -0
  403. package/src/time-series/spec.ts +5 -5
  404. package/src/time-series/types.ts +3 -1
  405. package/src/time-series/use-chart-resolution.ts +5 -0
  406. package/src/types/config.ts +123 -3
  407. package/src/types/data-provider.ts +11 -0
  408. package/src/types/headless.ts +161 -0
  409. package/src/types/plugin.ts +104 -20
  410. package/src/ui/host.tsx +19 -1
  411. package/src/ui/index.tsx +1 -0
  412. package/src/ui/toast.tsx +8 -4
  413. package/src/utils/csv.test.ts +13 -0
  414. package/src/utils/csv.ts +37 -0
  415. package/src/utils/format.ts +35 -0
  416. package/src/utils/fuzzy-search.test.ts +94 -0
  417. package/src/utils/fuzzy-search.ts +81 -22
  418. package/src/utils/save-text-file.test.ts +24 -0
  419. package/src/utils/save-text-file.ts +36 -0
  420. package/src/utils/shortcut-labels.ts +14 -0
  421. package/src/components/chart/core/axis-format.ts +0 -157
  422. package/src/components/chart/core/index.test.ts +0 -1075
  423. package/src/components/chart/core/projection.ts +0 -357
  424. package/src/components/chart/core/render-utils.ts +0 -4
  425. package/src/components/chart/core/renderer.ts +0 -244
  426. package/src/components/chart/core/scene.ts +0 -180
  427. package/src/components/chart/core/time-axis.ts +0 -330
  428. package/src/components/chart/cursor-motion.ts +0 -47
  429. package/src/components/chart/indicators/types.ts +0 -26
  430. package/src/components/chart/market-session.ts +0 -176
  431. package/src/components/chart/multi-line/renderer.test.ts +0 -83
  432. package/src/components/chart/multi-line/renderer.ts +0 -161
  433. package/src/components/chart/multi-line/scene.ts +0 -188
  434. package/src/components/chart/native/raster/layout.ts +0 -129
  435. package/src/components/chart/native/raster/price-chart.ts +0 -244
  436. package/src/components/chart/rendering/chart-draw.ts +0 -270
  437. package/src/components/chart/rendering/geometry.ts +0 -95
  438. package/src/components/chart/rendering/pixel-buffer.ts +0 -267
  439. package/src/components/chart/scatter-chart-renderer.test.ts +0 -31
  440. package/src/components/chart/scatter-chart-renderer.ts +0 -223
  441. package/src/components/chart/static/chart/surface.tsx +0 -358
  442. package/src/components/command-bar/routes/root/article-results.test.ts +0 -83
  443. package/src/components/command-bar/routes/root/article-results.ts +0 -55
  444. package/src/plugins/builtin/news/wire/article-search.test.ts +0 -72
  445. package/src/plugins/builtin/news/wire/article-search.ts +0 -140
  446. package/src/plugins/builtin/substack/api/auth.ts +0 -185
  447. package/src/plugins/builtin/substack/api/cache.ts +0 -82
  448. package/src/plugins/builtin/substack/api/loaders.ts +0 -170
  449. package/src/plugins/builtin/substack/api/store.ts +0 -186
  450. package/src/plugins/builtin/substack/api/types.ts +0 -42
  451. package/src/plugins/builtin/substack/api.test.ts +0 -298
  452. package/src/plugins/builtin/substack/article-detail.tsx +0 -397
  453. package/src/plugins/builtin/substack/article-stack.tsx +0 -133
  454. package/src/plugins/builtin/substack/content.ts +0 -478
  455. package/src/plugins/builtin/substack/feed-tabs.tsx +0 -44
  456. package/src/plugins/builtin/substack/index.tsx +0 -49
  457. package/src/plugins/builtin/substack/login-view.tsx +0 -126
  458. package/src/plugins/builtin/substack/model.test.ts +0 -155
  459. package/src/plugins/builtin/substack/normalize.ts +0 -343
  460. package/src/plugins/builtin/substack/pane-footer.ts +0 -52
  461. package/src/plugins/builtin/substack/pane-state.ts +0 -170
  462. package/src/plugins/builtin/substack/pane.tsx +0 -547
  463. package/src/plugins/builtin/substack/read-state.ts +0 -30
  464. package/src/plugins/builtin/substack/table.ts +0 -111
  465. package/src/plugins/builtin/substack/types.ts +0 -71
  466. package/src/plugins/builtin/substack/utils.ts +0 -131
  467. package/src/plugins/builtin/ticker-detail/data-panes/provider-search.tsx +0 -229
  468. package/src/plugins/ibkr/account-cache.test.ts +0 -102
  469. package/src/plugins/ibkr/account-cache.ts +0 -24
  470. package/src/plugins/ibkr/broker-adapter.ts +0 -286
  471. package/src/plugins/ibkr/config.test.ts +0 -79
  472. package/src/plugins/ibkr/config.ts +0 -250
  473. package/src/plugins/ibkr/dialogs.tsx +0 -40
  474. package/src/plugins/ibkr/flex/index.test.ts +0 -264
  475. package/src/plugins/ibkr/flex/index.ts +0 -367
  476. package/src/plugins/ibkr/flex/statement-client.ts +0 -235
  477. package/src/plugins/ibkr/fundamental-parser.ts +0 -149
  478. package/src/plugins/ibkr/gateway/account-loaders.ts +0 -266
  479. package/src/plugins/ibkr/gateway/account-summary.ts +0 -164
  480. package/src/plugins/ibkr/gateway/client-lock.ts +0 -154
  481. package/src/plugins/ibkr/gateway/connection-events.ts +0 -114
  482. package/src/plugins/ibkr/gateway/connection.ts +0 -152
  483. package/src/plugins/ibkr/gateway/contracts.ts +0 -132
  484. package/src/plugins/ibkr/gateway/fundamentals.ts +0 -83
  485. package/src/plugins/ibkr/gateway/helpers.ts +0 -33
  486. package/src/plugins/ibkr/gateway/history-requests.ts +0 -158
  487. package/src/plugins/ibkr/gateway/history.ts +0 -120
  488. package/src/plugins/ibkr/gateway/instrument-lookup.ts +0 -117
  489. package/src/plugins/ibkr/gateway/market-data.ts +0 -345
  490. package/src/plugins/ibkr/gateway/order-execution.ts +0 -218
  491. package/src/plugins/ibkr/gateway/orders.ts +0 -63
  492. package/src/plugins/ibkr/gateway/price-normalization.test.ts +0 -44
  493. package/src/plugins/ibkr/gateway/price-normalization.ts +0 -50
  494. package/src/plugins/ibkr/gateway/quote-stream-controller.ts +0 -203
  495. package/src/plugins/ibkr/gateway/quote-stream.ts +0 -171
  496. package/src/plugins/ibkr/gateway/selection.ts +0 -51
  497. package/src/plugins/ibkr/gateway/service/index.test.ts +0 -675
  498. package/src/plugins/ibkr/gateway/service/index.ts +0 -429
  499. package/src/plugins/ibkr/gateway/service/lifecycle.ts +0 -191
  500. package/src/plugins/ibkr/gateway/service/manager.ts +0 -52
  501. package/src/plugins/ibkr/gateway/service/market-data.ts +0 -48
  502. package/src/plugins/ibkr/gateway/service/native-loader.ts +0 -12
  503. package/src/plugins/ibkr/gateway/service/native.ts +0 -543
  504. package/src/plugins/ibkr/gateway/timeouts.ts +0 -13
  505. package/src/plugins/ibkr/gateway/types.ts +0 -27
  506. package/src/plugins/ibkr/index.test.tsx +0 -162
  507. package/src/plugins/ibkr/index.tsx +0 -159
  508. package/src/plugins/ibkr/instance-selection.test.ts +0 -120
  509. package/src/plugins/ibkr/instance-selection.ts +0 -36
  510. package/src/plugins/ibkr/portfolio-performance.test.ts +0 -32
  511. package/src/plugins/ibkr/portfolio-performance.ts +0 -129
  512. package/src/plugins/ibkr/trade/badge.tsx +0 -28
  513. package/src/plugins/ibkr/trade/dialogs.tsx +0 -44
  514. package/src/plugins/ibkr/trade/preview-panel.tsx +0 -130
  515. package/src/plugins/ibkr/trade/tab/actions.tsx +0 -443
  516. package/src/plugins/ibkr/trade/tab/field-editors.tsx +0 -79
  517. package/src/plugins/ibkr/trade/tab/footer.ts +0 -53
  518. package/src/plugins/ibkr/trade/tab/header.tsx +0 -167
  519. package/src/plugins/ibkr/trade/tab/index.test.tsx +0 -178
  520. package/src/plugins/ibkr/trade/tab/index.tsx +0 -298
  521. package/src/plugins/ibkr/trade/tab/model.ts +0 -159
  522. package/src/plugins/ibkr/trade/tab/order-request.ts +0 -64
  523. package/src/plugins/ibkr/trade/tab/shortcuts.ts +0 -89
  524. package/src/plugins/ibkr/trade/tab/state-sync.ts +0 -86
  525. package/src/plugins/ibkr/trade/ticket-panel.tsx +0 -301
  526. package/src/plugins/ibkr/trade/utils.test.ts +0 -175
  527. package/src/plugins/ibkr/trade/utils.ts +0 -144
  528. package/src/plugins/ibkr/trading/pane-view.tsx +0 -237
  529. package/src/plugins/ibkr/trading/pane.tsx +0 -332
  530. package/src/plugins/ibkr/trading/state.test.ts +0 -109
  531. package/src/plugins/ibkr/trading/state.ts +0 -335
@@ -1,24 +0,0 @@
1
- import type { BrokerInstanceConfig } from "../../types/config";
2
- import type { CachePolicy } from "../../types/persistence";
3
- import { normalizeIbkrConfig } from "./config";
4
- import { fnv1aHashString } from "../../utils/hash";
5
-
6
- const FLEX_ACCOUNT_CACHE_POLICY = {
7
- staleMs: 6 * 60 * 60 * 1000,
8
- expireMs: 30 * 24 * 60 * 60 * 1000,
9
- } as const satisfies CachePolicy;
10
-
11
- const GATEWAY_ACCOUNT_CACHE_POLICY = {
12
- staleMs: 30 * 1000,
13
- expireMs: 7 * 24 * 60 * 60 * 1000,
14
- } as const satisfies CachePolicy;
15
-
16
- export function getIbkrAccountCacheSourceKey(instance: BrokerInstanceConfig): string {
17
- return fnv1aHashString(JSON.stringify(normalizeIbkrConfig(instance.config)));
18
- }
19
-
20
- export function getIbkrAccountCachePolicy(instance: BrokerInstanceConfig): CachePolicy {
21
- return normalizeIbkrConfig(instance.config).connectionMode === "gateway"
22
- ? GATEWAY_ACCOUNT_CACHE_POLICY
23
- : FLEX_ACCOUNT_CACHE_POLICY;
24
- }
@@ -1,286 +0,0 @@
1
- import type { BrokerAdapter, BrokerPosition } from "../../types/broker";
2
- import {
3
- buildPersistedIbkrGatewayConfig,
4
- buildIbkrConfigFromValues,
5
- IBKR_CONFIG_FIELDS,
6
- isFlexConfigured,
7
- isGatewayConfigured,
8
- normalizeIbkrConfig,
9
- type FlexQueryConfig,
10
- } from "./config";
11
- import { getIbkrAccountCachePolicy, getIbkrAccountCacheSourceKey } from "./account-cache";
12
- import { loadFlexStatement, parseFlexAccounts, parseFlexPositions } from "./flex";
13
- import { ibkrGatewayManager } from "./gateway/service";
14
- import { refreshGatewayData } from "./gateway/helpers";
15
- import { getIbkrPortfolioPerformance } from "./portfolio-performance";
16
-
17
- async function importFlexPositions(config: FlexQueryConfig): Promise<BrokerPosition[]> {
18
- const xml = await loadFlexStatement(config);
19
- return parseFlexPositions(xml);
20
- }
21
-
22
- export const ibkrBroker: BrokerAdapter = {
23
- id: "ibkr",
24
- name: "Interactive Brokers",
25
- configSchema: IBKR_CONFIG_FIELDS,
26
-
27
- async validate(instance) {
28
- const normalized = normalizeIbkrConfig(instance.config);
29
- return normalized.connectionMode === "gateway"
30
- ? isGatewayConfigured(instance.config)
31
- : isFlexConfigured(instance.config);
32
- },
33
-
34
- async importPositions(instance) {
35
- const normalized = normalizeIbkrConfig(instance.config);
36
- if (normalized.connectionMode === "gateway") {
37
- await refreshGatewayData(instance);
38
- return ibkrGatewayManager.getService(instance.id).getPositions(normalized.gateway);
39
- }
40
- return importFlexPositions(normalized.flex);
41
- },
42
-
43
- async importPortfolioSnapshot(instance) {
44
- const normalized = normalizeIbkrConfig(instance.config);
45
- if (normalized.connectionMode === "gateway") {
46
- const service = ibkrGatewayManager.getService(instance.id);
47
- await refreshGatewayData(instance);
48
- const [accounts, positions] = await Promise.all([
49
- service.getAccounts(normalized.gateway),
50
- service.getPositions(normalized.gateway),
51
- ]);
52
- return { accounts, positions };
53
- }
54
-
55
- const xml = await loadFlexStatement(normalized.flex);
56
- return {
57
- accounts: parseFlexAccounts(xml),
58
- positions: parseFlexPositions(xml),
59
- };
60
- },
61
-
62
- async connect(instance) {
63
- const normalized = normalizeIbkrConfig(instance.config);
64
- if (normalized.connectionMode !== "gateway") return;
65
- await ibkrGatewayManager.getService(instance.id).connect(normalized.gateway);
66
- },
67
-
68
- async disconnect(instance) {
69
- await ibkrGatewayManager.removeInstance(instance.id);
70
- },
71
-
72
- getStatus(instance) {
73
- const normalized = normalizeIbkrConfig(instance.config);
74
- if (normalized.connectionMode !== "gateway") {
75
- return {
76
- state: "disconnected",
77
- message: "Flex profiles sync on demand",
78
- mode: "flex",
79
- updatedAt: 0,
80
- };
81
- }
82
- return { ...ibkrGatewayManager.getSnapshot(instance.id).status, mode: "gateway" };
83
- },
84
-
85
- subscribeStatus(instance, listener) {
86
- return ibkrGatewayManager.subscribe(instance.id, listener);
87
- },
88
-
89
- getPersistedConfigUpdate(instance) {
90
- const normalized = normalizeIbkrConfig(instance.config);
91
- if (normalized.connectionMode !== "gateway") return null;
92
- const resolved = ibkrGatewayManager.getService(instance.id).getResolvedConnection();
93
- return resolved ? buildPersistedIbkrGatewayConfig(instance.config, resolved) : null;
94
- },
95
-
96
- getAccountCacheSourceKey: getIbkrAccountCacheSourceKey,
97
- getAccountCachePolicy: getIbkrAccountCachePolicy,
98
-
99
- getProfileActions(instance) {
100
- const normalized = normalizeIbkrConfig(instance.config);
101
- return [{
102
- id: "ibkr-console",
103
- label: "IBKR Console",
104
- paneId: "ibkr-trading",
105
- disabled: normalized.connectionMode !== "gateway",
106
- disabledReason: "IBKR Console is available for Gateway / TWS profiles.",
107
- }];
108
- },
109
-
110
- toConfigValues(instance) {
111
- const normalized = normalizeIbkrConfig(instance.config);
112
- return {
113
- connectionMode: normalized.connectionMode,
114
- token: normalized.flex.token,
115
- queryId: normalized.flex.queryId,
116
- endpoint: normalized.flex.endpoint,
117
- gatewaySetupMode: normalized.gatewaySetupMode,
118
- host: normalized.gateway.host,
119
- port: normalized.gateway.port,
120
- clientId: normalized.gateway.clientId,
121
- marketDataType: normalized.gateway.marketDataType,
122
- };
123
- },
124
-
125
- fromConfigValues(values, previous) {
126
- const next = buildIbkrConfigFromValues(values);
127
- const previousConfig = previous ? normalizeIbkrConfig(previous.config) : null;
128
- if (!previousConfig || next.connectionMode !== "gateway") return next as unknown as Record<string, unknown>;
129
-
130
- return {
131
- ...next,
132
- gateway: {
133
- ...next.gateway,
134
- marketDataType: next.gateway.marketDataType ?? previousConfig.gateway.marketDataType,
135
- lastSuccessfulPort: previousConfig.gateway.lastSuccessfulPort,
136
- lastSuccessfulClientId: previousConfig.gateway.lastSuccessfulClientId,
137
- },
138
- } as unknown as Record<string, unknown>;
139
- },
140
-
141
- async listAccounts(instance) {
142
- const normalized = normalizeIbkrConfig(instance.config);
143
- if (normalized.connectionMode === "gateway") {
144
- return ibkrGatewayManager.getService(instance.id).getAccounts(normalized.gateway);
145
- }
146
- const xml = await loadFlexStatement(normalized.flex);
147
- return parseFlexAccounts(xml);
148
- },
149
-
150
- async getPortfolioPerformance(instance, accountId) {
151
- return getIbkrPortfolioPerformance(instance, accountId);
152
- },
153
-
154
- async searchInstruments(query, instance) {
155
- const normalized = normalizeIbkrConfig(instance.config);
156
- if (normalized.connectionMode !== "gateway") return [];
157
- return (await ibkrGatewayManager.getService(instance.id).searchInstruments(query, normalized.gateway)).map((result) => ({
158
- ...result,
159
- brokerInstanceId: result.brokerInstanceId ?? instance.id,
160
- brokerLabel: result.brokerLabel ?? instance.label,
161
- brokerContract: result.brokerContract
162
- ? { ...result.brokerContract, brokerInstanceId: result.brokerContract.brokerInstanceId ?? instance.id }
163
- : undefined,
164
- }));
165
- },
166
-
167
- async getTickerFinancials(ticker, instance, exchange, instrument) {
168
- const normalized = normalizeIbkrConfig(instance.config);
169
- if (normalized.connectionMode !== "gateway") {
170
- throw new Error("Gateway mode is required for broker market data");
171
- }
172
- return ibkrGatewayManager.getService(instance.id).getTickerFinancials(ticker, normalized.gateway, exchange, instrument);
173
- },
174
-
175
- async getQuote(ticker, instance, exchange, instrument) {
176
- const normalized = normalizeIbkrConfig(instance.config);
177
- if (normalized.connectionMode !== "gateway") {
178
- throw new Error("Gateway mode is required for broker quotes");
179
- }
180
- return ibkrGatewayManager.getService(instance.id).getQuote(ticker, normalized.gateway, exchange, instrument);
181
- },
182
-
183
- async getPriceHistory(ticker, instance, exchange, range, instrument) {
184
- const normalized = normalizeIbkrConfig(instance.config);
185
- if (normalized.connectionMode !== "gateway") {
186
- throw new Error("Gateway mode is required for broker history");
187
- }
188
- return ibkrGatewayManager.getService(instance.id).getPriceHistory(ticker, normalized.gateway, exchange, range, instrument);
189
- },
190
-
191
- getChartResolutionSupport(ticker, instance, exchange, instrument) {
192
- const normalized = normalizeIbkrConfig(instance.config);
193
- if (normalized.connectionMode !== "gateway") {
194
- throw new Error("Gateway mode is required for broker history");
195
- }
196
- return ibkrGatewayManager.getService(instance.id).getChartResolutionSupport(
197
- ticker,
198
- normalized.gateway,
199
- exchange,
200
- instrument,
201
- );
202
- },
203
-
204
- async getPriceHistoryForResolution(ticker, instance, exchange, bufferRange, resolution, instrument) {
205
- const normalized = normalizeIbkrConfig(instance.config);
206
- if (normalized.connectionMode !== "gateway") {
207
- throw new Error("Gateway mode is required for broker history");
208
- }
209
- return ibkrGatewayManager.getService(instance.id).getPriceHistoryForResolution(
210
- ticker,
211
- normalized.gateway,
212
- exchange,
213
- bufferRange,
214
- resolution,
215
- instrument,
216
- );
217
- },
218
-
219
- async getDetailedPriceHistory(ticker, instance, exchange, startDate, endDate, barSize, instrument) {
220
- const normalized = normalizeIbkrConfig(instance.config);
221
- if (normalized.connectionMode !== "gateway") {
222
- throw new Error("Gateway mode is required for broker history");
223
- }
224
- return ibkrGatewayManager.getService(instance.id).getDetailedPriceHistory(
225
- ticker,
226
- normalized.gateway,
227
- exchange,
228
- startDate,
229
- endDate,
230
- barSize,
231
- instrument,
232
- );
233
- },
234
-
235
- subscribeQuotes(instance, targets, onQuote) {
236
- const normalized = normalizeIbkrConfig(instance.config);
237
- if (normalized.connectionMode !== "gateway") {
238
- return () => {};
239
- }
240
- return ibkrGatewayManager.getService(instance.id).subscribeQuotes(normalized.gateway, targets, onQuote);
241
- },
242
-
243
- async listOpenOrders(instance) {
244
- const normalized = normalizeIbkrConfig(instance.config);
245
- if (normalized.connectionMode !== "gateway") return [];
246
- return ibkrGatewayManager.getService(instance.id).listOpenOrders(normalized.gateway);
247
- },
248
-
249
- async listExecutions(instance) {
250
- const normalized = normalizeIbkrConfig(instance.config);
251
- if (normalized.connectionMode !== "gateway") return [];
252
- return ibkrGatewayManager.getService(instance.id).listExecutions(normalized.gateway);
253
- },
254
-
255
- async previewOrder(instance, request) {
256
- const normalized = normalizeIbkrConfig(instance.config);
257
- if (normalized.connectionMode !== "gateway") {
258
- throw new Error("Gateway mode is required for order preview");
259
- }
260
- return ibkrGatewayManager.getService(instance.id).previewOrder(normalized.gateway, request);
261
- },
262
-
263
- async placeOrder(instance, request) {
264
- const normalized = normalizeIbkrConfig(instance.config);
265
- if (normalized.connectionMode !== "gateway") {
266
- throw new Error("Gateway mode is required for trading");
267
- }
268
- return ibkrGatewayManager.getService(instance.id).placeOrder(normalized.gateway, request);
269
- },
270
-
271
- async modifyOrder(instance, orderId, request) {
272
- const normalized = normalizeIbkrConfig(instance.config);
273
- if (normalized.connectionMode !== "gateway") {
274
- throw new Error("Gateway mode is required for trading");
275
- }
276
- return ibkrGatewayManager.getService(instance.id).modifyOrder(normalized.gateway, orderId, request);
277
- },
278
-
279
- async cancelOrder(instance, orderId) {
280
- const normalized = normalizeIbkrConfig(instance.config);
281
- if (normalized.connectionMode !== "gateway") {
282
- throw new Error("Gateway mode is required for trading");
283
- }
284
- return ibkrGatewayManager.getService(instance.id).cancelOrder(normalized.gateway, orderId);
285
- },
286
- };
@@ -1,79 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
- import {
3
- buildIbkrConfigFromValues,
4
- IBKR_STATEMENT_URL,
5
- LEGACY_IBKR_STATEMENT_URL,
6
- normalizeIbkrConfig,
7
- } from "./config";
8
-
9
- describe("ibkr config helpers", () => {
10
- test("builds nested manual gateway config from flat wizard values", () => {
11
- const config = buildIbkrConfigFromValues({
12
- connectionMode: "gateway",
13
- gatewaySetupMode: "manual",
14
- host: "127.0.0.1",
15
- port: "4002",
16
- });
17
-
18
- expect(config.connectionMode).toBe("gateway");
19
- expect(config.gatewaySetupMode).toBe("manual");
20
- expect(config.gateway).toEqual({
21
- host: "127.0.0.1",
22
- port: 4002,
23
- clientId: undefined,
24
- lastSuccessfulPort: undefined,
25
- lastSuccessfulClientId: undefined,
26
- marketDataType: "auto",
27
- });
28
- });
29
-
30
- test("treats explicit port/client configs as manual at runtime", () => {
31
- const config = normalizeIbkrConfig({
32
- connectionMode: "gateway",
33
- host: "127.0.0.1",
34
- port: 4002,
35
- clientId: 1,
36
- });
37
-
38
- expect(config.gatewaySetupMode).toBe("manual");
39
- expect(config.gateway.port).toBe(4002);
40
- expect(config.gateway.clientId).toBe(1);
41
- });
42
-
43
- test("normalizes flat flex wizard values", () => {
44
- const config = normalizeIbkrConfig({
45
- token: "abc",
46
- queryId: "123",
47
- });
48
-
49
- expect(config.connectionMode).toBe("flex");
50
- expect(config.gatewaySetupMode).toBe("auto");
51
- expect(config.flex.token).toBe("abc");
52
- expect(config.flex.queryId).toBe("123");
53
- expect(config.flex.endpoint).toBe(IBKR_STATEMENT_URL);
54
- });
55
-
56
- test("migrates the legacy default Flex endpoint to the current IBKR endpoint", () => {
57
- const config = normalizeIbkrConfig({
58
- flex: {
59
- token: "abc",
60
- queryId: "123",
61
- endpoint: LEGACY_IBKR_STATEMENT_URL,
62
- },
63
- });
64
-
65
- expect(config.flex.endpoint).toBe(IBKR_STATEMENT_URL);
66
- });
67
-
68
- test("preserves custom non-default Flex endpoints", () => {
69
- const config = normalizeIbkrConfig({
70
- flex: {
71
- token: "abc",
72
- queryId: "123",
73
- endpoint: "https://example.com/custom/SendRequest",
74
- },
75
- });
76
-
77
- expect(config.flex.endpoint).toBe("https://example.com/custom/SendRequest");
78
- });
79
- });
@@ -1,250 +0,0 @@
1
- import type { BrokerConfigField } from "../../types/broker";
2
- import type { IbkrGatewayConfig, ResolvedIbkrGatewayConnection } from "./gateway/service";
3
-
4
- export const LEGACY_IBKR_STATEMENT_URL = "https://gdcdyn.interactivebrokers.com/Universal/servlet/FlexStatementService.SendRequest";
5
- export const IBKR_STATEMENT_URL = "https://ndcdyn.interactivebrokers.com/AccountManagement/FlexWebService/SendRequest";
6
-
7
- type IbkrConnectionMode = "flex" | "gateway";
8
- type IbkrGatewaySetupMode = "auto" | "manual";
9
-
10
- export interface FlexQueryConfig {
11
- token: string;
12
- queryId: string;
13
- endpoint?: string;
14
- }
15
-
16
- export interface IbkrConfig {
17
- connectionMode: IbkrConnectionMode;
18
- gatewaySetupMode: IbkrGatewaySetupMode;
19
- flex: FlexQueryConfig;
20
- gateway: IbkrGatewayConfig;
21
- }
22
-
23
- const DEFAULT_FLEX_CONFIG: FlexQueryConfig = {
24
- token: "",
25
- queryId: "",
26
- endpoint: IBKR_STATEMENT_URL,
27
- };
28
-
29
- const DEFAULT_GATEWAY_HOST = "127.0.0.1";
30
-
31
- const DEFAULT_GATEWAY_CONFIG: IbkrGatewayConfig = {
32
- host: DEFAULT_GATEWAY_HOST,
33
- marketDataType: "auto",
34
- };
35
-
36
- export const IBKR_CONFIG_FIELDS: BrokerConfigField[] = [
37
- {
38
- key: "connectionMode",
39
- label: "Connection Mode",
40
- type: "select",
41
- required: true,
42
- options: [
43
- { label: "Flex (read-only)", value: "flex", description: "Syncs via IBKR's Flex API. No software needed." },
44
- { label: "Gateway / TWS", value: "gateway", description: "Use IB Gateway or TWS for live data and trading." },
45
- ],
46
- },
47
- {
48
- key: "token",
49
- label: "Flex Token",
50
- type: "password",
51
- required: true,
52
- placeholder: "Your Flex Web Service token",
53
- dependsOn: { key: "connectionMode", value: "flex" },
54
- },
55
- {
56
- key: "queryId",
57
- label: "Query ID",
58
- type: "text",
59
- required: true,
60
- placeholder: "Numeric Flex Query ID",
61
- dependsOn: { key: "connectionMode", value: "flex" },
62
- },
63
- {
64
- key: "endpoint",
65
- label: "Endpoint",
66
- type: "text",
67
- required: false,
68
- placeholder: IBKR_STATEMENT_URL,
69
- dependsOn: { key: "connectionMode", value: "flex" },
70
- },
71
- {
72
- key: "gatewaySetupMode",
73
- label: "Connection Setup",
74
- type: "select",
75
- required: true,
76
- defaultValue: "auto",
77
- options: [
78
- {
79
- label: "Automatic",
80
- value: "auto",
81
- description: "Detect the local IBKR API port and choose a client ID automatically.",
82
- },
83
- {
84
- label: "Manual",
85
- value: "manual",
86
- description: "Specify the host and socket port yourself.",
87
- },
88
- ],
89
- dependsOn: { key: "connectionMode", value: "gateway" },
90
- },
91
- {
92
- key: "host",
93
- label: "Gateway Host",
94
- type: "text",
95
- required: true,
96
- placeholder: DEFAULT_GATEWAY_HOST,
97
- defaultValue: DEFAULT_GATEWAY_HOST,
98
- dependsOn: { key: "gatewaySetupMode", value: "manual" },
99
- },
100
- {
101
- key: "port",
102
- label: "Gateway Port",
103
- type: "number",
104
- required: true,
105
- placeholder: "4001, 4002, 7496, or 7497",
106
- dependsOn: { key: "gatewaySetupMode", value: "manual" },
107
- },
108
- ];
109
-
110
- function coerceOptionalNumber(value: unknown): number | undefined {
111
- if (typeof value === "number" && Number.isFinite(value)) return value;
112
- if (typeof value === "string" && value.trim()) {
113
- const parsed = Number(value);
114
- if (Number.isFinite(parsed)) return parsed;
115
- }
116
- return undefined;
117
- }
118
-
119
- function coerceString(value: unknown, fallback = ""): string {
120
- return typeof value === "string" ? value : fallback;
121
- }
122
-
123
- function normalizeFlexEndpoint(value: unknown): string {
124
- const endpoint = coerceString(value, DEFAULT_FLEX_CONFIG.endpoint).trim();
125
- if (!endpoint || endpoint === LEGACY_IBKR_STATEMENT_URL) return IBKR_STATEMENT_URL;
126
- return endpoint;
127
- }
128
-
129
- function getMode(value: unknown): IbkrConnectionMode {
130
- return value === "gateway" ? "gateway" : "flex";
131
- }
132
-
133
- function getGatewaySetupMode(value: unknown): IbkrGatewaySetupMode | undefined {
134
- return value === "manual" || value === "auto" ? value : undefined;
135
- }
136
-
137
- function inferGatewaySetupMode(
138
- connectionMode: IbkrConnectionMode,
139
- input: Record<string, unknown>,
140
- nestedGateway: Record<string, unknown>,
141
- ): IbkrGatewaySetupMode {
142
- if (connectionMode !== "gateway") return "auto";
143
-
144
- const explicit = getGatewaySetupMode(input.gatewaySetupMode ?? nestedGateway.setupMode);
145
- if (explicit) return explicit;
146
-
147
- const rawHost = coerceString(nestedGateway.host ?? input.host, DEFAULT_GATEWAY_HOST);
148
- const rawPort = coerceOptionalNumber(nestedGateway.port ?? input.port);
149
- const rawClientId = coerceOptionalNumber(nestedGateway.clientId ?? input.clientId);
150
-
151
- return rawHost !== DEFAULT_GATEWAY_HOST || rawPort != null || rawClientId != null
152
- ? "manual"
153
- : "auto";
154
- }
155
-
156
- export function normalizeIbkrConfig(raw?: Record<string, unknown>): IbkrConfig {
157
- const input = raw ?? {};
158
- const nestedFlex = typeof input.flex === "object" && input.flex ? input.flex as Record<string, unknown> : {};
159
- const nestedGateway = typeof input.gateway === "object" && input.gateway ? input.gateway as Record<string, unknown> : {};
160
- const inferredMode = input.connectionMode
161
- ?? (input.host || input.port || input.clientId || nestedGateway.host || nestedGateway.port || nestedGateway.clientId
162
- ? "gateway"
163
- : "flex");
164
- const connectionMode = getMode(inferredMode);
165
- const gatewaySetupMode = inferGatewaySetupMode(connectionMode, input, nestedGateway);
166
- const host = coerceString(nestedGateway.host ?? input.host, DEFAULT_GATEWAY_HOST);
167
- const port = coerceOptionalNumber(nestedGateway.port ?? input.port);
168
- const clientId = coerceOptionalNumber(nestedGateway.clientId ?? input.clientId);
169
-
170
- return {
171
- connectionMode,
172
- gatewaySetupMode,
173
- flex: {
174
- token: coerceString(nestedFlex.token ?? input.token),
175
- queryId: coerceString(nestedFlex.queryId ?? input.queryId),
176
- endpoint: normalizeFlexEndpoint(nestedFlex.endpoint ?? input.endpoint),
177
- },
178
- gateway: {
179
- host,
180
- port: gatewaySetupMode === "manual" ? port : undefined,
181
- clientId: gatewaySetupMode === "manual" ? clientId : undefined,
182
- lastSuccessfulPort: coerceOptionalNumber(nestedGateway.lastSuccessfulPort ?? input.lastSuccessfulPort),
183
- lastSuccessfulClientId: coerceOptionalNumber(nestedGateway.lastSuccessfulClientId ?? input.lastSuccessfulClientId),
184
- marketDataType: coerceString(
185
- nestedGateway.marketDataType ?? input.marketDataType,
186
- DEFAULT_GATEWAY_CONFIG.marketDataType,
187
- ) as IbkrGatewayConfig["marketDataType"],
188
- },
189
- };
190
- }
191
-
192
- export function buildIbkrConfigFromValues(values: Record<string, unknown>): IbkrConfig {
193
- const normalized = normalizeIbkrConfig(values);
194
- return {
195
- connectionMode: normalized.connectionMode,
196
- gatewaySetupMode: normalized.gatewaySetupMode,
197
- flex: normalized.flex,
198
- gateway: normalized.gateway,
199
- };
200
- }
201
-
202
- export function getGatewayConfig(raw?: Record<string, unknown>): IbkrGatewayConfig {
203
- return normalizeIbkrConfig(raw).gateway;
204
- }
205
-
206
- export function isGatewayConfigured(raw?: Record<string, unknown>): boolean {
207
- const config = normalizeIbkrConfig(raw);
208
- return config.connectionMode === "gateway"
209
- && !!config.gateway.host
210
- && (config.gatewaySetupMode !== "manual" || Number.isFinite(config.gateway.port));
211
- }
212
-
213
- export function isFlexConfigured(raw?: Record<string, unknown>): boolean {
214
- const config = normalizeIbkrConfig(raw);
215
- return config.connectionMode === "flex"
216
- && !!config.flex.token
217
- && !!config.flex.queryId;
218
- }
219
-
220
- export function buildPersistedIbkrGatewayConfig(
221
- raw: Record<string, unknown> | undefined,
222
- resolved: ResolvedIbkrGatewayConnection,
223
- ): Record<string, unknown> | null {
224
- const normalized = normalizeIbkrConfig(raw);
225
- if (normalized.connectionMode !== "gateway") return null;
226
-
227
- if (
228
- normalized.gateway.lastSuccessfulPort === resolved.port
229
- && normalized.gateway.lastSuccessfulClientId === resolved.clientId
230
- ) {
231
- return null;
232
- }
233
-
234
- const gateway: Record<string, unknown> = {
235
- host: normalized.gateway.host,
236
- marketDataType: normalized.gateway.marketDataType,
237
- lastSuccessfulPort: resolved.port,
238
- lastSuccessfulClientId: resolved.clientId,
239
- };
240
-
241
- if (normalized.gateway.port != null) gateway.port = normalized.gateway.port;
242
- if (normalized.gateway.clientId != null) gateway.clientId = normalized.gateway.clientId;
243
-
244
- return {
245
- connectionMode: normalized.connectionMode,
246
- gatewaySetupMode: normalized.gatewaySetupMode,
247
- flex: normalized.flex,
248
- gateway,
249
- };
250
- }
@@ -1,40 +0,0 @@
1
- import { Box, Input, Text } from "../../ui";
2
- import { TextAttributes } from "../../ui";
3
- import { type InputRenderable } from "../../ui";
4
- import { useEffect, useRef, useState } from "react";
5
- import { type PromptContext } from "../../ui/dialog";
6
- import type { WizardStep } from "../../types/plugin";
7
- import { colors } from "../../theme/colors";
8
-
9
- export { ChoiceDialog } from "../../components";
10
-
11
- export function InputDialog({ resolve, step }: PromptContext<string> & { step: WizardStep }) {
12
- const inputRef = useRef<InputRenderable>(null);
13
- const [value, setValue] = useState("");
14
-
15
- useEffect(() => {
16
- inputRef.current?.focus?.();
17
- }, []);
18
-
19
- return (
20
- <Box flexDirection="column">
21
- <Text attributes={TextAttributes.BOLD} fg={colors.text}>{step.label}</Text>
22
- <Box height={1} />
23
- {step.body?.map((line, index) => (
24
- <Text key={index} fg={colors.textDim}>{line || " "}</Text>
25
- ))}
26
- <Box height={1} />
27
- <Input
28
- ref={inputRef}
29
- focused
30
- placeholder={step.placeholder || ""}
31
- textColor={colors.text}
32
- placeholderColor={colors.textDim}
33
- backgroundColor={colors.bg}
34
- onInput={(nextValue: string) => setValue(nextValue)}
35
- onChange={(nextValue: string) => setValue(nextValue)}
36
- onSubmit={() => resolve(value.trim())}
37
- />
38
- </Box>
39
- );
40
- }