@gloom-sh/terminal 0.19.1 → 0.19.3
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 +7 -1
- package/package.json +2 -1
- package/patches/electrobun@1.18.1.patch +108 -1
- package/src/account/upgrade-dialog.tsx +4 -23
- package/src/api-client/coalesce.ts +118 -0
- package/src/api-client/credit-boards.ts +13 -0
- package/src/api-client/crypto-etf-flows.ts +6 -0
- package/src/api-client/crypto-markets.ts +40 -0
- package/src/api-client/data.ts +201 -14
- package/src/api-client/equity-screener.ts +10 -0
- package/src/api-client/errors.ts +58 -0
- package/src/api-client/gpu.ts +29 -0
- package/src/api-client/index.ts +5 -2
- package/src/api-client/plan-access.ts +10 -1
- package/src/api-client/plan-rules.ts +35 -0
- package/src/api-client/research-activity.ts +1 -32
- package/src/api-client/types.ts +21 -1
- package/src/app/attention-notice.tsx +94 -0
- package/src/app/runtime/startup.ts +3 -1
- package/src/app.tsx +23 -1
- package/src/architecture/core-builtin-allowlist.json +2 -1
- package/src/capabilities/chart-series.ts +2 -1
- package/src/capabilities/factories.ts +1 -0
- package/src/cli/ascii-output.ts +42 -0
- package/src/cli/base-converter.ts +10 -2
- package/src/cli/command-options.ts +16 -1
- package/src/cli/commands/crypto-hints.ts +23 -4
- package/src/cli/commands/market.ts +101 -27
- package/src/cli/commands/news-search.ts +24 -5
- package/src/cli/commands/overview.ts +14 -10
- package/src/cli/commands/search.ts +84 -25
- package/src/cli/commands/system.ts +22 -30
- package/src/cli/commands/ticker.ts +49 -9
- package/src/cli/commands/version.ts +33 -0
- package/src/cli/context.ts +6 -9
- package/src/cli/data-dir.ts +7 -0
- package/src/cli/desktop-pane-shot-api-policy.ts +85 -0
- package/src/cli/desktop-pane-shot-browser.ts +320 -0
- package/src/cli/desktop-pane-shot-routes.ts +26 -1
- package/src/cli/desktop-pane-shot.ts +196 -256
- package/src/cli/early-command.ts +42 -0
- package/src/cli/earnings-calendar.ts +9 -0
- package/src/cli/entry.ts +19 -13
- package/src/cli/errors.ts +12 -2
- package/src/cli/glossary.ts +2 -1
- package/src/cli/help.ts +1 -1
- package/src/cli/history-export.ts +22 -2
- package/src/cli/history-rows.ts +189 -11
- package/src/cli/index.ts +18 -1
- package/src/cli/known-gaps.ts +51 -5
- package/src/cli/listing-arg.ts +63 -10
- package/src/cli/options.ts +1 -1
- package/src/cli/output-file.ts +60 -13
- package/src/cli/pane-functions/catalog.ts +14 -3
- package/src/cli/pane-functions/data.ts +1 -1
- package/src/cli/pane-functions/dom.ts +45 -0
- package/src/cli/pane-functions/freshness.ts +46 -9
- package/src/cli/pane-functions/function-help.ts +17 -9
- package/src/cli/pane-functions/headless.ts +22 -14
- package/src/cli/pane-functions/index.ts +6 -2
- package/src/cli/pane-functions/options.ts +6 -2
- package/src/cli/pane-functions/resolver.ts +27 -5
- package/src/cli/pane-functions/screenshot-assessment.ts +33 -0
- package/src/cli/pane-functions/screenshot-bridge.ts +94 -13
- package/src/cli/pane-functions/screenshot-http.ts +70 -0
- package/src/cli/pane-functions/screenshot-render.ts +19 -5
- package/src/cli/quote-answer.ts +49 -6
- package/src/cli/registry.ts +41 -13
- package/src/cli/result.ts +12 -6
- package/src/cli/ticker-resolution.ts +2 -1
- package/src/cli/types.ts +2 -0
- package/src/components/chart/composite/format.ts +3 -0
- package/src/components/chart-table/header.tsx +1 -1
- package/src/components/chart-table/layout.ts +28 -11
- package/src/components/command-bar/action-runtime.ts +4 -0
- package/src/components/command-bar/commands/direct/index.ts +18 -33
- package/src/components/command-bar/commands/direct/runtime.ts +5 -0
- package/src/components/command-bar/commands/registry.ts +10 -1
- package/src/components/command-bar/routes/root/command-items.ts +9 -4
- package/src/components/command-bar/routes/root/runtime.ts +51 -6
- package/src/components/command-bar/selection-runtime.ts +12 -29
- package/src/components/command-bar/surface/index.tsx +9 -3
- package/src/components/company-logo.tsx +2 -1
- package/src/components/layout/detached-pane-shell.tsx +2 -2
- package/src/components/layout/header.tsx +10 -5
- package/src/components/layout/market-summary.ts +25 -7
- package/src/components/layout/pane/footer/index.tsx +8 -2
- package/src/components/layout/pane/footer/model.ts +73 -6
- package/src/components/layout/pane/header.tsx +2 -2
- package/src/components/layout/pane/status-footer.ts +2 -1
- package/src/components/market-board/index.tsx +3 -2
- package/src/components/onboarding/desks-step.tsx +12 -4
- package/src/components/onboarding/first-run-workspace.ts +81 -4
- package/src/components/onboarding/onboarding-frame.tsx +4 -2
- package/src/components/onboarding/onboarding-keyboard.ts +8 -5
- package/src/components/onboarding/onboarding-wizard.tsx +60 -26
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +7 -2
- package/src/components/onboarding/run-setup-again.ts +24 -0
- package/src/components/onboarding/use-onboarding-progress.ts +33 -15
- package/src/components/onboarding/use-onboarding-upgrade.ts +2 -6
- package/src/components/onboarding/wizard-model.ts +57 -3
- package/src/components/onboarding/wizard-positions.ts +1 -1
- package/src/components/ui/delayed-mark.tsx +56 -0
- package/src/components/ui/display.tsx +16 -5
- package/src/components/ui/external-link.tsx +3 -6
- package/src/components/ui/icon.tsx +16 -3
- package/src/components/ui/logo-mark.tsx +8 -5
- package/src/components/ui/stat-grid.tsx +263 -19
- package/src/core/app-services.ts +11 -2
- package/src/data/app-persistence.ts +9 -7
- package/src/data/config/store/node.ts +11 -5
- package/src/data/config/store/normalize.ts +16 -3
- package/src/data/plugin-cache.ts +15 -0
- package/src/data/plugin-state-store.ts +81 -24
- package/src/data/profile-permissions.ts +47 -0
- package/src/data/resource-store.ts +165 -90
- package/src/data/session-store.ts +31 -8
- package/src/data/sqlite/access.ts +324 -0
- package/src/data/sqlite/checkpointer.ts +285 -0
- package/src/data/sqlite/database.ts +80 -4
- package/src/data/sqlite/retry.ts +50 -9
- package/src/data/ticker-store.ts +57 -23
- package/src/docs/snapshot.json +191 -78
- package/src/i18n/es.ts +18 -2
- package/src/i18n/ja.ts +18 -2
- package/src/i18n/ko.ts +18 -2
- package/src/i18n/zh-cn.ts +18 -2
- package/src/i18n/zh-tw.ts +18 -2
- package/src/layout/desk-keys.ts +4 -1
- package/src/layout/desks.ts +38 -5
- package/src/layout-marketplace/gallery-desktop.tsx +45 -16
- package/src/market-data/batched-reads.ts +16 -0
- package/src/market-data/coordinator/auxiliary.ts +4 -2
- package/src/market-data/coordinator/index.ts +11 -2
- package/src/market-data/futures-board.ts +1 -1
- package/src/market-data/futures-contract.ts +3 -1
- package/src/market-data/market/index-level.ts +6 -4
- package/src/market-data/published-apac-sessions.ts +6 -0
- package/src/market-data/realized-volatility.ts +4 -2
- package/src/news/aggregator.ts +7 -4
- package/src/news/news-model.ts +11 -0
- package/src/news/story-id.ts +22 -0
- package/src/news/ticker-symbols.ts +17 -1
- package/src/notifications/app-notifier.ts +35 -14
- package/src/plugins/auto-update-node.ts +10 -6
- package/src/plugins/builtin/account-management/form-components.tsx +1 -1
- package/src/plugins/builtin/account-management/index.tsx +2 -3
- package/src/plugins/builtin/account-management/model.ts +1 -1
- package/src/plugins/builtin/alerts/cli-forms.ts +15 -1
- package/src/plugins/builtin/alerts/events-pane.tsx +7 -5
- package/src/plugins/builtin/alerts/events.ts +10 -2
- package/src/plugins/builtin/alerts/index.tsx +5 -5
- package/src/plugins/builtin/alerts/research-builder.ts +5 -1
- package/src/plugins/builtin/alerts/research-rules.ts +18 -0
- package/src/plugins/builtin/alerts/targets.ts +4 -1
- package/src/plugins/builtin/attention/headless.ts +1 -1
- package/src/plugins/builtin/attention/index.tsx +2 -4
- package/src/plugins/builtin/attention/listing.ts +1 -1
- package/src/plugins/builtin/attention/series.ts +1 -1
- package/src/plugins/builtin/awards/index.tsx +1 -2
- package/src/plugins/builtin/backtest/client.ts +1 -0
- package/src/plugins/builtin/backtest/index.tsx +1 -2
- package/src/plugins/builtin/backtest/rules.ts +3 -1
- package/src/plugins/builtin/backtest/window.ts +8 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +16 -3
- package/src/plugins/builtin/broker-manager/index.tsx +1 -1
- package/src/plugins/builtin/buildout/cells.tsx +5 -0
- package/src/plugins/builtin/buildout/company/flow.tsx +367 -0
- package/src/plugins/builtin/buildout/company/id.ts +2 -0
- package/src/plugins/builtin/buildout/company/model.ts +247 -0
- package/src/plugins/builtin/buildout/company/pane.tsx +317 -0
- package/src/plugins/builtin/buildout/data-runtime.ts +31 -10
- package/src/plugins/builtin/buildout/facilities.ts +309 -0
- package/src/plugins/builtin/buildout/format.ts +9 -0
- package/src/plugins/builtin/buildout/index.tsx +51 -5
- package/src/plugins/builtin/buildout/model/index.ts +62 -10
- package/src/plugins/builtin/buildout/model/normalizers.ts +5 -0
- package/src/plugins/builtin/buildout/model/types.ts +11 -2
- package/src/plugins/builtin/buildout/pane/index.tsx +91 -20
- package/src/plugins/builtin/buildout/pane/status.tsx +1 -1
- package/src/plugins/builtin/buildout/pane/themes.tsx +110 -0
- package/src/plugins/builtin/buildout/table-model.ts +26 -2
- package/src/plugins/builtin/builtin-plugin-meta.ts +16 -0
- package/src/plugins/builtin/cds/headless.ts +10 -2
- package/src/plugins/builtin/cds/model.ts +7 -3
- package/src/plugins/builtin/central-bank-rates/index.tsx +1 -2
- package/src/plugins/builtin/central-bank-rates/pane.tsx +2 -1
- package/src/plugins/builtin/central-bank-rates/series.ts +2 -3
- package/src/plugins/builtin/changelog/index.tsx +3 -2
- package/src/plugins/builtin/chart-composer/cli-options.ts +16 -0
- package/src/plugins/builtin/chart-composer/headless-schema.ts +10 -0
- package/src/plugins/builtin/chart-composer/headless.ts +88 -21
- package/src/plugins/builtin/chart-composer/index.tsx +2 -3
- package/src/plugins/builtin/chart-composer/pane.tsx +30 -2
- package/src/plugins/builtin/chart-composer/series-expression.ts +3 -2
- package/src/plugins/builtin/chart-composer/session-range.ts +5 -2
- package/src/plugins/builtin/chart-composer/studies.ts +1 -1
- package/src/plugins/builtin/chat/controller/index.ts +1 -1
- package/src/plugins/builtin/chat/controller/messages.ts +15 -4
- package/src/plugins/builtin/chat/ghost-user.ts +8 -0
- package/src/plugins/builtin/chat/index.tsx +5 -5
- package/src/plugins/builtin/clinical-trials/index.tsx +1 -2
- package/src/plugins/builtin/cloud/company-picker.tsx +1 -1
- package/src/plugins/builtin/cloud/index.tsx +1 -2
- package/src/plugins/builtin/cloud/plugin.tsx +6 -4
- package/src/plugins/builtin/cloud/team/module.tsx +1 -1
- package/src/plugins/builtin/cloud/thesis/module.tsx +1 -1
- package/src/plugins/builtin/cloud/trial-offer-status-widget.tsx +24 -1
- package/src/plugins/builtin/cloud/upgrade-status-widget.tsx +39 -15
- package/src/plugins/builtin/comment-letters/index.tsx +1 -2
- package/src/plugins/builtin/commodity-balances/client.ts +4 -1
- package/src/plugins/builtin/commodity-balances/index.tsx +3 -3
- package/src/plugins/builtin/commodity-balances/pane.tsx +2 -2
- package/src/plugins/builtin/congress-trades/aggregates.ts +13 -2
- package/src/plugins/builtin/congress-trades/detail.tsx +20 -4
- package/src/plugins/builtin/congress-trades/headless.ts +2 -0
- package/src/plugins/builtin/congress-trades/model.ts +92 -64
- package/src/plugins/builtin/congress-trades/table.tsx +14 -2
- package/src/plugins/builtin/connections/index.ts +2 -3
- package/src/plugins/builtin/cot/client.ts +28 -2
- package/src/plugins/builtin/cot/headless.ts +4 -1
- package/src/plugins/builtin/cot/index.tsx +5 -4
- package/src/plugins/builtin/cot/model.ts +58 -7
- package/src/plugins/builtin/cot/pane.tsx +6 -2
- package/src/plugins/builtin/cpi/client.ts +6 -5
- package/src/plugins/builtin/cpi/index.tsx +1 -2
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +2 -1
- package/src/plugins/builtin/credit-boards/client.ts +7 -2
- package/src/plugins/builtin/credit-boards/headless.ts +25 -12
- package/src/plugins/builtin/credit-boards/model.ts +29 -0
- package/src/plugins/builtin/credit-boards/series.ts +3 -4
- package/src/plugins/builtin/credit-boards/sovr-pane.tsx +9 -4
- package/src/plugins/builtin/credit-conditions/client.ts +22 -14
- package/src/plugins/builtin/crypto-board/bitcoin-network.ts +143 -0
- package/src/plugins/builtin/crypto-board/client.ts +5 -5
- package/src/plugins/builtin/crypto-board/headless.ts +4 -3
- package/src/plugins/builtin/crypto-board/index.tsx +4 -2
- package/src/plugins/builtin/crypto-board/series.ts +6 -4
- package/src/plugins/builtin/crypto-etf-flows/client.ts +9 -2
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +61 -6
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +1 -2
- package/src/plugins/builtin/crypto-etf-flows/model.ts +14 -1
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +8 -5
- package/src/plugins/builtin/debt-maturities/headless.ts +4 -3
- package/src/plugins/builtin/debt-maturities/model.ts +17 -1
- package/src/plugins/builtin/debt-maturities/pane.tsx +18 -4
- package/src/plugins/builtin/debt-maturities/series.ts +3 -3
- package/src/plugins/builtin/debug/index.tsx +1 -1
- package/src/plugins/builtin/dividend-yield/client.ts +32 -2
- package/src/plugins/builtin/dividend-yield/headless.ts +58 -33
- package/src/plugins/builtin/dividend-yield/index.tsx +37 -2
- package/src/plugins/builtin/dividend-yield/pane.tsx +32 -13
- package/src/plugins/builtin/dividend-yield/ranking-reads.ts +73 -0
- package/src/plugins/builtin/dividend-yield/ranking-view.tsx +163 -0
- package/src/plugins/builtin/dividend-yield/ranking.ts +1 -1
- package/src/plugins/builtin/dividend-yield/view.ts +21 -0
- package/src/plugins/builtin/docs/index.tsx +2 -3
- package/src/plugins/builtin/doe/client.ts +6 -5
- package/src/plugins/builtin/doe/headless.ts +16 -3
- package/src/plugins/builtin/doe/index.tsx +5 -4
- package/src/plugins/builtin/doe/prices.ts +2 -3
- package/src/plugins/builtin/doe/series.ts +4 -4
- package/src/plugins/builtin/earnings/board.tsx +2 -1
- package/src/plugins/builtin/earnings/history.tsx +2 -1
- package/src/plugins/builtin/earnings-calls/calendar.tsx +10 -2
- package/src/plugins/builtin/earnings-calls/data.ts +19 -11
- package/src/plugins/builtin/earnings-calls/pane.tsx +27 -14
- package/src/plugins/builtin/earnings-ripple/client.ts +32 -7
- package/src/plugins/builtin/earnings-ripple/index.tsx +1 -2
- package/src/plugins/builtin/econ/calendar-model.ts +29 -6
- package/src/plugins/builtin/econ/detail-view.tsx +16 -2
- package/src/plugins/builtin/econ-statistics/index.tsx +1 -2
- package/src/plugins/builtin/equity-screener/client.ts +1 -1
- package/src/plugins/builtin/equity-screener/headless.ts +1 -0
- package/src/plugins/builtin/equity-screener/ideas.ts +30 -1
- package/src/plugins/builtin/equity-screener/index.tsx +1 -2
- package/src/plugins/builtin/equity-screener/model.ts +28 -4
- package/src/plugins/builtin/equity-screener/pane.tsx +5 -0
- package/src/plugins/builtin/equity-screener/screen-check.ts +23 -1
- package/src/plugins/builtin/estimate-revisions/index.tsx +1 -2
- package/src/plugins/builtin/executives/data.ts +6 -1
- package/src/plugins/builtin/executives/pane.tsx +9 -21
- package/src/plugins/builtin/exposure/holdings.ts +35 -13
- package/src/plugins/builtin/exposure/index.tsx +1 -2
- package/src/plugins/builtin/fear-greed/cache.ts +4 -0
- package/src/plugins/builtin/fear-greed/cli.ts +44 -0
- package/src/plugins/builtin/fear-greed/index.tsx +5 -53
- package/src/plugins/builtin/fear-greed/pane.tsx +2 -1
- package/src/plugins/builtin/fear-greed/series.ts +6 -4
- package/src/plugins/builtin/fixed-income/index.tsx +1 -2
- package/src/plugins/builtin/futures/board-reads.ts +25 -0
- package/src/plugins/builtin/futures/coalesced-bump.ts +44 -0
- package/src/plugins/builtin/futures/index.tsx +15 -0
- package/src/plugins/builtin/futures/model.ts +14 -0
- package/src/plugins/builtin/futures/use-board-terms.ts +22 -15
- package/src/plugins/builtin/futures/use-front-returns.ts +20 -14
- package/src/plugins/builtin/futures-curve/headless.ts +6 -1
- package/src/plugins/builtin/futures-curve/index.tsx +1 -2
- package/src/plugins/builtin/fx-matrix/index.tsx +2 -2
- package/src/plugins/builtin/gpu/board.tsx +51 -12
- package/src/plugins/builtin/gpu/client.ts +19 -3
- package/src/plugins/builtin/gpu/equities.tsx +5 -2
- package/src/plugins/builtin/gpu/headless.ts +14 -2
- package/src/plugins/builtin/gpu/index.tsx +1 -2
- package/src/plugins/builtin/gpu/model.ts +20 -2
- package/src/plugins/builtin/gpu/pane.tsx +1 -1
- package/src/plugins/builtin/gpu/series.ts +2 -3
- package/src/plugins/builtin/help/index.tsx +1 -1
- package/src/plugins/builtin/holders/beneficial-view.tsx +1 -2
- package/src/plugins/builtin/holders/index-holders.ts +24 -12
- package/src/plugins/builtin/holders/index.tsx +2 -3
- package/src/plugins/builtin/ipo-calendar/index.tsx +1 -2
- package/src/plugins/builtin/iv-history/index.tsx +1 -2
- package/src/plugins/builtin/jodi/client.ts +4 -1
- package/src/plugins/builtin/jodi/index.tsx +1 -2
- package/src/plugins/builtin/kelly-sizer/index.tsx +1 -2
- package/src/plugins/builtin/layout-manager/index.tsx +9 -8
- package/src/plugins/builtin/macro-day/pane.tsx +4 -2
- package/src/plugins/builtin/market-halts/index.tsx +1 -2
- package/src/plugins/builtin/market-heatmap/index.tsx +11 -2
- package/src/plugins/builtin/market-movers/client.ts +1 -0
- package/src/plugins/builtin/market-movers/index.tsx +16 -5
- package/src/plugins/builtin/market-movers/screener.ts +23 -6
- package/src/plugins/builtin/market-movers/session-body.tsx +6 -2
- package/src/plugins/builtin/market-valuation/index.tsx +1 -2
- package/src/plugins/builtin/members/index.tsx +1 -2
- package/src/plugins/builtin/money-markets/index.tsx +1 -2
- package/src/plugins/builtin/money-markets/pane.tsx +2 -1
- package/src/plugins/builtin/money-markets/series.ts +3 -5
- package/src/plugins/builtin/news/headless.ts +7 -0
- package/src/plugins/builtin/news/wire/index.tsx +1 -1
- package/src/plugins/builtin/news/wire/news/pop-out.tsx +9 -3
- package/src/plugins/builtin/notes/index.tsx +3 -6
- package/src/plugins/builtin/openfda/index.tsx +1 -2
- package/src/plugins/builtin/options/view.tsx +6 -5
- package/src/plugins/builtin/options-calculator/index.tsx +1 -2
- package/src/plugins/builtin/options-positioning/index.tsx +1 -2
- package/src/plugins/builtin/options-scenario/index.tsx +2 -4
- package/src/plugins/builtin/perps/index.tsx +1 -2
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -3
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +2 -1
- package/src/plugins/builtin/plugin-module.ts +16 -2
- package/src/plugins/builtin/portfolio-list/cli/render.ts +53 -3
- package/src/plugins/builtin/portfolio-list/index.tsx +1 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +11 -0
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +2 -2
- package/src/plugins/builtin/power/gas-client.ts +2 -1
- package/src/plugins/builtin/power/index.tsx +1 -2
- package/src/plugins/builtin/power/prices-client.ts +3 -2
- package/src/plugins/builtin/rate-path/index.tsx +1 -2
- package/src/plugins/builtin/realized-vol/headless.ts +2 -0
- package/src/plugins/builtin/realized-vol/index.tsx +1 -2
- package/src/plugins/builtin/realized-vol/model.ts +16 -2
- package/src/plugins/builtin/realized-vol/pane.tsx +3 -3
- package/src/plugins/builtin/relative-rotation/index.tsx +1 -2
- package/src/plugins/builtin/research/analyst-headless.ts +33 -6
- package/src/plugins/builtin/research/analyst-model.ts +37 -2
- package/src/plugins/builtin/research/analyst-pane.tsx +25 -5
- package/src/plugins/builtin/research/index.tsx +5 -8
- package/src/plugins/builtin/research-search/index.tsx +1 -2
- package/src/plugins/builtin/revenue-breakdown/headless.ts +22 -8
- package/src/plugins/builtin/revenue-breakdown/model.ts +23 -0
- package/src/plugins/builtin/reverse-dcf/pane.tsx +4 -2
- package/src/plugins/builtin/risk-factors/data.ts +8 -4
- package/src/plugins/builtin/risk-factors/index.tsx +3 -1
- package/src/plugins/builtin/risk-factors/pane.tsx +5 -8
- package/src/plugins/builtin/roadmap/index.tsx +2 -3
- package/src/plugins/builtin/roadmap/pane.tsx +49 -2
- package/src/plugins/builtin/scanner/hilo-model.ts +18 -1
- package/src/plugins/builtin/scanner/hilo-pane.tsx +12 -2
- package/src/plugins/builtin/scanner/live-pane.tsx +7 -4
- package/src/plugins/builtin/scanner/lock-note.ts +26 -3
- package/src/plugins/builtin/sec/filing-content.ts +38 -6
- package/src/plugins/builtin/sec/headless.ts +5 -1
- package/src/plugins/builtin/sec/index.tsx +4 -2
- package/src/plugins/builtin/sec/model.ts +2 -0
- package/src/plugins/builtin/sectors/index.tsx +11 -5
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/cloud-resource.ts +73 -8
- package/src/plugins/builtin/shared/cloud-upgrade.ts +24 -1
- package/src/plugins/builtin/shared/forming-bars.ts +29 -0
- package/src/plugins/builtin/shared/fred-points.ts +6 -1
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +17 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +23 -8
- package/src/plugins/builtin/shared/series-detail-chart.tsx +4 -2
- package/src/plugins/builtin/shared/series-warning.ts +13 -4
- package/src/plugins/builtin/shared/use-quote-board.ts +5 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +2 -1
- package/src/plugins/builtin/short-volume/pane.tsx +2 -1
- package/src/plugins/builtin/short-volume/series.ts +2 -3
- package/src/plugins/builtin/social-mentions/client.ts +15 -10
- package/src/plugins/builtin/social-mentions/index.tsx +1 -2
- package/src/plugins/builtin/social-mentions/pane.tsx +2 -1
- package/src/plugins/builtin/social-mentions/series.ts +2 -3
- package/src/plugins/builtin/supply-chain/client.ts +22 -1
- package/src/plugins/builtin/supply-chain/graph-client.ts +22 -1
- package/src/plugins/builtin/supply-chain/index.tsx +1 -2
- package/src/plugins/builtin/thirteenf/api.ts +127 -29
- package/src/plugins/builtin/thirteenf/data.ts +165 -35
- package/src/plugins/builtin/thirteenf/index.tsx +2 -4
- package/src/plugins/builtin/thirteenf/model.ts +2 -0
- package/src/plugins/builtin/thirteenf/overlap-pane.tsx +5 -1
- package/src/plugins/builtin/thirteenf/pane.tsx +41 -16
- package/src/plugins/builtin/thirteenf/types.ts +14 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +22 -6
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +81 -11
- package/src/plugins/builtin/ticker-detail/financials/model.ts +35 -2
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +53 -18
- package/src/plugins/builtin/ticker-detail/headless.ts +70 -11
- package/src/plugins/builtin/ticker-detail/index.tsx +5 -10
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +16 -6
- package/src/plugins/builtin/time-sales/index.tsx +1 -2
- package/src/plugins/builtin/time-sales/pane.tsx +3 -1
- package/src/plugins/builtin/trace-bonds/headless.ts +11 -2
- package/src/plugins/builtin/trace-bonds/model.ts +44 -10
- package/src/plugins/builtin/trace-bonds/pane.tsx +12 -7
- package/src/plugins/builtin/treasury-auctions/cache.ts +20 -8
- package/src/plugins/builtin/treasury-auctions/client.ts +3 -3
- package/src/plugins/builtin/treasury-auctions/headless.ts +3 -1
- package/src/plugins/builtin/treasury-auctions/pane.tsx +10 -4
- package/src/plugins/builtin/vol-surface/client.ts +18 -3
- package/src/plugins/builtin/vol-surface/index.tsx +1 -2
- package/src/plugins/builtin/volatility/client.ts +43 -16
- package/src/plugins/builtin/volatility/headless.ts +5 -2
- package/src/plugins/builtin/volatility/index.tsx +1 -2
- package/src/plugins/builtin/volatility/model.ts +17 -6
- package/src/plugins/builtin/volatility/pane.tsx +6 -2
- package/src/plugins/builtin/volatility/series.ts +2 -1
- package/src/plugins/builtin/world-indices/footer.ts +6 -1
- package/src/plugins/builtin/world-venue-map/client.ts +10 -1
- package/src/plugins/builtin/world-venue-map/index.ts +6 -2
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +48 -7
- package/src/plugins/builtin/world-venue-map/layers.ts +17 -0
- package/src/plugins/builtin/world-venue-map/local-layers.ts +141 -0
- package/src/plugins/builtin/world-venue-map/map-symbols.ts +18 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +4 -2
- package/src/plugins/builtin/world-venue-map/scope.ts +63 -0
- package/src/plugins/builtin/yield-curve/client.ts +4 -6
- package/src/plugins/builtin/yield-curve/curves.ts +16 -2
- package/src/plugins/builtin/yield-curve/headless.ts +3 -3
- package/src/plugins/bundle.ts +52 -2
- package/src/plugins/catalog-browser.ts +2 -2
- package/src/plugins/catalog-cli.ts +20 -0
- package/src/plugins/host-link.ts +13 -1
- package/src/plugins/installer.ts +64 -42
- package/src/plugins/loader.ts +43 -11
- package/src/plugins/peer-imports.ts +201 -0
- package/src/plugins/peer-retry.ts +26 -29
- package/src/plugins/plugin-process.ts +128 -0
- package/src/plugins/redirection-guard.ts +45 -0
- package/src/remote/endpoint.ts +16 -3
- package/src/renderers/browser/main.tsx +3 -2
- package/src/renderers/cloudflare/http-proxy.ts +7 -123
- package/src/renderers/dom/desktop/icons.tsx +5 -2
- package/src/renderers/dom/host/image-surface.tsx +46 -21
- package/src/renderers/dom/styles.css +7 -0
- package/src/renderers/dom/toast-host.tsx +2 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +7 -1
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +23 -1
- package/src/renderers/electrobun/bun/desktop/initialization.ts +12 -3
- package/src/renderers/electrobun/bun/desktop/rpc-timing.ts +88 -0
- package/src/renderers/electrobun/bun/desktop/update.ts +20 -4
- package/src/renderers/electrobun/bun/desktop/view-ids.ts +8 -4
- package/src/renderers/electrobun/bun/external-plugins.ts +4 -0
- package/src/renderers/electrobun/bun/window/attention.ts +54 -0
- package/src/renderers/electrobun/bun/window/create.ts +6 -2
- package/src/renderers/electrobun/bun/window/native-timing.ts +48 -0
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +82 -4
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +13 -5
- package/src/renderers/electrobun/view/desktop/window/snapshot.ts +3 -0
- package/src/renderers/electrobun/view/main.tsx +7 -2
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -0
- package/src/renderers/electrobun/view/ui-host.tsx +9 -2
- package/src/renderers/opentui/browser-open.ts +10 -4
- package/src/renderers/opentui/image/surface.tsx +1 -1
- package/src/renderers/opentui/start.tsx +12 -6
- package/src/renderers/opentui/toast-host.tsx +2 -1
- package/src/series/registry.ts +18 -0
- package/src/series/resolve.ts +2 -1
- package/src/series/standalone.ts +10 -1
- package/src/series/types.ts +12 -0
- package/src/series/validate.ts +11 -2
- package/src/sources/gloomberb-cloud/fred-series.ts +5 -3
- package/src/sources/gloomberb-cloud/index.ts +28 -5
- package/src/sources/gloomberb-cloud/news.ts +24 -3
- package/src/sources/gloomberb-cloud/normalizers.ts +17 -2
- package/src/sources/provider-errors.ts +26 -3
- package/src/sources/provider-router/history.ts +5 -0
- package/src/sources/provider-router/index.ts +13 -0
- package/src/sync/core-contributors.ts +32 -0
- package/src/telemetry/attention-counts.ts +64 -6
- package/src/telemetry/attention-setting.ts +33 -0
- package/src/telemetry/crash-reports-node.ts +3 -1
- package/src/telemetry/stall-clocks.ts +93 -0
- package/src/telemetry/stall-reports-node.ts +25 -9
- package/src/telemetry/stall-reports.ts +218 -13
- package/src/test-support/outage.ts +8 -0
- package/src/test-support/preload.ts +9 -0
- package/src/tickers/company-name-listing.ts +59 -29
- package/src/tickers/company-name.ts +84 -1
- package/src/tickers/listing-fate.ts +14 -3
- package/src/tickers/saved-instrument.ts +17 -0
- package/src/tickers/search/home-listing.ts +104 -8
- package/src/tickers/search/index.ts +5 -2
- package/src/tickers/search/types.ts +6 -1
- package/src/time-series/bar-aggregation.ts +7 -1
- package/src/time-series/base-series.ts +3 -3
- package/src/time-series/chart-bounds.ts +1 -1
- package/src/time-series/chart-data.ts +5 -2
- package/src/time-series/chart-seed.ts +1 -1
- package/src/time-series/coin-session-close.ts +211 -0
- package/src/time-series/live-bars.ts +13 -2
- package/src/time-series/live-quotes.ts +1 -1
- package/src/time-series/market.ts +5 -3
- package/src/time-series/official-close.ts +159 -0
- package/src/time-series/price-comparison.ts +75 -8
- package/src/time-series/resolve.ts +32 -4
- package/src/time-series/series-presentation.ts +1 -1
- package/src/time-series/studies/formula.ts +205 -0
- package/src/time-series/studies/indicators.ts +299 -0
- package/src/time-series/studies/leverage.ts +75 -0
- package/src/time-series/studies/pair.ts +138 -0
- package/src/time-series/studies/resolve.ts +333 -0
- package/src/time-series/studies/shared.ts +141 -0
- package/src/time-series/studies/units.ts +243 -0
- package/src/time-series/studies/vwap.ts +274 -0
- package/src/time-series/types.ts +7 -0
- package/src/types/config.ts +18 -2
- package/src/types/data-provider.ts +23 -0
- package/src/types/financials.ts +40 -3
- package/src/types/headless.ts +42 -3
- package/src/types/plugin.ts +32 -3
- package/src/ui/host.tsx +17 -1
- package/src/ui/toast.tsx +26 -1
- package/src/utils/ascii-text.ts +140 -0
- package/src/utils/cli-output.ts +91 -18
- package/src/utils/concurrency.ts +24 -0
- package/src/utils/exchanges.ts +6 -0
- package/src/utils/external-url.ts +20 -7
- package/src/utils/financial-statements.ts +73 -16
- package/src/utils/fundamentals.ts +17 -5
- package/src/utils/futures-generic.ts +4 -4
- package/src/utils/http-proxy-upstream.ts +124 -0
- package/src/utils/lease-liabilities.ts +54 -0
- package/src/utils/main-thread-stall.ts +122 -5
- package/src/utils/perf-marks.ts +58 -12
- package/src/utils/price-history-integrity.ts +47 -1
- package/src/utils/private-files.ts +141 -0
- package/src/utils/public-address.ts +99 -0
- package/src/account/upgrade-personalization.ts +0 -57
- package/src/account/upgrade-tickers.ts +0 -124
- package/src/api-client/upgrade-experiment.ts +0 -91
- package/src/plugins/builtin/cloud/browser.tsx +0 -3
- package/src/time-series/studies.ts +0 -1628
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import type { Readable, Writable } from "node:stream";
|
|
3
|
+
import { mkdir } from "fs/promises";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
import { logFailure } from "../utils/log-failure";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The headless Chrome a pane capture draws in (desktop-pane-shot.ts), driven
|
|
9
|
+
* over the DevTools protocol.
|
|
10
|
+
*
|
|
11
|
+
* On macOS and Linux the protocol runs over a pipe to the browser alone
|
|
12
|
+
* (`--remote-debugging-pipe`): no local port that another program on the
|
|
13
|
+
* machine could connect to, and the page's address (which carries the capture
|
|
14
|
+
* server's secret folder) is sent over that pipe, never on the command line,
|
|
15
|
+
* where other accounts could read it. Bun cannot hand a browser those pipes
|
|
16
|
+
* on Windows yet, so there the browser listens on a local port for its
|
|
17
|
+
* DevTools, as before, and is still told the page over the protocol.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/** A DevTools command sent to the capture's page, and its result. */
|
|
21
|
+
export interface CdpPage {
|
|
22
|
+
send(method: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ShotBrowser {
|
|
26
|
+
page: CdpPage;
|
|
27
|
+
/** Opens `url` in the page, resolving once it has loaded or once loading has run past its time. */
|
|
28
|
+
open(url: string): Promise<void>;
|
|
29
|
+
close(): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const CDP_CALL_TIMEOUT_MS = 10_000;
|
|
33
|
+
// Chrome gets 30 s to answer at all: 8 s was not enough on a busy machine.
|
|
34
|
+
const CHROME_START_TIMEOUT_MS = 30_000;
|
|
35
|
+
const PAGE_LOAD_TIMEOUT_MS = 45_000;
|
|
36
|
+
const CHROME_EXIT_TIMEOUT_MS = 5_000;
|
|
37
|
+
|
|
38
|
+
type CdpMessage = {
|
|
39
|
+
id?: number;
|
|
40
|
+
method?: string;
|
|
41
|
+
sessionId?: string;
|
|
42
|
+
result?: unknown;
|
|
43
|
+
error?: { message?: string; data?: string };
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
type PendingCdpCall = {
|
|
47
|
+
resolve: (value: unknown) => void;
|
|
48
|
+
reject: (error: Error) => void;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* One DevTools connection to the browser. Commands carry an id and, for the
|
|
53
|
+
* page, its session (flat sessions); replies settle them and events wake who
|
|
54
|
+
* waits on them.
|
|
55
|
+
*/
|
|
56
|
+
class CdpConnection {
|
|
57
|
+
private nextId = 1;
|
|
58
|
+
private closed = false;
|
|
59
|
+
private readonly pending = new Map<number, PendingCdpCall>();
|
|
60
|
+
private readonly waiters = new Set<{ method: string; sessionId?: string; settle: (seen: boolean) => void }>();
|
|
61
|
+
|
|
62
|
+
constructor(private readonly write: (text: string) => void) {}
|
|
63
|
+
|
|
64
|
+
receive(text: string): void {
|
|
65
|
+
let message: CdpMessage;
|
|
66
|
+
try {
|
|
67
|
+
message = JSON.parse(text) as CdpMessage;
|
|
68
|
+
} catch (error) {
|
|
69
|
+
logFailure("cli.screenshot", "Decode screenshot browser response failed")(error);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (message.id === undefined) {
|
|
73
|
+
for (const waiter of this.waiters) {
|
|
74
|
+
if (waiter.method === message.method && waiter.sessionId === message.sessionId) waiter.settle(true);
|
|
75
|
+
}
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const pending = this.pending.get(message.id);
|
|
79
|
+
if (!pending) return;
|
|
80
|
+
this.pending.delete(message.id);
|
|
81
|
+
if (message.error) pending.reject(new Error([message.error.message, message.error.data].filter(Boolean).join("\n")));
|
|
82
|
+
else pending.resolve(message.result);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
close(): void {
|
|
86
|
+
if (this.closed) return;
|
|
87
|
+
this.closed = true;
|
|
88
|
+
for (const pending of this.pending.values()) pending.reject(new Error("Chrome DevTools connection closed."));
|
|
89
|
+
this.pending.clear();
|
|
90
|
+
for (const waiter of this.waiters) waiter.settle(false);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
send(method: string, params?: Record<string, unknown>, sessionId?: string, timeoutMs = CDP_CALL_TIMEOUT_MS): Promise<unknown> {
|
|
94
|
+
if (this.closed) return Promise.reject(new Error("Chrome DevTools connection closed."));
|
|
95
|
+
const id = this.nextId++;
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
97
|
+
const timer = setTimeout(() => {
|
|
98
|
+
this.pending.delete(id);
|
|
99
|
+
reject(new Error(`Timed out waiting for Chrome DevTools method ${method}.`));
|
|
100
|
+
}, timeoutMs);
|
|
101
|
+
this.pending.set(id, {
|
|
102
|
+
resolve: (value) => {
|
|
103
|
+
clearTimeout(timer);
|
|
104
|
+
resolve(value);
|
|
105
|
+
},
|
|
106
|
+
reject: (error) => {
|
|
107
|
+
clearTimeout(timer);
|
|
108
|
+
reject(error);
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
try {
|
|
112
|
+
this.write(JSON.stringify({ id, method, params, ...(sessionId ? { sessionId } : {}) }));
|
|
113
|
+
} catch (error) {
|
|
114
|
+
this.pending.get(id)?.reject(error instanceof Error ? error : new Error(String(error)));
|
|
115
|
+
this.pending.delete(id);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** True once `method` arrives for the session, false when it has not within `timeoutMs` or the connection closed. */
|
|
121
|
+
waitForEvent(method: string, sessionId: string | undefined, timeoutMs: number): Promise<boolean> {
|
|
122
|
+
return new Promise((resolve) => {
|
|
123
|
+
if (this.closed) return resolve(false);
|
|
124
|
+
const waiter = {
|
|
125
|
+
method,
|
|
126
|
+
sessionId,
|
|
127
|
+
settle: (seen: boolean) => {
|
|
128
|
+
clearTimeout(timer);
|
|
129
|
+
this.waiters.delete(waiter);
|
|
130
|
+
resolve(seen);
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
const timer = setTimeout(() => waiter.settle(false), timeoutMs);
|
|
134
|
+
this.waiters.add(waiter);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const CHROME_ARGS = [
|
|
140
|
+
"--headless=new",
|
|
141
|
+
"--disable-gpu",
|
|
142
|
+
// Software WebGL for GPU-drawn panes (the 3D volatility surface).
|
|
143
|
+
"--use-angle=swiftshader",
|
|
144
|
+
"--enable-unsafe-swiftshader",
|
|
145
|
+
"--no-sandbox",
|
|
146
|
+
"--disable-dev-shm-usage",
|
|
147
|
+
"--disable-background-networking",
|
|
148
|
+
"--disable-default-apps",
|
|
149
|
+
"--disable-extensions",
|
|
150
|
+
"--disable-popup-blocking",
|
|
151
|
+
"--hide-scrollbars",
|
|
152
|
+
"--no-first-run",
|
|
153
|
+
"--no-default-browser-check",
|
|
154
|
+
"--allow-file-access-from-files",
|
|
155
|
+
];
|
|
156
|
+
|
|
157
|
+
interface LaunchedChrome {
|
|
158
|
+
connection: CdpConnection;
|
|
159
|
+
stop(): Promise<void>;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Chrome with DevTools on fds 3 (to the browser) and 4 (from it): messages are JSON, each ended by a NUL. */
|
|
163
|
+
function launchOverPipe(chrome: string, args: string[]): LaunchedChrome {
|
|
164
|
+
const child = spawn(chrome, [...args, "--remote-debugging-pipe", "about:blank"], {
|
|
165
|
+
stdio: ["ignore", "ignore", "ignore", "pipe", "pipe"],
|
|
166
|
+
});
|
|
167
|
+
const toChrome = child.stdio[3] as Writable;
|
|
168
|
+
const fromChrome = child.stdio[4] as Readable;
|
|
169
|
+
const connection = new CdpConnection((text) => toChrome.write(`${text}\0`));
|
|
170
|
+
let buffered = "";
|
|
171
|
+
fromChrome.setEncoding("utf8");
|
|
172
|
+
fromChrome.on("data", (chunk: string) => {
|
|
173
|
+
buffered += chunk;
|
|
174
|
+
for (let end = buffered.indexOf("\0"); end >= 0; end = buffered.indexOf("\0")) {
|
|
175
|
+
const message = buffered.slice(0, end);
|
|
176
|
+
buffered = buffered.slice(end + 1);
|
|
177
|
+
connection.receive(message);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
const closed = () => connection.close();
|
|
181
|
+
fromChrome.on("close", closed);
|
|
182
|
+
fromChrome.on("error", closed);
|
|
183
|
+
// Writes after the browser has gone fail; the connection already says it closed.
|
|
184
|
+
toChrome.on("error", closed);
|
|
185
|
+
child.on("error", closed);
|
|
186
|
+
const exited = new Promise<void>((resolve) => {
|
|
187
|
+
if (child.exitCode !== null || child.signalCode !== null) resolve();
|
|
188
|
+
else child.once("exit", () => resolve());
|
|
189
|
+
});
|
|
190
|
+
child.once("exit", closed);
|
|
191
|
+
return {
|
|
192
|
+
connection,
|
|
193
|
+
stop: async () => {
|
|
194
|
+
connection.close();
|
|
195
|
+
child.kill();
|
|
196
|
+
const timer = setTimeout(() => child.kill("SIGKILL"), CHROME_EXIT_TIMEOUT_MS);
|
|
197
|
+
await exited;
|
|
198
|
+
clearTimeout(timer);
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** Chrome with DevTools on a local port it picks and writes to DevToolsActivePort in its profile. */
|
|
204
|
+
async function launchOverPort(chrome: string, args: string[], userDataDir: string): Promise<LaunchedChrome> {
|
|
205
|
+
// A port picked here can be one Windows has reserved, where Chrome runs on
|
|
206
|
+
// without DevTools until the wait below times out; Chrome's own pick is free.
|
|
207
|
+
const proc = Bun.spawn([chrome, ...args, "--remote-debugging-port=0", "about:blank"], { stdout: "ignore", stderr: "ignore" });
|
|
208
|
+
const stop = async () => {
|
|
209
|
+
proc.kill();
|
|
210
|
+
await proc.exited.catch(() => { /* Intentional ignore: the capture browser was killed during cleanup; the capture result stands. */ });
|
|
211
|
+
};
|
|
212
|
+
try {
|
|
213
|
+
const endpoint = await waitForBrowserEndpoint(userDataDir);
|
|
214
|
+
const socket = new WebSocket(endpoint);
|
|
215
|
+
await new Promise<void>((resolve, reject) => {
|
|
216
|
+
socket.addEventListener("open", () => resolve(), { once: true });
|
|
217
|
+
socket.addEventListener("error", () => reject(new Error("Could not connect to Chrome DevTools.")), { once: true });
|
|
218
|
+
});
|
|
219
|
+
const connection = new CdpConnection((text) => socket.send(text));
|
|
220
|
+
socket.addEventListener("message", (event) => {
|
|
221
|
+
void messageText(event.data).then((text) => connection.receive(text));
|
|
222
|
+
});
|
|
223
|
+
socket.addEventListener("close", () => connection.close());
|
|
224
|
+
return {
|
|
225
|
+
connection,
|
|
226
|
+
stop: async () => {
|
|
227
|
+
connection.close();
|
|
228
|
+
socket.close();
|
|
229
|
+
await stop();
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
} catch (error) {
|
|
233
|
+
await stop();
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** The browser's DevTools socket, from the port and path Chrome writes to DevToolsActivePort once it listens. */
|
|
239
|
+
async function waitForBrowserEndpoint(userDataDir: string): Promise<string> {
|
|
240
|
+
const deadline = Date.now() + CHROME_START_TIMEOUT_MS;
|
|
241
|
+
while (Date.now() < deadline) {
|
|
242
|
+
try {
|
|
243
|
+
const [port, path] = (await Bun.file(join(userDataDir, "DevToolsActivePort")).text()).split("\n");
|
|
244
|
+
if (port && Number(port) > 0 && path?.startsWith("/devtools/browser/")) return `ws://127.0.0.1:${Number(port)}${path.trim()}`;
|
|
245
|
+
} catch {
|
|
246
|
+
// Intentional ignore: Chrome has not written the file yet; the deadline reports a browser that never does.
|
|
247
|
+
}
|
|
248
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
249
|
+
}
|
|
250
|
+
throw new Error("Timed out waiting for Chrome DevTools.");
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async function messageText(data: unknown): Promise<string> {
|
|
254
|
+
if (typeof data === "string") return data;
|
|
255
|
+
if (data instanceof ArrayBuffer) return new TextDecoder().decode(data);
|
|
256
|
+
if (ArrayBuffer.isView(data)) return new TextDecoder().decode(data as Uint8Array);
|
|
257
|
+
if (typeof Blob !== "undefined" && data instanceof Blob) return data.text();
|
|
258
|
+
return String(data);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Starts the capture browser with one blank page of `widthPx` by `heightPx`,
|
|
263
|
+
* its profile in `userDataDir`. Nothing is loaded until `open`.
|
|
264
|
+
*/
|
|
265
|
+
export async function launchShotBrowser(
|
|
266
|
+
chrome: string,
|
|
267
|
+
options: { widthPx: number; heightPx: number; userDataDir: string },
|
|
268
|
+
): Promise<ShotBrowser> {
|
|
269
|
+
await mkdir(options.userDataDir, { recursive: true });
|
|
270
|
+
const args = [...CHROME_ARGS, `--user-data-dir=${options.userDataDir}`, `--window-size=${options.widthPx},${options.heightPx}`];
|
|
271
|
+
const launched = process.platform === "win32"
|
|
272
|
+
? await launchOverPort(chrome, args, options.userDataDir)
|
|
273
|
+
: launchOverPipe(chrome, args);
|
|
274
|
+
const { connection } = launched;
|
|
275
|
+
try {
|
|
276
|
+
// The first answer waits for the browser to start.
|
|
277
|
+
await connection.send("Browser.getVersion", undefined, undefined, CHROME_START_TIMEOUT_MS);
|
|
278
|
+
const { targetId } = await connection.send("Target.createTarget", { url: "about:blank" }) as { targetId: string };
|
|
279
|
+
const { sessionId } = await connection.send("Target.attachToTarget", { targetId, flatten: true }) as { sessionId: string };
|
|
280
|
+
const page: CdpPage = { send: (method, params) => connection.send(method, params, sessionId) };
|
|
281
|
+
return {
|
|
282
|
+
page,
|
|
283
|
+
async open(url) {
|
|
284
|
+
await page.send("Page.enable");
|
|
285
|
+
const loaded = connection.waitForEvent("Page.loadEventFired", sessionId, PAGE_LOAD_TIMEOUT_MS);
|
|
286
|
+
const { errorText } = await page.send("Page.navigate", { url }) as { errorText?: string };
|
|
287
|
+
if (errorText) throw new Error(`Chrome could not open the capture page: ${errorText}`);
|
|
288
|
+
await loaded;
|
|
289
|
+
},
|
|
290
|
+
close: () => launched.stop(),
|
|
291
|
+
};
|
|
292
|
+
} catch (error) {
|
|
293
|
+
await launched.stop();
|
|
294
|
+
throw error;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/** The Chrome or Chromium a capture draws in: `CHROME_PATH`, or where each platform installs one. */
|
|
299
|
+
export async function findChromeExecutable(): Promise<string> {
|
|
300
|
+
const candidates = [
|
|
301
|
+
process.env.CHROME_PATH,
|
|
302
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
303
|
+
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
|
304
|
+
Bun.which("google-chrome"),
|
|
305
|
+
Bun.which("google-chrome-stable"),
|
|
306
|
+
Bun.which("chromium"),
|
|
307
|
+
Bun.which("chromium-browser"),
|
|
308
|
+
// Windows installs Chrome outside PATH, per machine or per user.
|
|
309
|
+
...["PROGRAMFILES", "PROGRAMFILES(X86)", "LOCALAPPDATA"].map((name) => {
|
|
310
|
+
const dir = process.env[name];
|
|
311
|
+
return dir ? join(dir, "Google", "Chrome", "Application", "chrome.exe") : null;
|
|
312
|
+
}),
|
|
313
|
+
].filter((value): value is string => !!value);
|
|
314
|
+
|
|
315
|
+
for (const candidate of candidates) {
|
|
316
|
+
const file = Bun.file(candidate);
|
|
317
|
+
if (await file.exists()) return candidate;
|
|
318
|
+
}
|
|
319
|
+
throw new Error("Drawing a pane needs Google Chrome or Chromium, and neither was found. Install one, or set CHROME_PATH to its executable.");
|
|
320
|
+
}
|
|
@@ -1,7 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Routes the pane screenshot page (cli-pane-shot-entry.tsx) calls on the Bun
|
|
3
|
-
* server that serves it (desktop-pane-shot.ts).
|
|
3
|
+
* server that serves it (desktop-pane-shot.ts). The server answers only below
|
|
4
|
+
* the secret folder the page is opened at, so the page reaches each route
|
|
5
|
+
* relative to its own address (`shotRouteUrl`), never from the server's root.
|
|
4
6
|
*/
|
|
5
7
|
export const SHOT_API_PROXY_PREFIX = "/__gloom_cli_api__";
|
|
6
8
|
export const SHOT_MARKET_BRIDGE_PATH = "/__gloom_cli_market__";
|
|
7
9
|
export const SHOT_HTTP_BRIDGE_PATH = "/__gloom_cli_http__";
|
|
10
|
+
/**
|
|
11
|
+
* The page's Cloud API reads, over one socket: a page's fetches share six
|
|
12
|
+
* connections to its origin, so a board's seventy contract histories and terms
|
|
13
|
+
* queued behind each other for seconds.
|
|
14
|
+
*/
|
|
15
|
+
export const SHOT_API_SOCKET_PATH = "/__gloom_cli_api_socket__";
|
|
16
|
+
|
|
17
|
+
/** A route (`SHOT_API_PROXY_PREFIX` and the rest) inside the folder of the page at `pageUrl`. */
|
|
18
|
+
export function shotRouteUrl(route: string, pageUrl: string): URL {
|
|
19
|
+
return new URL(`.${route}`, new URL("./", pageUrl));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** A read the page sends over the socket: an API path with its query, and the request's headers. */
|
|
23
|
+
export interface ShotApiSocketCall {
|
|
24
|
+
id: number;
|
|
25
|
+
path: string;
|
|
26
|
+
headers: Array<[string, string]>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** The server's answer to a call: the response with its body in base64, or why it could not be made. */
|
|
30
|
+
export type ShotApiSocketReply =
|
|
31
|
+
| { id: number; status: number; statusText: string; headers: Array<[string, string]>; body: string }
|
|
32
|
+
| { id: number; error: string };
|