gloomberb 0.18.3 → 0.18.4
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 +8 -8
- package/README.zh-CN.md +11 -11
- package/bin/{gloomberb → gloom} +3 -1
- package/package.json +6 -2
- package/src/account/checkout-handoff.tsx +225 -0
- package/src/account/device-signin-dialog.tsx +2 -2
- package/src/account/device-signin.ts +2 -2
- package/src/account/upgrade-dialog.tsx +1 -1
- package/src/api-client/askg.ts +2 -2
- package/src/api-client/auth.ts +2 -2
- package/src/api-client/central-bank-rates.ts +6 -0
- package/src/api-client/collections.ts +5 -1
- package/src/api-client/cot.ts +2 -0
- package/src/api-client/crypto-etf-flows.ts +37 -0
- package/src/api-client/crypto-markets.ts +60 -0
- package/src/api-client/data.ts +84 -5
- package/src/api-client/doe.ts +15 -0
- package/src/api-client/equity-screener.ts +28 -0
- package/src/api-client/exchange-announcements.ts +38 -0
- package/src/api-client/fund-facts.ts +39 -0
- package/src/api-client/futures-curve.ts +9 -1
- package/src/api-client/hiring.ts +301 -0
- package/src/api-client/index.ts +22 -5
- package/src/api-client/market-discovery.ts +14 -0
- package/src/api-client/members.ts +6 -0
- package/src/api-client/mna.ts +6 -0
- package/src/api-client/paths.ts +18 -1
- package/src/api-client/request.ts +21 -4
- package/src/api-client/short-side-publications.ts +37 -0
- package/src/api-client/socket.ts +64 -4
- package/src/api-client/swap-curve.ts +35 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +90 -2
- package/src/app/pane-runtime/plugin-bindings.ts +9 -2
- package/src/app/runtime/desktop-deeplink.ts +5 -5
- package/src/app/runtime/plugin-bindings.ts +2 -2
- package/src/app/runtime/startup.ts +13 -0
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/ui-literals-allowlist.json +3 -3
- package/src/architecture/ui-tokens-allowlist.json +1 -1
- package/src/brokers/broker-portfolio-sync.ts +37 -0
- package/src/brokers/directory.ts +11 -0
- package/src/brokers/logos.ts +3 -1
- package/src/brokers/signed-in/adapter.ts +304 -26
- package/src/brokers/signed-in/client.ts +14 -2
- package/src/brokers/signed-in/connect.ts +10 -2
- package/src/brokers/sync-broker-instance.ts +9 -1
- package/src/capabilities/chart-series.ts +22 -6
- package/src/cli/bank-section.ts +1 -1
- package/src/cli/base-converter.ts +23 -14
- package/src/cli/central-bank-events.ts +1 -1
- package/src/cli/command-options.ts +59 -4
- package/src/cli/commands/api.ts +9 -6
- package/src/cli/commands/broker.ts +2 -2
- package/src/cli/commands/command-utils.ts +2 -2
- package/src/cli/commands/crypto-hints.ts +7 -20
- package/src/cli/commands/fred-series.ts +4 -2
- package/src/cli/commands/keybindings.ts +2 -2
- package/src/cli/commands/market.ts +1117 -264
- package/src/cli/commands/news-hints.ts +2 -2
- package/src/cli/commands/news-search.ts +59 -6
- package/src/cli/commands/options-leaps.ts +41 -26
- package/src/cli/commands/overview.ts +121 -48
- package/src/cli/commands/plugins.ts +9 -9
- package/src/cli/commands/remote.ts +13 -10
- package/src/cli/commands/search.ts +64 -44
- package/src/cli/commands/system.ts +27 -19
- package/src/cli/commands/themes.ts +1 -1
- package/src/cli/commands/ticker.ts +192 -47
- package/src/cli/context.ts +3 -2
- package/src/cli/desktop-pane-shot-view.ts +2 -2
- package/src/cli/desktop-pane-shot.ts +1 -1
- package/src/cli/earnings-calendar.ts +4 -4
- package/src/cli/entry.ts +18 -1
- package/src/cli/errors.ts +20 -2
- package/src/cli/exit-codes.ts +1 -1
- package/src/cli/export-source.ts +10 -4
- package/src/cli/freshness.ts +2 -8
- package/src/cli/fx-forward.ts +130 -0
- package/src/cli/fx-pair.ts +10 -9
- package/src/cli/glossary.ts +64 -20
- package/src/cli/help.ts +19 -13
- package/src/cli/history-export.ts +126 -0
- package/src/cli/history-rows.ts +196 -43
- package/src/cli/index-roots.ts +5 -45
- package/src/cli/index.ts +24 -18
- package/src/cli/known-gaps.ts +118 -25
- package/src/cli/listing-arg.ts +300 -41
- package/src/cli/name-entries.ts +30 -18
- package/src/cli/native-smoke.ts +2 -0
- package/src/cli/not-a-ticker.ts +19 -9
- package/src/cli/opentui-libc.ts +5 -0
- package/src/cli/options.ts +12 -0
- package/src/cli/pane-functions/capabilities.ts +75 -20
- package/src/cli/pane-functions/catalog.ts +24 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +10 -7
- package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
- package/src/cli/pane-functions/freshness.ts +174 -23
- package/src/cli/pane-functions/function-help.ts +66 -27
- package/src/cli/pane-functions/headless.ts +24 -11
- package/src/cli/pane-functions/index.ts +18 -16
- package/src/cli/pane-functions/options.ts +22 -2
- package/src/cli/pane-functions/report-notices.ts +12 -4
- package/src/cli/pane-functions/report.ts +5 -5
- package/src/cli/pane-functions/resolver.ts +47 -10
- package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
- package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
- package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
- package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
- package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
- package/src/cli/pane-functions/screenshot-payload.ts +453 -0
- package/src/cli/pane-functions/screenshot-render.ts +316 -0
- package/src/cli/pane-functions/screenshot-types.ts +162 -0
- package/src/cli/pane-functions/shot-options.ts +8 -3
- package/src/cli/peso-dollar-rates.ts +79 -0
- package/src/cli/quote-answer.ts +38 -3
- package/src/cli/report-tables.ts +61 -16
- package/src/cli/restore-plugins.ts +29 -14
- package/src/cli/result.ts +111 -22
- package/src/cli/series-search.ts +5 -5
- package/src/cli/statement-filings.ts +19 -0
- package/src/cli/suffixed-listing-rows.ts +49 -0
- package/src/cli/symbol-args.ts +50 -15
- package/src/cli/symbol-cells.ts +120 -0
- package/src/cli/symbol-list.ts +198 -68
- package/src/cli/symbol-rows.ts +131 -25
- package/src/cli/ticker-resolution.ts +108 -11
- package/src/cli/treasury-yields.ts +5 -5
- package/src/cli/types.ts +2 -0
- package/src/cli/uncovered-instrument.ts +3 -3
- package/src/cli/unknown-command.ts +6 -6
- package/src/components/chart/composite/chart-layout.ts +131 -0
- package/src/components/chart/composite/composite-chart.tsx +373 -16
- package/src/components/chart/composite/interactions.ts +7 -2
- package/src/components/chart/composite/legend.tsx +75 -3
- package/src/components/chart/composite/levels.ts +5 -0
- package/src/components/chart/composite/panel-gestures.ts +41 -0
- package/src/components/chart/composite/panel-labels.ts +2 -1
- package/src/components/chart/composite/panel-surface.tsx +305 -11
- package/src/components/chart/composite/price-axis-labels.tsx +27 -3
- package/src/components/chart/composite/rasterizer.ts +44 -19
- package/src/components/chart/composite/scene.ts +16 -4
- package/src/components/chart/composite/text-renderer.ts +48 -21
- package/src/components/chart/composite/toolbar.tsx +52 -5
- package/src/components/chart/composite/types.ts +13 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
- package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
- package/src/components/chart/composite/use-composite-viewport.ts +12 -3
- package/src/components/chart/composite/value-scale.ts +149 -0
- package/src/components/chart/composite/volume-profile-paint.ts +6 -3
- package/src/components/chart/core/pointer.ts +2 -0
- package/src/components/chart-table/index.ts +2 -0
- package/src/components/chart-table/read.tsx +74 -0
- package/src/components/command-bar/commands/collection-list.ts +41 -19
- package/src/components/command-bar/commands/collection.ts +9 -3
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/commands/direct/runtime.ts +3 -2
- package/src/components/command-bar/pane-templates/items.ts +59 -6
- package/src/components/command-bar/pane-templates/workflow.ts +10 -1
- package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
- package/src/components/command-bar/routes/root/provider-search.ts +42 -11
- package/src/components/command-bar/routes/root/results.ts +18 -4
- package/src/components/command-bar/routes/root/runtime.ts +15 -3
- package/src/components/command-bar/routes/root/search-providers.ts +25 -2
- package/src/components/command-bar/routes/root/selection.ts +6 -1
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
- package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
- package/src/components/command-bar/selection-runtime.ts +50 -10
- package/src/components/command-bar/surface/index.tsx +24 -2
- package/src/components/command-bar/view-model.ts +7 -0
- package/src/components/command-bar/workflow/broker.ts +2 -2
- package/src/components/command-bar/workflow/collection-actions.ts +46 -7
- package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
- package/src/components/command-bar/workflow/fields.ts +8 -2
- package/src/components/command-bar/workflow/ops.ts +18 -4
- package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
- package/src/components/command-bar/workflow/submit.ts +3 -2
- package/src/components/command-bar/workflow/tickers.ts +5 -1
- package/src/components/company-logo.tsx +39 -0
- package/src/components/data-table/sections.ts +4 -2
- package/src/components/form-modal/confirm.tsx +2 -1
- package/src/components/form-modal/request.ts +5 -0
- package/src/components/form-modal/routes.ts +4 -1
- package/src/components/index.ts +12 -6
- package/src/components/layout/header.tsx +7 -6
- package/src/components/layout/market-summary.ts +9 -6
- package/src/components/layout/pane/capture-status.ts +1 -1
- package/src/components/layout/pane/footer/model.ts +11 -5
- package/src/components/layout/shell/chrome.ts +19 -6
- package/src/components/layout/shell/index.tsx +2 -1
- package/src/components/layout/shell/pane/layers.tsx +19 -1
- package/src/components/layout/status-bar.tsx +2 -2
- package/src/components/market-board/index.tsx +11 -3
- package/src/components/onboarding/onboarding-wizard.tsx +1 -0
- package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
- package/src/components/onboarding/wizard-broker-sync.ts +4 -1
- package/src/components/pane-settings-dialog/desktop.tsx +20 -7
- package/src/components/pane-settings-dialog/tui.tsx +17 -9
- package/src/components/pane-settings-dialog/value.ts +8 -1
- package/src/components/pane-settings-dialog.tsx +44 -13
- package/src/components/sign-in-code-panel.tsx +27 -19
- package/src/components/ui/column-grid.tsx +48 -4
- package/src/components/ui/country-flag-art.tsx +180 -0
- package/src/components/ui/country-flag.tsx +118 -12
- package/src/components/ui/data-table/opentui/index.tsx +61 -2
- package/src/components/ui/data-table/opentui/model.ts +109 -2
- package/src/components/ui/data-table/types.ts +1 -1
- package/src/components/ui/display.tsx +5 -1
- package/src/components/ui/index.ts +3 -1
- package/src/components/ui/logo-mark.tsx +11 -2
- package/src/components/ui/query-bar.tsx +1 -1
- package/src/components/ui/row-notes.ts +79 -0
- package/src/core/state/app/layout.ts +4 -4
- package/src/data/cached-query.ts +8 -1
- package/src/data/config/chart-settings.ts +3 -3
- package/src/data/config/home.ts +10 -2
- package/src/data/config/layout.ts +4 -1
- package/src/data/config/store/node.ts +4 -0
- package/src/data/config/store/normalize.ts +13 -3
- package/src/data/config/store/portfolio-as-of-column.ts +2 -2
- package/src/data/json-storage.ts +2 -0
- package/src/data/saved-copies.ts +84 -0
- package/src/docs/snapshot.json +65 -32
- package/src/i18n/es.ts +29 -12
- package/src/i18n/ja.ts +29 -12
- package/src/i18n/ko.ts +29 -12
- package/src/i18n/zh-cn.ts +29 -12
- package/src/i18n/zh-tw.ts +29 -12
- package/src/layout/desks.ts +1 -1
- package/src/layout/launch-layout.ts +1 -1
- package/src/layout/pane-manager/floating-actions.ts +5 -3
- package/src/layout/pane-manager/floating.ts +43 -1
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/layout/selected-ticker.ts +74 -0
- package/src/market-data/depositary-pair.ts +251 -0
- package/src/market-data/futures-board.ts +1 -1
- package/src/market-data/futures-contract.ts +124 -40
- package/src/market-data/fx-closes.ts +17 -2
- package/src/market-data/hooks.tsx +19 -11
- package/src/market-data/market/change-basis.ts +49 -7
- package/src/market-data/market/freshness.ts +34 -5
- package/src/market-data/market/period-return.ts +163 -0
- package/src/market-data/market/trading-sessions.ts +13 -0
- package/src/market-data/market/year-to-date.ts +8 -13
- package/src/market-data/performance.ts +20 -14
- package/src/market-data/perpetual-premium.ts +32 -0
- package/src/market-data/published-apac-sessions.ts +2 -1
- package/src/market-data/published-futures-sessions.ts +69 -0
- package/src/market-data/quotes/contributions.ts +5 -1
- package/src/market-data/quotes/freshness.ts +42 -0
- package/src/market-data/quotes/intraday-bar.ts +37 -0
- package/src/market-data/quotes/regular-session-valuation.ts +13 -8
- package/src/market-data/quotes/resolution.ts +4 -2
- package/src/market-data/tax-equivalent.ts +1 -1
- package/src/market-data/ticker-price-returns.ts +3 -1
- package/src/news/aggregator.ts +5 -1
- package/src/news/news-model.ts +4 -0
- package/src/news/types.ts +11 -0
- package/src/notifications/app-notifier.ts +1 -1
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/pane.tsx +9 -8
- package/src/plugins/builtin/alerts/alert-engine.ts +29 -19
- package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
- package/src/plugins/builtin/alerts/cli.ts +485 -76
- package/src/plugins/builtin/alerts/command.ts +5 -10
- package/src/plugins/builtin/alerts/event-rows.ts +9 -5
- package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
- package/src/plugins/builtin/alerts/events.ts +107 -5
- package/src/plugins/builtin/alerts/fired-log.ts +78 -0
- package/src/plugins/builtin/alerts/format.ts +2 -1
- package/src/plugins/builtin/alerts/headless.ts +100 -39
- package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
- package/src/plugins/builtin/alerts/history-rows.ts +89 -0
- package/src/plugins/builtin/alerts/index.tsx +45 -18
- package/src/plugins/builtin/alerts/iv-level.ts +365 -0
- package/src/plugins/builtin/alerts/levels.ts +3 -3
- package/src/plugins/builtin/alerts/pane.tsx +97 -29
- package/src/plugins/builtin/alerts/price.ts +35 -0
- package/src/plugins/builtin/alerts/quotes.ts +24 -0
- package/src/plugins/builtin/alerts/research-builder.ts +84 -11
- package/src/plugins/builtin/alerts/research-rules.ts +76 -3
- package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
- package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
- package/src/plugins/builtin/alerts/scheduled.ts +188 -29
- package/src/plugins/builtin/alerts/storage.ts +13 -10
- package/src/plugins/builtin/alerts/targets.ts +12 -3
- package/src/plugins/builtin/analytics/index.tsx +8 -2
- package/src/plugins/builtin/analytics/metrics.ts +1 -1
- package/src/plugins/builtin/analytics/risk-book.ts +215 -0
- package/src/plugins/builtin/analytics/risk-client.ts +13 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
- package/src/plugins/builtin/analytics/risk-math.ts +6 -3
- package/src/plugins/builtin/analytics/risk-model.ts +297 -104
- package/src/plugins/builtin/analytics/risk-options.ts +17 -2
- package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
- package/src/plugins/builtin/attention/pane.tsx +6 -2
- package/src/plugins/builtin/awards/headless.ts +7 -3
- package/src/plugins/builtin/awards/model.ts +18 -0
- package/src/plugins/builtin/awards/pane.tsx +6 -3
- package/src/plugins/builtin/backtest/headless.ts +3 -3
- package/src/plugins/builtin/backtest/rules.ts +41 -5
- package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
- package/src/plugins/builtin/broker-manager/footer.ts +27 -11
- package/src/plugins/builtin/broker-manager/index.tsx +21 -12
- package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
- package/src/plugins/builtin/broker-manager/model.ts +12 -2
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
- package/src/plugins/builtin/broker-manager/table.ts +28 -12
- package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
- package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
- package/src/plugins/builtin/broker-trading/controller.ts +45 -13
- package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
- package/src/plugins/builtin/broker-trading/headless.ts +2 -1
- package/src/plugins/builtin/broker-trading/index.tsx +7 -1
- package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
- package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
- package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
- package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
- package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
- package/src/plugins/builtin/broker-trading/pane.tsx +110 -23
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
- package/src/plugins/builtin/buildout/cells.tsx +4 -0
- package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
- package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
- package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
- package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
- package/src/plugins/builtin/catalysts/detail.tsx +3 -2
- package/src/plugins/builtin/catalysts/index.tsx +1 -1
- package/src/plugins/builtin/catalysts/model.ts +49 -4
- package/src/plugins/builtin/catalysts/pane.tsx +6 -8
- package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
- package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
- package/src/plugins/builtin/changelog/index.tsx +1 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
- package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
- package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
- package/src/plugins/builtin/chart-composer/headless.ts +253 -35
- package/src/plugins/builtin/chart-composer/index.tsx +12 -2
- package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +127 -28
- package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
- package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
- package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
- package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
- package/src/plugins/builtin/chart-composer/settings.ts +31 -19
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
- package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
- package/src/plugins/builtin/chat/attachments/model.ts +3 -1
- package/src/plugins/builtin/chat/content/index.tsx +1 -1
- package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
- package/src/plugins/builtin/chat/people.ts +1 -1
- package/src/plugins/builtin/clinical-trials/client.ts +5 -2
- package/src/plugins/builtin/clinical-trials/model.ts +13 -4
- package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
- package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
- package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
- package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
- package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
- package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
- package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
- package/src/plugins/builtin/company-attention/building-model.ts +222 -0
- package/src/plugins/builtin/company-attention/building.tsx +172 -0
- package/src/plugins/builtin/company-attention/client.ts +117 -1
- package/src/plugins/builtin/company-attention/evidence.ts +16 -3
- package/src/plugins/builtin/company-attention/headless.ts +101 -5
- package/src/plugins/builtin/company-attention/index.tsx +6 -3
- package/src/plugins/builtin/company-attention/model.ts +33 -7
- package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
- package/src/plugins/builtin/company-attention/moves.tsx +159 -0
- package/src/plugins/builtin/company-attention/pane.tsx +79 -23
- package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
- package/src/plugins/builtin/company-attention/signals.tsx +160 -0
- package/src/plugins/builtin/company-kpis/headless.ts +3 -2
- package/src/plugins/builtin/company-kpis/model.ts +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
- package/src/plugins/builtin/composite-plugins.ts +2 -1
- package/src/plugins/builtin/congress-trades/headless.ts +1 -1
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
- package/src/plugins/builtin/correlation/headless.ts +5 -3
- package/src/plugins/builtin/cot/headless.ts +28 -6
- package/src/plugins/builtin/cot/model.ts +12 -0
- package/src/plugins/builtin/cot/pane.tsx +3 -2
- package/src/plugins/builtin/cpi/headless.ts +5 -1
- package/src/plugins/builtin/cpi/pane.tsx +11 -9
- package/src/plugins/builtin/credit-boards/model.ts +2 -0
- package/src/plugins/builtin/credit-documents/headless.ts +1 -1
- package/src/plugins/builtin/crypto-board/client.ts +86 -0
- package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
- package/src/plugins/builtin/crypto-board/defi.ts +239 -0
- package/src/plugins/builtin/crypto-board/headless.ts +117 -6
- package/src/plugins/builtin/crypto-board/index.tsx +8 -3
- package/src/plugins/builtin/crypto-board/model.ts +40 -8
- package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
- package/src/plugins/builtin/crypto-board/series.ts +19 -1
- package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
- package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
- package/src/plugins/builtin/debug/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/docs/index.tsx +1 -1
- package/src/plugins/builtin/docs/pane.tsx +2 -2
- package/src/plugins/builtin/docs/targets.ts +1 -1
- package/src/plugins/builtin/doe/client.ts +5 -1
- package/src/plugins/builtin/doe/headless.ts +12 -6
- package/src/plugins/builtin/doe/model.ts +43 -6
- package/src/plugins/builtin/doe/pane.tsx +18 -11
- package/src/plugins/builtin/earnings/board-model.ts +13 -6
- package/src/plugins/builtin/earnings/board-table.ts +4 -1
- package/src/plugins/builtin/earnings/board.tsx +253 -50
- package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
- package/src/plugins/builtin/earnings/calendar.tsx +338 -0
- package/src/plugins/builtin/earnings/client.ts +4 -3
- package/src/plugins/builtin/earnings/headless.ts +53 -15
- package/src/plugins/builtin/earnings/history-model.ts +53 -36
- package/src/plugins/builtin/earnings/index.tsx +15 -22
- package/src/plugins/builtin/earnings/model.ts +17 -12
- package/src/plugins/builtin/earnings/scope.ts +89 -0
- package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
- package/src/plugins/builtin/earnings-calls/data.ts +146 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
- package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
- package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
- package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +132 -20
- package/src/plugins/builtin/econ/detail-view.tsx +48 -10
- package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
- package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
- package/src/plugins/builtin/econ/index.tsx +112 -25
- package/src/plugins/builtin/econ/print-watch.ts +2 -1
- package/src/plugins/builtin/econ/types.ts +32 -1
- package/src/plugins/builtin/econ-statistics/client.ts +16 -3
- package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
- package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
- package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
- package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
- package/src/plugins/builtin/econ-statistics/view.ts +16 -1
- package/src/plugins/builtin/equity-screener/client.ts +21 -3
- package/src/plugins/builtin/equity-screener/headless.ts +68 -6
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +6 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
- package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
- package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
- package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
- package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
- package/src/plugins/builtin/exposure/headless.ts +51 -6
- package/src/plugins/builtin/exposure/index.tsx +28 -2
- package/src/plugins/builtin/exposure/model.ts +7 -0
- package/src/plugins/builtin/exposure/pane.tsx +6 -1
- package/src/plugins/builtin/fear-greed/index.tsx +1 -1
- package/src/plugins/builtin/filing-events/index.tsx +1 -1
- package/src/plugins/builtin/futures/model.ts +10 -9
- package/src/plugins/builtin/futures/returns.ts +8 -36
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +40 -9
- package/src/plugins/builtin/futures-curve/headless.ts +39 -17
- package/src/plugins/builtin/futures-curve/model.ts +258 -69
- package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
- package/src/plugins/builtin/fx-matrix/client.ts +15 -8
- package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
- package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
- package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
- package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/help/index.tsx +13 -3
- package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
- package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +13 -1
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +46 -7
- package/src/plugins/builtin/holders/index-holders.ts +264 -0
- package/src/plugins/builtin/holders/pane.tsx +79 -15
- package/src/plugins/builtin/holders/report-rows.ts +35 -7
- package/src/plugins/builtin/holders/table-model.ts +2 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/headless.ts +1 -1
- package/src/plugins/builtin/insider/signals-client.ts +1 -1
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
- package/src/plugins/builtin/iv-history/client.ts +20 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -4
- package/src/plugins/builtin/iv-history/index.tsx +1 -1
- package/src/plugins/builtin/iv-history/model.ts +13 -4
- package/src/plugins/builtin/iv-history/series.ts +3 -1
- package/src/plugins/builtin/jobs/lock-note.ts +1 -1
- package/src/plugins/builtin/jobs/model.ts +4 -15
- package/src/plugins/builtin/jobs/pane.tsx +7 -5
- package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
- package/src/plugins/builtin/jodi/pane.tsx +10 -4
- package/src/plugins/builtin/layout-manager/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +20 -7
- package/src/plugins/builtin/macro-day/index.tsx +3 -2
- package/src/plugins/builtin/macro-day/model.ts +29 -8
- package/src/plugins/builtin/macro-day/pane.tsx +46 -10
- package/src/plugins/builtin/macro-day/releases.ts +55 -13
- package/src/plugins/builtin/market-heatmap/data.ts +9 -2
- package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
- package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
- package/src/plugins/builtin/market-heatmap/model.ts +10 -7
- package/src/plugins/builtin/market-movers/client.ts +33 -19
- package/src/plugins/builtin/market-movers/headless.ts +8 -2
- package/src/plugins/builtin/market-movers/index.tsx +16 -10
- package/src/plugins/builtin/market-movers/screener.ts +29 -8
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
- package/src/plugins/builtin/market-movers/session-table.ts +4 -2
- package/src/plugins/builtin/market-movers/table.ts +4 -1
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/view.ts +5 -0
- package/src/plugins/builtin/members/headless.ts +6 -5
- package/src/plugins/builtin/members/pane.tsx +11 -4
- package/src/plugins/builtin/mna/client.ts +1 -0
- package/src/plugins/builtin/mna/detail.tsx +20 -32
- package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
- package/src/plugins/builtin/mna/distress/model.ts +3 -2
- package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
- package/src/plugins/builtin/mna/headless.ts +6 -13
- package/src/plugins/builtin/mna/model.ts +93 -15
- package/src/plugins/builtin/mna/pane.tsx +5 -4
- package/src/plugins/builtin/news/headless.ts +12 -6
- package/src/plugins/builtin/news/index.tsx +10 -1
- package/src/plugins/builtin/news/wire/index.tsx +3 -2
- package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
- package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
- package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
- package/src/plugins/builtin/notes/cli.ts +49 -14
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/view.tsx +10 -10
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-scenario/client.ts +123 -28
- package/src/plugins/builtin/options-scenario/collar.ts +8 -6
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
- package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
- package/src/plugins/builtin/options-scenario/csp.ts +101 -21
- package/src/plugins/builtin/options-scenario/headless.ts +36 -15
- package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
- package/src/plugins/builtin/options-scenario/index.tsx +28 -3
- package/src/plugins/builtin/options-scenario/model.ts +13 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
- package/src/plugins/builtin/perps/equity-row.tsx +11 -3
- package/src/plugins/builtin/perps/freshness.ts +8 -5
- package/src/plugins/builtin/perps/headless.ts +3 -1
- package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
- package/src/plugins/builtin/perps/live-rows.ts +161 -0
- package/src/plugins/builtin/perps/markets-section.tsx +154 -0
- package/src/plugins/builtin/perps/pane.tsx +36 -17
- package/src/plugins/builtin/perps/venue-markets.ts +96 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
- package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
- package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
- package/src/plugins/builtin/portfolio-list/income.ts +13 -2
- package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
- package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
- package/src/plugins/builtin/power/client.ts +4 -1
- package/src/plugins/builtin/power/evidence.ts +22 -7
- package/src/plugins/builtin/power/gas.tsx +5 -1
- package/src/plugins/builtin/power/pane.tsx +8 -1
- package/src/plugins/builtin/power/prices.tsx +10 -3
- package/src/plugins/builtin/research/analyst-headless.ts +25 -8
- package/src/plugins/builtin/research/analyst-model.ts +68 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
- package/src/plugins/builtin/research/event-model.ts +3 -1
- package/src/plugins/builtin/research/event-sources.ts +12 -4
- package/src/plugins/builtin/research/index.tsx +2 -1
- package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
- package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
- package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
- package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
- package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
- package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/sec/forms.ts +13 -0
- package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
- package/src/plugins/builtin/sec/fund-facts.ts +68 -8
- package/src/plugins/builtin/sec/headless.ts +85 -8
- package/src/plugins/builtin/sec/index.tsx +58 -12
- package/src/plugins/builtin/sectors/client.ts +2 -1
- package/src/plugins/builtin/sectors/sector-model.ts +11 -15
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
- package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
- package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
- package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
- package/src/plugins/builtin/shared/earnings-report.ts +3 -3
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
- package/src/plugins/builtin/shared/job-posting.ts +129 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
- package/src/plugins/builtin/shared/report-freshness.ts +3 -0
- package/src/plugins/builtin/shared/research-trading.tsx +21 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/short-interest/client.ts +2 -0
- package/src/plugins/builtin/short-interest/headless.ts +41 -12
- package/src/plugins/builtin/short-interest/index.tsx +23 -1
- package/src/plugins/builtin/short-interest/model.ts +70 -19
- package/src/plugins/builtin/short-interest/pane.tsx +19 -2
- package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
- package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
- package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
- package/src/plugins/builtin/short-interest/schedule.ts +35 -2
- package/src/plugins/builtin/short-interest/surface.tsx +11 -4
- package/src/plugins/builtin/short-interest/types.ts +9 -0
- package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
- package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
- package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
- package/src/plugins/builtin/supply-chain/model.ts +51 -3
- package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
- package/src/plugins/builtin/themes/headless.ts +8 -5
- package/src/plugins/builtin/themes/model.ts +14 -4
- package/src/plugins/builtin/themes/pane.tsx +24 -5
- package/src/plugins/builtin/thirteenf/headless.ts +5 -5
- package/src/plugins/builtin/thirteenf/signals.ts +3 -1
- package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
- package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
- package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
- package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
- package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
- package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
- package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
- package/src/plugins/builtin/vol-surface/client.ts +5 -4
- package/src/plugins/builtin/vol-surface/headless.ts +12 -3
- package/src/plugins/builtin/vol-surface/model.ts +4 -2
- package/src/plugins/builtin/volatility/model.ts +5 -10
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
- package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
- package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
- package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -26
- package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
- package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
- package/src/plugins/builtin/yield-curve/client.ts +25 -0
- package/src/plugins/builtin/yield-curve/curves.ts +7 -4
- package/src/plugins/builtin/yield-curve/headless.ts +38 -4
- package/src/plugins/builtin/yield-curve/history.ts +4 -3
- package/src/plugins/builtin/yield-curve/index.tsx +12 -6
- package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
- package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
- package/src/plugins/bundle.ts +1 -1
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/compat.ts +3 -3
- package/src/plugins/dependencies.ts +75 -14
- package/src/plugins/extracted-plugins.ts +132 -34
- package/src/plugins/host-link.ts +149 -34
- package/src/plugins/installer.ts +35 -10
- package/src/plugins/loader.ts +206 -38
- package/src/plugins/manager-node.ts +2 -2
- package/src/plugins/marketplace/deactivation.ts +22 -0
- package/src/plugins/marketplace/model.ts +2 -2
- package/src/plugins/marketplace/packs.ts +1 -1
- package/src/plugins/ownership.ts +1 -1
- package/src/plugins/peer-retry.ts +155 -0
- package/src/plugins/registry/contributions.ts +3 -1
- package/src/plugins/registry/index.ts +4 -3
- package/src/plugins/registry/plugin-state.ts +3 -0
- package/src/plugins/seed-notice.ts +20 -0
- package/src/plugins/shortcut-argument.ts +39 -0
- package/src/portfolio/allocation.ts +1 -1
- package/src/portfolio/collection-name.ts +31 -0
- package/src/portfolio/column-values.ts +10 -8
- package/src/portfolio/cost-fx.ts +296 -19
- package/src/portfolio/manual-lots.ts +75 -0
- package/src/portfolio/mutations.ts +60 -22
- package/src/portfolio/suffixed-listings.ts +209 -0
- package/src/portfolio/totals-currency.ts +24 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
- package/src/public/time-series.ts +11 -8
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/config-host.ts +3 -0
- package/src/renderers/browser/main.tsx +23 -3
- package/src/renderers/dom/boot-frame-page.ts +187 -0
- package/src/renderers/dom/boot-frame.ts +237 -0
- package/src/renderers/dom/build-assets.ts +46 -8
- package/src/renderers/dom/dom-ui-host.tsx +4 -29
- package/src/renderers/dom/host/ascii-text.ts +16 -2
- package/src/renderers/dom/host/box.tsx +43 -2
- package/src/renderers/dom/host/chart-surface.tsx +2 -0
- package/src/renderers/dom/host/hls.chunk.ts +3 -0
- package/src/renderers/dom/host/image-surface.tsx +49 -0
- package/src/renderers/dom/host/media-surface.tsx +24 -18
- package/src/renderers/dom/host/mouse.ts +30 -0
- package/src/renderers/dom/host/size-observer.ts +1 -1
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/styles.css +76 -0
- package/src/renderers/dom/test-utils.tsx +2 -1
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +46 -3
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
- package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
- package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
- package/src/renderers/electrobun/bun/index.ts +11 -1
- package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
- package/src/renderers/electrobun/bun/window/create.ts +4 -1
- package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
- package/src/renderers/electrobun/shared/protocol.ts +6 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/config-host.ts +3 -0
- package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
- package/src/renderers/electrobun/view/main.tsx +30 -4
- package/src/renderers/electrobun/view/news-source.ts +5 -5
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
- package/src/renderers/electrobun/view/ui-host.tsx +1 -1
- package/src/renderers/opentui/browser-open.ts +88 -0
- package/src/renderers/opentui/host.tsx +5 -14
- package/src/renderers/opentui/image/loader.ts +3 -2
- package/src/renderers/opentui/native-smoke.ts +10 -1
- package/src/renderers/opentui/pane-image/index.ts +2 -1
- package/src/renderers/opentui/render-lib.ts +253 -0
- package/src/renderers/opentui/render-timing-smoke.ts +1 -1
- package/src/renderers/opentui/start.tsx +1 -1
- package/src/renderers/share/layout-view.tsx +2 -2
- package/src/renderers/share/main.tsx +4 -4
- package/src/renderers/share/view.tsx +1 -1
- package/src/series/resolve.ts +22 -6
- package/src/series/standalone.ts +30 -2
- package/src/series/types.ts +8 -1
- package/src/shares/api.ts +4 -1
- package/src/shares/pane.ts +1 -1
- package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
- package/src/sources/gloomberb-cloud/index.ts +32 -16
- package/src/sources/gloomberb-cloud/news.ts +39 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
- package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
- package/src/sources/listing-symbols.ts +37 -0
- package/src/sources/provider-errors.ts +16 -2
- package/src/sources/provider-router/financial-routes.ts +21 -3
- package/src/sources/provider-router/financials.ts +15 -2
- package/src/sources/provider-router/history.ts +30 -8
- package/src/sources/provider-router/primary.ts +1 -1
- package/src/state/app/bootstrap.ts +23 -0
- package/src/state/hooks/inline-tickers.ts +30 -5
- package/src/sync/controller.ts +1 -1
- package/src/sync/core-contributors.ts +46 -14
- package/src/team/collections-sync.ts +2 -1
- package/src/team/collections.ts +178 -17
- package/src/telemetry/crash-reports.ts +17 -4
- package/src/test-support/builtin-panes.ts +1 -1
- package/src/theme/colors.ts +3 -30
- package/src/theme/ui-tokens.ts +37 -1
- package/src/tickers/company-name-listing.ts +210 -33
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/metadata.ts +10 -0
- package/src/tickers/perpetual-listing.ts +5 -2
- package/src/tickers/search/home-listing.ts +75 -0
- package/src/tickers/search/index.ts +76 -27
- package/src/tickers/search/ranking.ts +54 -4
- package/src/tickers/search/upsert.ts +29 -0
- package/src/tickers/terminal-codes.ts +416 -40
- package/src/time-series/bar-aggregation.ts +243 -0
- package/src/time-series/base-series.ts +307 -0
- package/src/time-series/chart-bounds.ts +349 -0
- package/src/time-series/chart-seed.ts +142 -0
- package/src/time-series/economic.ts +5 -0
- package/src/time-series/fundamentals.ts +18 -3
- package/src/time-series/history-acquisition.ts +499 -0
- package/src/time-series/leverage.ts +100 -0
- package/src/time-series/market-resolution.ts +4 -2
- package/src/time-series/market.ts +2 -1
- package/src/time-series/price-comparison.ts +175 -30
- package/src/time-series/range.ts +9 -1
- package/src/time-series/resolution.ts +174 -16
- package/src/time-series/resolve-context.ts +157 -0
- package/src/time-series/resolve.ts +126 -1577
- package/src/time-series/series-name.ts +38 -0
- package/src/time-series/series-presentation.ts +208 -0
- package/src/time-series/spec.ts +11 -6
- package/src/time-series/studies.ts +109 -12
- package/src/time-series/tail-reconcile.ts +121 -0
- package/src/time-series/types.ts +29 -2
- package/src/time-series/use-chart-resolution.ts +4 -5
- package/src/types/broker.ts +10 -0
- package/src/types/config.ts +14 -0
- package/src/types/data-provider.ts +14 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +104 -7
- package/src/types/headless.ts +76 -6
- package/src/types/instrument.ts +3 -0
- package/src/types/plugin.ts +65 -8
- package/src/types/price-history.ts +2 -0
- package/src/types/ticker.ts +13 -0
- package/src/types/trading.ts +59 -1
- package/src/ui/ascii-font.ts +13 -1
- package/src/ui/host.tsx +6 -1
- package/src/updater/command-names.ts +175 -0
- package/src/updater/index.ts +10 -5
- package/src/utils/calendar-date.ts +32 -15
- package/src/utils/cash-runway.ts +241 -0
- package/src/utils/central-banks.ts +42 -0
- package/src/utils/cli-output.ts +259 -80
- package/src/utils/contract-month.ts +16 -0
- package/src/utils/crypto-pair.ts +61 -3
- package/src/utils/currency-units.ts +29 -0
- package/src/utils/datetime-format.ts +10 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +39 -6
- package/src/utils/exchange-announcements.ts +71 -0
- package/src/utils/exchange-rate-snapshot.ts +10 -0
- package/src/utils/financial-statements.ts +83 -4
- package/src/utils/format.ts +34 -16
- package/src/utils/fundamentals.ts +150 -34
- package/src/utils/fx-market-hours.ts +10 -1
- package/src/utils/latest-financial-period.ts +8 -0
- package/src/utils/linux-libc.ts +54 -0
- package/src/utils/market-capitalization.ts +111 -15
- package/src/utils/max-drawdown.ts +64 -0
- package/src/utils/network-failure.ts +83 -0
- package/src/utils/option-expiry.ts +139 -7
- package/src/utils/price-earnings.ts +11 -5
- package/src/utils/price-history.ts +18 -8
- package/src/utils/price-window.ts +131 -0
- package/src/utils/release-date.ts +47 -0
- package/src/utils/sec.ts +3 -0
- package/src/utils/throttled-fetch.ts +11 -4
- package/src/utils/trailing-eps.ts +67 -0
- package/src/utils/typed-text.ts +21 -0
- package/src/utils/utc-time.ts +24 -1
- package/src/version.ts +6 -0
- package/src/cli/pane-functions/screenshot.ts +0 -2122
|
@@ -42,10 +42,11 @@ import type { ResolvedPaneFunction } from "./resolver";
|
|
|
42
42
|
import { isRecord } from "../../utils/guards";
|
|
43
43
|
import { splitSymbolWords } from "../symbol-args";
|
|
44
44
|
import { formatUtcTime, localTimeSuffix } from "../../utils/utc-time";
|
|
45
|
-
import { deriveHeadlessFreshness, formatFreshnessLine, staleRowsText, type ReportFreshness } from "./freshness";
|
|
45
|
+
import { deriveHeadlessFreshness, formatFreshnessLine, staleRowsText, withSavedCopy, type ReportFreshness } from "./freshness";
|
|
46
46
|
import { accessGateStatus, errorsAccessGate, isProLock, reportGateText } from "./access-gate";
|
|
47
47
|
import { noArgumentMessage } from "./capabilities";
|
|
48
48
|
import { lockedHeadlessReport } from "./lock-note";
|
|
49
|
+
import { resumeStateKey } from "../../plugins/registry/plugin-state";
|
|
49
50
|
|
|
50
51
|
interface SerializableHeadlessColumn {
|
|
51
52
|
key: string;
|
|
@@ -69,7 +70,7 @@ function argumentName(definition: HeadlessPaneDefinition): string {
|
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
function requiredArgumentError(definition: HeadlessPaneDefinition, token: string): Error {
|
|
72
|
-
return new Error(`Usage:
|
|
73
|
+
return new Error(`Usage: gloom fn ${token} <${argumentName(definition)}>`);
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
function normalizeSymbol(value: string): string {
|
|
@@ -187,7 +188,7 @@ async function loadHeadlessPaneModel(
|
|
|
187
188
|
return result;
|
|
188
189
|
}
|
|
189
190
|
|
|
190
|
-
type HeadlessMarketContext = Pick<MarketContext, "config" | "store" | "refresh" | "resolveBroker"> & Partial<Pick<MarketContext, "persistence" | "seriesCapabilities">> & {
|
|
191
|
+
type HeadlessMarketContext = Pick<MarketContext, "config" | "store" | "refresh" | "resolveBroker"> & Partial<Pick<MarketContext, "persistence" | "seriesCapabilities" | "findCatalogSeries">> & {
|
|
191
192
|
dataProvider: HeadlessPaneContext["marketData"];
|
|
192
193
|
};
|
|
193
194
|
|
|
@@ -205,6 +206,8 @@ export function createHeadlessPaneContext(
|
|
|
205
206
|
...(context.refresh ? { refresh: true } : {}),
|
|
206
207
|
settings: resolved.instance.settings,
|
|
207
208
|
capabilities: getSharedRegistry() ?? context.seriesCapabilities,
|
|
209
|
+
catalogSeriesName: (expression) => (getSharedRegistry()?.series.findByExpression(expression)?.definition
|
|
210
|
+
?? context.findCatalogSeries?.(expression))?.name,
|
|
208
211
|
resolveBroker: context.resolveBroker,
|
|
209
212
|
async resolvePortfolio(id) {
|
|
210
213
|
const portfolio = findNamedCollection(context.config.portfolios, id);
|
|
@@ -223,10 +226,12 @@ export function createHeadlessPaneContext(
|
|
|
223
226
|
?? (key !== parsed.symbol ? await context.store.loadTicker(parsed.symbol) : null);
|
|
224
227
|
return { symbol: parsed.symbol, exchange: parsed.exchange ?? ticker?.metadata.exchange };
|
|
225
228
|
},
|
|
229
|
+
readDeviceState: <T,>(pluginId: string, key: string) =>
|
|
230
|
+
context.persistence?.pluginState.get<T>(pluginId, resumeStateKey(key))?.value ?? null,
|
|
226
231
|
async resolveListing(symbol, argumentWith) {
|
|
227
232
|
const command = `fn ${resolved.token}`;
|
|
228
233
|
const read = await readBareListing(symbol, context, {
|
|
229
|
-
command, noun: "a quote", retry: (key) => `
|
|
234
|
+
command, noun: "a quote", retry: (key) => `gloom ${command} ${argumentWith(key)}`,
|
|
230
235
|
}, { refresh: !!context.refresh });
|
|
231
236
|
if (!read) return null;
|
|
232
237
|
return { symbol: read.symbol, ...read.exchange ? { exchange: read.exchange } : {}, ...read.name ? { name: read.name } : {} };
|
|
@@ -363,7 +368,8 @@ export function serializeHeadlessPaneResult(
|
|
|
363
368
|
}
|
|
364
369
|
case "series": {
|
|
365
370
|
const series = result as HeadlessSeriesResult;
|
|
366
|
-
|
|
371
|
+
// `textDecimals` only shapes the text report; JSON keeps every digit and does not carry it.
|
|
372
|
+
return { ...common, series: series.series.map(({ textDecimals: _text, ...kept }) => kept), ...(series.stats ? { stats: series.stats } : {}) };
|
|
367
373
|
}
|
|
368
374
|
case "snapshot": {
|
|
369
375
|
const snapshot = result as HeadlessSnapshotResult;
|
|
@@ -484,7 +490,8 @@ function seriesPointExportDate(series: HeadlessSeries, date: SeriesPointDate, da
|
|
|
484
490
|
}
|
|
485
491
|
|
|
486
492
|
/**
|
|
487
|
-
* A latest value as the series report prints it: percentages
|
|
493
|
+
* A latest value as the series report prints it: percentages and percentage
|
|
494
|
+
* points, multiples and
|
|
488
495
|
* ratios (P/E, EV/EBITDA, one series over another, VIX 3M / VIX) to two
|
|
489
496
|
* decimals, which a ratio under 0.1 trades for three significant digits so it
|
|
490
497
|
* is not flattened to 0.03, and a 0 to 100 score to a tenth of a point. The
|
|
@@ -494,8 +501,9 @@ function seriesPointExportDate(series: HeadlessSeries, date: SeriesPointDate, da
|
|
|
494
501
|
function seriesValue(series: HeadlessSeries, value: number | null): string {
|
|
495
502
|
if (value == null) return "-";
|
|
496
503
|
if (!Number.isFinite(value)) return displayNumber(value);
|
|
504
|
+
if (series.textDecimals != null) return value.toFixed(series.textDecimals);
|
|
497
505
|
const unit = series.unit?.trim().toLowerCase();
|
|
498
|
-
if (unit === "%") return value.toFixed(2);
|
|
506
|
+
if (unit === "%" || unit === "pp") return value.toFixed(2);
|
|
499
507
|
if (unit === "x" || unit === "ratio") return value !== 0 && Math.abs(value) < 0.1 ? value.toPrecision(3) : value.toFixed(2);
|
|
500
508
|
if (unit === "score") return value.toFixed(1);
|
|
501
509
|
return displayNumber(value);
|
|
@@ -525,6 +533,7 @@ function renderRows(
|
|
|
525
533
|
minWidth: column.minWidth,
|
|
526
534
|
stackPriority: column.stackPriority,
|
|
527
535
|
stackRows: column.stackRows,
|
|
536
|
+
minTableWidth: column.minTableWidth,
|
|
528
537
|
})),
|
|
529
538
|
rows.map((row) => columns.map((column) => cell(row, column))),
|
|
530
539
|
{
|
|
@@ -612,7 +621,7 @@ const SERIES_FIELDS = ["value", "open", "high", "low", "close", "volume"] as con
|
|
|
612
621
|
* column names beside the bare `Value`, `Open`... headers.
|
|
613
622
|
*/
|
|
614
623
|
function seriesTable(series: HeadlessSeries): CliReportTable {
|
|
615
|
-
const fields = SERIES_FIELDS.filter((field) => series.points.some((point) => point[field] != null));
|
|
624
|
+
const fields = SERIES_FIELDS.filter((field) => !(field === "value" && series.valueIsClose) && series.points.some((point) => point[field] != null));
|
|
616
625
|
const days = observesDays(series);
|
|
617
626
|
const dates = series.points.map((point) => seriesPointExportDate(series, point.date, days));
|
|
618
627
|
const header = (field: (typeof SERIES_FIELDS)[number]) => `${field[0]!.toUpperCase()}${field.slice(1)}`;
|
|
@@ -754,7 +763,7 @@ export function headlessReportTables(
|
|
|
754
763
|
const rowsResult = result as HeadlessRowsResult;
|
|
755
764
|
const columns = displayedColumns(columnsFor(rowsResult.rows, rowsResult.columns, definition.columns));
|
|
756
765
|
const rowIdentities = rowIdentitiesOf(rowsResult.rows, rowsResult);
|
|
757
|
-
const own = exportRowsTable(title, columns, rowsResult.rows, { status: true });
|
|
766
|
+
const own = exportRowsTable(title, columns, rowsResult.rows, { status: true, ...(rowsResult.rowUnitKey ? { rowUnitKey: rowsResult.rowUnitKey } : {}) });
|
|
758
767
|
const interval = rowsResult.interval?.trim();
|
|
759
768
|
tables = [{ ...own, ...(rowIdentities ? { rowIdentities } : {}), ...(interval ? { identity: { interval } } : {}) }, ...(rowsResult.exportTables ?? []).map((extra) => {
|
|
760
769
|
const identity = {
|
|
@@ -775,7 +784,10 @@ export function headlessReportTables(
|
|
|
775
784
|
};
|
|
776
785
|
if (!("rows" in section && section.rows)) {
|
|
777
786
|
const entries = exportEntriesTable(section.title, section.entries);
|
|
778
|
-
|
|
787
|
+
// A figure that declares its unit names it in the unit column of its own line too.
|
|
788
|
+
const rowIdentities = section.entries.some((entry) => entry.unit?.trim())
|
|
789
|
+
? section.entries.map((entry) => entry.unit?.trim() ? { currencyOrUnit: entry.unit.trim() } : undefined) : undefined;
|
|
790
|
+
return { ...entries, ...(Object.keys(named).length > 0 ? { identity: named } : {}), ...(rowIdentities ? { rowIdentities } : {}) };
|
|
779
791
|
}
|
|
780
792
|
const table = exportRowsTable(section.title, displayedColumns(columnsFor(section.rows, section.columns, definition.columns)), section.rows, { status: true });
|
|
781
793
|
const identity = {
|
|
@@ -967,7 +979,8 @@ export async function buildHeadlessFunctionReport(
|
|
|
967
979
|
}
|
|
968
980
|
const { complete, unavailableSymbols, rowCount, symbols } = reportCoverage(loaded);
|
|
969
981
|
const serialized = serializeHeadlessPaneResult(loaded.definition, loaded.result);
|
|
970
|
-
|
|
982
|
+
// What the report shows from a saved copy, its refresh having failed, says so.
|
|
983
|
+
const freshness = withSavedCopy(deriveHeadlessFreshness(loaded.definition, loaded.result), loaded.result);
|
|
971
984
|
return {
|
|
972
985
|
data: {
|
|
973
986
|
kind: loaded.definition.shape,
|
|
@@ -21,10 +21,12 @@ import {
|
|
|
21
21
|
parsePaneFunctionArgs,
|
|
22
22
|
type ParsedPaneFunctionArgs,
|
|
23
23
|
} from "./options";
|
|
24
|
-
import { applyListingArgument, findPaneFunction, resolvePaneFunction, UnknownPaneFunctionError, type ResolvedPaneFunction } from "./resolver";
|
|
24
|
+
import { applyListingArgument, findPaneFunction, parsePaneFunctionArgsFor, resolvePaneFunction, UnknownPaneFunctionError, type ResolvedPaneFunction } from "./resolver";
|
|
25
25
|
import { buildFunctionReport } from "./report";
|
|
26
26
|
import { expandResolvedArgument } from "./headless";
|
|
27
|
-
import { defaultScreenshotPath,
|
|
27
|
+
import { defaultScreenshotPath, shotSizeWarnings } from "./screenshot-payload";
|
|
28
|
+
import { renderDesktopShot } from "./screenshot-render";
|
|
29
|
+
import { shotStatusIssues } from "./screenshot-assessment";
|
|
28
30
|
import {
|
|
29
31
|
buildPaneCatalogEntries,
|
|
30
32
|
} from "./catalog";
|
|
@@ -67,7 +69,7 @@ async function withPaneRuntime<T>(
|
|
|
67
69
|
const context: MarketContext = ctx.cliOptions.refresh ? { ...market, refresh: true } : market;
|
|
68
70
|
const registry = await createPaneCatalog(context, ctx.plugins);
|
|
69
71
|
try {
|
|
70
|
-
let parsed = await applyListingArgument(registry, context,
|
|
72
|
+
let parsed = await applyListingArgument(registry, context, parsePaneFunctionArgsFor(registry, args, ctx.cliOptions), settings.command);
|
|
71
73
|
let resolved = await resolvePaneFunction(registry, context, parsed, settings);
|
|
72
74
|
// A function that widens its argument (RV's --peers) runs, reports and captures the widened one.
|
|
73
75
|
const expansion = await withPersistedCloudSession(context, () => expandResolvedArgument(resolved, context, parsed.arg));
|
|
@@ -100,8 +102,8 @@ function commandWord(argument: string): string {
|
|
|
100
102
|
}
|
|
101
103
|
|
|
102
104
|
/**
|
|
103
|
-
* What to run when a command name is a function's code (`
|
|
104
|
-
* `
|
|
105
|
+
* What to run when a command name is a function's code (`gloom OVDV KO`,
|
|
106
|
+
* `gloom help OVDV`): `fn` with the reader's own arguments, or the
|
|
105
107
|
* function's argument hint when they gave none. Null when the word is no
|
|
106
108
|
* function code or the catalog cannot be read, and the command stays unknown.
|
|
107
109
|
*/
|
|
@@ -123,7 +125,7 @@ export async function functionCodeCommand(
|
|
|
123
125
|
});
|
|
124
126
|
if (!found) return null;
|
|
125
127
|
const code = word.replace(/^\$/, "").toUpperCase();
|
|
126
|
-
return { code, command: ["
|
|
128
|
+
return { code, command: ["gloom fn", code, args.length > 0 ? args.map(commandWord).join(" ") : found.argument].filter(Boolean).join(" ") };
|
|
127
129
|
} catch (error) {
|
|
128
130
|
logFailure("cli.pane-functions-index", "Resolve function code command failed")(error);
|
|
129
131
|
return null;
|
|
@@ -131,7 +133,7 @@ export async function functionCodeCommand(
|
|
|
131
133
|
}
|
|
132
134
|
|
|
133
135
|
/**
|
|
134
|
-
* The one function code a command name is a slip from (`
|
|
136
|
+
* The one function code a command name is a slip from (`gloom RCDF PLTR`
|
|
135
137
|
* for RDCF), with the command that runs it on the reader's arguments, read
|
|
136
138
|
* as a command word is (nearFunctionCodes), so a ticker is not taken for one.
|
|
137
139
|
* Null when no code, or more than one, is that close, or the catalog cannot
|
|
@@ -155,7 +157,7 @@ export async function nearFunctionCodeCommand(
|
|
|
155
157
|
});
|
|
156
158
|
if (near.length !== 1) return null;
|
|
157
159
|
const { code, label } = near[0]!;
|
|
158
|
-
return { code, label, command: ["
|
|
160
|
+
return { code, label, command: ["gloom fn", code, ...args.map(commandWord)].join(" ") };
|
|
159
161
|
} catch (error) {
|
|
160
162
|
logFailure("cli.pane-functions-index", "Find nearby function code command failed")(error);
|
|
161
163
|
return null;
|
|
@@ -272,7 +274,7 @@ export async function runPaneFunction(args: string[], ctx: CliCommandContext) {
|
|
|
272
274
|
)) {
|
|
273
275
|
throw new Error(
|
|
274
276
|
`${resolved.token} is not a verified bot-safe report capability. `
|
|
275
|
-
+ `Use "
|
|
277
|
+
+ `Use "gloom catalog ${resolved.token}" to inspect readiness.`,
|
|
276
278
|
);
|
|
277
279
|
}
|
|
278
280
|
const tabular = ctx.cliOptions.format === "csv" || ctx.cliOptions.format === "ndjson";
|
|
@@ -294,7 +296,7 @@ export async function runPaneFunction(args: string[], ctx: CliCommandContext) {
|
|
|
294
296
|
const fate = listing && quoteAnswer && isTickerLinkPeer(resolved.instance, registry.panes)
|
|
295
297
|
? listingFateLoader(listing, context, quoteAnswer().then((answer) => answer.quote))
|
|
296
298
|
: null;
|
|
297
|
-
const moved = { command: "fn", retry: (key: string) => `
|
|
299
|
+
const moved = { command: "fn", retry: (key: string) => `gloom fn ${resolved.token} ${key}` };
|
|
298
300
|
// A report that fails or comes back empty for an exchange the symbol is not listed on says so.
|
|
299
301
|
const report = await refuseMovedListing(fate, moved, () => withPersistedCloudSession(
|
|
300
302
|
context,
|
|
@@ -307,7 +309,7 @@ export async function runPaneFunction(args: string[], ctx: CliCommandContext) {
|
|
|
307
309
|
),
|
|
308
310
|
));
|
|
309
311
|
// A company's name typed where its ticker goes (`fn RDCF Palantir`) found nothing: the answer is `quote`'s,
|
|
310
|
-
// "Not a ticker: PALANTIR. Try `
|
|
312
|
+
// "Not a ticker: PALANTIR. Try `gloom search Palantir`.", not an empty report.
|
|
311
313
|
if (quoteAnswer && (report.data.empty || report.data.unavailableSymbols.length > 0)) {
|
|
312
314
|
const { quote, error } = await quoteAnswer();
|
|
313
315
|
const message = error instanceof Error ? error.message : null;
|
|
@@ -367,8 +369,8 @@ export function emptySeriesExport(
|
|
|
367
369
|
const ids = [...new Set(fred)];
|
|
368
370
|
return {
|
|
369
371
|
message: `${asked} has no data to export: ${ids.join(" and ")} ${ids.length === 1 ? "is a FRED series" : "are FRED series"}, not ${ids.length === 1 ? "a ticker" : "tickers"}.`,
|
|
370
|
-
details: `Chart it with the fred: prefix:
|
|
371
|
-
+ `${ids.length === 1 ? ` (or
|
|
372
|
+
details: `Chart it with the fred: prefix: gloom fn G ${ids.map((id) => `fred:${id}`).join(",")} ${formatFlag}`
|
|
373
|
+
+ `${ids.length === 1 ? ` (or gloom fred ${ids[0]} ${formatFlag})` : ""}.`,
|
|
372
374
|
};
|
|
373
375
|
}
|
|
374
376
|
const missing = data.unavailableSymbols.length > 0 ? ` for ${data.unavailableSymbols.join(", ")}` : "";
|
|
@@ -377,7 +379,7 @@ export function emptySeriesExport(
|
|
|
377
379
|
message: `${asked} has no data to export${missing}.`,
|
|
378
380
|
details: [
|
|
379
381
|
...reasons,
|
|
380
|
-
`Check the symbol with
|
|
382
|
+
`Check the symbol with gloom search, or run gloom ${asked} without ${formatFlag} to see the report.`,
|
|
381
383
|
].join("\n"),
|
|
382
384
|
};
|
|
383
385
|
}
|
|
@@ -405,7 +407,7 @@ async function capturePaneScreenshot(args: string[], ctx: CliCommandContext, onS
|
|
|
405
407
|
)) {
|
|
406
408
|
throw new Error(
|
|
407
409
|
`${resolved.token} is not a verified bot-safe screenshot capability. `
|
|
408
|
-
+ `Use "
|
|
410
|
+
+ `Use "gloom catalog ${resolved.token}" to inspect readiness.`,
|
|
409
411
|
);
|
|
410
412
|
}
|
|
411
413
|
// An option the pane cannot draw fails here, before a capture of its default is saved as if it were the view asked for.
|
|
@@ -469,7 +471,7 @@ function runGlossary(term: string, ctx: CliCommandContext): void {
|
|
|
469
471
|
const { exact, partial } = lookupGlossary(term);
|
|
470
472
|
const entries = [...exact, ...partial];
|
|
471
473
|
if (entries.length === 0) {
|
|
472
|
-
ctx.fail(`No glossary entry for "${term}".`, knownGapMessage(term) ?? "
|
|
474
|
+
ctx.fail(`No glossary entry for "${term}".`, knownGapMessage(term) ?? "gloom catalog glossary lists every term.");
|
|
473
475
|
}
|
|
474
476
|
ctx.printResult({ data: entries.map(glossaryRecord) }, { text: () => renderGlossaryEntries(entries).join("\n") });
|
|
475
477
|
}
|
|
@@ -106,7 +106,17 @@ export function parseArgumentsOption(value: string): Record<string, string> {
|
|
|
106
106
|
return pairs;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
/** How many words one value of an option takes, by its key as parsed (`fxShift`); one when it is not a pair. */
|
|
110
|
+
export type OptionValueWords = (key: string) => number;
|
|
111
|
+
|
|
112
|
+
/** Words in the last value of a list (`TRY -20, EUR 5` ends with two); a decimal comma (`TRY -2,5`) separates nothing. */
|
|
113
|
+
const lastValueWords = (value: string) => value.split(/(?<!\d),|,(?!\d)/).at(-1)!.trim().split(/\s+/).filter(Boolean).length;
|
|
114
|
+
|
|
115
|
+
export function parsePaneFunctionArgs(
|
|
116
|
+
args: string[],
|
|
117
|
+
globalOptions: { limit?: number; tail?: number } = {},
|
|
118
|
+
valueWords?: OptionValueWords,
|
|
119
|
+
): ParsedPaneFunctionArgs {
|
|
110
120
|
const positionals: string[] = [];
|
|
111
121
|
const options: Record<string, string | true> = {};
|
|
112
122
|
let outputPath: string | null = null;
|
|
@@ -153,8 +163,18 @@ export function parsePaneFunctionArgs(args: string[], globalOptions: { limit?: n
|
|
|
153
163
|
}
|
|
154
164
|
const next = args[index + 1];
|
|
155
165
|
const nextValue = inlineValue === undefined && next && !next.startsWith("--") ? args[++index] : true;
|
|
156
|
-
|
|
166
|
+
let value: string | true = inlineValue ?? nextValue ?? true;
|
|
157
167
|
const normalizedKey = normalizeOptionKey(key);
|
|
168
|
+
// A value that is a pair (`--fx-shift TRY -20`) takes the words after it, and a list of them the words after a comma.
|
|
169
|
+
const words = value === true ? 1 : valueWords?.(normalizedKey) ?? 1;
|
|
170
|
+
if (words > 1 && value !== true) {
|
|
171
|
+
while (index + 1 < args.length && !args[index + 1]!.startsWith("--")
|
|
172
|
+
&& (lastValueWords(value) < words || value.trimEnd().endsWith(","))) {
|
|
173
|
+
value = `${value} ${args[++index]!}`;
|
|
174
|
+
}
|
|
175
|
+
const earlier = options[normalizedKey];
|
|
176
|
+
if (typeof earlier === "string") value = `${earlier}, ${value}`;
|
|
177
|
+
}
|
|
158
178
|
if (normalizedKey === "requireBotSafe" || normalizedKey === "botSafe") {
|
|
159
179
|
requireBotSafe = value === true || String(value).toLowerCase() === "true";
|
|
160
180
|
} else if (normalizedKey === "output" || normalizedKey === "out" || normalizedKey === "o") {
|
|
@@ -66,24 +66,29 @@ function publishedSources(value: unknown): NonNullable<HeadlessPaneFreshness["so
|
|
|
66
66
|
return sources.length ? sources : null;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
function isStringList(value: unknown): value is string[] {
|
|
70
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
71
|
+
}
|
|
72
|
+
|
|
69
73
|
/**
|
|
70
74
|
* How current a rendered pane says its data is, from the `report-freshness`
|
|
71
75
|
* node it publishes: `{ asOf?, status?, delayMinutes?, source?, sources?,
|
|
72
|
-
* maxAgeMinutes?, oldestAge?, note?, basis?, asOfLabel? }`; `basis` names what a pane
|
|
76
|
+
* maxAgeMinutes?, oldestAge?, ageOnly?, note?, noteVariants?, basis?, asOfLabel?, datesEachVenue? }`; `basis` names what a pane
|
|
73
77
|
* that is not a feed lists, when one pane lists different things (NI's
|
|
74
78
|
* stories, and its LTR code's letters). A capture keeps no footer status and
|
|
75
79
|
* few cells carry a time, so a pane that knows its feed (OMON's chain) dates
|
|
76
80
|
* the report here, as the plain command over the same data does, and a pane
|
|
77
|
-
* over several venues (PERP) dates each one as its report does
|
|
81
|
+
* over several venues (PERP) dates each one as its report does, as does one
|
|
82
|
+
* whose quotes trade on several markets (RV's `datesEachVenue`). A pane whose
|
|
78
83
|
* figures come from several dated quotes (FXC's pair rates) publishes them
|
|
79
84
|
* instead, see `renderedReportObservations`.
|
|
80
85
|
*/
|
|
81
86
|
export function renderedReportFreshness(
|
|
82
87
|
semanticUi: readonly RemoteUiNodeSnapshot[],
|
|
83
|
-
): Pick<HeadlessPaneFreshness, "asOf" | "status" | "delayMinutes" | "source" | "sources" | "maxAgeMinutes" | "oldestAge" | "note" | "basis" | "asOfLabel"> {
|
|
88
|
+
): Pick<HeadlessPaneFreshness, "asOf" | "status" | "delayMinutes" | "source" | "sources" | "maxAgeMinutes" | "oldestAge" | "ageOnly" | "note" | "noteVariants" | "basis" | "asOfLabel" | "datesEachVenue"> {
|
|
84
89
|
const metadata = semanticUi.find((node) => node.role === "report-freshness")?.metadata;
|
|
85
90
|
if (!metadata) return {};
|
|
86
|
-
const { asOf, status, delayMinutes, source, maxAgeMinutes, oldestAge, note, basis, asOfLabel } = metadata as Record<string, unknown>;
|
|
91
|
+
const { asOf, status, delayMinutes, source, maxAgeMinutes, oldestAge, ageOnly, note, noteVariants, basis, asOfLabel, datesEachVenue } = metadata as Record<string, unknown>;
|
|
87
92
|
const sources = publishedSources(metadata.sources);
|
|
88
93
|
return {
|
|
89
94
|
...(typeof asOf === "string" || isFiniteNumber(asOf) ? { asOf } : {}),
|
|
@@ -93,9 +98,12 @@ export function renderedReportFreshness(
|
|
|
93
98
|
...(sources ? { sources } : {}),
|
|
94
99
|
...(isFiniteNumber(maxAgeMinutes) && maxAgeMinutes > 0 ? { maxAgeMinutes } : {}),
|
|
95
100
|
...(oldestAge === true ? { oldestAge } : {}),
|
|
101
|
+
...(ageOnly === true ? { ageOnly } : {}),
|
|
96
102
|
...(typeof note === "string" && note.trim() ? { note } : {}),
|
|
103
|
+
...(isStringList(noteVariants) && noteVariants.length > 0 ? { noteVariants } : {}),
|
|
97
104
|
...(typeof basis === "string" && basis.trim() ? { basis } : {}),
|
|
98
105
|
...(typeof asOfLabel === "string" && asOfLabel.trim() ? { asOfLabel } : {}),
|
|
106
|
+
...(datesEachVenue === true ? { datesEachVenue } : {}),
|
|
99
107
|
};
|
|
100
108
|
}
|
|
101
109
|
|
|
@@ -51,10 +51,10 @@ export function resolvePaneFunctionReportSource(
|
|
|
51
51
|
return resolved.capability.reportReadiness === "live-dom" ? "dom" : null;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
/** `
|
|
54
|
+
/** `gloom shot CAT santander`, the argument quoted when it has spaces. */
|
|
55
55
|
function shotCommand(token: string, rawArg: string): string {
|
|
56
56
|
const arg = rawArg.trim();
|
|
57
|
-
return ["
|
|
57
|
+
return ["gloom shot", token, arg && /\s/.test(arg) ? JSON.stringify(arg) : arg].filter(Boolean).join(" ");
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
export async function buildFunctionReport(
|
|
@@ -67,7 +67,7 @@ export async function buildFunctionReport(
|
|
|
67
67
|
if (!source) {
|
|
68
68
|
// HELP is what a newcomer tries first: send them to the command guide and the function list.
|
|
69
69
|
if (resolved.pane.id === "help") {
|
|
70
|
-
throw new Error("HELP is an in-app pane, so it has no report. For the commands run `
|
|
70
|
+
throw new Error("HELP is an in-app pane, so it has no report. For the commands run `gloom help`; for the functions run `gloom catalog`.");
|
|
71
71
|
}
|
|
72
72
|
// A pane `shot` can draw is still one command away.
|
|
73
73
|
const screenshot = resolved.capability.screenshotReadiness;
|
|
@@ -88,10 +88,10 @@ export async function buildFunctionReport(
|
|
|
88
88
|
}
|
|
89
89
|
if (source === "dom") {
|
|
90
90
|
const view = domReportView(report.data);
|
|
91
|
-
report.text = appendDomReportFooter(report.text,
|
|
91
|
+
report.text = appendDomReportFooter(report.text, view, report.data.freshness);
|
|
92
92
|
report.tables = {
|
|
93
93
|
...report.tables,
|
|
94
|
-
footer: [...report.tables.footer, `note: ${domReportNote(
|
|
94
|
+
footer: [...report.tables.footer, `note: ${domReportNote(view)}`],
|
|
95
95
|
};
|
|
96
96
|
}
|
|
97
97
|
return report;
|
|
@@ -36,16 +36,20 @@ import {
|
|
|
36
36
|
cleanTickerInput,
|
|
37
37
|
normalizeLookupToken,
|
|
38
38
|
optionSettings,
|
|
39
|
+
parsePaneFunctionArgs,
|
|
39
40
|
type ParsedPaneFunctionArgs,
|
|
40
41
|
} from "./options";
|
|
41
42
|
import { argumentSymbols, validateSymbolCount } from "./headless";
|
|
42
43
|
import {
|
|
43
44
|
capabilityHasOption,
|
|
44
45
|
capabilityPaneSettings,
|
|
46
|
+
findCapabilityOption,
|
|
45
47
|
getHeadlessPaneDefinition,
|
|
46
48
|
getPaneFunctionCapability,
|
|
47
49
|
noArgumentMessage,
|
|
48
50
|
normalizeCapabilityOptions,
|
|
51
|
+
paneFunctionArgument,
|
|
52
|
+
takesNoArgument,
|
|
49
53
|
type NormalizedPaneFunctionOptions,
|
|
50
54
|
type PaneFunctionCapability,
|
|
51
55
|
} from "./capabilities";
|
|
@@ -124,6 +128,24 @@ export function findPaneFunction(registry: PaneFunctionCatalog, target: string):
|
|
|
124
128
|
return { template, pane: template ? registry.panes.get(template.paneId) : entry as PaneDef };
|
|
125
129
|
}
|
|
126
130
|
|
|
131
|
+
/**
|
|
132
|
+
* `fn` and `shot` arguments read with the function's own options: one whose
|
|
133
|
+
* value is a pair (MARS's `--fx-shift TRY -20`) takes the words after its
|
|
134
|
+
* flag, which a function that has none would read as its argument.
|
|
135
|
+
*/
|
|
136
|
+
export function parsePaneFunctionArgsFor(
|
|
137
|
+
registry: PaneFunctionCatalog,
|
|
138
|
+
args: string[],
|
|
139
|
+
globalOptions: { limit?: number; tail?: number } = {},
|
|
140
|
+
): ParsedPaneFunctionArgs {
|
|
141
|
+
const parsed = parsePaneFunctionArgs(args, globalOptions);
|
|
142
|
+
const found = parsed.target ? findPaneFunction(registry, parsed.target) : null;
|
|
143
|
+
if (!found?.pane) return parsed;
|
|
144
|
+
const capability = getPaneFunctionCapability(found.template, found.pane);
|
|
145
|
+
if (!capability.options.some((option) => (option.valueWords ?? 1) > 1)) return parsed;
|
|
146
|
+
return parsePaneFunctionArgs(args, globalOptions, (key) => findCapabilityOption(capability, key)?.valueWords ?? 1);
|
|
147
|
+
}
|
|
148
|
+
|
|
127
149
|
/**
|
|
128
150
|
* `fn ANR SAN --exchange EPA` is `fn ANR SAN:EPA`: a function that takes
|
|
129
151
|
* tickers gets each listing as `quote` reads it (`resolveCliListing`), so
|
|
@@ -153,14 +175,24 @@ export async function applyListingArgument(
|
|
|
153
175
|
}
|
|
154
176
|
const exchange = typeof args.options.exchange === "string" ? args.options.exchange : undefined;
|
|
155
177
|
const { exchange: _exchange, ...options } = args.options;
|
|
156
|
-
// A list entry with spaces is a company's name search finds, or the symbols it holds.
|
|
157
|
-
const typed = takesOneTicker ? [args.arg] : await readNameEntries(splitSymbolArgs([args.arg]), context.dataProvider);
|
|
178
|
+
// A list entry with spaces, or an argument of words, is a company's name search finds, or the symbols it holds.
|
|
179
|
+
const typed = takesOneTicker ? [args.arg] : await readNameEntries(splitSymbolArgs([args.arg], { phrases: true }), context.dataProvider);
|
|
158
180
|
if (typed.length === 0) return args;
|
|
159
181
|
// RY.TO is the listing its quote names, RY:TSX, as `quote` reads it: a function's data is read by venue.
|
|
160
182
|
let listings = await Promise.all(typed.map((raw) => resolveCliListing(raw, exchange, context, { ownExchangeWins: typed.length > 1, venueSuffix: true })));
|
|
161
183
|
// A separator stuck to the end of a pasted list (`UPST;`) is not part of a symbol; it is named.
|
|
162
184
|
const notes: string[] = takesOneTicker ? [] : stripStrayEdges(args.arg).notes;
|
|
163
185
|
const token = found.template?.shortcut?.prefix ?? args.target.toUpperCase();
|
|
186
|
+
// Words search finds no company for, and that are not symbols either, name nothing a function can read: tickers do.
|
|
187
|
+
const unnamed = takesList ? listings.filter((listing) => /\s/.test(listing.symbol)) : [];
|
|
188
|
+
if (unnamed.length > 0) {
|
|
189
|
+
const names = unnamed.map((listing) => typed[listings.indexOf(listing)]!.trim());
|
|
190
|
+
const answer = `No company found for ${names.map((name) => `"${name}"`).join(", ")}; type tickers`;
|
|
191
|
+
const details = `Such as gloom ${command} ${token} GME,AMC. Find a company's ticker with gloom search "${names[0]!.replace(/"/g, "")}".`;
|
|
192
|
+
listings = listings.filter((listing) => !unnamed.includes(listing));
|
|
193
|
+
if (listings.length === 0) throw new ListingArgError(`${answer}.`, details);
|
|
194
|
+
notes.push(`${answer}, such as GME,AMC.`);
|
|
195
|
+
}
|
|
164
196
|
// A function with company data answers an index or an ETF with what it is and where its data is, before
|
|
165
197
|
// any request: its source would only say "Unknown ticker" or come back empty. A list leaves it out.
|
|
166
198
|
const covered = found.pane.instruments;
|
|
@@ -185,7 +217,7 @@ export async function applyListingArgument(
|
|
|
185
217
|
const abroad = usOnly ? listings.filter((listing) => listingAbroadVenue(listing.key) != null) : [];
|
|
186
218
|
if (usOnly && abroad.length > 0) {
|
|
187
219
|
const answers = await Promise.all(abroad.map(async (listing) => {
|
|
188
|
-
const answer = await usListingsOnlyMessage(usOnly, listing, context, (key) => `
|
|
220
|
+
const answer = await usListingsOnlyMessage(usOnly, listing, context, (key) => `gloom ${command} ${token} ${key}`);
|
|
189
221
|
const hint = headless?.usListingsOnlyHint?.(listing.key);
|
|
190
222
|
return hint ? { ...answer, details: `${answer.details}\n${hint}` } : answer;
|
|
191
223
|
}));
|
|
@@ -264,11 +296,11 @@ async function unknownPaneFunctionError(
|
|
|
264
296
|
const runs = suggested.length > 0 ? suggested : near.length === 1 ? near : [];
|
|
265
297
|
return new UnknownPaneFunctionError(name, [
|
|
266
298
|
// A function a word asks for, typed with no argument, shows the one it takes (`<ticker>`).
|
|
267
|
-
...runs.map(({ code }, index) => [index === 0 ? "Run:" : " ", "
|
|
299
|
+
...runs.map(({ code }, index) => [index === 0 ? "Run:" : " ", "gloom", command, code,
|
|
268
300
|
argument.trim() || (suggested.length > 0 ? findFunctionCode(registry, code)?.argument : "")].filter(Boolean).join(" ")),
|
|
269
301
|
...closest.length > 0
|
|
270
|
-
? ["Closest matches:", ...closest.map((entry) => ` ${entry.token.padEnd(tokenWidth)} ${entry.label}`), `Search the catalog:
|
|
271
|
-
: near.length > 0 ? [] : [`No function code is close to ${word}. List every function:
|
|
302
|
+
? ["Closest matches:", ...closest.map((entry) => ` ${entry.token.padEnd(tokenWidth)} ${entry.label}`), `Search the catalog: gloom catalog ${word}`]
|
|
303
|
+
: near.length > 0 ? [] : [`No function code is close to ${word}. List every function: gloom catalog`],
|
|
272
304
|
].join("\n"), near.length > 0 ? nearCodesText(near) : null);
|
|
273
305
|
}
|
|
274
306
|
|
|
@@ -280,7 +312,7 @@ export async function resolvePaneFunction(
|
|
|
280
312
|
): Promise<ResolvedPaneFunction> {
|
|
281
313
|
let args = parsedArgs;
|
|
282
314
|
if (!args.target) {
|
|
283
|
-
throw new Error("Usage:
|
|
315
|
+
throw new Error("Usage: gloom fn <function-or-pane> [argument] [--key value]");
|
|
284
316
|
}
|
|
285
317
|
|
|
286
318
|
const found = findPaneFunction(registry, args.target);
|
|
@@ -302,16 +334,21 @@ export async function resolvePaneFunction(
|
|
|
302
334
|
// What the user types for the function, which every error about it names.
|
|
303
335
|
const token = template?.shortcut?.prefix ?? template?.id ?? pane.id;
|
|
304
336
|
// A word after a function that takes none is most often one of its option values (`fn JODI gas`).
|
|
305
|
-
|
|
337
|
+
// Every function the catalog lists with no argument refuses one, a rendered view (HALT) as a report (CBR).
|
|
338
|
+
// The catalog lists templates and the panes no template opens (HELP); a pane opened by its id stands for its templates.
|
|
339
|
+
const listed = template !== undefined || ![...registry.paneTemplates.values()].some((entry) => entry.paneId === pane.id);
|
|
340
|
+
const refusesArgument = listed ? takesNoArgument(paneFunctionArgument(template, pane)) : headless?.argument.kind === "none";
|
|
341
|
+
if (refusesArgument && args.arg?.trim()) {
|
|
306
342
|
throw new Error(noArgumentMessage(capability.options, token, args.arg, resolutionSettings.command ?? "fn"));
|
|
307
343
|
}
|
|
308
344
|
const normalizedOptions = normalizeCapabilityOptions(capability, args.options, {
|
|
309
|
-
strict: args.requireBotSafe || (!!headless && resolutionSettings.strictHeadlessOptions === true),
|
|
345
|
+
strict: args.requireBotSafe || capability.strictOptions === true || (!!headless && resolutionSettings.strictHeadlessOptions === true),
|
|
310
346
|
code: token,
|
|
311
347
|
argument: args.arg || null,
|
|
312
348
|
});
|
|
313
349
|
const settings = {
|
|
314
|
-
|
|
350
|
+
// A view that takes only its declared options gets only their settings.
|
|
351
|
+
...capability.strictOptions ? {} : optionSettings(args.options),
|
|
315
352
|
...capabilityPaneSettings(capability, normalizedOptions),
|
|
316
353
|
};
|
|
317
354
|
if (args.requireBotSafe) {
|