gloomberb 0.4.0 → 0.5.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 (218) hide show
  1. package/README.md +2 -2
  2. package/package.json +1 -1
  3. package/src/app.tsx +184 -69
  4. package/src/cli/commands/ticker.ts +45 -15
  5. package/src/cli/helpers.ts +4 -2
  6. package/src/cli/registry.test.ts +42 -35
  7. package/src/cli.test.ts +4 -2
  8. package/src/components/chart/chart-control-hint.tsx +39 -0
  9. package/src/components/chart/chart-controller.test.ts +110 -0
  10. package/src/components/chart/chart-controller.ts +364 -2
  11. package/src/components/chart/chart-data.ts +177 -29
  12. package/src/components/chart/chart-indicator-selector.tsx +53 -0
  13. package/src/components/chart/chart-pane-settings.ts +20 -0
  14. package/src/components/chart/chart-renderer.ts +220 -30
  15. package/src/components/chart/chart-resolution.test.ts +67 -0
  16. package/src/components/chart/chart-resolution.ts +74 -4
  17. package/src/components/chart/chart-scroll.test.ts +69 -0
  18. package/src/components/chart/chart-scroll.ts +104 -0
  19. package/src/components/chart/chart-types.ts +12 -0
  20. package/src/components/chart/chart-viewport.test.ts +5 -1
  21. package/src/components/chart/chart-viewport.ts +1 -1
  22. package/src/components/chart/chart.test.ts +249 -10
  23. package/src/components/chart/comparison-chart-renderer.test.ts +71 -1
  24. package/src/components/chart/comparison-chart-renderer.ts +40 -3
  25. package/src/components/chart/comparison-stock-chart.tsx +218 -123
  26. package/src/components/chart/indicators/bands.test.ts +50 -0
  27. package/src/components/chart/indicators/bands.ts +29 -0
  28. package/src/components/chart/indicators/moving-averages.test.ts +54 -0
  29. package/src/components/chart/indicators/moving-averages.ts +42 -0
  30. package/src/components/chart/indicators/options.test.ts +32 -0
  31. package/src/components/chart/indicators/options.ts +107 -0
  32. package/src/components/chart/indicators/oscillators.test.ts +79 -0
  33. package/src/components/chart/indicators/oscillators.ts +92 -0
  34. package/src/components/chart/indicators/types.ts +36 -0
  35. package/src/components/chart/native/chart-rasterizer.ts +51 -0
  36. package/src/components/chart/native/kitty.test.ts +68 -0
  37. package/src/components/chart/stock-chart-renderer-switch.test.tsx +740 -9
  38. package/src/components/chart/stock-chart.test.ts +239 -0
  39. package/src/components/chart/stock-chart.tsx +2257 -372
  40. package/src/components/command-bar/command-bar.test.tsx +337 -5
  41. package/src/components/command-bar/command-bar.tsx +296 -120
  42. package/src/components/command-bar/helpers.ts +1 -1
  43. package/src/components/command-bar/root-shortcuts.ts +33 -4
  44. package/src/components/command-bar/view-model.test.ts +3 -3
  45. package/src/components/command-bar/view-model.ts +4 -4
  46. package/src/components/command-bar/workflow-ops.ts +10 -0
  47. package/src/components/layout/floating-pane.tsx +3 -1
  48. package/src/components/layout/header.tsx +5 -4
  49. package/src/components/layout/pane-sizing.ts +6 -0
  50. package/src/components/layout/pane.tsx +5 -1
  51. package/src/components/layout/shell.test.tsx +263 -32
  52. package/src/components/layout/shell.tsx +10 -6
  53. package/src/components/layout/status-bar.test.tsx +16 -7
  54. package/src/components/layout/status-bar.tsx +4 -1
  55. package/src/components/markdown-editor.tsx +1 -0
  56. package/src/components/pane-settings-dialog.tsx +13 -152
  57. package/src/components/pane-template-wizard.tsx +1 -0
  58. package/src/components/price-selector-dialog.tsx +12 -7
  59. package/src/components/ticker-badge-text.test.tsx +50 -0
  60. package/src/components/ticker-badge-text.tsx +17 -2
  61. package/src/components/ticker-badge.tsx +2 -2
  62. package/src/components/ticker-list-table.tsx +62 -2
  63. package/src/components/toggle-list.tsx +15 -2
  64. package/src/components/ui/data-table.tsx +82 -5
  65. package/src/components/ui/external-link.tsx +48 -11
  66. package/src/components/ui/fields.tsx +2 -1
  67. package/src/components/ui/index.ts +8 -1
  68. package/src/components/ui/multi-select-chips.tsx +69 -0
  69. package/src/components/ui/multi-select-dialog.tsx +267 -0
  70. package/src/components/ui/multi-select.ts +78 -0
  71. package/src/components/ui/ui.test.tsx +343 -1
  72. package/src/data/plugin-state-store.ts +30 -19
  73. package/src/data/resource-store.ts +133 -103
  74. package/src/data/session-store.ts +19 -12
  75. package/src/data/sqlite-cache.test.ts +37 -2
  76. package/src/data/sqlite-database.ts +8 -2
  77. package/src/data/sqlite-retry.test.ts +63 -0
  78. package/src/data/sqlite-retry.ts +66 -0
  79. package/src/data/ticker-store.ts +29 -18
  80. package/src/index.tsx +6 -1
  81. package/src/market-data/coordinator.test.ts +114 -5
  82. package/src/market-data/coordinator.ts +70 -1
  83. package/src/market-data/hooks.test.tsx +73 -2
  84. package/src/market-data/hooks.tsx +16 -4
  85. package/src/notifications/app-notifier.test.ts +177 -0
  86. package/src/notifications/app-notifier.ts +241 -0
  87. package/src/pane-settings.test.ts +2 -0
  88. package/src/plugins/builtin/ai/index.test.tsx +1 -1
  89. package/src/plugins/builtin/ai/screener-pane.test.tsx +2 -0
  90. package/src/plugins/builtin/ai/screener-pane.tsx +1 -0
  91. package/src/plugins/builtin/ai/ticker-context.ts +3 -2
  92. package/src/plugins/builtin/alerts/alert-engine.test.ts +90 -0
  93. package/src/plugins/builtin/alerts/alert-engine.ts +55 -0
  94. package/src/plugins/builtin/alerts/index.test.tsx +357 -0
  95. package/src/plugins/builtin/alerts/index.tsx +519 -0
  96. package/src/plugins/builtin/alerts/types.ts +14 -0
  97. package/src/plugins/builtin/analytics/index.test.tsx +300 -0
  98. package/src/plugins/builtin/analytics/index.tsx +775 -0
  99. package/src/plugins/builtin/analytics/metrics.test.ts +125 -0
  100. package/src/plugins/builtin/analytics/metrics.ts +155 -0
  101. package/src/plugins/builtin/ask-ai.test.tsx +2 -0
  102. package/src/plugins/builtin/chat-controller.test.ts +92 -18
  103. package/src/plugins/builtin/chat-controller.ts +40 -11
  104. package/src/plugins/builtin/chat.test.tsx +715 -4
  105. package/src/plugins/builtin/chat.tsx +420 -119
  106. package/src/plugins/builtin/comparison-chart.test.tsx +97 -57
  107. package/src/plugins/builtin/comparison-chart.tsx +1 -2
  108. package/src/plugins/builtin/correlation/compute.test.ts +147 -0
  109. package/src/plugins/builtin/correlation/compute.ts +115 -0
  110. package/src/plugins/builtin/correlation/index.tsx +385 -0
  111. package/src/plugins/builtin/correlation/plugin.test.ts +44 -0
  112. package/src/plugins/builtin/correlation/settings.test.ts +34 -0
  113. package/src/plugins/builtin/correlation/settings.ts +95 -0
  114. package/src/plugins/builtin/debug.tsx +36 -50
  115. package/src/plugins/builtin/earnings/earnings-cache.test.ts +181 -0
  116. package/src/plugins/builtin/earnings/earnings-cache.ts +136 -0
  117. package/src/plugins/builtin/earnings/earnings-data.test.ts +59 -0
  118. package/src/plugins/builtin/earnings/earnings-data.ts +50 -0
  119. package/src/plugins/builtin/earnings/index.tsx +337 -0
  120. package/src/plugins/builtin/econ/calendar-source.test.ts +219 -0
  121. package/src/plugins/builtin/econ/calendar-source.ts +121 -0
  122. package/src/plugins/builtin/econ/fred-client.test.ts +63 -0
  123. package/src/plugins/builtin/econ/fred-client.ts +79 -0
  124. package/src/plugins/builtin/econ/fred-series-map.ts +88 -0
  125. package/src/plugins/builtin/econ/index.tsx +999 -0
  126. package/src/plugins/builtin/econ/types.ts +13 -0
  127. package/src/plugins/builtin/fred-settings.ts +10 -0
  128. package/src/plugins/builtin/fx-matrix/index.tsx +178 -0
  129. package/src/plugins/builtin/fx-matrix/pairs.ts +30 -0
  130. package/src/plugins/builtin/help.test.tsx +1 -5
  131. package/src/plugins/builtin/help.tsx +1 -16
  132. package/src/plugins/builtin/insider/index.tsx +417 -0
  133. package/src/plugins/builtin/insider/insider-data.test.ts +55 -0
  134. package/src/plugins/builtin/insider/insider-data.ts +49 -0
  135. package/src/plugins/builtin/layout-manager.tsx +33 -16
  136. package/src/plugins/builtin/market-movers/index.tsx +573 -0
  137. package/src/plugins/builtin/market-movers/screener.test.ts +143 -0
  138. package/src/plugins/builtin/market-movers/screener.ts +105 -0
  139. package/src/plugins/builtin/options.tsx +4 -3
  140. package/src/plugins/builtin/portfolio-list/cli/commands.ts +11 -6
  141. package/src/plugins/builtin/portfolio-list/command-bar.ts +6 -3
  142. package/src/plugins/builtin/portfolio-list/header.tsx +3 -2
  143. package/src/plugins/builtin/portfolio-list/metrics.ts +22 -11
  144. package/src/plugins/builtin/portfolio-list/pane.tsx +3 -9
  145. package/src/plugins/builtin/portfolio-list/settings.ts +9 -0
  146. package/src/plugins/builtin/portfolio-list/table.tsx +3 -0
  147. package/src/plugins/builtin/portfolio-list.test.tsx +3 -1
  148. package/src/plugins/builtin/portfolio-metrics.test.ts +13 -1
  149. package/src/plugins/builtin/sec.tsx +114 -7
  150. package/src/plugins/builtin/sectors/index.tsx +359 -0
  151. package/src/plugins/builtin/sectors/sector-data.ts +18 -0
  152. package/src/plugins/builtin/ticker-detail/chart-tab.tsx +75 -13
  153. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +316 -80
  154. package/src/plugins/builtin/ticker-detail/quote-monitor.tsx +4 -6
  155. package/src/plugins/builtin/ticker-detail-chart-tab-switch.test.tsx +17 -12
  156. package/src/plugins/builtin/ticker-detail.test.tsx +3 -3
  157. package/src/plugins/builtin/world-indices/index.tsx +410 -0
  158. package/src/plugins/builtin/world-indices/indices.ts +52 -0
  159. package/src/plugins/builtin/yield-curve/index.tsx +242 -0
  160. package/src/plugins/builtin/yield-curve/treasury-data.test.ts +212 -0
  161. package/src/plugins/builtin/yield-curve/treasury-data.ts +107 -0
  162. package/src/plugins/catalog.ts +22 -0
  163. package/src/plugins/gridlock-notification.ts +15 -0
  164. package/src/plugins/ibkr/__snapshots__/trade-tab.test.tsx.snap +5 -5
  165. package/src/plugins/ibkr/gateway-service.test.ts +22 -0
  166. package/src/plugins/ibkr/gateway-service.ts +6 -0
  167. package/src/plugins/ibkr/index.test.tsx +1 -1
  168. package/src/plugins/ibkr/index.tsx +8 -2
  169. package/src/plugins/ibkr/trade-tab.tsx +23 -5
  170. package/src/plugins/ibkr/trade-utils.test.ts +1 -1
  171. package/src/plugins/ibkr/trade-utils.ts +7 -6
  172. package/src/plugins/ibkr/trading-pane.tsx +8 -7
  173. package/src/plugins/plugin-runtime.test.tsx +2 -0
  174. package/src/plugins/plugin-runtime.tsx +10 -0
  175. package/src/plugins/prediction-markets/controller-data.ts +129 -14
  176. package/src/plugins/prediction-markets/controller.ts +1 -1
  177. package/src/plugins/prediction-markets/detail/shared.tsx +7 -6
  178. package/src/plugins/prediction-markets/index.tsx +5 -1
  179. package/src/plugins/prediction-markets/pane.test.tsx +78 -0
  180. package/src/plugins/prediction-markets/pane.tsx +7 -3
  181. package/src/plugins/prediction-markets/plugin.test.tsx +48 -1
  182. package/src/plugins/prediction-markets/services/fetch.ts +17 -7
  183. package/src/plugins/prediction-markets/services/polymarket-adapter.ts +29 -11
  184. package/src/plugins/prediction-markets/services/polymarket-ws.ts +20 -0
  185. package/src/plugins/prediction-markets/test-helpers.tsx +22 -5
  186. package/src/plugins/registry.ts +45 -13
  187. package/src/sources/provider-router.test.ts +3 -2
  188. package/src/sources/sec-edgar.ts +13 -1
  189. package/src/sources/yahoo-finance.ts +75 -1
  190. package/src/state/app-context-selector.test.tsx +17 -1
  191. package/src/state/app-context.test.tsx +24 -0
  192. package/src/state/app-context.tsx +29 -6
  193. package/src/theme/colors.ts +5 -0
  194. package/src/theme/themes.ts +25 -0
  195. package/src/types/config.test.ts +107 -0
  196. package/src/types/config.ts +30 -1
  197. package/src/types/data-provider.ts +13 -0
  198. package/src/types/plugin.ts +35 -1
  199. package/src/updater.test.ts +2 -0
  200. package/src/utils/api-client.ts +12 -0
  201. package/src/utils/format.test.ts +11 -1
  202. package/src/utils/format.ts +86 -8
  203. package/src/utils/inline-content-tokenizer.test.ts +22 -0
  204. package/src/utils/inline-content-tokenizer.ts +76 -0
  205. package/src/utils/link-tokenizer.test.ts +27 -0
  206. package/src/utils/link-tokenizer.ts +93 -0
  207. package/src/utils/market-format.test.ts +109 -0
  208. package/src/utils/market-format.ts +299 -0
  209. package/src/utils/market-status.ts +3 -2
  210. package/src/utils/selection-clipboard.test.ts +43 -0
  211. package/src/utils/selection-clipboard.ts +88 -0
  212. package/src/utils/terminal-input-reset.test.ts +50 -0
  213. package/src/utils/terminal-input-reset.ts +24 -0
  214. package/src/utils/throttled-fetch.test.ts +145 -0
  215. package/src/utils/throttled-fetch.ts +212 -0
  216. package/src/utils/ticker-tokenizer.test.ts +31 -0
  217. package/src/utils/ticker-tokenizer.ts +7 -42
  218. package/src/version.ts +1 -1
@@ -1,8 +1,9 @@
1
1
  import { saveConfig } from "../../data/config-store";
2
2
  import { findPaneInstance, type LayoutConfig } from "../../types/config";
3
- import type { GloomPlugin, GloomPluginContext } from "../../types/plugin";
3
+ import type { AppNotificationRequest, GloomPlugin, GloomPluginContext } from "../../types/plugin";
4
4
  import type { AppAction } from "../../state/app-context";
5
5
  import { getSharedRegistry } from "../registry";
6
+ import { notifyGridlockComplete } from "../gridlock-notification";
6
7
  import {
7
8
  dockPane,
8
9
  floatPane,
@@ -25,6 +26,11 @@ export function setLayoutManagerDispatch(
25
26
  getStateRef = getState;
26
27
  }
27
28
 
29
+ export function clearLayoutManagerDispatch() {
30
+ dispatchRef = null;
31
+ getStateRef = null;
32
+ }
33
+
28
34
  function persistLayout(layout: LayoutConfig) {
29
35
  if (!dispatchRef) return;
30
36
  dispatchRef({ type: "PUSH_LAYOUT_HISTORY" });
@@ -49,6 +55,10 @@ export const layoutManagerPlugin: GloomPlugin = {
49
55
  description: "Pane layout management commands",
50
56
 
51
57
  setup(ctx) {
58
+ const notify = (body: string, options?: Omit<AppNotificationRequest, "body">) => {
59
+ ctx.notify({ body, ...options });
60
+ };
61
+
52
62
  ctx.registerCommand({
53
63
  id: "float-pane",
54
64
  label: "Float Pane",
@@ -63,7 +73,7 @@ export const layoutManagerPlugin: GloomPlugin = {
63
73
  const { layout, termWidth, termHeight, focusedPaneId } = getStateRef();
64
74
  const focusedPane = getFocusedPane(layout, focusedPaneId);
65
75
  if (!focusedPane || !isPaneDocked(layout, focusedPane.instanceId)) {
66
- ctx.showToast("Focus a docked pane to float it", { type: "info" });
76
+ notify("Focus a docked pane to float it", { type: "info" });
67
77
  return;
68
78
  }
69
79
 
@@ -88,7 +98,7 @@ export const layoutManagerPlugin: GloomPlugin = {
88
98
  const { layout, focusedPaneId } = getStateRef();
89
99
  const focusedPane = getFocusedPane(layout, focusedPaneId);
90
100
  if (!focusedPane || !layout.floating.some((entry) => entry.instanceId === focusedPane.instanceId)) {
91
- ctx.showToast("Focus a floating pane to dock it", { type: "info" });
101
+ notify("Focus a floating pane to dock it", { type: "info" });
92
102
  return;
93
103
  }
94
104
 
@@ -107,7 +117,7 @@ export const layoutManagerPlugin: GloomPlugin = {
107
117
  hidden: () => true,
108
118
  execute: async () => {
109
119
  ctx.openCommandBar("NP ");
110
- ctx.showToast("Choose a pane template to create", { type: "info" });
120
+ notify("Choose a pane template to create", { type: "info" });
111
121
  },
112
122
  });
113
123
 
@@ -116,12 +126,15 @@ export const layoutManagerPlugin: GloomPlugin = {
116
126
  label: "Gridlock All Windows",
117
127
  description: "Arrange all visible panes into a tiled grid",
118
128
  keywords: ["grid", "gridlock", "tile", "arrange", "windows", "layout"],
129
+ shortcut: "GL",
119
130
  category: "config",
120
131
  execute: async () => {
121
132
  if (!getStateRef) return;
122
133
  const { layout, termWidth, termHeight } = getStateRef();
123
134
  persistLayout(gridlockAllPanes(layout, { x: 0, y: 0, width: termWidth, height: termHeight }));
124
- ctx.showToast("Retiled all panes", { type: "success" });
135
+ notifyGridlockComplete(ctx.notify, () => {
136
+ dispatchRef?.({ type: "UNDO_LAYOUT" });
137
+ });
125
138
  },
126
139
  });
127
140
 
@@ -136,7 +149,7 @@ export const layoutManagerPlugin: GloomPlugin = {
136
149
  const { layout, focusedPaneId } = getStateRef();
137
150
  const focusedPane = getFocusedPane(layout, focusedPaneId);
138
151
  if (!focusedPane || !isPaneInLayout(layout, focusedPane.instanceId)) {
139
- ctx.showToast("Focus a pane to remove it", { type: "info" });
152
+ notify("Focus a pane to remove it", { type: "info" });
140
153
  return;
141
154
  }
142
155
  persistLayout(removePane(layout, focusedPane.instanceId));
@@ -153,11 +166,11 @@ export const layoutManagerPlugin: GloomPlugin = {
153
166
  execute: async (values) => {
154
167
  const name = values?.name?.trim();
155
168
  if (!name) {
156
- ctx.showToast("Layout name is required", { type: "error" });
169
+ notify("Layout name is required", { type: "error" });
157
170
  return;
158
171
  }
159
172
  dispatchRef?.({ type: "NEW_LAYOUT", name });
160
- ctx.showToast(`Layout "${name}" created`, { type: "success" });
173
+ notify(`Layout "${name}" created`, { type: "success" });
161
174
  },
162
175
  });
163
176
 
@@ -186,13 +199,13 @@ export const layoutManagerPlugin: GloomPlugin = {
186
199
  if (!registry) return;
187
200
  const config = registry.getConfigFn();
188
201
  if (config.layouts.length <= 1) {
189
- ctx.showToast("Can't delete the only layout", { type: "error" });
202
+ notify("Can't delete the only layout", { type: "error" });
190
203
  return;
191
204
  }
192
205
  const index = config.activeLayoutIndex;
193
206
  const name = config.layouts[index]!.name;
194
207
  dispatchRef?.({ type: "DELETE_LAYOUT", index });
195
- ctx.showToast(`Layout "${name}" deleted`, { type: "success" });
208
+ notify(`Layout "${name}" deleted`, { type: "success" });
196
209
  },
197
210
  });
198
211
 
@@ -206,13 +219,13 @@ export const layoutManagerPlugin: GloomPlugin = {
206
219
  execute: async (values) => {
207
220
  const name = values?.name?.trim();
208
221
  if (!name) {
209
- ctx.showToast("Name is required", { type: "error" });
222
+ notify("Name is required", { type: "error" });
210
223
  return;
211
224
  }
212
225
  const registry = getSharedRegistry();
213
226
  if (!registry) return;
214
227
  dispatchRef?.({ type: "RENAME_LAYOUT", index: registry.getConfigFn().activeLayoutIndex, name });
215
- ctx.showToast(`Layout renamed to "${name}"`, { type: "success" });
228
+ notify(`Layout renamed to "${name}"`, { type: "success" });
216
229
  },
217
230
  });
218
231
 
@@ -226,7 +239,7 @@ export const layoutManagerPlugin: GloomPlugin = {
226
239
  const registry = getSharedRegistry();
227
240
  if (!registry) return;
228
241
  dispatchRef?.({ type: "DUPLICATE_LAYOUT", index: registry.getConfigFn().activeLayoutIndex });
229
- ctx.showToast("Layout duplicated", { type: "success" });
242
+ notify("Layout duplicated", { type: "success" });
230
243
  },
231
244
  });
232
245
 
@@ -242,11 +255,11 @@ export const layoutManagerPlugin: GloomPlugin = {
242
255
  const focusedPane = getFocusedPane(layout, focusedPaneId);
243
256
  const dockedPaneIds = getDockedPaneIds(layout);
244
257
  if (dockedPaneIds.length < 2) {
245
- ctx.showToast("Need at least 2 docked panes to swap", { type: "info" });
258
+ notify("Need at least 2 docked panes to swap", { type: "info" });
246
259
  return;
247
260
  }
248
261
  if (!focusedPane || !isPaneDocked(layout, focusedPane.instanceId)) {
249
- ctx.showToast("Focus a docked pane to swap it", { type: "info" });
262
+ notify("Focus a docked pane to swap it", { type: "info" });
250
263
  return;
251
264
  }
252
265
 
@@ -257,8 +270,12 @@ export const layoutManagerPlugin: GloomPlugin = {
257
270
  }
258
271
 
259
272
  ctx.openCommandBar("LAY ");
260
- ctx.showToast("Choose a swap target from layout mode", { type: "info" });
273
+ notify("Choose a swap target from layout mode", { type: "info" });
261
274
  },
262
275
  });
263
276
  },
277
+
278
+ dispose() {
279
+ clearLayoutManagerDispatch();
280
+ },
264
281
  };