gloomberb 0.18.4 → 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/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/package.json +1 -1
- package/patches/electrobun@1.18.1.patch +169 -5
- package/src/account/auth-model.ts +7 -3
- package/src/api-client/auth.ts +9 -4
- package/src/api-client/catalysts.ts +2 -1
- package/src/api-client/cot.ts +6 -2
- package/src/api-client/credit-documents.ts +6 -0
- package/src/api-client/data.ts +31 -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 +171 -11
- package/src/api-client/live-scan.ts +91 -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 +13 -1
- package/src/api-client/perps.ts +43 -0
- package/src/api-client/request.ts +222 -41
- package/src/api-client/research-activity.ts +6 -12
- package/src/api-client/types.ts +74 -0
- package/src/app/keybindings/index.ts +3 -0
- package/src/app/keybindings/labels.ts +18 -1
- package/src/app/keybindings/resolve.ts +14 -0
- package/src/app/pane-runtime/plugin-bindings.ts +9 -5
- package/src/app/runtime/broker-import.ts +42 -27
- package/src/app/runtime/plugin-bindings.ts +73 -56
- package/src/architecture/core-builtin-allowlist.json +1 -1
- 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/fred-series.ts +5 -0
- package/src/cli/commands/keybindings.ts +23 -0
- package/src/cli/commands/market.ts +138 -46
- package/src/cli/commands/options-chain.ts +107 -10
- package/src/cli/commands/options-leaps.ts +9 -3
- package/src/cli/commands/overview.ts +176 -39
- package/src/cli/commands/search.ts +39 -3
- package/src/cli/commands/themes.ts +11 -2
- package/src/cli/commands/ticker.ts +57 -35
- package/src/cli/company-name-hint.ts +41 -0
- package/src/cli/earnings-calendar.ts +1 -1
- package/src/cli/errors.ts +10 -2
- package/src/cli/export-source.ts +29 -1
- package/src/cli/glossary.ts +73 -1
- package/src/cli/history-rows.ts +87 -16
- package/src/cli/index.ts +2 -0
- package/src/cli/known-gaps.ts +5 -2
- package/src/cli/listing-arg.ts +195 -56
- 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 +111 -16
- package/src/cli/pane-functions/function-help.ts +23 -13
- package/src/cli/pane-functions/headless.ts +56 -12
- package/src/cli/pane-functions/index.ts +58 -16
- package/src/cli/pane-functions/market-session.ts +81 -9
- package/src/cli/pane-functions/options.ts +19 -1
- package/src/cli/pane-functions/report.ts +5 -1
- package/src/cli/pane-functions/resolver.ts +35 -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 +30 -13
- package/src/cli/report-tables.ts +18 -7
- package/src/cli/restore-plugins.ts +13 -1
- package/src/cli/result.ts +57 -5
- package/src/cli/ticker-resolution.ts +3 -2
- package/src/components/chart/composite/composite-chart.tsx +26 -4
- package/src/components/chart/composite/format.ts +27 -0
- package/src/components/chart/composite/interactions.ts +6 -0
- package/src/components/chart/composite/legend.tsx +45 -7
- package/src/components/chart/composite/levels.ts +2 -0
- package/src/components/chart/composite/panel-gestures.ts +33 -0
- package/src/components/chart/composite/panel-series.ts +1 -0
- package/src/components/chart/composite/panel-surface.tsx +61 -5
- package/src/components/chart/composite/range-statistics.ts +62 -0
- package/src/components/chart/composite/rasterizer.ts +24 -13
- package/src/components/chart/composite/scene.ts +46 -7
- package/src/components/chart/composite/series-axis-tags.tsx +16 -9
- 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/types.ts +4 -0
- 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/panel/prompt-binding.ts +0 -8
- package/src/components/command-bar/workflow/alert.ts +1 -1
- package/src/components/command-bar/workflow/collection-actions.ts +3 -3
- package/src/components/layout/header.tsx +26 -40
- package/src/components/layout/pane/footer/index.tsx +1 -0
- package/src/components/layout/pane/footer/model.ts +27 -0
- package/src/components/onboarding/onboarding-frame.tsx +1 -1
- package/src/components/onboarding/onboarding-wizard.tsx +4 -1
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +14 -9
- 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/display.tsx +5 -1
- 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/core/state/app/layout.ts +2 -0
- package/src/core/state/app/state.ts +9 -0
- package/src/core/state/app/types.ts +3 -0
- package/src/data/config/chart-settings.ts +1 -1
- package/src/data/json-ticker-repository.ts +17 -8
- package/src/data/saved-copies.ts +55 -16
- 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 +427 -216
- package/src/i18n/es.ts +19 -3
- package/src/i18n/ja.ts +19 -3
- package/src/i18n/ko.ts +19 -3
- package/src/i18n/zh-cn.ts +19 -3
- package/src/i18n/zh-tw.ts +19 -3
- package/src/market-data/coordinator/financials.ts +10 -2
- package/src/market-data/coordinator/index.ts +3 -1
- package/src/market-data/coordinator/quotes.ts +4 -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 +48 -7
- package/src/market-data/market/dated-previous-close.ts +203 -0
- package/src/market-data/market/format.ts +25 -0
- package/src/market-data/market/freshness.ts +2 -1
- package/src/market-data/market/futures-week.ts +68 -0
- package/src/market-data/market/status.ts +16 -4
- package/src/market-data/options-alternatives.ts +141 -4
- package/src/market-data/quotes/contributions.ts +20 -2
- package/src/market-data/quotes/resolution.ts +3 -0
- package/src/market-data/selectors.ts +3 -0
- 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/notifications/notification-log.ts +6 -4
- package/src/plugins/builtin/alerts/alert-engine.ts +25 -2
- package/src/plugins/builtin/alerts/alert-log.ts +33 -0
- package/src/plugins/builtin/alerts/calendar-events.ts +57 -6
- package/src/plugins/builtin/alerts/cli-forms.ts +216 -0
- package/src/plugins/builtin/alerts/cli.ts +380 -82
- package/src/plugins/builtin/alerts/command.ts +31 -0
- package/src/plugins/builtin/alerts/constants.ts +1 -1
- package/src/plugins/builtin/alerts/events-pane.tsx +19 -4
- package/src/plugins/builtin/alerts/fired-log.ts +113 -8
- package/src/plugins/builtin/alerts/format.ts +80 -4
- package/src/plugins/builtin/alerts/headless.ts +30 -7
- package/src/plugins/builtin/alerts/history-rows.ts +7 -3
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +135 -22
- package/src/plugins/builtin/alerts/live.ts +3 -3
- package/src/plugins/builtin/alerts/metric-command.ts +134 -0
- package/src/plugins/builtin/alerts/metric-data.ts +111 -0
- package/src/plugins/builtin/alerts/metric-model.ts +324 -0
- package/src/plugins/builtin/alerts/metric-parity-fixture.json +725 -0
- package/src/plugins/builtin/alerts/pane.tsx +90 -39
- package/src/plugins/builtin/alerts/quotes.ts +6 -0
- package/src/plugins/builtin/alerts/storage.ts +37 -10
- package/src/plugins/builtin/alerts/types.ts +7 -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/backtest/headless.ts +10 -5
- package/src/plugins/builtin/backtest/pane.tsx +9 -4
- package/src/plugins/builtin/backtest/presets.ts +29 -3
- package/src/plugins/builtin/broker-manager/index.tsx +10 -5
- package/src/plugins/builtin/broker-manager/model.ts +6 -1
- package/src/plugins/builtin/broker-trading/controller.ts +22 -12
- package/src/plugins/builtin/broker-trading/index.tsx +13 -1
- package/src/plugins/builtin/broker-trading/order-feed.ts +9 -4
- package/src/plugins/builtin/broker-trading/pane.tsx +1 -1
- 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 +7 -3
- package/src/plugins/builtin/catalysts/model.ts +2 -1
- package/src/plugins/builtin/changelog/index.tsx +9 -6
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +6 -1
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +1 -1
- package/src/plugins/builtin/chart-composer/cli-options.ts +9 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +12 -2
- package/src/plugins/builtin/chart-composer/editor/controller.ts +4 -2
- package/src/plugins/builtin/chart-composer/editor/model.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +7 -5
- package/src/plugins/builtin/chart-composer/formula.ts +71 -18
- package/src/plugins/builtin/chart-composer/headless-schema.ts +21 -4
- package/src/plugins/builtin/chart-composer/headless.ts +19 -3
- package/src/plugins/builtin/chart-composer/index.tsx +1 -1
- package/src/plugins/builtin/chart-composer/pane.tsx +53 -9
- package/src/plugins/builtin/chart-composer/presets.ts +50 -15
- package/src/plugins/builtin/chart-composer/quick-add.tsx +40 -25
- package/src/plugins/builtin/chart-composer/session-history.ts +18 -9
- package/src/plugins/builtin/chart-composer/settings.ts +27 -0
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +40 -26
- package/src/plugins/builtin/chat/content/command-suggestions.ts +93 -0
- package/src/plugins/builtin/chat/content/composer.tsx +13 -6
- package/src/plugins/builtin/chat/content/footer.tsx +6 -3
- package/src/plugins/builtin/chat/content/index.tsx +50 -21
- package/src/plugins/builtin/chat/content/open-targets.ts +14 -3
- package/src/plugins/builtin/chat/controller/session-runtime.ts +4 -2
- package/src/plugins/builtin/chat/index.tsx +23 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +1 -0
- package/src/plugins/builtin/chat/message/inline-tokens.tsx +23 -0
- package/src/plugins/builtin/chat/message/pane-chip.tsx +50 -20
- package/src/plugins/builtin/chat/pane-links/commands.ts +271 -0
- package/src/plugins/builtin/chat/pane-links/model.ts +12 -3
- package/src/plugins/builtin/chat/pane-links/open.ts +8 -1
- package/src/plugins/builtin/chat/unread-inbox-pane.tsx +10 -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/cloud/plugin.tsx +1 -1
- 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/calendar-model.ts +14 -9
- package/src/plugins/builtin/econ/figures.ts +72 -0
- package/src/plugins/builtin/econ/index.tsx +33 -3
- package/src/plugins/builtin/econ/types.ts +4 -0
- package/src/plugins/builtin/econ-statistics/defs.ts +6 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +85 -35
- package/src/plugins/builtin/econ-statistics/stats.ts +37 -9
- package/src/plugins/builtin/econ-statistics/view.ts +3 -0
- 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 +70 -15
- package/src/plugins/builtin/exposure/charts.tsx +2 -2
- package/src/plugins/builtin/exposure/model.ts +13 -1
- package/src/plugins/builtin/exposure/pane.tsx +4 -4
- package/src/plugins/builtin/fixed-income/pane.tsx +2 -1
- package/src/plugins/builtin/futures/index.tsx +1 -0
- package/src/plugins/builtin/futures/model.ts +2 -1
- package/src/plugins/builtin/futures/table.tsx +2 -2
- 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 +11 -3
- package/src/plugins/builtin/fx-matrix/headless.ts +6 -3
- package/src/plugins/builtin/fx-matrix/index.tsx +16 -4
- package/src/plugins/builtin/fx-matrix/live-legs.ts +54 -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/keybindings-editor.tsx +18 -14
- 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 +36 -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/pane.tsx +7 -5
- 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/footer.ts +2 -2
- 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 +82 -0
- package/src/plugins/builtin/members/client.ts +19 -4
- package/src/plugins/builtin/members/headless.ts +20 -7
- package/src/plugins/builtin/members/index.tsx +9 -9
- package/src/plugins/builtin/members/model.ts +23 -4
- package/src/plugins/builtin/members/pane.tsx +25 -15
- 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 +54 -6
- package/src/plugins/builtin/options/enrichment.ts +17 -5
- package/src/plugins/builtin/options/model-spot.ts +5 -2
- package/src/plugins/builtin/options/strike-window.ts +2 -1
- package/src/plugins/builtin/options/table.ts +6 -9
- package/src/plugins/builtin/options/types.ts +2 -0
- package/src/plugins/builtin/options/view.tsx +42 -12
- package/src/plugins/builtin/options-positioning/client.ts +30 -0
- package/src/plugins/builtin/options-positioning/headless.ts +74 -21
- package/src/plugins/builtin/options-positioning/index.tsx +4 -4
- package/src/plugins/builtin/options-positioning/model.ts +122 -14
- package/src/plugins/builtin/options-positioning/pane.tsx +87 -42
- 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/freshness.ts +12 -10
- package/src/plugins/builtin/perps/headless.ts +65 -9
- package/src/plugins/builtin/perps/index.tsx +7 -5
- package/src/plugins/builtin/perps/live-rows.ts +10 -3
- package/src/plugins/builtin/perps/model.ts +18 -4
- package/src/plugins/builtin/perps/pane.tsx +32 -31
- 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 +12 -7
- package/src/plugins/builtin/portfolio-list/headless.ts +1 -1
- 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/summary/index.tsx +11 -8
- package/src/plugins/builtin/portfolio-list/table.tsx +11 -3
- package/src/plugins/builtin/primary-dealers/client.ts +13 -38
- package/src/plugins/builtin/rate-path/pane.tsx +2 -2
- 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 +11 -9
- 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/feed.ts +2 -2
- 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 +40 -6
- package/src/plugins/builtin/scanner/live-condition-editor.tsx +222 -0
- package/src/plugins/builtin/scanner/live-feed.ts +168 -0
- package/src/plugins/builtin/scanner/live-headless.ts +138 -0
- package/src/plugins/builtin/scanner/live-model.ts +362 -0
- package/src/plugins/builtin/scanner/live-pane.tsx +677 -0
- package/src/plugins/builtin/scanner/live-track.ts +186 -0
- 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 +3 -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/macro-releases.ts +65 -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/scanner-capture.ts +3 -0
- 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 +10 -3
- package/src/plugins/builtin/shared/volatility/live-session.ts +34 -8
- package/src/plugins/builtin/shared/volatility/pricing.ts +26 -1
- package/src/plugins/builtin/shared/wall-view-lifecycle.ts +3 -1
- package/src/plugins/builtin/themes/headless.ts +6 -4
- package/src/plugins/builtin/themes/model.ts +17 -8
- package/src/plugins/builtin/themes/pane.tsx +7 -7
- 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-footer.ts +6 -1
- 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/charts.tsx +9 -4
- package/src/plugins/builtin/vol-surface/client.ts +9 -17
- package/src/plugins/builtin/vol-surface/headless.ts +63 -14
- package/src/plugins/builtin/vol-surface/index.tsx +2 -2
- package/src/plugins/builtin/vol-surface/model.ts +22 -7
- package/src/plugins/builtin/vol-surface/pane.tsx +48 -9
- package/src/plugins/builtin/vol-surface/tables.ts +31 -3
- package/src/plugins/builtin/volatility/dvol.ts +46 -0
- package/src/plugins/builtin/volatility/index.tsx +2 -2
- package/src/plugins/builtin/volatility/pane.tsx +4 -4
- package/src/plugins/builtin/volatility/series.ts +26 -0
- package/src/plugins/builtin/world-indices/footer.ts +1 -1
- package/src/plugins/builtin/world-venue-map/headless.ts +3 -3
- package/src/plugins/catalog-browser.ts +13 -8
- package/src/plugins/catalog-manifest.ts +2 -1
- package/src/plugins/marketplace/model.ts +18 -5
- package/src/portfolio/column-values.ts +5 -5
- package/src/portfolio/futures-positions.ts +6 -3
- package/src/portfolio/position-quantity.ts +15 -9
- package/src/public/__snapshots__/public-api.test.ts.snap +1 -0
- package/src/remote/resources.ts +2 -1
- package/src/renderers/browser/app-services.ts +1 -7
- package/src/renderers/browser/config-host.ts +2 -55
- package/src/renderers/browser/main.tsx +7 -57
- 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 +222 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +29 -7
- 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/relaunch.ts +74 -25
- package/src/renderers/electrobun/bun/desktop/state-broadcaster.ts +1 -0
- package/src/renderers/electrobun/bun/desktop/update.ts +173 -5
- package/src/renderers/electrobun/bun/desktop/view-ids.ts +52 -0
- package/src/renderers/electrobun/bun/desktop/workspace/index.ts +2 -0
- package/src/renderers/electrobun/bun/index.ts +25 -1
- package/src/renderers/electrobun/shared/app-name.ts +30 -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/cli-pane-shot-frame.tsx +3 -3
- package/src/renderers/electrobun/view/desktop/window/snapshot.ts +1 -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/renderers/opentui/toast-host.tsx +71 -43
- 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/gloomberb-cloud/normalizers.ts +2 -0
- package/src/sources/provider-router/batches.ts +10 -2
- package/src/sources/provider-router/financial-routes.ts +3 -3
- package/src/sources/provider-router/financials.ts +15 -3
- package/src/sources/provider-router/history.ts +28 -7
- package/src/sources/provider-router/index.ts +149 -10
- package/src/sources/provider-router/search.ts +13 -2
- package/src/state/app/context/index.tsx +3 -0
- package/src/state/ticker-cleanup.ts +50 -0
- package/src/sync/auth-transition.ts +19 -9
- package/src/sync/baseline.ts +10 -4
- package/src/sync/controller.ts +70 -19
- package/src/sync/core-contributors.ts +90 -31
- package/src/sync/react.ts +4 -1
- package/src/sync/types.ts +3 -0
- 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/telemetry/usage-counts.ts +0 -18
- package/src/test-support/preload.ts +14 -0
- package/src/theme/colors.ts +8 -0
- package/src/theme/themes.ts +10 -0
- package/src/tickers/company-name.ts +103 -3
- package/src/tickers/listing-venues.ts +38 -3
- package/src/tickers/search/bare-symbol.ts +36 -0
- package/src/tickers/search/index.ts +36 -7
- package/src/tickers/search/ranking.ts +10 -1
- package/src/tickers/search/types.ts +5 -0
- package/src/tickers/terminal-codes.ts +19 -0
- package/src/time-series/alignment.ts +1 -1
- package/src/time-series/base-series.ts +13 -5
- package/src/time-series/daily-valuation.ts +62 -0
- package/src/time-series/economic.ts +18 -4
- package/src/time-series/field-catalog.ts +2 -4
- package/src/time-series/filed-trailing-eps.ts +197 -0
- package/src/time-series/forward-valuation.ts +32 -0
- package/src/time-series/fundamentals.ts +198 -7
- package/src/time-series/hooks.ts +1 -0
- package/src/time-series/ice-credit.ts +3 -0
- package/src/time-series/price-comparison.ts +30 -2
- package/src/time-series/price-units.ts +72 -2
- package/src/time-series/resolve-context.ts +7 -1
- package/src/time-series/resolve.ts +116 -15
- package/src/time-series/series-presentation.ts +40 -6
- package/src/time-series/session-bar.ts +11 -0
- package/src/time-series/spec.ts +5 -3
- package/src/time-series/studies.ts +278 -74
- package/src/time-series/total-return.ts +160 -0
- package/src/time-series/transforms.ts +3 -3
- package/src/time-series/types.ts +27 -1
- package/src/time-series/valuation-releases.ts +39 -0
- package/src/types/data-provider.ts +9 -1
- package/src/types/desktop-window.ts +2 -0
- package/src/types/financials.ts +73 -2
- package/src/types/headless.ts +61 -5
- package/src/types/instrument.ts +3 -0
- package/src/types/news-source.ts +1 -0
- package/src/types/plugin.ts +10 -1
- package/src/ui/host.tsx +3 -0
- package/src/updater/command-names.ts +12 -7
- 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/financial-statements.ts +6 -1
- 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/network-failure.ts +9 -6
- package/src/utils/option-expiry.ts +48 -1
- package/src/utils/options.ts +10 -0
- package/src/utils/plugin-proxy-hosts.json +1 -0
- package/src/utils/price-history.ts +12 -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/renderers/browser/first-screen.ts +0 -193
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, type Dispatch } from "react";
|
|
1
|
+
import { useCallback, useRef, type Dispatch } from "react";
|
|
2
2
|
import {
|
|
3
3
|
rebaseBrokerSyncConfig,
|
|
4
4
|
restoreBrokerPortfoliosFromTickerPositions,
|
|
@@ -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;
|
|
@@ -53,6 +52,7 @@ export function useBrokerImportRuntime({
|
|
|
53
52
|
stateRef: { current: AppState };
|
|
54
53
|
tickerRepository: AppTickerRepositoryPort;
|
|
55
54
|
}): AppBrokerImportRuntime {
|
|
55
|
+
const syncRequests = useRef(new Map<string, object>());
|
|
56
56
|
/**
|
|
57
57
|
* Commits a sync: carried onto the app as it is now (a pull or an edit while
|
|
58
58
|
* the broker answered stays) and handed to the app before anything is
|
|
@@ -104,36 +104,51 @@ export function useBrokerImportRuntime({
|
|
|
104
104
|
tickerMap?: Map<string, TickerRecord>,
|
|
105
105
|
options?: BrokerImportOptions,
|
|
106
106
|
) => {
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
persistResolvedBrokerConfig: options?.persistResolvedBrokerConfig,
|
|
116
|
-
signal: options?.signal,
|
|
117
|
-
deferPersistence: true,
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
// A profile removed while its broker was answering stays removed, positions included.
|
|
121
|
-
if (!options?.config && !getBrokerInstance(stateRef.current.config.brokerInstances, instanceId)) return result;
|
|
122
|
-
let commitStarted = false;
|
|
107
|
+
const request = {};
|
|
108
|
+
syncRequests.current.set(instanceId, request);
|
|
109
|
+
const report = (error: string | null) => {
|
|
110
|
+
// A late read must not replace the outcome of a newer manual retry.
|
|
111
|
+
if (syncRequests.current.get(instanceId) === request && !options?.signal?.aborted) {
|
|
112
|
+
dispatch({ type: "SET_BROKER_SYNC_ERROR", instanceId, error });
|
|
113
|
+
}
|
|
114
|
+
};
|
|
123
115
|
try {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
116
|
+
const baseConfig = options?.config ?? stateRef.current.config;
|
|
117
|
+
const result = await syncBrokerInstance({
|
|
118
|
+
config: baseConfig,
|
|
119
|
+
instanceId,
|
|
120
|
+
brokers: pluginRegistry.brokers,
|
|
121
|
+
tickerRepository,
|
|
122
|
+
existingTickers: tickerMap ?? new Map(stateRef.current.tickers),
|
|
123
|
+
resources: pluginRegistry.persistence.resources,
|
|
124
|
+
signal: options?.signal,
|
|
125
|
+
deferPersistence: true,
|
|
130
126
|
});
|
|
131
127
|
|
|
132
|
-
|
|
128
|
+
// A profile removed while its broker was answering stays removed, positions included.
|
|
129
|
+
if (!options?.config && !getBrokerInstance(stateRef.current.config.brokerInstances, instanceId)) return result;
|
|
130
|
+
let commitStarted = false;
|
|
131
|
+
try {
|
|
132
|
+
throwIfBrokerImportCancelled(options?.signal);
|
|
133
|
+
options?.onCommitStart?.();
|
|
134
|
+
commitStarted = true;
|
|
135
|
+
await applyBrokerImportResult(instanceId, result, baseConfig, {
|
|
136
|
+
...options,
|
|
137
|
+
callerOwnsConfig: options?.config !== undefined,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
report(null);
|
|
141
|
+
return result;
|
|
142
|
+
} finally {
|
|
143
|
+
if (commitStarted) options?.onCommitEnd?.();
|
|
144
|
+
}
|
|
145
|
+
} catch (error) {
|
|
146
|
+
report("Positions could not be synced. Use Sync to retry.");
|
|
147
|
+
throw error;
|
|
133
148
|
} finally {
|
|
134
|
-
if (
|
|
149
|
+
if (syncRequests.current.get(instanceId) === request) syncRequests.current.delete(instanceId);
|
|
135
150
|
}
|
|
136
|
-
}, [applyBrokerImportResult, pluginRegistry.brokers, pluginRegistry.persistence.resources, stateRef, tickerRepository]);
|
|
151
|
+
}, [applyBrokerImportResult, dispatch, pluginRegistry.brokers, pluginRegistry.persistence.resources, stateRef, tickerRepository]);
|
|
137
152
|
|
|
138
153
|
const autoImportBrokerPositions = useCallback(async (tickerMap: Map<string, TickerRecord>) => {
|
|
139
154
|
// Once per install, manual portfolios held in one other currency take it (see adoptHeldPortfolioCurrencies).
|
|
@@ -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"));
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"src/components/layout/shell/index.tsx": ["cloud"],
|
|
28
28
|
"src/components/onboarding/use-onboarding-upgrade.ts": ["chat"],
|
|
29
29
|
"src/layout/desks.ts": ["chart-composer"],
|
|
30
|
-
"src/plugins/catalog-browser.ts": ["alerts","analytics","attention","awards","backtest","bond-calculator","catalysts","cds","central-bank-rates","changelog","chart-composer","clinical-trials","cloud","comment-letters","commodities-energy","commodity-balances","company-attention","company-kpis","connections","correlation","cot","cpi","credit-boards","credit-conditions","credit-documents","crypto-board","crypto-etf-flows","debt-maturities","dividend-yield","docs","doe","earnings-calls","earnings-ripple","econ","econ-statistics","equity-screener","estimate-revisions","executives","exposure","fear-greed","filing-events","fixed-income","futures","futures-curve","fx-matrix","gpu","help","insider","ipo-calendar","iv-history","jobs","jodi","kelly-sizer","layout-manager","macro-day","market-halts","market-heatmap","market-valuation","members","mna","money-markets","news","openfda","options","options-calculator","options-positioning","options-scenario","pe-band","perps","portfolio-list","power","primary-dealers","rate-path","realized-vol","relative-rotation","research","research-search","revenue-breakdown","reverse-dcf","risk-factors","scanner","seasonality","sec","sectors","short-interest","short-volume","social-mentions","supply-chain","ticker-detail","time-sales","trace-bonds","treasury-auctions","treasury-daily","vol-surface","volatility","world-indices","world-venue-map","yield-curve"],
|
|
30
|
+
"src/plugins/catalog-browser.ts": ["alerts","analytics","attention","awards","backtest","bond-calculator","catalysts","cds","central-bank-rates","changelog","chart-composer","clinical-trials","cloud","comment-letters","commodities-energy","commodity-balances","company-attention","company-kpis","connections","correlation","cot","cpi","credit-boards","credit-conditions","credit-documents","crypto-board","crypto-etf-flows","debt-maturities","dividend-yield","docs","doe","earnings","earnings-calls","earnings-ripple","econ","econ-statistics","equity-screener","estimate-revisions","executives","exposure","fear-greed","filing-events","fixed-income","futures","futures-curve","fx-matrix","gpu","help","holders","insider","ipo-calendar","iv-history","jobs","jodi","kelly-sizer","layout-manager","macro-day","market-halts","market-heatmap","market-valuation","members","mna","money-markets","news","openfda","options","options-calculator","options-positioning","options-scenario","pe-band","perps","portfolio-list","power","primary-dealers","rate-path","realized-vol","relative-rotation","research","research-search","revenue-breakdown","reverse-dcf","risk-factors","scanner","seasonality","sec","sectors","short-interest","short-volume","social-mentions","supply-chain","thirteenf","ticker-detail","time-sales","trace-bonds","treasury-auctions","treasury-daily","vol-surface","volatility","world-indices","world-venue-map","yield-curve"],
|
|
31
31
|
"src/plugins/catalog-ui.ts": ["alerts","clinical-trials","cloud","comment-letters","custom-view","fear-greed","ipo-calendar","market-halts","market-heatmap","members","news","notes","openfda","research-search"],
|
|
32
32
|
"src/plugins/catalog.ts": ["debug"],
|
|
33
33
|
"src/remote/controller.ts": ["custom-view"],
|
|
@@ -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);
|
|
@@ -44,6 +44,11 @@ export function fredInterval(frequency: string | null | undefined): string | nul
|
|
|
44
44
|
return word || null;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
/** Whether a series' dates are days it was observed on (FRED's `Daily`, `Weekly, Ending Friday`), not the start of a period; false when it does not say. */
|
|
48
|
+
export function fredObservesDays(frequency: string | null | undefined): boolean {
|
|
49
|
+
return /^(?:daily|weekly)\b/i.test(frequency?.trim() ?? "");
|
|
50
|
+
}
|
|
51
|
+
|
|
47
52
|
/**
|
|
48
53
|
* The observations from the series' first one on: Gloom Cloud answers a
|
|
49
54
|
* `--start` before a series begins with a blank row for every day in between
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
applyActionBinding,
|
|
3
|
+
coreActionOnChord,
|
|
3
4
|
describeKeybindingIssue,
|
|
5
|
+
formatChordForHost,
|
|
4
6
|
isCoreKeybindingActionId,
|
|
5
7
|
isTypingChord,
|
|
6
8
|
parseKeyChord,
|
|
@@ -9,7 +11,9 @@ import {
|
|
|
9
11
|
resolveKeybindings,
|
|
10
12
|
serializeKeyChord,
|
|
11
13
|
setCommandBinding,
|
|
14
|
+
takenChordMessage,
|
|
12
15
|
updateKeybindingsConfig,
|
|
16
|
+
type KeyChord,
|
|
13
17
|
} from "../../app/keybindings";
|
|
14
18
|
import type { AppConfig } from "../../types/config";
|
|
15
19
|
|
|
@@ -34,6 +38,21 @@ export function describeKeybindingsForCli(config: AppConfig): Record<string, unk
|
|
|
34
38
|
};
|
|
35
39
|
}
|
|
36
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Why the first of `chords` a built-in action other than `exceptId` already
|
|
43
|
+
* uses is refused, as the shortcuts editor says it; null when none is. The
|
|
44
|
+
* table is the terminal's and the desktop's at once, so an action either has
|
|
45
|
+
* keeps its key.
|
|
46
|
+
*/
|
|
47
|
+
function takenByCoreAction(config: AppConfig, chords: readonly KeyChord[], exceptId?: string): string | null {
|
|
48
|
+
const resolved = resolveKeybindings(config.keybindings);
|
|
49
|
+
for (const chord of chords) {
|
|
50
|
+
const core = coreActionOnChord(resolved, chord, exceptId);
|
|
51
|
+
if (core) return takenChordMessage(formatChordForHost(chord, "terminal"), core);
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
37
56
|
export type KeybindingCliSetResult =
|
|
38
57
|
| { ok: true; config: AppConfig; value: unknown }
|
|
39
58
|
| { ok: false; message: string };
|
|
@@ -71,6 +90,8 @@ export function applyKeybindingCliSet(config: AppConfig, key: string, rawValue:
|
|
|
71
90
|
if (!chord) return { ok: false, message: `"${text}" is not a key chord. Examples: Ctrl+T, CmdOrCtrl+Shift+F, Alt+1, F5, \`` };
|
|
72
91
|
chords.push(chord);
|
|
73
92
|
}
|
|
93
|
+
const taken = takenByCoreAction(config, chords, target);
|
|
94
|
+
if (taken) return { ok: false, message: taken };
|
|
74
95
|
return {
|
|
75
96
|
ok: true,
|
|
76
97
|
config: updateKeybindingsConfig(config, applyActionBinding(config.keybindings, target, chords)),
|
|
@@ -91,6 +112,8 @@ export function applyKeybindingCliSet(config: AppConfig, key: string, rawValue:
|
|
|
91
112
|
if (isTypingChord(chord)) {
|
|
92
113
|
return { ok: false, message: `"${target}" would fire while typing; command bindings need Ctrl, Cmd, Alt or a function key.` };
|
|
93
114
|
}
|
|
115
|
+
const taken = takenByCoreAction(config, [chord]);
|
|
116
|
+
if (taken) return { ok: false, message: taken };
|
|
94
117
|
return {
|
|
95
118
|
ok: true,
|
|
96
119
|
config: updateKeybindingsConfig(config, setCommandBinding(config.keybindings, chord, value)),
|