@gloom-sh/terminal 0.18.5 → 0.19.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.
- package/package.json +1 -1
- package/patches/electrobun@1.18.1.patch +140 -7
- package/src/api-client/cot.ts +6 -2
- package/src/api-client/credit-documents.ts +6 -0
- package/src/api-client/data.ts +17 -6
- package/src/api-client/equity-screener.ts +24 -0
- package/src/api-client/fund-facts.ts +45 -4
- package/src/api-client/index.ts +11 -0
- package/src/api-client/market-discovery.ts +10 -0
- package/src/api-client/market-movers.ts +7 -0
- package/src/api-client/members.ts +1 -1
- package/src/api-client/perps.ts +43 -0
- package/src/api-client/research-activity.ts +3 -2
- package/src/api-client/types.ts +70 -2
- package/src/app/pane-runtime/plugin-bindings.ts +9 -5
- package/src/app/runtime/broker-import.ts +0 -2
- package/src/app/runtime/plugin-bindings.ts +73 -56
- package/src/architecture/pane-tabs-allowlist.json +3 -0
- package/src/architecture/ttl-caches-allowlist.json +19 -0
- package/src/brokers/sync-broker-instance.ts +2 -8
- package/src/capabilities/chart-series.ts +1 -1
- package/src/cli/commands/crypto-hints.ts +40 -24
- package/src/cli/commands/market.ts +72 -26
- package/src/cli/commands/options-chain.ts +48 -7
- package/src/cli/commands/options-leaps.ts +9 -3
- package/src/cli/commands/overview.ts +61 -12
- package/src/cli/commands/search.ts +21 -1
- package/src/cli/commands/themes.ts +11 -2
- package/src/cli/commands/ticker.ts +55 -34
- package/src/cli/company-name-hint.ts +41 -0
- package/src/cli/earnings-calendar.ts +1 -1
- package/src/cli/errors.ts +8 -0
- package/src/cli/glossary.ts +25 -2
- package/src/cli/history-rows.ts +57 -9
- package/src/cli/index.ts +2 -0
- package/src/cli/listing-arg.ts +180 -52
- package/src/cli/output-file.ts +68 -0
- package/src/cli/pane-functions/capabilities.ts +3 -0
- package/src/cli/pane-functions/catalog.ts +80 -7
- package/src/cli/pane-functions/dom.ts +13 -3
- package/src/cli/pane-functions/freshness.ts +86 -3
- package/src/cli/pane-functions/function-help.ts +13 -10
- package/src/cli/pane-functions/headless.ts +17 -7
- package/src/cli/pane-functions/index.ts +49 -14
- package/src/cli/pane-functions/market-session.ts +66 -4
- package/src/cli/pane-functions/options.ts +19 -1
- package/src/cli/pane-functions/resolver.ts +19 -8
- package/src/cli/pane-functions/screenshot-assessment.ts +6 -4
- package/src/cli/pane-functions/screenshot-types.ts +5 -0
- package/src/cli/quote-answer.ts +22 -11
- package/src/cli/ticker-resolution.ts +3 -2
- package/src/components/chart/composite/composite-chart.tsx +4 -0
- package/src/components/chart/composite/interactions.ts +6 -0
- package/src/components/chart/composite/legend.tsx +45 -7
- package/src/components/chart/composite/panel-gestures.ts +33 -0
- package/src/components/chart/composite/panel-surface.tsx +52 -3
- package/src/components/chart/composite/rasterizer.ts +24 -13
- package/src/components/chart/composite/scene.ts +39 -4
- package/src/components/chart/composite/series-cues.ts +14 -0
- package/src/components/chart/composite/text-renderer.ts +9 -2
- package/src/components/chart/composite/tool-catalog.ts +36 -0
- package/src/components/chart/composite/tools.ts +203 -44
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +11 -4
- package/src/components/command-bar/assist/inventory.ts +2 -1
- package/src/components/command-bar/commands/direct/index.ts +28 -13
- package/src/components/command-bar/pane-templates/items.ts +3 -2
- package/src/components/command-bar/workflow/collection-actions.ts +3 -3
- package/src/components/onboarding/onboarding-wizard.tsx +4 -1
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +12 -7
- package/src/components/onboarding/wizard-broker-sync.ts +0 -1
- package/src/components/onboarding/wizard-positions.ts +3 -3
- package/src/components/ticker/list-table-view.tsx +4 -1
- package/src/components/ui/choice-dialog.tsx +23 -18
- package/src/components/ui/choice-groups.ts +18 -0
- package/src/components/ui/data-table/opentui/index.tsx +9 -7
- package/src/components/ui/data-table/opentui/model.ts +26 -1
- package/src/components/ui/data-table/types.ts +2 -0
- package/src/components/ui/list-view.tsx +8 -4
- package/src/components/ui/query-bar-keys.tsx +2 -0
- package/src/components/ui/query-bar.tsx +1 -0
- package/src/components/ui/select-button.tsx +5 -1
- package/src/components/ui/select-field.tsx +1 -0
- package/src/components/ui/table-layout.ts +8 -5
- package/src/core/app-runtime.ts +2 -0
- package/src/core/app-services.ts +2 -2
- package/src/data/config/chart-settings.ts +1 -1
- package/src/data/json-ticker-repository.ts +17 -8
- package/src/data/ticker-repository.ts +16 -9
- package/src/data/ticker-writes.ts +81 -0
- package/src/data/ttl-cache.ts +165 -0
- package/src/docs/snapshot.json +71 -137
- package/src/i18n/es.ts +18 -2
- package/src/i18n/ja.ts +18 -2
- package/src/i18n/ko.ts +18 -2
- package/src/i18n/zh-cn.ts +18 -2
- package/src/i18n/zh-tw.ts +18 -2
- package/src/market-data/depositary-pair.ts +2 -2
- package/src/market-data/fund-facts.ts +50 -0
- package/src/market-data/market/change-basis.ts +16 -3
- package/src/market-data/market/format.ts +25 -0
- package/src/market-data/market/freshness.ts +2 -1
- package/src/market-data/options-alternatives.ts +81 -4
- package/src/news/aggregator.ts +113 -9
- package/src/news/cloud-session.ts +21 -0
- package/src/news/hooks.ts +1 -0
- package/src/news/news-model.ts +1 -0
- package/src/news/types.ts +11 -0
- package/src/plugins/builtin/alerts/alert-engine.ts +20 -1
- package/src/plugins/builtin/alerts/alert-log.ts +33 -0
- package/src/plugins/builtin/alerts/cli-forms.ts +216 -0
- package/src/plugins/builtin/alerts/cli.ts +336 -77
- package/src/plugins/builtin/alerts/command.ts +25 -1
- package/src/plugins/builtin/alerts/events-pane.tsx +19 -4
- package/src/plugins/builtin/alerts/fired-log.ts +73 -9
- package/src/plugins/builtin/alerts/format.ts +75 -5
- package/src/plugins/builtin/alerts/headless.ts +24 -6
- package/src/plugins/builtin/alerts/history-rows.ts +3 -2
- package/src/plugins/builtin/alerts/history.ts +1 -1
- package/src/plugins/builtin/alerts/index.tsx +79 -16
- package/src/plugins/builtin/alerts/metric-command.ts +77 -4
- package/src/plugins/builtin/alerts/metric-data.ts +54 -13
- package/src/plugins/builtin/alerts/metric-model.ts +163 -14
- package/src/plugins/builtin/alerts/metric-parity-fixture.json +1 -1
- package/src/plugins/builtin/alerts/pane.tsx +61 -23
- package/src/plugins/builtin/alerts/quotes.ts +6 -0
- package/src/plugins/builtin/alerts/storage.ts +12 -8
- package/src/plugins/builtin/alerts/types.ts +4 -0
- package/src/plugins/builtin/analytics/index.tsx +2 -1
- package/src/plugins/builtin/analytics/risk-client.ts +16 -5
- package/src/plugins/builtin/analytics/risk-fx.ts +70 -15
- package/src/plugins/builtin/analytics/risk-headless.ts +27 -0
- package/src/plugins/builtin/analytics/risk-model.ts +55 -9
- package/src/plugins/builtin/analytics/risk-pane.tsx +8 -2
- package/src/plugins/builtin/attention/index.tsx +2 -1
- package/src/plugins/builtin/attention/listing.ts +14 -0
- package/src/plugins/builtin/broker-manager/index.tsx +7 -3
- package/src/plugins/builtin/buildout/cells.tsx +12 -4
- package/src/plugins/builtin/buildout/format.ts +38 -0
- package/src/plugins/builtin/buildout/model/normalizers.ts +36 -1
- package/src/plugins/builtin/buildout/pane/index.tsx +4 -1
- package/src/plugins/builtin/buildout/table-model.ts +23 -2
- package/src/plugins/builtin/builtin-plugin-meta.ts +6 -2
- package/src/plugins/builtin/changelog/index.tsx +9 -6
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +3 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +4 -0
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +7 -0
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -2
- package/src/plugins/builtin/chart-composer/headless-schema.ts +7 -1
- package/src/plugins/builtin/chart-composer/headless.ts +6 -1
- package/src/plugins/builtin/chart-composer/index.tsx +1 -1
- package/src/plugins/builtin/chart-composer/pane.tsx +37 -8
- package/src/plugins/builtin/chart-composer/settings.ts +27 -0
- package/src/plugins/builtin/chat/content/command-suggestions.ts +1 -0
- package/src/plugins/builtin/chat/pane-links/commands.ts +7 -1
- package/src/plugins/builtin/clinical-trials/model.ts +0 -9
- package/src/plugins/builtin/clinical-trials/pane.tsx +15 -22
- package/src/plugins/builtin/clinical-trials/sponsor-tickers.ts +8 -6
- package/src/plugins/builtin/cloud/askg/manifest.ts +2 -0
- package/src/plugins/builtin/company-attention/building.tsx +5 -1
- package/src/plugins/builtin/company-attention/client.ts +8 -9
- package/src/plugins/builtin/company-attention/evidence.ts +4 -1
- package/src/plugins/builtin/company-attention/moves.tsx +5 -1
- package/src/plugins/builtin/company-attention/pane.tsx +9 -2
- package/src/plugins/builtin/company-attention/signals.tsx +5 -1
- package/src/plugins/builtin/correlation/headless.ts +13 -5
- package/src/plugins/builtin/correlation/history.ts +22 -0
- package/src/plugins/builtin/cot/client.ts +22 -18
- package/src/plugins/builtin/cot/headless.ts +15 -10
- package/src/plugins/builtin/cot/model.ts +14 -1
- package/src/plugins/builtin/cot/pane.tsx +22 -14
- package/src/plugins/builtin/credit-boards/client.ts +6 -10
- package/src/plugins/builtin/credit-conditions/headless.ts +8 -2
- package/src/plugins/builtin/credit-conditions/index.tsx +5 -1
- package/src/plugins/builtin/credit-conditions/model.ts +4 -0
- package/src/plugins/builtin/credit-conditions/series.ts +3 -1
- package/src/plugins/builtin/credit-documents/detail.tsx +2 -2
- package/src/plugins/builtin/credit-documents/export.ts +173 -0
- package/src/plugins/builtin/credit-documents/headless.ts +7 -7
- package/src/plugins/builtin/credit-documents/model.ts +104 -14
- package/src/plugins/builtin/credit-documents/pane.tsx +12 -5
- package/src/plugins/builtin/custom-view/sources.ts +2 -0
- package/src/plugins/builtin/dividend-yield/client.ts +131 -23
- package/src/plugins/builtin/dividend-yield/headless.ts +44 -16
- package/src/plugins/builtin/dividend-yield/model.ts +8 -5
- package/src/plugins/builtin/dividend-yield/pane.tsx +38 -13
- package/src/plugins/builtin/dividend-yield/ranking.ts +37 -14
- package/src/plugins/builtin/dividend-yield/types.ts +20 -2
- package/src/plugins/builtin/dividend-yield/view.ts +30 -2
- package/src/plugins/builtin/docs/targets.ts +5 -1
- package/src/plugins/builtin/earnings/board-model.ts +16 -15
- package/src/plugins/builtin/earnings/board.tsx +62 -71
- package/src/plugins/builtin/earnings/headless.ts +40 -4
- package/src/plugins/builtin/earnings/scope.ts +31 -43
- package/src/plugins/builtin/earnings-calls/calendar.tsx +2 -2
- package/src/plugins/builtin/earnings-calls/format.ts +31 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +7 -2
- package/src/plugins/builtin/earnings-calls/model.ts +6 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +5 -4
- package/src/plugins/builtin/econ/types.ts +2 -0
- package/src/plugins/builtin/econ-statistics/defs.ts +6 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +6 -4
- package/src/plugins/builtin/econ-statistics/stats.ts +36 -9
- package/src/plugins/builtin/equity-screener/categories.ts +179 -0
- package/src/plugins/builtin/equity-screener/client.ts +4 -2
- package/src/plugins/builtin/equity-screener/headless.ts +144 -13
- package/src/plugins/builtin/equity-screener/ideas.ts +49 -0
- package/src/plugins/builtin/equity-screener/model.ts +99 -10
- package/src/plugins/builtin/equity-screener/pane.tsx +68 -13
- package/src/plugins/builtin/fixed-income/pane.tsx +2 -1
- package/src/plugins/builtin/futures/use-board-terms.ts +42 -28
- package/src/plugins/builtin/futures/use-front-returns.ts +45 -28
- package/src/plugins/builtin/fx-matrix/client.ts +6 -3
- package/src/plugins/builtin/fx-matrix/headless.ts +1 -1
- package/src/plugins/builtin/fx-matrix/index.tsx +4 -2
- package/src/plugins/builtin/fx-matrix/live-legs.ts +42 -3
- package/src/plugins/builtin/gpu/headless.ts +8 -2
- package/src/plugins/builtin/help/function-index.ts +4 -1
- package/src/plugins/builtin/help/index.tsx +1 -0
- package/src/plugins/builtin/help/shortcut-model.ts +1 -1
- package/src/plugins/builtin/holders/fund-holders.ts +51 -0
- package/src/plugins/builtin/holders/headless.ts +18 -1
- package/src/plugins/builtin/iv-history/client.ts +52 -11
- package/src/plugins/builtin/iv-history/format.ts +36 -23
- package/src/plugins/builtin/iv-history/headless.ts +33 -18
- package/src/plugins/builtin/iv-history/index.tsx +2 -2
- package/src/plugins/builtin/iv-history/model.ts +163 -27
- package/src/plugins/builtin/iv-history/pane.tsx +10 -6
- package/src/plugins/builtin/iv-history/screen-pane.tsx +22 -15
- package/src/plugins/builtin/iv-history/universe.ts +5 -1
- package/src/plugins/builtin/jobs/client.ts +25 -29
- package/src/plugins/builtin/kelly-sizer/model.ts +12 -8
- package/src/plugins/builtin/kelly-sizer/pane.tsx +9 -9
- package/src/plugins/builtin/kelly-sizer/sections.tsx +19 -10
- package/src/plugins/builtin/kelly-sizer/types.ts +10 -4
- package/src/plugins/builtin/macro-day/release-table.ts +2 -2
- package/src/plugins/builtin/market-heatmap/data.ts +8 -33
- package/src/plugins/builtin/market-movers/client.ts +25 -7
- package/src/plugins/builtin/market-movers/headless.ts +32 -12
- package/src/plugins/builtin/market-movers/index.tsx +26 -14
- package/src/plugins/builtin/market-movers/min-float.ts +74 -0
- package/src/plugins/builtin/market-movers/model.ts +4 -1
- package/src/plugins/builtin/market-movers/screener.ts +14 -0
- package/src/plugins/builtin/market-movers/session-body.tsx +13 -8
- package/src/plugins/builtin/market-movers/session-table.ts +4 -3
- package/src/plugins/builtin/market-movers/table.ts +17 -5
- package/src/plugins/builtin/members/breadth-pane.tsx +2 -1
- package/src/plugins/builtin/news/index.tsx +1 -0
- package/src/plugins/builtin/news/wire/categories.ts +19 -3
- package/src/plugins/builtin/news/wire/industry-pane.tsx +1 -0
- package/src/plugins/builtin/news/wire/news/footer.ts +31 -5
- package/src/plugins/builtin/news/wire/news/preset-pane.tsx +6 -1
- package/src/plugins/builtin/news/wire/news/table.tsx +2 -2
- package/src/plugins/builtin/openfda/client.ts +14 -2
- package/src/plugins/builtin/openfda/index.tsx +3 -2
- package/src/plugins/builtin/openfda/model.ts +9 -0
- package/src/plugins/builtin/openfda/pane.tsx +42 -6
- package/src/plugins/builtin/options/analytics.ts +29 -5
- package/src/plugins/builtin/options/enrichment.ts +17 -5
- package/src/plugins/builtin/options/table.ts +5 -2
- package/src/plugins/builtin/options/types.ts +2 -0
- package/src/plugins/builtin/options/view.tsx +17 -4
- package/src/plugins/builtin/options-positioning/client.ts +11 -0
- package/src/plugins/builtin/options-positioning/headless.ts +21 -8
- package/src/plugins/builtin/options-positioning/index.tsx +1 -1
- package/src/plugins/builtin/options-positioning/model.ts +78 -9
- package/src/plugins/builtin/options-positioning/pane.tsx +21 -6
- package/src/plugins/builtin/options-scenario/client.ts +116 -47
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +142 -10
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +206 -55
- package/src/plugins/builtin/options-scenario/csp-screen.ts +63 -23
- package/src/plugins/builtin/options-scenario/csp.ts +8 -2
- package/src/plugins/builtin/options-scenario/index.tsx +9 -7
- package/src/plugins/builtin/options-scenario/strategy-screen.ts +532 -0
- package/src/plugins/builtin/pe-band/model.ts +12 -49
- package/src/plugins/builtin/perps/cascade-tabs.tsx +161 -0
- package/src/plugins/builtin/perps/cascade.ts +236 -0
- package/src/plugins/builtin/perps/client.ts +56 -2
- package/src/plugins/builtin/perps/headless.ts +65 -9
- package/src/plugins/builtin/perps/index.tsx +7 -5
- package/src/plugins/builtin/perps/model.ts +18 -4
- package/src/plugins/builtin/perps/pane.tsx +19 -22
- package/src/plugins/builtin/perps/status-line.ts +25 -0
- package/src/plugins/builtin/plugin-module.ts +5 -1
- package/src/plugins/builtin/portfolio-list/cached-account.ts +3 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +2 -8
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +4 -4
- package/src/plugins/builtin/portfolio-list/cli/render.ts +7 -5
- package/src/plugins/builtin/portfolio-list/pane/futures-front.ts +40 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +4 -1
- package/src/plugins/builtin/portfolio-list/pane/streaming.ts +5 -2
- package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +3 -2
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +3 -1
- package/src/plugins/builtin/portfolio-list/table.tsx +11 -3
- package/src/plugins/builtin/primary-dealers/client.ts +13 -38
- package/src/plugins/builtin/realized-vol/index.tsx +2 -2
- package/src/plugins/builtin/realized-vol/pane.tsx +3 -3
- package/src/plugins/builtin/relative-rotation/client.ts +18 -4
- package/src/plugins/builtin/relative-rotation/headless.ts +3 -3
- package/src/plugins/builtin/relative-rotation/index.tsx +2 -1
- package/src/plugins/builtin/relative-rotation/model.ts +16 -40
- package/src/plugins/builtin/relative-rotation/pane.tsx +3 -2
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +3 -2
- package/src/plugins/builtin/research/event-model.ts +10 -8
- package/src/plugins/builtin/research/headless.ts +1 -1
- package/src/plugins/builtin/research/relative-valuation-headless.ts +5 -1
- package/src/plugins/builtin/research/relative-valuation-model.ts +31 -3
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +7 -5
- package/src/plugins/builtin/reverse-dcf/headless.ts +5 -3
- package/src/plugins/builtin/reverse-dcf/model.ts +61 -6
- package/src/plugins/builtin/reverse-dcf/pane.tsx +7 -4
- package/src/plugins/builtin/scanner/flow-model.ts +50 -4
- package/src/plugins/builtin/scanner/flow-pane.tsx +367 -65
- package/src/plugins/builtin/scanner/flow-session.ts +146 -0
- package/src/plugins/builtin/scanner/headless.ts +204 -35
- package/src/plugins/builtin/scanner/index.ts +16 -5
- package/src/plugins/builtin/scanner/live-headless.ts +27 -3
- package/src/plugins/builtin/scanner/live-model.ts +11 -0
- package/src/plugins/builtin/scanner/live-pane.tsx +3 -3
- package/src/plugins/builtin/scanner/lock-note.ts +3 -2
- package/src/plugins/builtin/seasonality/headless.ts +10 -1
- package/src/plugins/builtin/sec/fund-facts-view.tsx +5 -2
- package/src/plugins/builtin/sec/fund-facts.ts +116 -34
- package/src/plugins/builtin/sec/headless.ts +2 -1
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/cloud-resource.ts +3 -2
- package/src/plugins/builtin/shared/cloud-upgrade.ts +4 -3
- package/src/plugins/builtin/shared/earnings-calendar.ts +6 -2
- package/src/plugins/builtin/shared/earnings-report.ts +2 -2
- package/src/plugins/builtin/shared/job-posting.ts +1 -0
- package/src/plugins/builtin/shared/members-menu.tsx +3 -2
- package/src/plugins/builtin/shared/pro-lock-note.ts +12 -12
- package/src/plugins/builtin/shared/report-freshness.ts +3 -2
- package/src/plugins/builtin/shared/ticker-choice.tsx +2 -1
- package/src/plugins/builtin/shared/ticker-company.ts +77 -0
- package/src/plugins/builtin/shared/use-quote-board.ts +2 -1
- package/src/plugins/builtin/shared/volatility/live-session.ts +34 -8
- package/src/plugins/builtin/shared/volatility/pricing.ts +19 -0
- package/src/plugins/builtin/shared/wall-view-lifecycle.ts +3 -1
- package/src/plugins/builtin/themes/model.ts +16 -7
- package/src/plugins/builtin/themes/pane.tsx +5 -5
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +43 -18
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +3 -2
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +62 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +83 -46
- package/src/plugins/builtin/ticker-detail/headless.ts +31 -16
- package/src/plugins/builtin/ticker-detail/overview/model.ts +1 -1
- package/src/plugins/builtin/ticker-detail/pane.tsx +3 -2
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/settings.ts +1 -0
- package/src/plugins/builtin/time-sales/pane.tsx +31 -19
- package/src/plugins/builtin/treasury-daily/client.ts +41 -5
- package/src/plugins/builtin/treasury-daily/headless.ts +2 -2
- package/src/plugins/builtin/treasury-daily/index.tsx +1 -1
- package/src/plugins/builtin/treasury-daily/model.ts +50 -3
- package/src/plugins/builtin/treasury-daily/pane.tsx +81 -2
- package/src/plugins/builtin/vol-surface/client.ts +3 -13
- package/src/plugins/builtin/vol-surface/headless.ts +3 -3
- package/src/plugins/builtin/vol-surface/index.tsx +1 -1
- package/src/plugins/builtin/vol-surface/pane.tsx +7 -5
- package/src/plugins/builtin/volatility/index.tsx +2 -2
- package/src/plugins/builtin/volatility/pane.tsx +2 -2
- package/src/plugins/builtin/world-venue-map/headless.ts +3 -3
- package/src/plugins/catalog-manifest.ts +2 -1
- package/src/plugins/marketplace/model.ts +18 -5
- package/src/portfolio/futures-positions.ts +6 -3
- package/src/portfolio/position-quantity.ts +15 -9
- package/src/remote/resources.ts +2 -1
- package/src/renderers/dom/data-table/row.tsx +26 -0
- package/src/renderers/dom/desktop/list-view.tsx +13 -10
- package/src/renderers/dom/desktop/query-bar.tsx +4 -2
- package/src/renderers/dom/desktop/select-field.tsx +4 -2
- package/src/renderers/dom/host/chart-surface.tsx +21 -0
- package/src/renderers/electrobun/bun/desktop/app-name.ts +3 -3
- package/src/renderers/electrobun/bun/desktop/backend.ts +12 -0
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +7 -0
- package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -0
- package/src/renderers/electrobun/bun/desktop/update.ts +115 -14
- package/src/renderers/electrobun/bun/desktop/view-ids.ts +52 -0
- package/src/renderers/electrobun/shared/app-name.ts +13 -0
- package/src/renderers/electrobun/shared/protocol.ts +10 -0
- package/src/renderers/electrobun/view/backend-rpc.ts +6 -0
- package/src/renderers/electrobun/view/main.tsx +24 -1
- package/src/renderers/electrobun/view/news-source.ts +3 -1
- package/src/renderers/electrobun/view/remote/ticker-repository.ts +14 -7
- package/src/renderers/electrobun/view/view-ids.ts +85 -0
- package/src/renderers/opentui/start.tsx +5 -0
- package/src/series/registry.ts +1 -0
- package/src/series/types.ts +6 -0
- package/src/series/validate.ts +1 -0
- package/src/sources/gloomberb-cloud/index.ts +1 -0
- package/src/sources/gloomberb-cloud/news.ts +47 -7
- package/src/sources/provider-router/financials.ts +15 -3
- package/src/sources/provider-router/index.ts +8 -5
- package/src/state/ticker-cleanup.ts +50 -0
- package/src/sync/controller.ts +4 -3
- package/src/sync/core-contributors.ts +90 -31
- package/src/telemetry/stall-reports-dom.ts +38 -0
- package/src/telemetry/stall-reports-node.ts +75 -0
- package/src/telemetry/stall-reports.ts +214 -0
- package/src/test-support/preload.ts +14 -0
- package/src/theme/themes.ts +10 -0
- package/src/tickers/company-name.ts +44 -3
- package/src/tickers/listing-venues.ts +15 -3
- package/src/tickers/terminal-codes.ts +19 -0
- package/src/time-series/alignment.ts +1 -1
- package/src/time-series/economic.ts +18 -4
- package/src/time-series/field-catalog.ts +1 -1
- package/src/time-series/filed-trailing-eps.ts +197 -0
- package/src/time-series/fundamentals.ts +44 -1
- package/src/time-series/ice-credit.ts +3 -0
- package/src/time-series/price-comparison.ts +30 -2
- package/src/time-series/resolve-context.ts +3 -1
- package/src/time-series/resolve.ts +56 -4
- package/src/time-series/session-bar.ts +11 -0
- package/src/time-series/spec.ts +3 -2
- package/src/time-series/studies.ts +8 -2
- package/src/time-series/total-return.ts +160 -0
- package/src/time-series/transforms.ts +2 -3
- package/src/time-series/types.ts +22 -1
- package/src/types/financials.ts +32 -1
- package/src/types/headless.ts +21 -3
- package/src/types/news-source.ts +1 -0
- package/src/types/plugin.ts +9 -0
- package/src/ui/host.tsx +3 -0
- package/src/updater/failure.ts +4 -1
- package/src/utils/cli-output.ts +42 -1
- package/src/utils/crypto-pair.ts +44 -0
- package/src/utils/forward-dividend.ts +2 -0
- package/src/utils/fundamentals.ts +24 -3
- package/src/utils/fx-market-hours.ts +26 -3
- package/src/utils/main-thread-stall.ts +35 -2
- package/src/utils/market-capitalization.ts +24 -1
- package/src/utils/price-history.ts +7 -1
- package/src/utils/shell-word.ts +8 -0
- package/src/utils/trailing-dividend.ts +53 -4
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +0 -17
package/src/api-client/types.ts
CHANGED
|
@@ -518,10 +518,16 @@ export interface CloudEconEventPayload {
|
|
|
518
518
|
source?: { name: string; url?: string };
|
|
519
519
|
/**
|
|
520
520
|
* The indicator this release is of, the same from one release to the next
|
|
521
|
-
* (
|
|
522
|
-
*
|
|
521
|
+
* (`us-unemployment-rate` on every month's row), where `id` names the one
|
|
522
|
+
* row. Absent from a server that names none; exports leave the column empty.
|
|
523
523
|
*/
|
|
524
524
|
indicatorId?: string | null;
|
|
525
|
+
/**
|
|
526
|
+
* Where the forecast (the consensus) was read from, `week-feed` or
|
|
527
|
+
* `release-calendar`, and when that feed was read. Absent on a row with no
|
|
528
|
+
* forecast and on one kept before the read was recorded.
|
|
529
|
+
*/
|
|
530
|
+
consensus?: { source: string; readAt: string } | null;
|
|
525
531
|
}
|
|
526
532
|
|
|
527
533
|
/** One currency's short-term rate, as GET /cloud/econ/short-rates serves it. */
|
|
@@ -891,6 +897,13 @@ export interface CloudEarningsCallPayload {
|
|
|
891
897
|
* New York day). Absent from a server that predates it.
|
|
892
898
|
*/
|
|
893
899
|
callTimeKnown?: boolean;
|
|
900
|
+
/**
|
|
901
|
+
* "other" for an event that is not an earnings call (a deal call, a
|
|
902
|
+
* conference, an investor day), named by eventLabel and with no fiscal
|
|
903
|
+
* period; null when unclear. Older servers omit both.
|
|
904
|
+
*/
|
|
905
|
+
eventKind?: "earnings" | "other" | null;
|
|
906
|
+
eventLabel?: string | null;
|
|
894
907
|
}
|
|
895
908
|
|
|
896
909
|
interface CloudJobsSeriesPoint {
|
|
@@ -1255,6 +1268,13 @@ export interface CloudEarningsTranscriptPayload {
|
|
|
1255
1268
|
companyName: string | null;
|
|
1256
1269
|
fiscalYear: number | null;
|
|
1257
1270
|
fiscalQuarter: number | null;
|
|
1271
|
+
/**
|
|
1272
|
+
* "other" for an event that is not an earnings call (a deal call, a
|
|
1273
|
+
* conference, an investor day), named by eventLabel and with no fiscal
|
|
1274
|
+
* period; null when unclear. Older servers omit both.
|
|
1275
|
+
*/
|
|
1276
|
+
eventKind?: "earnings" | "other" | null;
|
|
1277
|
+
eventLabel?: string | null;
|
|
1258
1278
|
callAt: string | null;
|
|
1259
1279
|
timing: string | null;
|
|
1260
1280
|
webcastUrl: string | null;
|
|
@@ -1536,6 +1556,8 @@ export interface CloudNewsPayload {
|
|
|
1536
1556
|
export interface CloudNewsListResponse {
|
|
1537
1557
|
items: CloudNewsPayload[];
|
|
1538
1558
|
nextCursor: string | null;
|
|
1559
|
+
/** Which news the service answered with, when it says: the live wire, or the one held back for a free account. */
|
|
1560
|
+
access?: "realtime" | "delayed";
|
|
1539
1561
|
}
|
|
1540
1562
|
|
|
1541
1563
|
interface CloudTweetUserPayload {
|
|
@@ -1739,6 +1761,14 @@ export interface CloudMarketScreenerItem extends CloudMoverSessionFields {
|
|
|
1739
1761
|
exchange: string;
|
|
1740
1762
|
lastUpdated: number;
|
|
1741
1763
|
dataSource: "live";
|
|
1764
|
+
/** The listing's float as the equity screener serves it; absent where it serves none. */
|
|
1765
|
+
floatShares?: number;
|
|
1766
|
+
/** Set with a float the source states no measurement date for: `partial`. */
|
|
1767
|
+
floatSharesState?: "partial";
|
|
1768
|
+
/** Why the float is partial, as the server says it. */
|
|
1769
|
+
floatSharesReason?: string;
|
|
1770
|
+
/** When the statistics the float is read from were retrieved (ISO). */
|
|
1771
|
+
floatSharesRetrievedAt?: string;
|
|
1742
1772
|
}
|
|
1743
1773
|
|
|
1744
1774
|
export interface CloudMarketScreenerPayload {
|
|
@@ -1933,6 +1963,44 @@ export interface ScannerFlowHistoryPage {
|
|
|
1933
1963
|
hasMore: boolean;
|
|
1934
1964
|
}
|
|
1935
1965
|
|
|
1966
|
+
/**
|
|
1967
|
+
* Premium of a slice of the session's recorded prints by where it traded: at
|
|
1968
|
+
* or above the ask (bought) or at or below the bid (sold). Mid and unknown
|
|
1969
|
+
* prints count as neither.
|
|
1970
|
+
*/
|
|
1971
|
+
interface ScannerFlowSidePremium {
|
|
1972
|
+
callAsk: number;
|
|
1973
|
+
callBid: number;
|
|
1974
|
+
putAsk: number;
|
|
1975
|
+
putBid: number;
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
/** The session's prints in one time bucket, which starts at `at`. */
|
|
1979
|
+
export interface ScannerFlowSessionBucket extends ScannerFlowSidePremium {
|
|
1980
|
+
at: number;
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
/** What one name printed at one expiry and strike during the session. */
|
|
1984
|
+
export interface ScannerFlowSessionStrike extends ScannerFlowSidePremium {
|
|
1985
|
+
expiry: string;
|
|
1986
|
+
strike: number;
|
|
1987
|
+
/** Every call print's premium, mid and unknown included. */
|
|
1988
|
+
callPremium: number;
|
|
1989
|
+
putPremium: number;
|
|
1990
|
+
prints: number;
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1993
|
+
/** The latest session's recorded prints under the FLOW pane's filters, summed. */
|
|
1994
|
+
export interface ScannerFlowSession {
|
|
1995
|
+
/** The New York date of the session; null before any print was recorded. */
|
|
1996
|
+
session: string | null;
|
|
1997
|
+
bucketMs: number;
|
|
1998
|
+
/** Buckets with a matching print, oldest first. */
|
|
1999
|
+
buckets: ScannerFlowSessionBucket[];
|
|
2000
|
+
/** Only when one name was asked for: most premium first. */
|
|
2001
|
+
strikes: ScannerFlowSessionStrike[] | null;
|
|
2002
|
+
}
|
|
2003
|
+
|
|
1936
2004
|
export type ScannerPayload = ScannerHiloPayload | ScannerFlowPayload;
|
|
1937
2005
|
|
|
1938
2006
|
/** What a scanner subscriber receives: data, or the entitlement refusal. */
|
|
@@ -513,13 +513,17 @@ export function bindAppPanePluginRegistry({
|
|
|
513
513
|
removeExternalPlugin(pluginId, directory);
|
|
514
514
|
},
|
|
515
515
|
contributions: (pluginId) => {
|
|
516
|
+
// An unlisted function (`listed: false`) and a pane only it opens are left out, as of every list.
|
|
517
|
+
const registered = pluginRegistry.getPluginPaneTemplateIds(pluginId)
|
|
518
|
+
.map((id) => ({ id, template: pluginRegistry.paneTemplates.get(id) }));
|
|
519
|
+
const listedPaneIds = new Set(registered.flatMap(({ template }) => template && template.listed !== false ? [template.paneId] : []));
|
|
520
|
+
const unlistedPaneIds = new Set(registered.flatMap(({ template }) => template?.listed === false && !listedPaneIds.has(template.paneId) ? [template.paneId] : []));
|
|
516
521
|
const panes = pluginRegistry.getPluginPaneIds(pluginId)
|
|
522
|
+
.filter((id) => !unlistedPaneIds.has(id))
|
|
517
523
|
.map((id) => ({ id, name: pluginRegistry.panes.get(id)?.name ?? id }));
|
|
518
|
-
const templates =
|
|
519
|
-
.
|
|
520
|
-
|
|
521
|
-
return { id, label: template?.label ?? id, ...(template?.shortcut?.prefix ? { prefix: template.shortcut.prefix } : {}) };
|
|
522
|
-
});
|
|
524
|
+
const templates = registered
|
|
525
|
+
.filter(({ template }) => template?.listed !== false)
|
|
526
|
+
.map(({ id, template }) => ({ id, label: template?.label ?? id, ...(template?.shortcut?.prefix ? { prefix: template.shortcut.prefix } : {}) }));
|
|
523
527
|
const commands = [...pluginRegistry.commands.entries()]
|
|
524
528
|
.filter(([id]) => pluginRegistry.getCommandPluginId(id) === pluginId && !id.endsWith(":setup"))
|
|
525
529
|
.map(([id, command]) => ({ id, label: command.label, ...(command.shortcut ? { shortcut: command.shortcut } : {}) }));
|
|
@@ -28,7 +28,6 @@ export interface AppBrokerImportRuntime {
|
|
|
28
28
|
interface BrokerImportOptions {
|
|
29
29
|
refreshImportedTickers?: boolean;
|
|
30
30
|
config?: AppConfig;
|
|
31
|
-
persistResolvedBrokerConfig?: boolean;
|
|
32
31
|
signal?: AbortSignal;
|
|
33
32
|
onCommitStart?: () => void;
|
|
34
33
|
onCommitEnd?: () => void;
|
|
@@ -122,7 +121,6 @@ export function useBrokerImportRuntime({
|
|
|
122
121
|
tickerRepository,
|
|
123
122
|
existingTickers: tickerMap ?? new Map(stateRef.current.tickers),
|
|
124
123
|
resources: pluginRegistry.persistence.resources,
|
|
125
|
-
persistResolvedBrokerConfig: options?.persistResolvedBrokerConfig,
|
|
126
124
|
signal: options?.signal,
|
|
127
125
|
deferPersistence: true,
|
|
128
126
|
});
|
|
@@ -10,6 +10,8 @@ import type { MarketDataCoordinator } from "../../market-data/coordinator";
|
|
|
10
10
|
import { instrumentFromTicker } from "../../market-data/request-types";
|
|
11
11
|
import type { PluginRegistry } from "../../plugins/registry";
|
|
12
12
|
import { saveConfigImmediately } from "../../state/config-save-scheduler";
|
|
13
|
+
import { persistTickerCleanup } from "../../state/ticker-cleanup";
|
|
14
|
+
import { hasPendingTickerWrites } from "../../data/ticker-writes";
|
|
13
15
|
import { settleWithin } from "../../utils/async-deadline";
|
|
14
16
|
import type { AppAction, AppState } from "../../state/app/context";
|
|
15
17
|
import type { AppConfig, BrokerInstanceConfig } from "../../types/config";
|
|
@@ -215,66 +217,81 @@ export function bindPluginRegistryRuntimeAccess({
|
|
|
215
217
|
else removedPortfolioIds.add(portfolio.id);
|
|
216
218
|
}
|
|
217
219
|
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
220
|
+
const removeProfile = (config: AppConfig): AppConfig => ({
|
|
221
|
+
...config,
|
|
222
|
+
brokerInstances: config.brokerInstances.filter((entry) => entry.id !== instanceId),
|
|
223
|
+
portfolios: config.portfolios.flatMap((portfolio) => {
|
|
224
|
+
if (removedPortfolioIds.has(portfolio.id)) return [];
|
|
225
|
+
const heirId = heirs.get(portfolio.id);
|
|
226
|
+
return [heirId ? { ...portfolio, brokerInstanceId: heirId } : portfolio];
|
|
227
|
+
}),
|
|
222
228
|
});
|
|
223
|
-
const nextTickers = new Map(stateRef.current.tickers);
|
|
224
|
-
const nextBrokerInstances = stateRef.current.config.brokerInstances.filter((entry) => entry.id !== instanceId);
|
|
225
|
-
// What older removals and pulls from other devices left behind goes as well.
|
|
226
|
-
const known = knownBrokerHoldings({ portfolios: nextPortfolios, brokerInstances: nextBrokerInstances });
|
|
227
229
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
metadata
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
230
|
+
const cleanTickers = () => persistTickerCleanup({
|
|
231
|
+
tickerRepository,
|
|
232
|
+
getTickers: () => stateRef.current.tickers,
|
|
233
|
+
transform: (ticker) => {
|
|
234
|
+
// A position without a profile came from another device's sync of this one.
|
|
235
|
+
const nextPositions = ticker.metadata.positions.filter((position) => position.brokerInstanceId !== instanceId
|
|
236
|
+
&& !(removedPortfolioIds.has(position.portfolio) && !position.brokerInstanceId));
|
|
237
|
+
const heldPortfolioIds = new Set(nextPositions.map((position) => position.portfolio));
|
|
238
|
+
const nextPortfolioRefs = ticker.metadata.portfolios.filter((portfolioId) =>
|
|
239
|
+
!removedPortfolioIds.has(portfolioId) && (!heirs.has(portfolioId) || heldPortfolioIds.has(portfolioId)));
|
|
240
|
+
const nextBrokerContracts = (ticker.metadata.broker_contracts ?? []).filter((contract) => contract.brokerInstanceId !== instanceId);
|
|
241
|
+
const changed = nextPositions.length !== ticker.metadata.positions.length
|
|
242
|
+
|| nextPortfolioRefs.length !== ticker.metadata.portfolios.length
|
|
243
|
+
|| nextBrokerContracts.length !== (ticker.metadata.broker_contracts ?? []).length;
|
|
244
|
+
const removedTicker: TickerRecord = changed ? {
|
|
245
|
+
...ticker,
|
|
246
|
+
metadata: {
|
|
247
|
+
...ticker.metadata,
|
|
248
|
+
positions: nextPositions,
|
|
249
|
+
portfolios: nextPortfolioRefs,
|
|
250
|
+
broker_contracts: nextBrokerContracts,
|
|
251
|
+
},
|
|
252
|
+
} : ticker;
|
|
253
|
+
// Also clear holdings left behind by older removals or pulls.
|
|
254
|
+
const known = knownBrokerHoldings(removeProfile(stateRef.current.config));
|
|
255
|
+
const nextTicker = clearLeftoverBrokerHoldings(removedTicker, known) ?? removedTicker;
|
|
256
|
+
if (nextTicker === ticker) return ticker;
|
|
257
|
+
const empty = nextTicker.metadata.positions.length === 0
|
|
258
|
+
&& nextTicker.metadata.portfolios.length === 0
|
|
259
|
+
&& nextTicker.metadata.watchlists.length === 0
|
|
260
|
+
&& (nextTicker.metadata.broker_contracts ?? []).length === 0
|
|
261
|
+
&& nextTicker.metadata.tags.length === 0
|
|
262
|
+
&& Object.keys(nextTicker.metadata.custom).length === 0;
|
|
263
|
+
return empty ? null : nextTicker;
|
|
264
|
+
},
|
|
265
|
+
publish: (symbol, ticker) => {
|
|
266
|
+
if (ticker) dispatch({ type: "UPDATE_TICKER", ticker });
|
|
267
|
+
else {
|
|
268
|
+
dispatch({ type: "REMOVE_TICKER", symbol });
|
|
269
|
+
pluginRegistry.events.emit("ticker:removed", { symbol });
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
});
|
|
255
273
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
274
|
+
// Keep the profile available for retry until cleanup and config both
|
|
275
|
+
// succeed. Rebase after callbacks and edits, including during config saves.
|
|
276
|
+
let savedRemoval = false;
|
|
277
|
+
for (;;) {
|
|
278
|
+
const cleaned = await cleanTickers().catch(async (error: unknown) => {
|
|
279
|
+
// A config acknowledgement can precede a late row write. If that
|
|
280
|
+
// cleanup fails, keep its removal intent durable for a restart too.
|
|
281
|
+
if (savedRemoval) await saveConfigImmediately(stateRef.current.config);
|
|
282
|
+
throw error;
|
|
283
|
+
});
|
|
284
|
+
if (hasPendingTickerWrites(tickerRepository) || stateRef.current.tickers !== cleaned) continue;
|
|
285
|
+
const source = stateRef.current.config;
|
|
286
|
+
const nextConfig = removeProfile(source);
|
|
287
|
+
await saveConfigImmediately(nextConfig);
|
|
288
|
+
savedRemoval = true;
|
|
289
|
+
if (stateRef.current.config !== source || stateRef.current.tickers !== cleaned
|
|
290
|
+
|| hasPendingTickerWrites(tickerRepository)) continue;
|
|
291
|
+
dispatch({ type: "SET_CONFIG", config: nextConfig });
|
|
292
|
+
pluginRegistry.events.emit("config:changed", { config: nextConfig });
|
|
293
|
+
break;
|
|
266
294
|
}
|
|
267
|
-
|
|
268
|
-
const nextConfig = {
|
|
269
|
-
...stateRef.current.config,
|
|
270
|
-
brokerInstances: nextBrokerInstances,
|
|
271
|
-
portfolios: nextPortfolios,
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
dispatch({ type: "SET_CONFIG", config: nextConfig });
|
|
275
|
-
dispatch({ type: "SET_TICKERS", tickers: nextTickers });
|
|
276
|
-
await saveConfigImmediately(nextConfig);
|
|
277
|
-
pluginRegistry.events.emit("config:changed", { config: nextConfig });
|
|
278
295
|
// The profile that kept a portfolio fills in what the removed one held there.
|
|
279
296
|
for (const heirId of new Set(heirs.values())) {
|
|
280
297
|
void importBrokerPositions(heirId).catch(logFailure("app.runtime.plugin-bindings", "Replacement broker positions import failed"));
|
|
@@ -53,6 +53,9 @@
|
|
|
53
53
|
"src/plugins/builtin/research-search/pane.tsx": {
|
|
54
54
|
"signInRequired || verificationRequired": "Signed out or unverified, every mode is the same sign-in wall."
|
|
55
55
|
},
|
|
56
|
+
"src/plugins/builtin/scanner/flow-pane.tsx": {
|
|
57
|
+
"!feed.denied": "Signed out or without Pro, every tab is the same sign-in or plan wall."
|
|
58
|
+
},
|
|
56
59
|
"src/plugins/builtin/shared/filing-year-reader.tsx": {
|
|
57
60
|
"years.length > 1": "The tabs are the filings on record, known once their list answers; a single filing has no other year to pick."
|
|
58
61
|
},
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"src/plugins/builtin/alerts/metric-model.ts": {
|
|
3
|
+
"deadline: now < cached.retryAt": "A byte-identical copy of Gloom Cloud's delivery model (metric-parity-fixture.json pins its hash), so it cannot import the helper. Its failed-read backoff is the rejectionMs rule; move it when both copies move together.",
|
|
4
|
+
"map: new Map<string, { day: string; retryAt: number; result: Promise<MetricReading>; }>()": "A byte-identical copy of Gloom Cloud's delivery model (metric-parity-fixture.json pins its hash), so it cannot import the helper. Its failed-read backoff is the rejectionMs rule; move it when both copies move together."
|
|
5
|
+
},
|
|
6
|
+
"src/plugins/builtin/cloud-tweets/table.tsx": {
|
|
7
|
+
"age: Date.now() - cached.fetchedAt < TWEET_CACHE_TTL_MS": "Feed results kept across tab switches and shown stale while a refetch runs; the entry's fetchedAt also drives the pane's auto-refresh and moves with every appended page, so the stamp is state the view reads.",
|
|
8
|
+
"map: new Map<string, { data: CloudTweetSearchResponse; fetchedAt: number; hasMore: boolean; }>()": "Feed results kept across tab switches and shown stale while a refetch runs; the entry's fetchedAt also drives the pane's auto-refresh and moves with every appended page, so the stamp is state the view reads."
|
|
9
|
+
},
|
|
10
|
+
"src/plugins/builtin/correlation/index.tsx": {
|
|
11
|
+
"map: new Map<string, { values: DailyClose[]; fetchedAt: number; }>()": "Not a TTL cache: the last good series per range, kept so a failed refresh still draws it. Nothing expires, and fetchedAt is shown with the data."
|
|
12
|
+
},
|
|
13
|
+
"src/plugins/builtin/portfolio-list/since-last-seen.ts": {
|
|
14
|
+
"map: new Map<string, Departure>()": "Not loaded data: what a pane showed when it went out of sight, read once on return against the reader's own away threshold, then used up."
|
|
15
|
+
},
|
|
16
|
+
"src/plugins/builtin/sec/command-bar-search.ts": {
|
|
17
|
+
"map: new Map<string, FocusRequest>()": "Not loaded data: a filing to focus handed from the command bar to the SEC pane, taken on first read and dropped after a few seconds unread."
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -32,7 +32,6 @@ export interface SyncBrokerInstanceArgs {
|
|
|
32
32
|
tickerRepository: AppTickerRepositoryPort;
|
|
33
33
|
existingTickers?: Map<string, TickerRecord>;
|
|
34
34
|
resources?: AppResourceStorePort;
|
|
35
|
-
persistResolvedBrokerConfig?: boolean;
|
|
36
35
|
signal?: AbortSignal;
|
|
37
36
|
deferPersistence?: boolean;
|
|
38
37
|
}
|
|
@@ -69,7 +68,6 @@ export interface SyncBrokerInstancesArgs {
|
|
|
69
68
|
tickerRepository: AppTickerRepositoryPort;
|
|
70
69
|
existingTickers: Map<string, TickerRecord>;
|
|
71
70
|
resources?: AppResourceStorePort;
|
|
72
|
-
persistResolvedBrokerConfig?: boolean;
|
|
73
71
|
/** Leave each result's ticker writes to `onResult`, which calls `result.commit()`. */
|
|
74
72
|
deferPersistence?: boolean;
|
|
75
73
|
onResult?: (result: SyncBrokerInstanceResult, instance: BrokerInstanceConfig, previousConfig: AppConfig) => void | Promise<void>;
|
|
@@ -168,9 +166,8 @@ async function maybePersistResolvedBrokerConfig(
|
|
|
168
166
|
config: AppConfig,
|
|
169
167
|
instance: BrokerInstanceConfig,
|
|
170
168
|
broker: BrokerAdapter,
|
|
171
|
-
persistResolvedBrokerConfig: boolean,
|
|
172
169
|
): Promise<AppConfig> {
|
|
173
|
-
if (!
|
|
170
|
+
if (!broker.getPersistedConfigUpdate) {
|
|
174
171
|
return config;
|
|
175
172
|
}
|
|
176
173
|
|
|
@@ -203,7 +200,6 @@ export async function syncBrokerInstance({
|
|
|
203
200
|
tickerRepository,
|
|
204
201
|
existingTickers,
|
|
205
202
|
resources,
|
|
206
|
-
persistResolvedBrokerConfig = false,
|
|
207
203
|
signal,
|
|
208
204
|
deferPersistence = false,
|
|
209
205
|
}: SyncBrokerInstanceArgs): Promise<SyncBrokerInstanceResult> {
|
|
@@ -336,7 +332,7 @@ export async function syncBrokerInstance({
|
|
|
336
332
|
: []);
|
|
337
333
|
|
|
338
334
|
nextConfig = removeStaleBrokerPortfolios(nextConfig, instance.id, currentPortfolioIds);
|
|
339
|
-
nextConfig = await maybePersistResolvedBrokerConfig(nextConfig, instance, broker
|
|
335
|
+
nextConfig = await maybePersistResolvedBrokerConfig(nextConfig, instance, broker);
|
|
340
336
|
throwIfBrokerImportCancelled(signal);
|
|
341
337
|
nextConfig = markBrokerInstanceSynced(nextConfig, instance.id, syncedAt);
|
|
342
338
|
const syncedConfig = nextConfig;
|
|
@@ -436,7 +432,6 @@ export async function syncBrokerInstances({
|
|
|
436
432
|
tickerRepository,
|
|
437
433
|
existingTickers,
|
|
438
434
|
resources,
|
|
439
|
-
persistResolvedBrokerConfig = false,
|
|
440
435
|
deferPersistence = false,
|
|
441
436
|
onResult,
|
|
442
437
|
}: SyncBrokerInstancesArgs): Promise<SyncBrokerInstancesResult> {
|
|
@@ -457,7 +452,6 @@ export async function syncBrokerInstances({
|
|
|
457
452
|
tickerRepository,
|
|
458
453
|
existingTickers: nextTickers,
|
|
459
454
|
resources,
|
|
460
|
-
persistResolvedBrokerConfig,
|
|
461
455
|
deferPersistence,
|
|
462
456
|
});
|
|
463
457
|
|
|
@@ -28,7 +28,7 @@ const SERIES_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._~%:/-]{0,239}$/;
|
|
|
28
28
|
const chartSeriesLog = debugLog.createLogger("chart-series");
|
|
29
29
|
const ranges = new Set<string>(TIME_RANGES);
|
|
30
30
|
const periods = new Set(["auto", "daily", "weekly", "monthly", "quarterly", "annual", "ttm"]);
|
|
31
|
-
const styles = new Set(["line", "area", "step", "columns", "points", "candles", "ohlc", "hlc"]);
|
|
31
|
+
const styles = new Set(["line", "area", "step", "columns", "points", "candles", "hollow", "heikin-ashi", "ohlc", "hlc"]);
|
|
32
32
|
const transforms = new Set(["raw", "percent", "index100", "yoy", "qoq", "log"]);
|
|
33
33
|
const shapes = new Set(["scalar", "ohlcv", "event", "band"]);
|
|
34
34
|
const axes = new Set(["left", "right"]);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isCryptoInstrumentType } from "../../tickers/search/ranking";
|
|
2
2
|
import { isCryptoVenuePerpetual } from "../../tickers/instrument-kind";
|
|
3
3
|
import type { Quote } from "../../types/financials";
|
|
4
|
-
import { isCryptoPairSymbol,
|
|
4
|
+
import { isCryptoPairSymbol, TOP_COIN_NAMES } from "../../utils/crypto-pair";
|
|
5
5
|
import { isNotATickerMessage } from "../not-a-ticker";
|
|
6
6
|
import { groupByCompany } from "../../tickers/company-name";
|
|
7
7
|
import { DATA_SERVICE_UNREACHABLE_MESSAGE } from "../../utils/network-failure";
|
|
@@ -10,27 +10,49 @@ import type { TickerRecord } from "../../types/ticker";
|
|
|
10
10
|
/** Where a crypto pair that will not load can still be read. `fn CRYP` takes no argument. */
|
|
11
11
|
export const CRYPTO_BOARD_HINT = "Crypto prices may be briefly unavailable; the CRYP function (gloom fn CRYP) shows the crypto board.";
|
|
12
12
|
|
|
13
|
-
// How the note names the coin, and
|
|
14
|
-
const MAJOR_COINS =
|
|
13
|
+
// How the note names the coin, and which tickers it speaks for.
|
|
14
|
+
const MAJOR_COINS = TOP_COIN_NAMES;
|
|
15
|
+
|
|
16
|
+
/** What a coin note reads of a listing: its quote's, or what a saved listing keeps. */
|
|
17
|
+
interface CoinListing {
|
|
18
|
+
name?: string | null;
|
|
19
|
+
instrumentType?: string | null;
|
|
20
|
+
/** The feed says the price is old. */
|
|
21
|
+
stale?: boolean;
|
|
22
|
+
/** The exchange removed the listing, or its last trade is all that is known. */
|
|
23
|
+
delisting?: unknown;
|
|
24
|
+
}
|
|
15
25
|
|
|
16
26
|
/**
|
|
17
|
-
* A bare coin ticker usually resolves to a
|
|
18
|
-
* the listing is not crypto and
|
|
19
|
-
*
|
|
20
|
-
*
|
|
27
|
+
* A bare coin ticker usually resolves to a listing that is not the coin. The note applies to a
|
|
28
|
+
* top coin's symbol whenever the listing is not a crypto product, and says how sure it is:
|
|
29
|
+
*
|
|
30
|
+
* - "SOL is Emeren Group ..., not solana. For solana use SOL-USD." when the listing cannot be
|
|
31
|
+
* what was meant: its name says the coin (a "Bitcoin" trust), or it is stale or delisted
|
|
32
|
+
* (SOL's Emeren Group last traded months ago).
|
|
33
|
+
* - "LINK is Interlink Electronics, Inc. Also a coin: LINK-USD." for a live company that
|
|
34
|
+
* happens to share the letters, which may well be the one meant.
|
|
35
|
+
*
|
|
36
|
+
* Every command that reads a bare symbol as a listing says it: quote, ticker, history, options,
|
|
37
|
+
* news, charts, alerts, and the portfolio and watchlist adds.
|
|
21
38
|
*/
|
|
22
|
-
export function notTheCoinNote(symbol: string,
|
|
39
|
+
export function notTheCoinNote(symbol: string, listing: CoinListing | null | undefined): string | null {
|
|
23
40
|
const coin = MAJOR_COINS.get(symbol);
|
|
24
|
-
const type =
|
|
25
|
-
const name =
|
|
41
|
+
const type = listing?.instrumentType?.trim();
|
|
42
|
+
const name = listing?.name?.trim();
|
|
26
43
|
if (!coin || !name || !type || isCryptoInstrumentType(type)) return null;
|
|
27
|
-
|
|
28
|
-
return
|
|
44
|
+
const cannotBeIt = listing?.stale === true || !!listing?.delisting || new RegExp(`\\b${coin}\\b`, "i").test(name);
|
|
45
|
+
return cannotBeIt
|
|
46
|
+
? `${symbol} is ${name}, not ${coin}. For ${coin} use ${symbol}-USD.`
|
|
47
|
+
: `${symbol} is ${name}${/[.!?]$/.test(name) ? "" : "."} Also a coin: ${symbol}-USD.`;
|
|
29
48
|
}
|
|
30
49
|
|
|
31
|
-
/**
|
|
32
|
-
|
|
33
|
-
|
|
50
|
+
/**
|
|
51
|
+
* `notTheCoinNote` for a saved listing, by the name and asset category it was saved with.
|
|
52
|
+
* `ended` says the listing stopped trading, which the saved record does not keep.
|
|
53
|
+
*/
|
|
54
|
+
export function savedListingCoinNote(symbol: string, ticker: Pick<TickerRecord, "metadata">, { ended = false }: { ended?: boolean } = {}): string | null {
|
|
55
|
+
return notTheCoinNote(symbol, { name: ticker.metadata.name, instrumentType: ticker.metadata.assetCategory, stale: ended });
|
|
34
56
|
}
|
|
35
57
|
|
|
36
58
|
/**
|
|
@@ -70,10 +92,10 @@ function failureReason(message: string, symbol: string): string {
|
|
|
70
92
|
|
|
71
93
|
/**
|
|
72
94
|
* Text-mode notes under a quote table: one line per distinct failure reason (with the crypto board
|
|
73
|
-
* pointer when a failed symbol is a crypto pair, unless nothing could be reached), then
|
|
74
|
-
*
|
|
95
|
+
* pointer when a failed symbol is a crypto pair, unless nothing could be reached), then the perpetual futures line.
|
|
96
|
+
* A bare coin ticker read as another listing is said with the listing (`listingChoiceNotes`).
|
|
75
97
|
*/
|
|
76
|
-
export function quoteNotes(results: QuoteNoteResult[]
|
|
98
|
+
export function quoteNotes(results: QuoteNoteResult[]): string[] {
|
|
77
99
|
const failures = new Map<string, string[]>();
|
|
78
100
|
for (const result of results) {
|
|
79
101
|
if (!result.error || result.quote) continue;
|
|
@@ -87,12 +109,6 @@ export function quoteNotes(results: QuoteNoteResult[], options: { exchange?: str
|
|
|
87
109
|
? reason
|
|
88
110
|
: `${symbols.join(", ")}: ${reason}${symbols.some(isCryptoPairSymbol) && reason !== DATA_SERVICE_UNREACHABLE_MESSAGE ? `${/[.!?]$/.test(reason) ? "" : "."} ${CRYPTO_BOARD_HINT}` : ""}`
|
|
89
111
|
));
|
|
90
|
-
if (!options.exchange) {
|
|
91
|
-
for (const result of results) {
|
|
92
|
-
const note = notTheCoinNote(result.target.symbol, result.quote);
|
|
93
|
-
if (note) notes.push(note);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
112
|
const perpetuals = results
|
|
97
113
|
.filter((result) => result.quote && isCryptoVenuePerpetual(result.quote.instrumentType, result.quote.name))
|
|
98
114
|
.map((result) => result.target.symbol);
|