gloomberb 0.17.4 → 0.17.6
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.
- package/package.json +3 -1
- package/patches/electrobun@1.18.1.patch +80 -0
- package/src/api-client/chat.ts +9 -0
- package/src/api-client/commodity-balances.ts +77 -0
- package/src/api-client/data.ts +35 -3
- package/src/api-client/earnings.ts +10 -0
- package/src/api-client/index.ts +5 -0
- package/src/api-client/insider-signals.ts +75 -0
- package/src/api-client/market-discovery.ts +1 -1
- package/src/api-client/normalizers.ts +1 -0
- package/src/api-client/paths.ts +9 -0
- package/src/api-client/research-activity.ts +10 -3
- package/src/api-client/socket.ts +10 -0
- package/src/api-client/types.ts +25 -1
- package/src/app/pane-runtime/ticker-open-runtime.ts +2 -1
- package/src/app/runtime/broker-import.ts +23 -21
- package/src/app/runtime/plugin-bindings.ts +13 -7
- package/src/app/runtime/update.ts +64 -4
- package/src/app.tsx +2 -0
- package/src/architecture/core-builtin-allowlist.json +2 -10
- package/src/ask-gloom/pane-context.ts +11 -1
- package/src/brokers/broker-portfolio-sync.ts +66 -0
- package/src/brokers/sync-broker-instance.ts +75 -41
- package/src/cli/commands/market.ts +101 -34
- package/src/cli/commands/options-chain.ts +20 -6
- package/src/cli/commands/overview.ts +54 -13
- package/src/cli/commands/search.ts +1 -1
- package/src/cli/commands/system.ts +19 -1
- package/src/cli/commands/ticker.ts +24 -4
- package/src/cli/context.ts +13 -0
- package/src/cli/errors.ts +15 -2
- package/src/cli/fx-pair.ts +77 -0
- package/src/cli/glossary.ts +34 -4
- package/src/cli/history-rows.ts +25 -11
- package/src/cli/index.ts +30 -12
- package/src/cli/listing-arg.ts +61 -138
- package/src/cli/listing-suggestion.ts +3 -21
- package/src/cli/pane-functions/catalog.ts +50 -0
- package/src/cli/pane-functions/freshness.ts +44 -9
- package/src/cli/pane-functions/function-help.ts +9 -9
- package/src/cli/pane-functions/headless.ts +19 -7
- package/src/cli/pane-functions/index.ts +63 -5
- package/src/cli/pane-functions/market-session.ts +18 -3
- package/src/cli/pane-functions/resolver.ts +29 -8
- package/src/cli/pane-functions/screenshot.ts +2 -0
- package/src/cli/report-tables.ts +11 -4
- package/src/cli/result.ts +2 -0
- package/src/cli/series-search.ts +6 -1
- package/src/cli/ticker-resolution.ts +1 -2
- package/src/cli/unknown-command.ts +18 -0
- package/src/components/chart/composite/composite-chart.tsx +80 -19
- package/src/components/chart/composite/format.ts +17 -0
- package/src/components/chart/composite/legend.tsx +26 -15
- package/src/components/chart/composite/panel-labels.ts +38 -0
- package/src/components/chart/composite/panel-series.ts +1 -0
- package/src/components/chart/composite/panel-surface.tsx +25 -7
- package/src/components/chart/composite/price-axis-labels.tsx +16 -3
- package/src/components/chart/composite/scene.ts +60 -2
- package/src/components/chart/composite/series-axis-tags.tsx +67 -0
- package/src/components/chart/composite/tools.ts +2 -2
- package/src/components/chart/composite/types.ts +28 -0
- package/src/components/chart/core/view-reset.ts +46 -0
- package/src/components/command-bar/commands/collection.ts +1 -1
- package/src/components/command-bar/commands/direct/index.ts +48 -1
- package/src/components/command-bar/commands/registry.ts +8 -0
- package/src/components/command-bar/list/model.ts +7 -0
- package/src/components/command-bar/pane-templates/workflow.ts +5 -0
- package/src/components/command-bar/panel/prompt-binding.ts +8 -0
- package/src/components/command-bar/routes/root/command-items.ts +17 -2
- package/src/components/command-bar/routes/root/pick-prefetch.ts +38 -0
- package/src/components/command-bar/routes/root/provider-search.ts +6 -0
- package/src/components/command-bar/routes/root/runtime.ts +3 -0
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +3 -1
- package/src/components/command-bar/routes/root/shortcut-items.ts +1 -1
- package/src/components/command-bar/routes/ticker-search/actions.ts +34 -0
- package/src/components/command-bar/surface/index.tsx +7 -1
- package/src/components/command-bar/workflow/collection-actions.ts +6 -5
- package/src/components/command-bar/workflow/ops.ts +8 -5
- package/src/components/command-bar/workflow/pane-reuse.ts +3 -2
- package/src/components/command-bar/workflow/tickers.ts +1 -1
- package/src/components/form-modal/confirm.tsx +1 -0
- package/src/components/form-modal/request.ts +2 -0
- package/src/components/layout/detached-pane-shell.tsx +6 -1
- package/src/components/layout/pane/content.tsx +11 -8
- package/src/components/layout/pane/sidebar.tsx +24 -11
- package/src/components/layout/pane/ticker-fate-gate.tsx +56 -0
- package/src/components/layout/shell/index.tsx +5 -1
- package/src/components/layout/shell/menu.ts +8 -0
- package/src/components/layout/shell/pane/capture.ts +29 -12
- package/src/components/onboarding/wizard-model.ts +1 -1
- package/src/components/onboarding/wizard-positions.ts +18 -10
- package/src/components/ticker/badge/format.ts +64 -15
- package/src/components/ticker/badge/index.tsx +32 -11
- package/src/components/ticker/badge/list.tsx +4 -3
- package/src/components/ticker/badge/text.tsx +2 -2
- package/src/components/ticker/list-table-view.tsx +8 -1
- package/src/components/ui/confirm-dialog.tsx +30 -4
- package/src/components/ui/data-table/opentui/index.tsx +61 -20
- package/src/components/ui/data-table/opentui/model.ts +104 -0
- package/src/components/ui/fields.tsx +5 -0
- package/src/components/ui/inline-quick-add.tsx +4 -1
- package/src/components/ui/query-bar-keys.tsx +29 -5
- package/src/components/ui/query-bar.tsx +29 -4
- package/src/components/ui/windowed-list.tsx +27 -0
- package/src/data/config/store/normalize.ts +8 -0
- package/src/docs/snapshot.json +248 -5
- package/src/i18n/es.ts +3 -1
- package/src/i18n/ja.ts +3 -1
- package/src/i18n/ko.ts +3 -1
- package/src/i18n/zh-cn.ts +3 -1
- package/src/i18n/zh-tw.ts +3 -1
- package/src/layout-marketplace/cloud.ts +16 -5
- package/src/layout-marketplace/gallery.tsx +4 -4
- package/src/layout-marketplace/linked-sync.ts +9 -3
- package/src/layout-marketplace/linked.ts +24 -3
- package/src/layout-marketplace/model.ts +39 -4
- package/src/market-data/coordinator/events.ts +5 -1
- package/src/market-data/coordinator/index.ts +38 -1
- package/src/market-data/coordinator/quotes.ts +4 -0
- package/src/market-data/futures-contract.ts +53 -0
- package/src/market-data/hooks.tsx +225 -30
- package/src/market-data/market/bar-period.ts +71 -0
- package/src/market-data/market/format.ts +14 -2
- package/src/market-data/market/freshness.ts +28 -1
- package/src/market-data/market/status.ts +152 -13
- package/src/market-data/model-dividend-yield.ts +76 -0
- package/src/market-data/quotes/freshness.ts +30 -1
- package/src/{plugins/builtin/portfolio-list → market-data/quotes}/live-valuation.ts +6 -6
- package/src/market-data/quotes/regular-session-valuation.ts +32 -1
- package/src/plugins/builtin/analytics/metrics.ts +8 -4
- package/src/plugins/builtin/analytics/risk-headless.ts +12 -5
- package/src/plugins/builtin/analytics/risk-model.ts +74 -15
- package/src/plugins/builtin/analytics/risk-pane.tsx +6 -6
- package/src/plugins/builtin/broker-manager/detail.tsx +2 -2
- package/src/plugins/builtin/broker-manager/model.ts +2 -2
- package/src/plugins/builtin/builtin-plugin-meta.ts +0 -1
- package/src/plugins/builtin/chart-composer/editor/controller.ts +14 -10
- package/src/plugins/builtin/chart-composer/formula.ts +233 -0
- package/src/plugins/builtin/chart-composer/headless.ts +27 -2
- package/src/plugins/builtin/chart-composer/index.tsx +3 -2
- package/src/plugins/builtin/chart-composer/pane.tsx +41 -10
- package/src/plugins/builtin/chart-composer/presets.ts +91 -2
- package/src/plugins/builtin/chart-composer/quick-add.tsx +9 -2
- package/src/plugins/builtin/chart-composer/series-catalog.ts +44 -11
- package/src/plugins/builtin/chart-composer/series-expression.ts +1 -1
- package/src/plugins/builtin/chart-composer/settings.ts +16 -4
- package/src/plugins/builtin/chart-composer/studies.ts +1 -1
- package/src/plugins/builtin/chat/content/channel-navigation.ts +17 -6
- package/src/plugins/builtin/chat/content/footer.tsx +5 -2
- package/src/plugins/builtin/chat/content/index.tsx +12 -5
- package/src/plugins/builtin/chat/content/mentions.ts +50 -21
- package/src/plugins/builtin/chat/content/scroll.ts +12 -5
- package/src/plugins/builtin/chat/content/snapshot.ts +11 -0
- package/src/plugins/builtin/chat/content/transcript.tsx +48 -37
- package/src/plugins/builtin/chat/content/whole-message-copy.ts +44 -2
- package/src/plugins/builtin/chat/controller/index.ts +88 -17
- package/src/plugins/builtin/chat/controller/mention-candidates.ts +104 -0
- package/src/plugins/builtin/chat/controller/messages.ts +14 -2
- package/src/plugins/builtin/chat/controller/realtime.ts +9 -0
- package/src/plugins/builtin/chat/controller/state.ts +25 -0
- package/src/plugins/builtin/chat/controller/unread-people.ts +240 -0
- package/src/plugins/builtin/chat/controller/view.ts +4 -0
- package/src/plugins/builtin/chat/conversation-recency.ts +73 -0
- package/src/plugins/builtin/chat/conversations.ts +12 -5
- package/src/plugins/builtin/chat/index.tsx +1 -1
- package/src/plugins/builtin/chat/layout.ts +23 -5
- package/src/plugins/builtin/chat/message/desktop.tsx +2 -0
- package/src/plugins/builtin/chat/share/flow.tsx +18 -9
- package/src/plugins/builtin/chat/sidebar-rows.ts +18 -5
- package/src/plugins/builtin/chat/sidebar.tsx +6 -1
- package/src/plugins/builtin/chat/unread-badge.ts +38 -7
- package/src/plugins/builtin/cloud/askg/manifest.ts +4 -3
- package/src/plugins/builtin/cloud/askg/pane-attachment.ts +2 -3
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +16 -5
- package/src/plugins/builtin/commodities-energy/index.tsx +23 -4
- package/src/plugins/builtin/commodity-balances/client.ts +51 -193
- package/src/plugins/builtin/commodity-balances/headless.ts +10 -3
- package/src/plugins/builtin/commodity-balances/model.ts +5 -180
- package/src/plugins/builtin/commodity-balances/pane.tsx +3 -0
- package/src/plugins/builtin/custom-view/index.tsx +1 -1
- package/src/plugins/builtin/custom-view/loader.ts +57 -7
- package/src/plugins/builtin/custom-view/sources.ts +146 -0
- package/src/plugins/builtin/custom-view/view-spec.ts +37 -1
- package/src/plugins/builtin/earnings/board-model.ts +33 -3
- package/src/plugins/builtin/earnings/board-table.ts +59 -14
- package/src/plugins/builtin/earnings/board.tsx +36 -3
- package/src/plugins/builtin/earnings/headless.ts +24 -5
- package/src/plugins/builtin/earnings/history-model.ts +9 -1
- package/src/plugins/builtin/earnings/history-table.ts +16 -5
- package/src/plugins/builtin/earnings/history.tsx +40 -10
- package/src/plugins/builtin/earnings/index.tsx +3 -1
- package/src/plugins/builtin/earnings/no-earnings.ts +52 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +4 -1
- package/src/plugins/builtin/econ-statistics/headless.ts +5 -0
- package/src/plugins/builtin/econ-statistics/pane.tsx +1 -1
- package/src/plugins/builtin/econ-statistics/view.ts +4 -0
- package/src/plugins/builtin/futures/model.ts +5 -4
- package/src/plugins/builtin/futures/series.ts +38 -1
- package/src/plugins/builtin/futures-curve/client.ts +4 -4
- package/src/plugins/builtin/futures-curve/headless.ts +33 -8
- package/src/plugins/builtin/futures-curve/index.tsx +4 -4
- package/src/plugins/builtin/futures-curve/model.ts +109 -6
- package/src/plugins/builtin/futures-curve/pane.tsx +24 -13
- package/src/plugins/builtin/insider/headless.ts +74 -4
- package/src/plugins/builtin/insider/index.tsx +99 -5
- package/src/plugins/builtin/insider/signals-client.ts +69 -0
- package/src/plugins/builtin/insider/signals-model.ts +146 -0
- package/src/plugins/builtin/insider/signals.tsx +176 -0
- package/src/plugins/builtin/iv-history/client.ts +41 -2
- package/src/plugins/builtin/iv-history/headless.ts +24 -16
- package/src/plugins/builtin/iv-history/screen-pane.tsx +25 -7
- package/src/plugins/builtin/jodi/client.ts +42 -205
- package/src/plugins/builtin/jodi/headless.ts +13 -4
- package/src/plugins/builtin/jodi/model.ts +18 -43
- package/src/plugins/builtin/jodi/pane.tsx +5 -0
- package/src/plugins/builtin/kelly-sizer/headless.ts +1 -1
- package/src/plugins/builtin/kelly-sizer/history.ts +5 -3
- package/src/plugins/builtin/kelly-sizer/pane.tsx +1 -1
- package/src/plugins/builtin/macro-day/release-table.ts +3 -3
- package/src/plugins/builtin/market-movers/client.ts +32 -6
- package/src/plugins/builtin/market-movers/headless.ts +7 -2
- package/src/plugins/builtin/market-movers/model.ts +64 -3
- package/src/plugins/builtin/market-movers/screener.ts +20 -9
- package/src/plugins/builtin/market-valuation/detail.tsx +7 -2
- package/src/plugins/builtin/market-valuation/headless.ts +17 -4
- package/src/plugins/builtin/market-valuation/pane.tsx +7 -3
- package/src/plugins/builtin/market-valuation/view.ts +10 -0
- package/src/plugins/builtin/mna/model.ts +2 -1
- package/src/plugins/builtin/options-positioning/client.ts +10 -0
- package/src/plugins/builtin/options-positioning/headless.ts +88 -13
- package/src/plugins/builtin/options-positioning/index.tsx +2 -2
- package/src/plugins/builtin/options-positioning/model.ts +47 -0
- package/src/plugins/builtin/options-positioning/pane.tsx +55 -26
- package/src/plugins/builtin/options-scenario/charts.tsx +13 -4
- package/src/plugins/builtin/options-scenario/client.ts +111 -17
- package/src/plugins/builtin/options-scenario/collar.ts +141 -0
- package/src/plugins/builtin/options-scenario/csp.ts +1 -1
- package/src/plugins/builtin/options-scenario/freshness.ts +27 -0
- package/src/plugins/builtin/options-scenario/headless.ts +28 -12
- package/src/plugins/builtin/options-scenario/index.tsx +1 -1
- package/src/plugins/builtin/options-scenario/model.ts +55 -5
- package/src/plugins/builtin/options-scenario/pane.tsx +24 -5
- package/src/plugins/builtin/perps/client.ts +77 -6
- package/src/plugins/builtin/perps/headless.ts +25 -14
- package/src/plugins/builtin/perps/index.tsx +1 -1
- package/src/plugins/builtin/perps/model.ts +32 -0
- package/src/plugins/builtin/perps/pane.tsx +5 -4
- package/src/plugins/builtin/portfolio-list/allocation.ts +9 -4
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +39 -20
- package/src/plugins/builtin/portfolio-list/cli/render.ts +5 -3
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +15 -7
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +1 -1
- package/src/plugins/builtin/portfolio-list/column-values.ts +4 -3
- package/src/plugins/builtin/portfolio-list/command-bar.ts +1 -1
- package/src/plugins/builtin/portfolio-list/headless.ts +10 -3
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +36 -4
- package/src/plugins/builtin/portfolio-list/pane/remove-ticker.ts +1 -1
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +35 -6
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +2 -1
- package/src/plugins/builtin/portfolio-list/settings.ts +22 -0
- package/src/plugins/builtin/portfolio-list/since-last-seen.ts +197 -0
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +1 -1
- package/src/plugins/builtin/portfolio-list/table.tsx +14 -2
- package/src/plugins/builtin/rate-path/model.ts +1 -1
- package/src/plugins/builtin/rate-path/pane.tsx +2 -1
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +14 -5
- package/src/plugins/builtin/research/event-model.ts +41 -49
- package/src/plugins/builtin/research/event-sources.ts +1 -1
- package/src/plugins/builtin/research/headless.ts +1 -1
- package/src/plugins/builtin/research/relative-valuation-model.ts +6 -0
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +3 -3
- package/src/plugins/builtin/reverse-dcf/headless.ts +25 -9
- package/src/plugins/builtin/reverse-dcf/index.tsx +4 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +39 -5
- package/src/plugins/builtin/reverse-dcf/pane.tsx +16 -6
- package/src/plugins/builtin/sectors/client.ts +46 -19
- package/src/plugins/builtin/sectors/sector-model.ts +22 -10
- package/src/plugins/builtin/shared/earnings-report.ts +48 -1
- package/src/plugins/builtin/shared/history-span.ts +55 -0
- package/src/plugins/builtin/shared/report-freshness.ts +20 -11
- package/src/plugins/builtin/shared/series-detail-chart.tsx +5 -2
- package/src/plugins/builtin/shared/series-list-detail.tsx +7 -3
- package/src/plugins/builtin/shared/ticker-surface.ts +16 -2
- package/src/plugins/builtin/shared/use-quote-board.ts +12 -5
- package/src/plugins/builtin/themes/headless.ts +15 -2
- package/src/plugins/builtin/thirteenf/api.ts +60 -43
- package/src/plugins/builtin/thirteenf/data.ts +76 -35
- package/src/plugins/builtin/thirteenf/headless.ts +2 -0
- package/src/plugins/builtin/thirteenf/pane.tsx +10 -2
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +85 -17
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +92 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +26 -8
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +4 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +95 -22
- package/src/plugins/builtin/ticker-detail/overview/model.ts +1 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +1 -1
- package/src/plugins/builtin/world-venue-map/headless.ts +17 -3
- package/src/plugins/builtin/yield-curve/curves.ts +15 -1
- package/src/plugins/builtin/yield-curve/headless.ts +17 -7
- package/src/plugins/builtin/yield-curve/history.ts +2 -0
- package/src/plugins/builtin/yield-curve/index.tsx +23 -18
- package/src/plugins/builtin/yield-curve/series.ts +19 -9
- package/src/plugins/builtin/yield-curve/treasury-data.ts +2 -0
- package/src/plugins/builtin/yield-curve/world.ts +4 -0
- package/src/plugins/registry/host-actions.ts +3 -0
- package/src/{plugins/builtin/portfolio-list → portfolio}/mutations.ts +6 -6
- package/src/portfolio/valuation-basis.ts +4 -21
- package/src/public/__snapshots__/public-api.test.ts.snap +2 -0
- package/src/remote/controller.ts +27 -7
- package/src/remote/schema.ts +25 -9
- package/src/renderers/browser/app-services.ts +7 -1
- package/src/renderers/browser/config-host.ts +55 -2
- package/src/renderers/browser/first-screen.ts +193 -0
- package/src/renderers/browser/main.tsx +59 -7
- package/src/renderers/cloudflare/http-proxy.ts +21 -13
- package/src/renderers/dom/desktop/controls.tsx +2 -0
- package/src/renderers/dom/desktop/query-bar.tsx +1 -1
- package/src/renderers/dom/dom-ui-host.tsx +2 -0
- package/src/renderers/dom/windowed-list.tsx +201 -0
- package/src/renderers/dom/windowed-rows.ts +65 -0
- package/src/renderers/electrobun/bun/application-menu/index.ts +1 -0
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -7
- package/src/renderers/electrobun/bun/desktop/http-stream.ts +21 -6
- package/src/renderers/electrobun/bun/desktop/update.ts +132 -14
- package/src/renderers/electrobun/shared/protocol.ts +7 -4
- package/src/renderers/electrobun/view/http-fetch.ts +12 -1
- package/src/renderers/electrobun/view/update-host.ts +2 -2
- package/src/shares/bug-report-dialog.tsx +162 -0
- package/src/shares/bug-report-flow.tsx +84 -0
- package/src/shares/bug-report.ts +42 -0
- package/src/shares/capture-flow.ts +19 -0
- package/src/shares/capture-preview.tsx +129 -0
- package/src/shares/chat.ts +10 -1
- package/src/shares/dialog.tsx +16 -91
- package/src/shares/flow.tsx +12 -16
- package/src/shares/personal-pane.ts +35 -1
- package/src/sources/listing-symbols.ts +8 -4
- package/src/state/app/context/index.tsx +13 -0
- package/src/state/app/tab-cursor.ts +85 -0
- package/src/sync/core-contributors.ts +206 -59
- package/src/telemetry/usage-counts.ts +16 -0
- package/src/test-support/config-store.ts +31 -0
- package/src/test-support/moved-symbols.ts +64 -0
- package/src/theme/colors.ts +30 -0
- package/src/tickers/listing-fate.ts +242 -0
- package/src/tickers/open-target.ts +61 -11
- package/src/tickers/search/index.ts +45 -3
- package/src/tickers/search/ranking.ts +19 -2
- package/src/tickers/search/types.ts +3 -0
- package/src/tickers/search/upsert.ts +22 -7
- package/src/tickers/ticker-changes.ts +26 -9
- package/src/time-series/bar-spacing.ts +19 -0
- package/src/time-series/chart-data.ts +37 -13
- package/src/time-series/field-catalog.ts +5 -2
- package/src/time-series/forward-valuation.ts +10 -7
- package/src/time-series/fundamentals.ts +49 -11
- package/src/time-series/hooks.ts +2 -0
- package/src/time-series/live-bars.ts +3 -1
- package/src/time-series/parsed-history-cache.ts +2 -0
- package/src/time-series/price-units.ts +69 -0
- package/src/time-series/resolve.ts +71 -11
- package/src/time-series/session-bar.ts +138 -0
- package/src/time-series/spec.ts +20 -3
- package/src/time-series/studies.ts +211 -12
- package/src/time-series/transforms.ts +2 -0
- package/src/time-series/types.ts +11 -1
- package/src/time-series/valuation-price.ts +13 -0
- package/src/types/config.ts +24 -1
- package/src/types/financials.ts +2 -0
- package/src/types/headless.ts +27 -0
- package/src/types/plugin.ts +7 -0
- package/src/ui/host.tsx +5 -0
- package/src/updater/channel.ts +51 -0
- package/src/updater/github-releases.ts +85 -16
- package/src/updater/index.ts +128 -17
- package/src/utils/asset-category.ts +20 -0
- package/src/utils/datetime-format.ts +7 -1
- package/src/utils/decimal-comma.ts +83 -3
- package/src/utils/fundamentals.ts +7 -2
- package/src/utils/http-proxy-response.ts +66 -9
- package/src/utils/plugin-proxy-hosts.json +1 -5
- package/src/utils/semver.ts +47 -2
- package/src/utils/typo-distance.ts +22 -0
- package/src/plugins/builtin/shared/zip-text.ts +0 -46
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gloomberb",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.6",
|
|
4
4
|
"packageManager": "bun@1.3.11",
|
|
5
5
|
"description": "Market research and portfolio tracker for the terminal",
|
|
6
6
|
"module": "src/public/index.ts",
|
|
@@ -83,6 +83,7 @@
|
|
|
83
83
|
"benchmark:tui:compare": "bun run scripts/benchmark-tui-compare.ts",
|
|
84
84
|
"benchmark:tui:memory": "bun run scripts/benchmark-tui-memory.ts",
|
|
85
85
|
"check:pane-chrome": "bun run scripts/pane-chrome/checks.ts",
|
|
86
|
+
"check:chat-mentions": "bun scripts/pane-chrome/chat-mentions.ts",
|
|
86
87
|
"check:pane-screenshot": "bun run scripts/pane-chrome/screenshot.ts",
|
|
87
88
|
"check:pane-rest": "bun run scripts/pane-chrome/rest-diff.ts",
|
|
88
89
|
"check:pane-layout": "bun run scripts/pane-chrome/layout-sweep.ts",
|
|
@@ -111,6 +112,7 @@
|
|
|
111
112
|
"gloom-polls": "github:gloom-sh/gloom-polls",
|
|
112
113
|
"gloom-prediction-markets": "github:gloom-sh/gloom-prediction-markets",
|
|
113
114
|
"happy-dom": "^20.11.1",
|
|
115
|
+
"playwright-core": "1.60.0",
|
|
114
116
|
"png-to-ico": "^2.1.8",
|
|
115
117
|
"rcedit": "^4.0.1",
|
|
116
118
|
"typescript": "^5.9.2",
|
|
@@ -53,6 +53,86 @@ index c26c2c977ee1fc25a8dc144b85bac8626a45f572..8920a2905380228c23cba66c20d9bfd1
|
|
|
53
53
|
frame: {
|
|
54
54
|
width: this.frame.width,
|
|
55
55
|
height: this.frame.height,
|
|
56
|
+
diff --git a/dist/api/bun/core/Updater.ts b/dist/api/bun/core/Updater.ts
|
|
57
|
+
index 39daf6d341780af8e30c2c50327162863f5977ec..bf4a4b615f84904759d4bcd57be0d899c9464a5f 100644
|
|
58
|
+
--- a/dist/api/bun/core/Updater.ts
|
|
59
|
+
+++ b/dist/api/bun/core/Updater.ts
|
|
60
|
+
@@ -132,6 +132,19 @@ let updateInfo: {
|
|
61
|
+
error: string;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
+// Where updates are fetched from when it is not the channel and baseUrl that
|
|
65
|
+
+// version.json names. Only the download URLs read it: the app data folder and
|
|
66
|
+
+// the "dev" check keep the installed build's own channel.
|
|
67
|
+
+let updateSource: { channel: string; baseUrl: string } | null = null;
|
|
68
|
+
+
|
|
69
|
+
+function updateSourceChannel(): string {
|
|
70
|
+
+ return updateSource?.channel ?? localInfo.channel;
|
|
71
|
+
+}
|
|
72
|
+
+
|
|
73
|
+
+function updateSourceBaseUrl(): string {
|
|
74
|
+
+ return updateSource?.baseUrl ?? localInfo.baseUrl;
|
|
75
|
+
+}
|
|
76
|
+
+
|
|
77
|
+
function cleanupExtractionFolder(
|
|
78
|
+
extractionFolder: string,
|
|
79
|
+
keepTarHash: string,
|
|
80
|
+
@@ -176,6 +189,12 @@ const Updater = {
|
|
81
|
+
onStatusChangeCallback = callback;
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
+ // Checks and downloads from `source` (a channel prefix and the URL its
|
|
85
|
+
+ // files sit under) until it is set again; null goes back to version.json.
|
|
86
|
+
+ setUpdateSource: (source: { channel: string; baseUrl: string } | null) => {
|
|
87
|
+
+ updateSource = source;
|
|
88
|
+
+ },
|
|
89
|
+
+
|
|
90
|
+
// todo: allow switching channels, by default will check the current channel
|
|
91
|
+
checkForUpdate: async () => {
|
|
92
|
+
emitStatus("checking", "Checking for updates...");
|
|
93
|
+
@@ -196,11 +215,11 @@ const Updater = {
|
|
94
|
+
|
|
95
|
+
const cacheBuster = Math.random().toString(36).substring(7);
|
|
96
|
+
const platformPrefix = getPlatformPrefix(
|
|
97
|
+
- localInfo.channel,
|
|
98
|
+
+ updateSourceChannel(),
|
|
99
|
+
currentOS,
|
|
100
|
+
currentArch,
|
|
101
|
+
);
|
|
102
|
+
- const updateInfoUrl = `${localInfo.baseUrl.replace(/\/+$/, "")}/${platformPrefix}-update.json?${cacheBuster}`;
|
|
103
|
+
+ const updateInfoUrl = `${updateSourceBaseUrl().replace(/\/+$/, "")}/${platformPrefix}-update.json?${cacheBuster}`;
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
const updateInfoResponse = await fetch(updateInfoUrl);
|
|
107
|
+
@@ -329,11 +348,11 @@ const Updater = {
|
|
108
|
+
|
|
109
|
+
// check if there's a patch file for it
|
|
110
|
+
const platformPrefix = getPlatformPrefix(
|
|
111
|
+
- localInfo.channel,
|
|
112
|
+
+ updateSourceChannel(),
|
|
113
|
+
currentOS,
|
|
114
|
+
currentArch,
|
|
115
|
+
);
|
|
116
|
+
- const patchUrl = `${localInfo.baseUrl.replace(/\/+$/, "")}/${platformPrefix}-${currentHash}.patch`;
|
|
117
|
+
+ const patchUrl = `${updateSourceBaseUrl().replace(/\/+$/, "")}/${platformPrefix}-${currentHash}.patch`;
|
|
118
|
+
emitStatus(
|
|
119
|
+
"fetching-patch",
|
|
120
|
+
`Checking for patch: ${currentHash.slice(0, 8)}`,
|
|
121
|
+
@@ -612,12 +631,12 @@ const Updater = {
|
|
122
|
+
|
|
123
|
+
const cacheBuster = Math.random().toString(36).substring(7);
|
|
124
|
+
const platformPrefix = getPlatformPrefix(
|
|
125
|
+
- localInfo.channel,
|
|
126
|
+
+ updateSourceChannel(),
|
|
127
|
+
currentOS,
|
|
128
|
+
currentArch,
|
|
129
|
+
);
|
|
130
|
+
const tarballName = getTarballFileName(appFileName, currentOS);
|
|
131
|
+
- const urlToLatestTarball = `${localInfo.baseUrl.replace(/\/+$/, "")}/${platformPrefix}-${tarballName}`;
|
|
132
|
+
+ const urlToLatestTarball = `${updateSourceBaseUrl().replace(/\/+$/, "")}/${platformPrefix}-${tarballName}`;
|
|
133
|
+
const prevVersionCompressedTarballPath = join(
|
|
134
|
+
appDataFolder,
|
|
135
|
+
"self-extraction",
|
|
56
136
|
diff --git a/dist/api/bun/proc/native.ts b/dist/api/bun/proc/native.ts
|
|
57
137
|
index f0f6c2532ba2eb467ec1d452a25c835b6db72661..ae77cf58d32392ad4cc8e2103ac7ed27baae8bea 100644
|
|
58
138
|
--- a/dist/api/bun/proc/native.ts
|
package/src/api-client/chat.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type {
|
|
|
12
12
|
ChatAttachment,
|
|
13
13
|
ChatChannel,
|
|
14
14
|
ChatChannelState,
|
|
15
|
+
ChatMentionCandidate,
|
|
15
16
|
ChatDiscordLink,
|
|
16
17
|
ChatMessage,
|
|
17
18
|
ChatNotification,
|
|
@@ -118,6 +119,14 @@ export class CloudChatApi {
|
|
|
118
119
|
this.emitAttachmentSupport();
|
|
119
120
|
}
|
|
120
121
|
|
|
122
|
+
getMentionCandidates(channelId: string): Promise<ChatMentionCandidate[]> {
|
|
123
|
+
return this.request(`/chat/channels/${encodeURIComponent(channelId)}/mention-candidates`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
subscribeMentionCandidatesChanged(listener: () => void): () => void {
|
|
127
|
+
return this.options.socket.subscribeChatMentionCandidatesChanged(listener);
|
|
128
|
+
}
|
|
129
|
+
|
|
121
130
|
async getChannels(): Promise<ChatChannel[]> {
|
|
122
131
|
const channels =
|
|
123
132
|
await this.request<ChatChannel[]>("/chat/channels");
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/** Whether a board is whole, missing a part, or not loaded on the server yet. */
|
|
2
|
+
type BalanceBoardStatus = "available" | "partial" | "unavailable";
|
|
3
|
+
|
|
4
|
+
/** One country's crude or natural gas balance, as GET /cloud/jodi/board serves it. */
|
|
5
|
+
export interface JodiBalanceRow {
|
|
6
|
+
country: string;
|
|
7
|
+
/** The month the figures are for, YYYY-MM: each country's own latest report. Null when it never reported one. */
|
|
8
|
+
month: string | null;
|
|
9
|
+
production: number | null;
|
|
10
|
+
demand: number | null;
|
|
11
|
+
imports: number | null;
|
|
12
|
+
exports: number | null;
|
|
13
|
+
stocks: number | null;
|
|
14
|
+
unit: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface JodiBalanceBoard {
|
|
18
|
+
/** The newest month on the board, YYYY-MM. */
|
|
19
|
+
month: string;
|
|
20
|
+
commodity: "oil" | "gas";
|
|
21
|
+
rows: JodiBalanceRow[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** The Oil & Gas board: JODI's monthly crude and natural gas balances. */
|
|
25
|
+
export interface JodiBoardPayload {
|
|
26
|
+
source: "JODI";
|
|
27
|
+
status: BalanceBoardStatus;
|
|
28
|
+
/** When JODI last confirmed the oldest copy on the board, ISO. */
|
|
29
|
+
checkedAt: string | null;
|
|
30
|
+
/** The server has not been able to read JODI for days: these are the last copies it read. */
|
|
31
|
+
stale: boolean;
|
|
32
|
+
gaps: string[];
|
|
33
|
+
oil: JodiBalanceBoard | null;
|
|
34
|
+
gas: JodiBalanceBoard | null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** One crop, country and attribute of the latest market year, as GET /cloud/psd/board serves it. */
|
|
38
|
+
export interface PsdBalanceRow {
|
|
39
|
+
id: string;
|
|
40
|
+
crop: string;
|
|
41
|
+
country: string;
|
|
42
|
+
attribute: string;
|
|
43
|
+
value: number;
|
|
44
|
+
unit: string;
|
|
45
|
+
/** Market year, 2026/27. */
|
|
46
|
+
year: string;
|
|
47
|
+
cropOrder: number;
|
|
48
|
+
countryOrder: number;
|
|
49
|
+
attributeOrder: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** A season-average farm price forecast. */
|
|
53
|
+
export interface PsdPriceForecast {
|
|
54
|
+
id: string;
|
|
55
|
+
crop: string;
|
|
56
|
+
forecast: number;
|
|
57
|
+
unit: string;
|
|
58
|
+
season: string;
|
|
59
|
+
cropOrder: number;
|
|
60
|
+
seasonYear: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** The Crops board: USDA's world crop balances and season-average price forecasts. */
|
|
64
|
+
export interface PsdBoardPayload {
|
|
65
|
+
source: "USDA";
|
|
66
|
+
status: BalanceBoardStatus;
|
|
67
|
+
checkedAt: string | null;
|
|
68
|
+
stale: boolean;
|
|
69
|
+
gaps: string[];
|
|
70
|
+
/** YYYY-MM of the newest estimate on the board: the monthly supply and demand report that set it. */
|
|
71
|
+
month: string | null;
|
|
72
|
+
marketYear: string | null;
|
|
73
|
+
rows: PsdBalanceRow[];
|
|
74
|
+
prices: PsdPriceForecast[];
|
|
75
|
+
/** The model forecast date of the prices, YYYY-MM-DD. */
|
|
76
|
+
pricesDate: string | null;
|
|
77
|
+
}
|
package/src/api-client/data.ts
CHANGED
|
@@ -35,10 +35,12 @@ import type { CloudCurveHistory, CloudCurveId, CloudCurveView, CloudWorldCurves
|
|
|
35
35
|
import type { CdxBoardPayload, CloudCreditBoardParams, SovrBoardPayload } from "./credit-boards";
|
|
36
36
|
import type { ShortVolumePayload, ShortVolumeScope } from "./short-volume";
|
|
37
37
|
import type { BeneficialOwnersPayload, CloudBeneficialOwnersParams } from "./beneficial-owners";
|
|
38
|
+
import type { CloudInsiderSignalsParams, InsiderSignalsPayload } from "./insider-signals";
|
|
38
39
|
import type { SocialMentionDayPosts, SocialMentionsPayload, SocialMentionsRange } from "./social-mentions";
|
|
39
40
|
import type { FuturesContractTermsPayload, FuturesCurveAsOfPayload, FuturesCurvePayload } from "./futures-curve";
|
|
40
41
|
import type { CotBoardPayload, CotContractPayload, CotFamily, CotClass } from "./cot";
|
|
41
42
|
import type { DoeBoardPayload, DoePricesPayload } from "./doe";
|
|
43
|
+
import type { JodiBoardPayload, PsdBoardPayload } from "./commodity-balances";
|
|
42
44
|
import type { CarbonBoard, CarbonHistory, EuropePowerBoard, EuropePowerHistory, GasStorageBoard, GasStorageHistory, GasStorageSeasonal } from "./europe-energy";
|
|
43
45
|
import type { GpuBoardPayload, GpuEventsPayload, GpuHistoryPayload, GpuHistoryQuery } from "./gpu";
|
|
44
46
|
import type { CpiBoardPayload } from "./cpi";
|
|
@@ -81,6 +83,7 @@ import {
|
|
|
81
83
|
cloudExchangeRatePath,
|
|
82
84
|
cloudSec13FPath,
|
|
83
85
|
cloudSecBeneficialOwnersPath,
|
|
86
|
+
cloudSecInsiderSignalsPath,
|
|
84
87
|
cloudSecFilingContentPath,
|
|
85
88
|
cloudSecFilingDocumentsPath,
|
|
86
89
|
cloudSecFilingsPath,
|
|
@@ -143,6 +146,7 @@ import type {
|
|
|
143
146
|
CloudMarketResponse,
|
|
144
147
|
CloudMarketScreenerCategory,
|
|
145
148
|
CloudMarketScreenerPayload,
|
|
149
|
+
CloudMoverSession,
|
|
146
150
|
CloudNewsListResponse,
|
|
147
151
|
CloudNewsPayload,
|
|
148
152
|
CloudSavedSearch,
|
|
@@ -283,8 +287,10 @@ export class CloudDataApi {
|
|
|
283
287
|
return this.request(`/news/article-summary?${new URLSearchParams({ url })}`);
|
|
284
288
|
}
|
|
285
289
|
|
|
286
|
-
|
|
290
|
+
/** `session` is what Gainers and Losers are ranked by (see CloudMoverSession). */
|
|
291
|
+
getMarketMovers(category: "day_gainers" | "day_losers" | "most_actives", count = 25, refresh = false, session?: CloudMoverSession): Promise<CloudMarketResponse<MarketMoversPayload>> {
|
|
287
292
|
const params = new URLSearchParams({ category, count: String(count), mode: refresh ? "refresh" : "cache-first" });
|
|
293
|
+
if (session && category !== "most_actives") params.set("session", session);
|
|
288
294
|
return this.request(`/market/movers?${params}`);
|
|
289
295
|
}
|
|
290
296
|
|
|
@@ -300,12 +306,17 @@ export class CloudDataApi {
|
|
|
300
306
|
return this.requestMarketSymbol("/market/dividends", symbol, exchange);
|
|
301
307
|
}
|
|
302
308
|
|
|
303
|
-
/**
|
|
309
|
+
/**
|
|
310
|
+
* Gainers, losers and most active, or the pre-market, after-hours and gap
|
|
311
|
+
* lists with a `side`. `session` is what Gainers and Losers are ranked by
|
|
312
|
+
* (see CloudMoverSession).
|
|
313
|
+
*/
|
|
304
314
|
async getCloudMarketScreener<Category extends CloudMarketScreenerCategory | CloudSessionMoversCategory>(
|
|
305
315
|
category: Category,
|
|
306
316
|
count = 25,
|
|
307
317
|
mode: "cache-first" | "refresh" = "cache-first",
|
|
308
318
|
side?: CloudSessionMoversSide,
|
|
319
|
+
session?: CloudMoverSession,
|
|
309
320
|
): Promise<CloudMarketResponse<Category extends CloudSessionMoversCategory ? CloudSessionMoversPayload : CloudMarketScreenerPayload>> {
|
|
310
321
|
const requestedCount = Number.isFinite(count) ? Math.round(count) : 25;
|
|
311
322
|
const params = new URLSearchParams({
|
|
@@ -314,6 +325,7 @@ export class CloudDataApi {
|
|
|
314
325
|
mode,
|
|
315
326
|
});
|
|
316
327
|
if (side && isSessionMoversCategory(category)) params.set("side", side);
|
|
328
|
+
if (session && (category === "gainers" || category === "losers")) params.set("session", session);
|
|
317
329
|
return this.request(`/market/screener?${params.toString()}`);
|
|
318
330
|
}
|
|
319
331
|
|
|
@@ -590,6 +602,14 @@ export class CloudDataApi {
|
|
|
590
602
|
return this.request<DoePricesPayload>("/cloud/doe/prices");
|
|
591
603
|
}
|
|
592
604
|
|
|
605
|
+
getCloudJodiBoard(signal?: AbortSignal): Promise<JodiBoardPayload> {
|
|
606
|
+
return this.request<JodiBoardPayload>("/cloud/jodi/board", { signal });
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
getCloudPsdBoard(signal?: AbortSignal): Promise<PsdBoardPayload> {
|
|
610
|
+
return this.request<PsdBoardPayload>("/cloud/psd/board", { signal });
|
|
611
|
+
}
|
|
612
|
+
|
|
593
613
|
async getCloudAttention(window: AttentionWindow = "now", symbol?: string): Promise<AttentionPayload> {
|
|
594
614
|
const path = symbol ? `/cloud/attention/${encodeURIComponent(symbol)}` : "/cloud/attention";
|
|
595
615
|
return this.request<AttentionPayload>(`${path}?window=${window}`);
|
|
@@ -934,6 +954,15 @@ export class CloudDataApi {
|
|
|
934
954
|
});
|
|
935
955
|
}
|
|
936
956
|
|
|
957
|
+
async getCloudSecInsiderSignals(
|
|
958
|
+
params: CloudInsiderSignalsParams = {},
|
|
959
|
+
options?: { signal?: AbortSignal },
|
|
960
|
+
): Promise<InsiderSignalsPayload> {
|
|
961
|
+
return this.request<InsiderSignalsPayload>(cloudSecInsiderSignalsPath(params), {
|
|
962
|
+
signal: options?.signal,
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
|
|
937
966
|
async getCloudSecFilingDocuments(
|
|
938
967
|
params: CloudSecFilingParams,
|
|
939
968
|
): Promise<CloudSecDocumentsResponse> {
|
|
@@ -953,8 +982,11 @@ export class CloudDataApi {
|
|
|
953
982
|
async getCloudSec13F(
|
|
954
983
|
path: string,
|
|
955
984
|
params: Record<string, string | number | undefined> = {},
|
|
985
|
+
options?: { signal?: AbortSignal },
|
|
956
986
|
): Promise<unknown> {
|
|
957
|
-
return this.request<unknown>(cloudSec13FPath(path, params)
|
|
987
|
+
return this.request<unknown>(cloudSec13FPath(path, params), {
|
|
988
|
+
signal: options?.signal,
|
|
989
|
+
});
|
|
958
990
|
}
|
|
959
991
|
|
|
960
992
|
/**
|
|
@@ -27,6 +27,8 @@ interface EarningsRealizedMove {
|
|
|
27
27
|
afterClose: number;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
type EarningsActualSource = "calendar" | "press-release";
|
|
31
|
+
|
|
30
32
|
export interface EarningsReport {
|
|
31
33
|
symbol: string;
|
|
32
34
|
name: string | null;
|
|
@@ -43,6 +45,12 @@ export interface EarningsReport {
|
|
|
43
45
|
/** For an upcoming report, the consensus every earnings view shows, with `epsAnalysts` behind it. */
|
|
44
46
|
epsEstimate: number | null;
|
|
45
47
|
epsActual: number | null;
|
|
48
|
+
/**
|
|
49
|
+
* Where `epsActual` comes from: `press-release` is the company's own
|
|
50
|
+
* release, read the day it reports and provisional until the calendar's
|
|
51
|
+
* figure replaces it. Absent from older servers.
|
|
52
|
+
*/
|
|
53
|
+
epsActualSource?: EarningsActualSource | null;
|
|
46
54
|
epsAnalysts: number | null;
|
|
47
55
|
revenueEstimate: number | null;
|
|
48
56
|
revenueAnalysts: number | null;
|
|
@@ -69,6 +77,8 @@ export interface EarningsCalendarPayload {
|
|
|
69
77
|
|
|
70
78
|
interface EarningsHistoryReport extends EarningsReport {
|
|
71
79
|
revenueActual: number | null;
|
|
80
|
+
/** `press-release` until the statements have the quarter; absent from older servers. */
|
|
81
|
+
revenueActualSource?: "statements" | "press-release" | null;
|
|
72
82
|
}
|
|
73
83
|
|
|
74
84
|
export interface EarningsHistoryPayload {
|
package/src/api-client/index.ts
CHANGED
|
@@ -645,6 +645,8 @@ class GloomApiClient {
|
|
|
645
645
|
getChannels = this.chat.getChannels.bind(this.chat);
|
|
646
646
|
getChatPresence = this.chat.getPresence.bind(this.chat);
|
|
647
647
|
getChatState = this.chat.getState.bind(this.chat);
|
|
648
|
+
getChatMentionCandidates = this.chat.getMentionCandidates.bind(this.chat);
|
|
649
|
+
subscribeChatMentionCandidatesChanged = this.chat.subscribeMentionCandidatesChanged.bind(this.chat);
|
|
648
650
|
updateChatChannelState = this.chat.updateChannelState.bind(this.chat);
|
|
649
651
|
markChatNotificationsDelivered = this.chat.markNotificationsDelivered.bind(this.chat);
|
|
650
652
|
getUnseenChatNotificationIds = this.chat.getUnseenNotificationIds.bind(this.chat);
|
|
@@ -826,6 +828,8 @@ class GloomApiClient {
|
|
|
826
828
|
getCloudAward = this.data.getCloudAward.bind(this.data);
|
|
827
829
|
getCloudDoeBoard = this.data.getCloudDoeBoard.bind(this.data);
|
|
828
830
|
getCloudDoePrices = this.data.getCloudDoePrices.bind(this.data);
|
|
831
|
+
getCloudJodiBoard = this.data.getCloudJodiBoard.bind(this.data);
|
|
832
|
+
getCloudPsdBoard = this.data.getCloudPsdBoard.bind(this.data);
|
|
829
833
|
getCloudAttention = this.data.getCloudAttention.bind(this.data);
|
|
830
834
|
getCloudPowerBoard = this.data.getCloudPowerBoard.bind(this.data);
|
|
831
835
|
getCloudPowerHistory = this.data.getCloudPowerHistory.bind(this.data);
|
|
@@ -864,6 +868,7 @@ class GloomApiClient {
|
|
|
864
868
|
getRiskReport = this.data.getRiskReport.bind(this.data);
|
|
865
869
|
getCloudSecFilings = this.data.getCloudSecFilings.bind(this.data);
|
|
866
870
|
getCloudSecBeneficialOwners = this.data.getCloudSecBeneficialOwners.bind(this.data);
|
|
871
|
+
getCloudSecInsiderSignals = this.data.getCloudSecInsiderSignals.bind(this.data);
|
|
867
872
|
getCloudSecFilingDocuments = this.data.getCloudSecFilingDocuments.bind(this.data);
|
|
868
873
|
getCloudSecFilingContent = this.data.getCloudSecFilingContent.bind(this.data);
|
|
869
874
|
getCloudSec13F = this.data.getCloudSec13F.bind(this.data);
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Companies ranked by recent open-market insider buying, as
|
|
3
|
+
* `GET /cloud/sec/insider-signals` returns them. Only Form 4 purchases (code
|
|
4
|
+
* P) by officers, directors and 10% owners count. Dates are `YYYY-MM-DD`,
|
|
5
|
+
* values USD.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
type InsiderSignalRole =
|
|
9
|
+
| "CEO"
|
|
10
|
+
| "CFO"
|
|
11
|
+
| "COO"
|
|
12
|
+
| "President"
|
|
13
|
+
| "Chair"
|
|
14
|
+
| "Officer"
|
|
15
|
+
| "Director"
|
|
16
|
+
| "10% owner";
|
|
17
|
+
|
|
18
|
+
interface InsiderSignalBuyer {
|
|
19
|
+
name: string;
|
|
20
|
+
role: InsiderSignalRole;
|
|
21
|
+
value: number;
|
|
22
|
+
/** Days the insider bought in the window. */
|
|
23
|
+
buys: number;
|
|
24
|
+
lastBuy: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface InsiderSignalRow {
|
|
28
|
+
ticker: string;
|
|
29
|
+
issuerCik: string;
|
|
30
|
+
company: string;
|
|
31
|
+
/** 0 to 100. */
|
|
32
|
+
score: number;
|
|
33
|
+
/** Why the company ranks, strongest first, in plain words. */
|
|
34
|
+
reasons: string[];
|
|
35
|
+
/** Distinct insiders who bought in the window. */
|
|
36
|
+
insiders: number;
|
|
37
|
+
/** Insider buy days in the window. */
|
|
38
|
+
buys: number;
|
|
39
|
+
value: number;
|
|
40
|
+
shares: number;
|
|
41
|
+
firstBuy: string;
|
|
42
|
+
lastBuy: string;
|
|
43
|
+
lastFiled: string;
|
|
44
|
+
signals: {
|
|
45
|
+
clusterInsiders: number;
|
|
46
|
+
repeatBuys: number;
|
|
47
|
+
usualRatio: number | null;
|
|
48
|
+
stakeIncreasePct: number | null;
|
|
49
|
+
newPosition: boolean;
|
|
50
|
+
};
|
|
51
|
+
/** The biggest buyers, up to five. */
|
|
52
|
+
buyers: InsiderSignalBuyer[];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface InsiderSignalsPayload {
|
|
56
|
+
/** Days of buying each row covers, ending `through`. */
|
|
57
|
+
window: number;
|
|
58
|
+
through: string;
|
|
59
|
+
/** The newest filing day read. */
|
|
60
|
+
asOf: string | null;
|
|
61
|
+
/**
|
|
62
|
+
* Days whose filings have all been read. `missingDays`: weekdays since
|
|
63
|
+
* `from` the server no longer reads on its own and has not read whole, a gap
|
|
64
|
+
* an outage left (left out by servers that predate it).
|
|
65
|
+
*/
|
|
66
|
+
coverage: { from: string | null; through: string | null; missingDays?: string[] };
|
|
67
|
+
rows: InsiderSignalRow[];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface CloudInsiderSignalsParams {
|
|
71
|
+
/** Days, 1 to 90; the server reads 30 when left out. */
|
|
72
|
+
window?: number;
|
|
73
|
+
/** Rows, 1 to 200; the server reads 50 when left out. */
|
|
74
|
+
limit?: number;
|
|
75
|
+
}
|
|
@@ -19,7 +19,7 @@ export interface ScreenerQuote {
|
|
|
19
19
|
lastUpdated?: number;
|
|
20
20
|
/** Session-fixed, so the price column reads its decimals from it rather than from each tick. */
|
|
21
21
|
previousClose?: number;
|
|
22
|
-
/** The quote's sessions beside the live print the
|
|
22
|
+
/** The quote's sessions beside the live print the server ranked the row by, when the server sends them. */
|
|
23
23
|
sessions?: CloudMoverSessionFields;
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -220,6 +220,7 @@ export function normalizeChatChannel(
|
|
|
220
220
|
...channel,
|
|
221
221
|
kind: channel.kind ?? fallbackKind,
|
|
222
222
|
created_at: normalizeTimestamp(channel.created_at),
|
|
223
|
+
...(typeof channel.lastMessageAt === "string" ? { lastMessageAt: normalizeTimestamp(channel.lastMessageAt) } : {}),
|
|
223
224
|
...(channel.dmUser ? { dmUser: normalizeChatUser(channel.dmUser) } : {}),
|
|
224
225
|
...(Array.isArray(channel.members) ? { members: channel.members.map(normalizeChatUser) } : {}),
|
|
225
226
|
};
|
package/src/api-client/paths.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { isUsListingExchange, normalizeSymbol, parsePublicTickerKey, publicTicke
|
|
|
7
7
|
import { nonUsSecListingVenue } from "../utils/sec";
|
|
8
8
|
import type { HistoryRetention } from "../sources/history-retention";
|
|
9
9
|
import type { CloudBeneficialOwnersParams } from "./beneficial-owners";
|
|
10
|
+
import type { CloudInsiderSignalsParams } from "./insider-signals";
|
|
10
11
|
import type { RevenueBreakdownView } from "./revenue-breakdown";
|
|
11
12
|
|
|
12
13
|
export type CloudHistoryParams = {
|
|
@@ -444,6 +445,14 @@ export function cloudSecBeneficialOwnersPath(params: CloudBeneficialOwnersParams
|
|
|
444
445
|
return appendQuery("/cloud/sec/beneficial-owners", search);
|
|
445
446
|
}
|
|
446
447
|
|
|
448
|
+
/** Companies ranked by recent open-market insider buying. */
|
|
449
|
+
export function cloudSecInsiderSignalsPath(params: CloudInsiderSignalsParams = {}): string {
|
|
450
|
+
const search = new URLSearchParams();
|
|
451
|
+
if (params.window != null) search.set("window", String(params.window));
|
|
452
|
+
if (params.limit != null) search.set("limit", String(params.limit));
|
|
453
|
+
return appendQuery("/cloud/sec/insider-signals", search);
|
|
454
|
+
}
|
|
455
|
+
|
|
447
456
|
export function cloudSecFilingDocumentsPath(
|
|
448
457
|
params: CloudSecFilingParams,
|
|
449
458
|
): string {
|
|
@@ -28,7 +28,10 @@ export type ResearchActivity =
|
|
|
28
28
|
| "onboarding_signed_in"
|
|
29
29
|
| "onboarding_pro_viewed"
|
|
30
30
|
| "onboarding_completed"
|
|
31
|
-
| "onboarding_skipped"
|
|
31
|
+
| "onboarding_skipped"
|
|
32
|
+
// The first action of a web visitor counted in the first-screen experiment,
|
|
33
|
+
// in that first session. Keep in sync with the server's list.
|
|
34
|
+
| "first_screen_engaged";
|
|
32
35
|
export type ResearchFeature =
|
|
33
36
|
| "overview"
|
|
34
37
|
| "chart"
|
|
@@ -451,7 +454,10 @@ function webExperimentAttribution(): { experiments?: string } {
|
|
|
451
454
|
* visitors on term.gloom.sh with an analytics id (no Do Not Track or Global
|
|
452
455
|
* Privacy Control) and not driven by automation are asked. See web-experiments.ts.
|
|
453
456
|
*/
|
|
454
|
-
export function exposeWebExperiment(
|
|
457
|
+
export function exposeWebExperiment(
|
|
458
|
+
experiment: string,
|
|
459
|
+
{ placement, signal }: { placement?: string; signal?: AbortSignal } = {},
|
|
460
|
+
): Promise<string | null> {
|
|
455
461
|
if (!researchTelemetryAllowed()) return Promise.resolve(null);
|
|
456
462
|
if (getCurrentPluginTarget() !== "web") return Promise.resolve(null);
|
|
457
463
|
try {
|
|
@@ -468,7 +474,8 @@ export function exposeWebExperiment(experiment: string): Promise<string | null>
|
|
|
468
474
|
attribution: attributionPayload(),
|
|
469
475
|
experiment: key,
|
|
470
476
|
variant,
|
|
471
|
-
|
|
477
|
+
...(placement && ACTIVITY_ID.test(placement) ? { placement } : {}),
|
|
478
|
+
}, signal),
|
|
472
479
|
});
|
|
473
480
|
} catch {
|
|
474
481
|
return Promise.resolve(null);
|
package/src/api-client/socket.ts
CHANGED
|
@@ -109,6 +109,7 @@ export class CloudApiSocket {
|
|
|
109
109
|
private reconnectDelayMs = 1000;
|
|
110
110
|
|
|
111
111
|
private readonly channelListeners = new Map<string, Set<ChannelListener>>();
|
|
112
|
+
private readonly chatMentionCandidatesListeners = new Set<() => void>();
|
|
112
113
|
private readonly chatNotificationListeners =
|
|
113
114
|
new Set<ChatNotificationListener>();
|
|
114
115
|
private readonly chatChannelStateListeners =
|
|
@@ -254,6 +255,11 @@ export class CloudApiSocket {
|
|
|
254
255
|
};
|
|
255
256
|
}
|
|
256
257
|
|
|
258
|
+
subscribeChatMentionCandidatesChanged(listener: () => void): () => void {
|
|
259
|
+
this.chatMentionCandidatesListeners.add(listener);
|
|
260
|
+
return () => { this.chatMentionCandidatesListeners.delete(listener); };
|
|
261
|
+
}
|
|
262
|
+
|
|
257
263
|
/**
|
|
258
264
|
* The reader's read state or mute changed on another device or window. Like
|
|
259
265
|
* notifications, it never opens the socket by itself.
|
|
@@ -631,6 +637,10 @@ export class CloudApiSocket {
|
|
|
631
637
|
return;
|
|
632
638
|
}
|
|
633
639
|
|
|
640
|
+
if (parsed?.type === "chat.mentions_changed") {
|
|
641
|
+
for (const listener of this.chatMentionCandidatesListeners) listener();
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
634
644
|
if (parsed?.type === "chat.channel_state") {
|
|
635
645
|
const state = normalizeChatChannelStateFrame(parsed.data);
|
|
636
646
|
if (state) {
|
package/src/api-client/types.ts
CHANGED
|
@@ -143,6 +143,21 @@ export interface ChatChannel {
|
|
|
143
143
|
teamId?: string;
|
|
144
144
|
dmUser?: ChatUserSummary | null;
|
|
145
145
|
members?: ChatUserSummary[];
|
|
146
|
+
/**
|
|
147
|
+
* When the newest message you can see in a direct or group conversation was
|
|
148
|
+
* sent; null when it has none. Absent from channels of other kinds and from
|
|
149
|
+
* servers that do not report it.
|
|
150
|
+
*/
|
|
151
|
+
lastMessageAt?: string | null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Minimal identities scoped by the server to this channel and existing DMs. */
|
|
155
|
+
export interface ChatMentionCandidate {
|
|
156
|
+
id: string;
|
|
157
|
+
username: string;
|
|
158
|
+
displayName: string | null;
|
|
159
|
+
channelActivityAt: string | null;
|
|
160
|
+
conversationActivityAt: string | null;
|
|
146
161
|
}
|
|
147
162
|
|
|
148
163
|
export interface ChatChannelState {
|
|
@@ -1517,6 +1532,15 @@ export interface CloudMarketBatchPayload<T> {
|
|
|
1517
1532
|
|
|
1518
1533
|
export type CloudMarketScreenerCategory = "gainers" | "losers" | "most-active";
|
|
1519
1534
|
|
|
1535
|
+
/**
|
|
1536
|
+
* What Gloom Cloud selects and ranks Gainers and Losers by: `regular` the last
|
|
1537
|
+
* completed regular session's move, the Chg% a row shows; `extended` the
|
|
1538
|
+
* latest print, after-hours or pre-market included. While the regular session
|
|
1539
|
+
* trades the two are one list. A server that predates the choice ignores it
|
|
1540
|
+
* and ranks by the latest print.
|
|
1541
|
+
*/
|
|
1542
|
+
export type CloudMoverSession = "regular" | "extended";
|
|
1543
|
+
|
|
1520
1544
|
/**
|
|
1521
1545
|
* A movers row's quote sessions, under the quote's field names and meaning:
|
|
1522
1546
|
* the session it was read in, the day its change is dated to, the last
|
|
@@ -1529,7 +1553,7 @@ export type CloudMoverSessionFields = Partial<Pick<Quote,
|
|
|
1529
1553
|
| "preMarketPrice" | "preMarketChange" | "preMarketChangePercent"
|
|
1530
1554
|
| "postMarketPrice" | "postMarketChange" | "postMarketChangePercent">>;
|
|
1531
1555
|
|
|
1532
|
-
/** price, change and changePercent are the live print the
|
|
1556
|
+
/** price, change and changePercent are the live print the server ranks the list by; the session fields say how it reads. */
|
|
1533
1557
|
export interface CloudMarketScreenerItem extends CloudMoverSessionFields {
|
|
1534
1558
|
rank: number;
|
|
1535
1559
|
symbol: string;
|
|
@@ -21,6 +21,7 @@ import type { DataProvider } from "../../types/data-provider";
|
|
|
21
21
|
import type { PinTickerOptions } from "../../types/plugin";
|
|
22
22
|
import {
|
|
23
23
|
resolveTickerOpenTarget,
|
|
24
|
+
tickerOpenFailureMessage,
|
|
24
25
|
type TickerOpenTarget,
|
|
25
26
|
} from "../../tickers/open-target";
|
|
26
27
|
import { AmbiguousTickerError, findExactTickerSearchMatch } from "../../tickers/search";
|
|
@@ -73,7 +74,7 @@ export function useAppTickerOpenRuntime({
|
|
|
73
74
|
tickerRepository,
|
|
74
75
|
});
|
|
75
76
|
if (!target && canPresentFeedback()) {
|
|
76
|
-
pluginRegistry.notify({ body:
|
|
77
|
+
pluginRegistry.notify({ body: tickerOpenFailureMessage(rawSymbol), type: "error" });
|
|
77
78
|
}
|
|
78
79
|
return target;
|
|
79
80
|
} catch (err) {
|