gloomberb 0.13.2 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -302
- package/README.zh-CN.md +47 -239
- package/package.json +16 -8
- package/src/api-client/askg.test.ts +256 -0
- package/src/api-client/askg.ts +544 -0
- package/src/api-client/auth.ts +110 -50
- package/src/api-client/chat.ts +58 -24
- package/src/api-client/collections.ts +53 -0
- package/src/api-client/data.ts +260 -69
- package/src/api-client/errors.ts +31 -4
- package/src/api-client/index.test.ts +568 -303
- package/src/api-client/index.ts +374 -476
- package/src/api-client/normalizers.ts +43 -13
- package/src/api-client/notes.ts +89 -0
- package/src/api-client/paths.test.ts +32 -0
- package/src/api-client/paths.ts +169 -36
- package/src/api-client/request.test.ts +35 -18
- package/src/api-client/request.ts +170 -34
- package/src/api-client/research-activity.test.ts +316 -0
- package/src/api-client/research-activity.ts +339 -32
- package/src/api-client/session-request-lifetime.test.ts +184 -0
- package/src/api-client/socket-health.test.ts +18 -12
- package/src/api-client/socket-lifetime.test.ts +76 -0
- package/src/api-client/socket.ts +279 -75
- package/src/api-client/teams.test.ts +270 -0
- package/src/api-client/teams.ts +241 -0
- package/src/api-client/theses.ts +177 -0
- package/src/api-client/types.ts +757 -10
- package/src/api-client/views.ts +125 -0
- package/src/app/global-shortcuts.test.tsx +5 -37
- package/src/app/pane-runtime/plugin-bindings.ts +125 -6
- package/src/app/pane-runtime/ticker-navigation-runtime.test.ts +144 -0
- package/src/app/pane-runtime/ticker-open-runtime.test.tsx +170 -0
- package/src/app/pane-runtime/ticker-open-runtime.ts +68 -12
- package/src/app/runtime/desktop-deeplink.test.ts +44 -1
- package/src/app/runtime/desktop-deeplink.ts +22 -11
- package/src/app/runtime/layout-warmup.test.ts +73 -0
- package/src/app/runtime/layout-warmup.ts +118 -0
- package/src/app/runtime/startup.ts +47 -2
- package/src/app/runtime/ticker-refresh.test.tsx +115 -0
- package/src/app/runtime/ticker-refresh.ts +109 -157
- package/src/app.tsx +32 -6
- package/src/architecture/browser-entry-graph.test.ts +1 -0
- package/src/architecture/import-boundaries.test.ts +14 -0
- package/src/brokers/bond-price-basis.test.ts +35 -0
- package/src/brokers/broker-ticker-sync.ts +6 -2
- package/src/brokers/legacy-contract.test.ts +51 -0
- package/src/brokers/sync-broker-instance.test.ts +70 -0
- package/src/capabilities/factories.ts +4 -0
- package/src/capabilities/index.ts +1 -0
- package/src/capabilities/service-capabilities.ts +43 -3
- package/src/capabilities/stream-client.ts +39 -0
- package/src/cli/base-converter.test.ts +16 -0
- package/src/cli/base-converter.ts +5 -4
- package/src/cli/commands/automation.ts +1 -147
- package/src/cli/commands/futures-price-precision.test.tsx +65 -0
- package/src/cli/commands/market-fx.test.ts +59 -0
- package/src/cli/commands/market.ts +10 -5
- package/src/cli/commands/overview.ts +1 -32
- package/src/cli/commands/plugins.ts +461 -79
- package/src/cli/commands/quote-price-basis.test.ts +82 -0
- package/src/cli/commands/system.ts +83 -5
- package/src/cli/commands/ticker-financial-units.test.ts +43 -0
- package/src/cli/commands/ticker-period.test.ts +62 -0
- package/src/cli/commands/ticker.ts +170 -106
- package/src/cli/desktop-pane-shot.ts +98 -7
- package/src/cli/entry.test.ts +55 -0
- package/src/cli/entry.ts +13 -6
- package/src/cli/helpers.ts +5 -3
- package/src/cli/index.ts +6 -3
- package/src/cli/native-smoke.ts +16 -0
- package/src/cli/pane-functions/capabilities.ts +9 -383
- package/src/cli/pane-functions/catalog.ts +6 -5
- package/src/cli/pane-functions/cloud-session.test.ts +23 -0
- package/src/cli/pane-functions/cloud-session.ts +9 -0
- package/src/cli/pane-functions/data.ts +0 -6
- package/src/cli/pane-functions/discovery.test.ts +36 -0
- package/src/cli/pane-functions/discovery.ts +30 -18
- package/src/cli/pane-functions/headless.test.ts +67 -0
- package/src/cli/pane-functions/headless.ts +24 -6
- package/src/cli/pane-functions/index.test.ts +29 -0
- package/src/cli/pane-functions/index.ts +1 -1
- package/src/cli/pane-functions/intraday-shot.test.ts +84 -20
- package/src/cli/pane-functions/options.ts +5 -2
- package/src/cli/pane-functions/report.test.ts +6 -3
- package/src/cli/pane-functions/report.ts +5 -857
- package/src/cli/pane-functions/resolver.ts +1 -1
- package/src/cli/pane-functions/screenshot.test.ts +27 -6
- package/src/cli/pane-functions/screenshot.ts +179 -135
- package/src/cli/registry.test.ts +24 -50
- package/src/cli/result.test.ts +18 -0
- package/src/cli/result.ts +3 -1
- package/src/cli.test.ts +14 -5
- package/src/components/chart/composite/axis-overlays.tsx +4 -2
- package/src/components/chart/composite/column-layout.ts +2 -2
- package/src/components/chart/composite/composite-chart.test.tsx +164 -7
- package/src/components/chart/composite/composite-chart.tsx +131 -30
- package/src/components/chart/composite/format.test.ts +74 -0
- package/src/components/chart/composite/format.ts +85 -12
- package/src/components/chart/composite/fx-precision.test.ts +92 -0
- package/src/components/chart/composite/interactions.test.ts +13 -0
- package/src/components/chart/composite/interactions.ts +3 -1
- package/src/components/chart/composite/panel-series.ts +2 -0
- package/src/components/chart/composite/price-axis-labels.test.ts +8 -0
- package/src/components/chart/composite/price-axis-labels.tsx +3 -1
- package/src/components/chart/composite/price-series.ts +18 -11
- package/src/components/chart/composite/renderers.test.ts +5 -5
- package/src/components/chart/composite/scene-market-cursor.test.ts +148 -0
- package/src/components/chart/composite/scene.test.ts +166 -0
- package/src/components/chart/composite/scene.ts +57 -21
- package/src/{plugins/prediction-markets/chart.test.tsx → components/chart/composite/scroll-surface.test.tsx} +34 -22
- package/src/components/chart/composite/text-renderer.ts +5 -2
- package/src/components/chart/composite/time-axis.test.ts +11 -2
- package/src/components/chart/composite/time-axis.ts +8 -5
- package/src/components/chart/composite/types.ts +9 -0
- package/src/components/chart/native/kitty/index.test.ts +4 -79
- package/src/components/chart/static/chart-surface.test.tsx +13 -0
- package/src/components/chart/static/chart-surface.tsx +19 -11
- package/src/components/chart/static/series.ts +3 -3
- package/src/components/command-bar/assist/model.test.ts +66 -0
- package/src/components/command-bar/assist/model.ts +82 -7
- package/src/components/command-bar/commands/collection.ts +27 -7
- package/src/components/command-bar/commands/direct/runtime.ts +7 -2
- package/src/components/command-bar/list/model.ts +9 -0
- package/src/components/command-bar/list/view.tsx +25 -83
- package/src/components/command-bar/multi-select-picker.tsx +6 -8
- package/src/components/command-bar/pane-actions.ts +13 -7
- package/src/components/command-bar/pane-templates/workflow.ts +28 -3
- package/src/components/command-bar/panel/index.tsx +189 -76
- package/src/components/command-bar/panel/layout.test.ts +32 -0
- package/src/components/command-bar/panel/layout.ts +9 -1
- package/src/components/command-bar/panel/palette.ts +28 -0
- package/src/components/command-bar/panel/state.ts +6 -0
- package/src/components/command-bar/panel/types.ts +1 -14
- package/src/components/command-bar/routes/ticker-search/actions.ts +33 -12
- package/src/components/command-bar/routes/ticker-search/results.test.ts +42 -1
- package/src/components/command-bar/routes/ticker-search/results.ts +14 -11
- package/src/components/command-bar/routing/actions.ts +9 -8
- package/src/components/command-bar/surface/index.tsx +20 -1
- package/src/components/command-bar/surface/listing-selection.test.tsx +84 -0
- package/src/components/command-bar/surface/test-harness.tsx +11 -93
- package/src/components/command-bar/theme-picker.tsx +12 -27
- package/src/components/command-bar/workflow/body.tsx +8 -35
- package/src/components/command-bar/workflow/builtin.ts +55 -14
- package/src/components/command-bar/workflow/collection-actions.test.ts +11 -0
- package/src/components/command-bar/workflow/collection-actions.ts +50 -11
- package/src/components/command-bar/workflow/collection-identity.test.ts +180 -0
- package/src/components/command-bar/workflow/collection-ticker.ts +65 -0
- package/src/components/command-bar/workflow/coordinator.ts +0 -1
- package/src/components/command-bar/workflow/field-row.tsx +20 -35
- package/src/components/command-bar/workflow/ops.test.ts +167 -1
- package/src/components/command-bar/workflow/ops.ts +59 -3
- package/src/components/command-bar/workflow/runtime.ts +13 -0
- package/src/components/command-bar/workflow/submit.ts +9 -2
- package/src/components/command-bar/workflow/ticker-listing-picker.test.ts +41 -0
- package/src/components/command-bar/workflow/ticker-listing-picker.ts +35 -0
- package/src/components/command-bar/workflow/tickers.ts +42 -11
- package/src/components/data-table/export.ts +4 -1
- package/src/components/data-table/frozen-column.test.tsx +114 -0
- package/src/components/data-table/horizontal-navigation.test.tsx +154 -0
- package/src/components/data-table/stack-view.test.tsx +23 -18
- package/src/components/data-table/stack-view.tsx +37 -1
- package/src/components/data-table/view.test.tsx +107 -63
- package/src/components/data-table/view.tsx +40 -3
- package/src/components/feed-data-table/stack-view.tsx +20 -5
- package/src/components/index.ts +40 -15
- package/src/components/layout/detached-pane-shell.tsx +71 -17
- package/src/components/layout/floating-pane.tsx +7 -0
- package/src/components/layout/header.tsx +3 -0
- package/src/components/layout/market-summary.ts +1 -1
- package/src/components/layout/missing-pane.tsx +111 -0
- package/src/components/layout/pane/content.tsx +29 -9
- package/src/components/layout/pane/footer/current-actions.test.tsx +108 -0
- package/src/components/layout/pane/footer/index.tsx +44 -3
- package/src/components/layout/pane/footer/model.ts +11 -0
- package/src/components/layout/pane/footer/notice.desktop.test.tsx +56 -0
- package/src/components/layout/pane/footer/registration.tsx +32 -1
- package/src/components/layout/pane/header.tsx +31 -1
- package/src/components/layout/pane/index.tsx +3 -0
- package/src/components/layout/pane/sizing.test.ts +1 -0
- package/src/components/layout/pane/sizing.ts +4 -1
- package/src/components/layout/shell/chrome.ts +7 -2
- package/src/components/layout/shell/index.test.tsx +117 -34
- package/src/components/layout/shell/index.tsx +42 -22
- package/src/components/layout/shell/menu.test.ts +34 -0
- package/src/components/layout/shell/menu.ts +9 -0
- package/src/components/layout/shell/pane/actions.ts +20 -3
- package/src/components/layout/shell/pane/layers.tsx +26 -0
- package/src/components/layout/shell/pane-occlusion.test.ts +52 -0
- package/src/components/layout/shell/pane-occlusion.ts +63 -0
- package/src/components/layout/status-bar-groups.test.ts +92 -0
- package/src/components/layout/status-bar-groups.ts +85 -0
- package/src/components/layout/status-bar.test.tsx +6 -6
- package/src/components/layout/status-bar.tsx +140 -31
- package/src/components/layout/titlebar-overlay.ts +11 -1
- package/src/components/layout/window-fullscreen.ts +32 -0
- package/src/components/onboarding/account-step/form-panel.tsx +13 -32
- package/src/components/onboarding/account-step/index.tsx +13 -29
- package/src/components/onboarding/first-run-workspace.test.ts +81 -0
- package/src/components/onboarding/first-run-workspace.ts +215 -0
- package/src/components/onboarding/onboarding-frame.tsx +109 -35
- package/src/components/onboarding/onboarding-wizard.test.tsx +389 -202
- package/src/components/onboarding/onboarding-wizard.tsx +379 -303
- package/src/components/onboarding/portfolio-step/index.tsx +13 -0
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +292 -0
- package/src/components/onboarding/portfolio-step/types.ts +7 -1
- package/src/components/onboarding/wizard-account.ts +38 -18
- package/src/components/onboarding/wizard-model.test.ts +67 -0
- package/src/components/onboarding/wizard-model.ts +99 -3
- package/src/components/onboarding/wizard-positions.ts +327 -0
- package/src/components/price-performance.tsx +1 -1
- package/src/components/sign-in-gate.test.tsx +10 -78
- package/src/components/table-view-shared.tsx +4 -3
- package/src/components/ticker/badge/format.test.ts +66 -0
- package/src/components/ticker/badge/format.ts +51 -19
- package/src/components/ticker/badge/index.tsx +12 -5
- package/src/components/ticker/badge/list.test.tsx +84 -0
- package/src/components/ticker/badge/list.tsx +69 -6
- package/src/components/ticker/list-table-view.tsx +8 -0
- package/src/components/ui/action-row.tsx +36 -0
- package/src/components/ui/button.tsx +44 -11
- package/src/components/ui/checkbox.tsx +5 -2
- package/src/components/ui/choice-dialog.tsx +15 -6
- package/src/components/ui/data-table/opentui/index.tsx +101 -33
- package/src/components/ui/data-table/stable-columns.ts +34 -0
- package/src/components/ui/data-table/types.ts +6 -1
- package/src/components/ui/display.desktop.test.tsx +55 -0
- package/src/components/ui/display.test.tsx +36 -0
- package/src/components/ui/display.tsx +124 -0
- package/src/components/ui/external-link.test.tsx +25 -0
- package/src/components/ui/external-link.tsx +11 -3
- package/src/components/ui/fields.tsx +17 -4
- package/src/components/ui/index.ts +19 -3
- package/src/components/ui/list-view.tsx +32 -16
- package/src/components/ui/loading.tsx +5 -4
- package/src/components/ui/native-select.tsx +14 -5
- package/src/components/ui/prose.tsx +110 -0
- package/src/components/ui/select-button.tsx +49 -18
- package/src/components/ui/status.tsx +63 -54
- package/src/components/ui/tabs.tsx +3 -1
- package/src/components/ui/toggle.tsx +22 -1
- package/src/components/ui/ui.test.tsx +62 -26
- package/src/components/use-pane-notice-footer.test.tsx +116 -0
- package/src/components/use-pane-notice-footer.tsx +128 -0
- package/src/core/app-runtime.test.ts +113 -0
- package/src/core/app-runtime.ts +97 -0
- package/src/core/app-services.ts +35 -103
- package/src/core/state/app/instrument.ts +77 -0
- package/src/core/state/app/layout-reducer.ts +60 -0
- package/src/core/state/app/layout.ts +149 -19
- package/src/core/state/app/state.ts +2 -2
- package/src/core/state/app/types.ts +14 -1
- package/src/core/state/session-persistence.ts +18 -48
- package/src/data/cached-query.test.ts +95 -0
- package/src/data/cached-query.ts +106 -0
- package/src/data/config/layout.ts +35 -1
- package/src/data/config/store/index.test.ts +41 -0
- package/src/data/config/store/normalize.ts +65 -7
- package/src/data/fred-series.ts +22 -66
- package/src/{renderers/browser/persistence.ts → data/json-persistence.ts} +8 -8
- package/src/{renderers/browser/storage.ts → data/json-storage.ts} +5 -5
- package/src/{renderers/browser/ticker-repository.ts → data/json-ticker-repository.ts} +7 -7
- package/src/data/memory-resource-store.test.ts +24 -0
- package/src/{renderers/electrobun/view/resource-store.ts → data/memory-resource-store.ts} +2 -2
- package/src/data/plugin-cache.test.ts +46 -0
- package/src/data/plugin-cache.ts +89 -0
- package/src/data/response-sequence.ts +6 -0
- package/src/i18n/es.ts +84 -3
- package/src/i18n/ja.ts +84 -3
- package/src/i18n/ko.ts +84 -3
- package/src/i18n/zh-cn.ts +84 -3
- package/src/i18n/zh-tw.ts +84 -3
- package/src/layout-marketplace/cloud.test.ts +154 -0
- package/src/layout-marketplace/cloud.ts +215 -0
- package/src/layout-marketplace/gallery-desktop.test.tsx +19 -74
- package/src/layout-marketplace/gallery-desktop.tsx +65 -3
- package/src/layout-marketplace/gallery-terminal.tsx +83 -5
- package/src/layout-marketplace/gallery.tsx +254 -18
- package/src/layout-marketplace/linked-sync.ts +104 -0
- package/src/layout-marketplace/linked.ts +119 -0
- package/src/layout-marketplace/mini-workspace.test.tsx +9 -62
- package/src/layout-marketplace/model.ts +71 -19
- package/src/layout-marketplace/payload.test.ts +156 -0
- package/src/layout-marketplace/payload.ts +77 -16
- package/src/layout-marketplace/use-marketplace.ts +68 -1
- package/src/market-data/coordinator/auxiliary.ts +40 -11
- package/src/market-data/coordinator/entries.ts +11 -1
- package/src/market-data/coordinator/events.test.ts +33 -3
- package/src/market-data/coordinator/events.ts +25 -1
- package/src/market-data/coordinator/financials.ts +2 -61
- package/src/market-data/coordinator/fx-refresh.test.ts +61 -0
- package/src/market-data/coordinator/index.test.ts +25 -0
- package/src/market-data/coordinator/index.ts +129 -27
- package/src/market-data/coordinator/quotes.ts +1 -0
- package/src/market-data/coordinator/subscriptions.test.ts +12 -5
- package/src/market-data/hooks.tsx +8 -13
- package/src/market-data/legacy-contract-hooks.test.tsx +49 -0
- package/src/market-data/legacy-contract.test.ts +99 -0
- package/src/market-data/market/format.test.ts +77 -1
- package/src/market-data/market/format.ts +100 -6
- package/src/market-data/market/freshness.ts +13 -1
- package/src/market-data/market/price-basis.ts +9 -0
- package/src/market-data/market/status.test.ts +15 -1
- package/src/market-data/market/status.ts +18 -22
- package/src/market-data/performance.ts +21 -6
- package/src/market-data/portfolio-financials.ts +27 -0
- package/src/market-data/portfolio-instrument.test.ts +80 -0
- package/src/market-data/quotes/contributions.ts +32 -9
- package/src/market-data/quotes/day-range.test.ts +84 -0
- package/src/market-data/quotes/day-range.ts +95 -0
- package/src/market-data/quotes/freshness.test.ts +63 -0
- package/src/market-data/quotes/freshness.ts +17 -11
- package/src/market-data/quotes/metadata.ts +55 -0
- package/src/market-data/quotes/observation-time.test.ts +74 -0
- package/src/market-data/quotes/price-basis.test.ts +44 -0
- package/src/market-data/quotes/resolution.test.ts +137 -0
- package/src/market-data/quotes/resolution.ts +57 -11
- package/src/market-data/request-types.ts +27 -13
- package/src/market-data/result-types.ts +3 -0
- package/src/market-data/selectors.ts +2 -23
- package/src/market-data/snapshot-contract.test.ts +110 -0
- package/src/market-data/snapshot-provider.test.ts +93 -0
- package/src/market-data/snapshot-provider.ts +175 -0
- package/src/market-data/ticker-price-returns.test.ts +26 -0
- package/src/market-data/ticker-price-returns.ts +18 -0
- package/src/news/aggregator.test.ts +20 -4
- package/src/news/aggregator.ts +40 -10
- package/src/news/news-model.ts +33 -2
- package/src/news/types.ts +2 -0
- package/src/pane-settings.ts +24 -0
- package/src/plugins/builtin/account-management/form-components.tsx +22 -94
- package/src/plugins/builtin/account-management/model.ts +26 -12
- package/src/plugins/builtin/account-management/navigation.ts +1 -1
- package/src/plugins/builtin/account-management/pane.tsx +31 -54
- package/src/plugins/builtin/alerts/index.test.tsx +52 -42
- package/src/plugins/builtin/alerts/index.tsx +7 -2
- package/src/plugins/builtin/alerts/quotes.ts +2 -2
- package/src/plugins/builtin/analytics/broker-performance.test.ts +79 -0
- package/src/plugins/builtin/analytics/broker-performance.ts +57 -70
- package/src/plugins/builtin/analytics/display.ts +6 -3
- package/src/plugins/builtin/analytics/index.test.tsx +262 -53
- package/src/plugins/builtin/analytics/index.tsx +85 -51
- package/src/plugins/builtin/analytics/metrics.test.ts +23 -6
- package/src/plugins/builtin/analytics/metrics.ts +97 -49
- package/src/plugins/builtin/analytics/pane-model.test.ts +191 -0
- package/src/plugins/builtin/analytics/pane-model.ts +194 -100
- package/src/plugins/builtin/analytics/portfolio-identity.test.tsx +272 -0
- package/src/plugins/builtin/analytics/return-window.test.ts +72 -0
- package/src/plugins/builtin/analytics/sector-model.test.ts +56 -0
- package/src/plugins/builtin/analytics/sector-model.ts +38 -23
- package/src/plugins/builtin/analytics/sharpe-cadence.test.ts +111 -0
- package/src/plugins/builtin/analytics/sharpe-cadence.ts +161 -0
- package/src/plugins/builtin/analytics/view.tsx +61 -66
- package/src/plugins/builtin/broker-manager/index.test.tsx +5 -9
- package/src/plugins/builtin/broker-manager/index.tsx +11 -12
- package/src/plugins/builtin/buildout/cells.test.tsx +31 -0
- package/src/plugins/builtin/buildout/cells.tsx +2 -12
- package/src/plugins/builtin/buildout/detail/company.tsx +23 -42
- package/src/plugins/builtin/buildout/detail/index.tsx +0 -1
- package/src/plugins/builtin/buildout/detail/intel.tsx +5 -10
- package/src/plugins/builtin/buildout/detail/site.tsx +15 -33
- package/src/plugins/builtin/buildout/detail/ui.tsx +17 -56
- package/src/plugins/builtin/buildout/pane/header.tsx +3 -11
- package/src/plugins/builtin/buildout/pane/status.tsx +3 -18
- package/src/plugins/builtin/cds/headless.test.ts +20 -2
- package/src/plugins/builtin/cds/model.test.ts +10 -0
- package/src/plugins/builtin/cds/model.ts +18 -8
- package/src/plugins/builtin/cds/pane.test.tsx +2 -2
- package/src/plugins/builtin/cds/pane.tsx +32 -41
- package/src/plugins/builtin/chart-composer/catalog-inventory.test.ts +17 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +57 -16
- package/src/plugins/builtin/chart-composer/cli-options.ts +7 -4
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +24 -2
- package/src/plugins/builtin/chart-composer/editor/controller.ts +7 -1
- package/src/plugins/builtin/chart-composer/editor/opentui-view.tsx +2 -0
- package/src/plugins/builtin/chart-composer/editor.test.tsx +32 -23
- package/src/plugins/builtin/chart-composer/editor.tsx +3 -6
- package/src/plugins/builtin/chart-composer/financial-periods.fixture.json +225 -0
- package/src/plugins/builtin/chart-composer/headless-schema.ts +221 -0
- package/src/plugins/builtin/chart-composer/headless.test.ts +158 -0
- package/src/plugins/builtin/chart-composer/headless.ts +225 -0
- package/src/plugins/builtin/chart-composer/index.tsx +90 -8
- package/src/plugins/builtin/chart-composer/loading.test.tsx +134 -0
- package/src/plugins/builtin/chart-composer/pane-share.test.ts +74 -1
- package/src/plugins/builtin/chart-composer/pane.tsx +125 -134
- package/src/plugins/builtin/chart-composer/presets.test.ts +46 -0
- package/src/plugins/builtin/chart-composer/presets.ts +41 -13
- package/src/plugins/builtin/chart-composer/quick-add.tsx +7 -1
- package/src/plugins/builtin/chart-composer/quote-metadata.test.ts +176 -0
- package/src/plugins/builtin/chart-composer/semantic.ts +1 -0
- package/src/plugins/builtin/chart-composer/settings.test.ts +30 -0
- package/src/plugins/builtin/chart-composer/settings.ts +1 -1
- package/src/plugins/builtin/chart-composer/use-series-catalog.test.tsx +94 -0
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +7 -2
- package/src/plugins/builtin/chat/channel-labels.ts +13 -0
- package/src/plugins/builtin/chat/channels.ts +2 -0
- package/src/plugins/builtin/chat/content/channel-navigation.ts +16 -3
- package/src/plugins/builtin/chat/content/composer.tsx +13 -46
- package/src/plugins/builtin/chat/content/index.tsx +3 -1
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -15
- package/src/plugins/builtin/chat/controller/channels.ts +5 -1
- package/src/plugins/builtin/chat/controller/index.ts +17 -4
- package/src/plugins/builtin/chat/controller/session-lifetime.test.ts +182 -0
- package/src/plugins/builtin/chat/controller/session-runtime.ts +16 -4
- package/src/plugins/builtin/chat/controller.test.ts +173 -296
- package/src/plugins/builtin/chat/message/desktop.tsx +9 -9
- package/src/plugins/builtin/chat/message/profile-popover.tsx +3 -23
- package/src/plugins/builtin/chat/message/terminal.tsx +9 -9
- package/src/plugins/builtin/chat/sidebar.test.tsx +107 -0
- package/src/plugins/builtin/chat/sidebar.tsx +71 -18
- package/src/plugins/builtin/chat/status-widget.tsx +6 -12
- package/src/plugins/builtin/chat/test-harness.test.ts +46 -0
- package/src/plugins/builtin/chat/test-harness.tsx +12 -6
- package/src/plugins/builtin/cloud/askg/controller.test.ts +275 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +440 -0
- package/src/plugins/builtin/cloud/askg/host.ts +87 -0
- package/src/plugins/builtin/cloud/askg/model.test.ts +222 -0
- package/src/plugins/builtin/cloud/askg/model.ts +623 -0
- package/src/plugins/builtin/cloud/askg/pane.tsx +734 -0
- package/src/plugins/builtin/cloud/askg/pending-question.ts +38 -0
- package/src/plugins/builtin/cloud/askg/protocol.ts +11 -0
- package/src/plugins/builtin/cloud/auth-actions.tsx +49 -51
- package/src/plugins/builtin/cloud/auth-form.tsx +5 -7
- package/src/plugins/builtin/cloud/auth-model.ts +8 -6
- package/src/plugins/builtin/cloud/plugin.tsx +57 -3
- package/src/plugins/builtin/cloud/team/acm-tab.tsx +127 -0
- package/src/plugins/builtin/cloud/team/capability.ts +71 -0
- package/src/plugins/builtin/cloud/team/collections-sync.ts +222 -0
- package/src/plugins/builtin/cloud/team/collections.test.ts +126 -0
- package/src/plugins/builtin/cloud/team/collections.ts +181 -0
- package/src/plugins/builtin/cloud/team/command.ts +313 -0
- package/src/plugins/builtin/cloud/team/model.test.ts +174 -0
- package/src/plugins/builtin/cloud/team/model.ts +209 -0
- package/src/plugins/builtin/cloud/team/module.tsx +78 -0
- package/src/plugins/builtin/cloud/team/pane-model.test.ts +100 -0
- package/src/plugins/builtin/cloud/team/pane-model.ts +156 -0
- package/src/plugins/builtin/cloud/team/pane-request.ts +47 -0
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +509 -0
- package/src/plugins/builtin/cloud/team/pane-ui.tsx +325 -0
- package/src/plugins/builtin/cloud/team/pane.test.tsx +196 -0
- package/src/plugins/builtin/cloud/team/pane.tsx +712 -0
- package/src/plugins/builtin/cloud/team/status-widget.tsx +75 -0
- package/src/plugins/builtin/cloud/team/store.test.ts +231 -0
- package/src/plugins/builtin/cloud/team/store.ts +318 -0
- package/src/plugins/builtin/cloud/team/team-state-host.ts +70 -0
- package/src/plugins/builtin/cloud/team/views.ts +185 -0
- package/src/plugins/builtin/cloud/thesis/board-pane.test.tsx +239 -0
- package/src/plugins/builtin/cloud/thesis/board-pane.tsx +471 -0
- package/src/plugins/builtin/cloud/thesis/detail.tsx +522 -0
- package/src/plugins/builtin/cloud/thesis/exposure.ts +119 -0
- package/src/plugins/builtin/cloud/thesis/flows.ts +552 -0
- package/src/plugins/builtin/cloud/thesis/model.test.ts +171 -0
- package/src/plugins/builtin/cloud/thesis/model.ts +406 -0
- package/src/plugins/builtin/cloud/thesis/module.tsx +63 -0
- package/src/plugins/builtin/cloud/thesis/pane-request.ts +47 -0
- package/src/plugins/builtin/cloud/thesis/prompts.tsx +214 -0
- package/src/plugins/builtin/cloud/thesis/store.ts +279 -0
- package/src/plugins/builtin/cloud/thesis/ticker-tab.tsx +131 -0
- package/src/plugins/builtin/cloud/upgrade-status-widget.tsx +2 -15
- package/src/plugins/builtin/cloud/verification-status-widget.tsx +72 -0
- package/src/plugins/builtin/cloud-tweets/model.ts +13 -0
- package/src/plugins/builtin/cloud-tweets/pane.tsx +4 -2
- package/src/plugins/builtin/cloud-tweets/table.test.tsx +125 -0
- package/src/plugins/builtin/cloud-tweets/table.tsx +66 -20
- package/src/plugins/builtin/composite-plugins.ts +2 -12
- package/src/plugins/builtin/congress-trades/detail.tsx +42 -7
- package/src/plugins/builtin/congress-trades/footer.ts +23 -7
- package/src/plugins/builtin/congress-trades/keyboard.ts +10 -1
- package/src/plugins/builtin/congress-trades/model.test.ts +29 -10
- package/src/plugins/builtin/congress-trades/model.ts +28 -3
- package/src/plugins/builtin/congress-trades/pane.tsx +24 -6
- package/src/plugins/builtin/congress-trades/table.tsx +0 -1
- package/src/plugins/builtin/connections/pane.test.tsx +12 -16
- package/src/plugins/builtin/connections/pane.tsx +18 -30
- package/src/plugins/builtin/correlation/compute.test.ts +53 -86
- package/src/plugins/builtin/correlation/compute.ts +54 -60
- package/src/plugins/builtin/correlation/headless-schema.ts +69 -0
- package/src/plugins/builtin/correlation/headless.test.ts +147 -0
- package/src/plugins/builtin/correlation/headless.ts +110 -0
- package/src/plugins/builtin/correlation/history.ts +16 -0
- package/src/plugins/builtin/correlation/index.test.tsx +27 -55
- package/src/plugins/builtin/correlation/index.tsx +31 -13
- package/src/plugins/builtin/correlation/matrix/model.ts +38 -21
- package/src/plugins/builtin/correlation/relationship/controls.tsx +0 -30
- package/src/plugins/builtin/correlation/relationship/history.test.tsx +62 -0
- package/src/plugins/builtin/correlation/relationship/history.ts +31 -57
- package/src/plugins/builtin/correlation/relationship/model.ts +29 -62
- package/src/plugins/builtin/correlation/relationship/pane.tsx +47 -38
- package/src/plugins/builtin/credit-conditions/client.test.ts +43 -1
- package/src/plugins/builtin/credit-conditions/client.ts +17 -6
- package/src/plugins/builtin/credit-conditions/index.test.tsx +59 -38
- package/src/plugins/builtin/credit-conditions/index.tsx +35 -60
- package/src/plugins/builtin/credit-conditions/model.test.ts +1 -0
- package/src/plugins/builtin/credit-conditions/model.ts +1 -0
- package/src/plugins/builtin/custom-view/index.tsx +69 -0
- package/src/plugins/builtin/custom-view/loader.ts +107 -0
- package/src/plugins/builtin/custom-view/pane.tsx +308 -0
- package/src/plugins/builtin/custom-view/view-spec.test.ts +107 -0
- package/src/plugins/builtin/custom-view/view-spec.ts +347 -0
- package/src/plugins/builtin/debug/index.tsx +65 -46
- package/src/plugins/builtin/debug/template.ts +8 -0
- package/src/plugins/builtin/dividend-yield/browser.tsx +26 -0
- package/src/plugins/builtin/dividend-yield/calendar.ts +9 -0
- package/src/plugins/builtin/dividend-yield/client.test.ts +204 -2
- package/src/plugins/builtin/dividend-yield/client.ts +148 -96
- package/src/plugins/builtin/dividend-yield/dividend-source-integrity.test.ts +232 -0
- package/src/plugins/builtin/dividend-yield/headless.test.ts +35 -1
- package/src/plugins/builtin/dividend-yield/headless.ts +48 -11
- package/src/plugins/builtin/dividend-yield/index.tsx +64 -51
- package/src/plugins/builtin/dividend-yield/pane.test.tsx +349 -0
- package/src/plugins/builtin/dividend-yield/pane.tsx +118 -117
- package/src/plugins/builtin/dividend-yield/provider-client.test.ts +61 -0
- package/src/plugins/builtin/dividend-yield/provider-client.ts +44 -0
- package/src/plugins/builtin/dividend-yield/reference-price.test.ts +115 -0
- package/src/plugins/builtin/dividend-yield/reference-price.ts +27 -0
- package/src/plugins/builtin/dividend-yield/view.test.ts +58 -0
- package/src/plugins/builtin/dividend-yield/view.ts +35 -0
- package/src/plugins/builtin/earnings/data/cache.test.ts +21 -1
- package/src/plugins/builtin/earnings/data/cache.ts +11 -86
- package/src/plugins/builtin/earnings/detail-model.test.ts +103 -0
- package/src/plugins/builtin/earnings/detail-model.ts +165 -0
- package/src/plugins/builtin/earnings/detail-view.tsx +131 -0
- package/src/plugins/builtin/earnings/estimate-basis.test.ts +158 -0
- package/src/plugins/builtin/earnings/estimate-basis.ts +76 -0
- package/src/plugins/builtin/earnings/estimate-fixtures.test-data.ts +327 -0
- package/src/plugins/builtin/earnings/headless.ts +29 -18
- package/src/plugins/builtin/earnings/index.tsx +114 -63
- package/src/plugins/builtin/earnings/model.test.ts +29 -1
- package/src/plugins/builtin/earnings/table.test.ts +60 -0
- package/src/plugins/builtin/earnings/table.ts +46 -36
- package/src/plugins/builtin/earnings-calls/data.test.ts +252 -0
- package/src/plugins/builtin/earnings-calls/data.ts +66 -28
- package/src/plugins/builtin/earnings-calls/headless-freshness.test.ts +41 -0
- package/src/plugins/builtin/earnings-calls/headless.test.ts +69 -3
- package/src/plugins/builtin/earnings-calls/headless.ts +82 -89
- package/src/plugins/builtin/earnings-calls/index.tsx +22 -22
- package/src/plugins/builtin/earnings-calls/model.ts +1 -0
- package/src/plugins/builtin/earnings-calls/pane.test.tsx +466 -0
- package/src/plugins/builtin/earnings-calls/pane.tsx +225 -65
- package/src/plugins/builtin/earnings-calls/prose.test.ts +16 -1
- package/src/plugins/builtin/earnings-calls/prose.ts +33 -30
- package/src/plugins/builtin/earnings-calls/transcript-view.tsx +138 -115
- package/src/plugins/builtin/econ/calendar-model.ts +10 -61
- package/src/plugins/builtin/econ/detail-view.tsx +35 -81
- package/src/plugins/builtin/econ/fred-cache.test.ts +39 -1
- package/src/plugins/builtin/econ/fred-client.test.ts +34 -7
- package/src/plugins/builtin/econ/fred-series-map.ts +57 -36
- package/src/plugins/builtin/econ/index.test.tsx +10 -13
- package/src/plugins/builtin/econ-statistics/client.test.ts +108 -0
- package/src/plugins/builtin/econ-statistics/client.ts +42 -13
- package/src/plugins/builtin/econ-statistics/defs.ts +3 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +12 -13
- package/src/plugins/builtin/econ-statistics/headless.test.ts +1 -1
- package/src/plugins/builtin/econ-statistics/headless.ts +6 -1
- package/src/plugins/builtin/econ-statistics/pane.test.tsx +69 -0
- package/src/plugins/builtin/econ-statistics/pane.tsx +52 -87
- package/src/plugins/builtin/econ-statistics/stats.ts +30 -11
- package/src/plugins/builtin/econ-statistics/transform.test.ts +23 -0
- package/src/plugins/builtin/econ-statistics/transform.ts +13 -4
- package/src/plugins/builtin/econ-statistics/view.test.ts +27 -0
- package/src/plugins/builtin/econ-statistics/view.ts +20 -1
- package/src/plugins/builtin/executives/data.ts +126 -0
- package/src/plugins/builtin/executives/format.test.ts +23 -0
- package/src/plugins/builtin/executives/format.ts +58 -0
- package/src/plugins/builtin/executives/index.tsx +61 -0
- package/src/plugins/builtin/executives/pane.test.tsx +335 -0
- package/src/plugins/builtin/executives/pane.tsx +467 -0
- package/src/plugins/builtin/filing-events/feed.test.ts +146 -0
- package/src/plugins/builtin/filing-events/feed.ts +189 -0
- package/src/plugins/builtin/filing-events/index.tsx +50 -0
- package/src/plugins/builtin/filing-events/pane.test.tsx +107 -0
- package/src/plugins/builtin/filing-events/pane.tsx +253 -0
- package/src/plugins/builtin/futures/index.tsx +15 -8
- package/src/plugins/builtin/futures/model.test.ts +25 -0
- package/src/plugins/builtin/futures/model.ts +12 -3
- package/src/plugins/builtin/futures/pane.test.tsx +8 -28
- package/src/plugins/builtin/futures/table.tsx +2 -2
- package/src/plugins/builtin/fx-matrix/export.test.ts +30 -0
- package/src/plugins/builtin/fx-matrix/export.ts +32 -0
- package/src/plugins/builtin/fx-matrix/index.tsx +24 -41
- package/src/plugins/builtin/fx-matrix/pairs.test.ts +11 -0
- package/src/plugins/builtin/fx-matrix/pairs.ts +3 -2
- package/src/plugins/builtin/fx-matrix/pane.test.tsx +6 -9
- package/src/plugins/builtin/fx-matrix/refresh.test.tsx +69 -0
- package/src/plugins/builtin/help/components.tsx +6 -26
- package/src/plugins/builtin/help/index.tsx +34 -44
- package/src/plugins/builtin/holders/headless.ts +8 -0
- package/src/plugins/builtin/insider/amendments.test.ts +112 -0
- package/src/plugins/builtin/insider/amendments.ts +65 -0
- package/src/plugins/builtin/insider/client.ts +4 -8
- package/src/plugins/builtin/insider/headless.test.ts +14 -0
- package/src/plugins/builtin/insider/headless.ts +27 -5
- package/src/plugins/builtin/insider/index.tsx +70 -36
- package/src/plugins/builtin/insider/insider-data.test.ts +50 -37
- package/src/plugins/builtin/insider/insider-data.ts +100 -31
- package/src/plugins/builtin/insider/model.ts +102 -55
- package/src/plugins/builtin/insider/pane.test.tsx +87 -0
- package/src/plugins/builtin/jobs/client.ts +85 -0
- package/src/plugins/builtin/jobs/headless.ts +215 -0
- package/src/plugins/builtin/jobs/index.tsx +83 -0
- package/src/plugins/builtin/jobs/model.test.ts +119 -0
- package/src/plugins/builtin/jobs/model.ts +350 -0
- package/src/plugins/builtin/jobs/pages.test.tsx +103 -0
- package/src/plugins/builtin/jobs/pages.ts +48 -0
- package/src/plugins/builtin/jobs/pane.tsx +710 -0
- package/src/plugins/builtin/jobs/share-bars.tsx +93 -0
- package/src/plugins/builtin/kelly-sizer/model.test.ts +6 -0
- package/src/plugins/builtin/kelly-sizer/model.ts +2 -2
- package/src/plugins/builtin/kelly-sizer/pane.tsx +21 -13
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +9 -11
- package/src/plugins/builtin/kelly-sizer/sections.tsx +17 -23
- package/src/plugins/builtin/kelly-sizer/view.test.tsx +11 -0
- package/src/plugins/builtin/kelly-sizer/view.tsx +20 -58
- package/src/plugins/builtin/market-movers/headless.ts +9 -8
- package/src/plugins/builtin/market-movers/index.tsx +26 -21
- package/src/plugins/builtin/market-movers/integrity.test.ts +119 -0
- package/src/plugins/builtin/market-movers/model.ts +44 -10
- package/src/plugins/builtin/market-movers/pane-research.test.tsx +138 -0
- package/src/plugins/builtin/market-movers/screener.ts +77 -51
- package/src/plugins/builtin/market-movers/table.ts +12 -12
- package/src/plugins/builtin/market-valuation/align.ts +28 -17
- package/src/plugins/builtin/market-valuation/cache.ts +9 -1
- package/src/plugins/builtin/market-valuation/chart-projection.ts +11 -9
- package/src/plugins/builtin/market-valuation/chart-series.ts +14 -4
- package/src/plugins/builtin/market-valuation/client.test.ts +160 -21
- package/src/plugins/builtin/market-valuation/client.ts +54 -16
- package/src/plugins/builtin/market-valuation/defs.ts +13 -1
- package/src/plugins/builtin/market-valuation/detail.tsx +25 -43
- package/src/plugins/builtin/market-valuation/headless.test.ts +19 -2
- package/src/plugins/builtin/market-valuation/headless.ts +11 -6
- package/src/plugins/builtin/market-valuation/indicators.ts +51 -84
- package/src/plugins/builtin/market-valuation/model.test.ts +79 -43
- package/src/plugins/builtin/market-valuation/pane.test.tsx +47 -53
- package/src/plugins/builtin/market-valuation/pane.tsx +87 -100
- package/src/plugins/builtin/market-valuation/series.ts +18 -1
- package/src/plugins/builtin/market-valuation/sources.ts +74 -10
- package/src/plugins/builtin/market-valuation/trend.ts +2 -4
- package/src/plugins/builtin/market-valuation/view.ts +26 -23
- package/src/plugins/builtin/news/index.tsx +8 -3
- package/src/plugins/builtin/news/wire/breaking/pane.test.tsx +13 -41
- package/src/plugins/builtin/news/wire/breaking/pane.tsx +7 -3
- package/src/plugins/builtin/news/wire/index.tsx +30 -9
- package/src/plugins/builtin/news/wire/industry-pane.tsx +7 -3
- package/src/plugins/builtin/news/wire/news/detail-view.test.tsx +279 -0
- package/src/plugins/builtin/news/wire/news/detail-view.tsx +91 -47
- package/src/plugins/builtin/news/wire/news/footer.ts +17 -22
- package/src/plugins/builtin/news/wire/news/preset-pane.tsx +7 -3
- package/src/plugins/builtin/news/wire/news/table.tsx +11 -1
- package/src/plugins/builtin/news/wire/persisted-articles.ts +23 -2
- package/src/plugins/builtin/news/wire/rss/feed-xml.ts +104 -0
- package/src/plugins/builtin/news/wire/rss/parser.test.ts +63 -1
- package/src/plugins/builtin/news/wire/rss/parser.ts +70 -96
- package/src/plugins/builtin/news/wire/rss/source.test.ts +38 -1
- package/src/plugins/builtin/news/wire/rss/source.ts +26 -25
- package/src/plugins/builtin/notes/export.ts +57 -0
- package/src/plugins/builtin/notes/files.ts +6 -1
- package/src/plugins/builtin/notes/index.tsx +85 -10
- package/src/plugins/builtin/notes/migration.ts +80 -0
- package/src/plugins/builtin/notes/owner.tsx +129 -0
- package/src/plugins/builtin/notes/quick-notes-pane.test.tsx +10 -2
- package/src/plugins/builtin/notes/quick-notes-pane.tsx +130 -42
- package/src/plugins/builtin/notes/store.test.ts +245 -0
- package/src/plugins/builtin/notes/store.ts +304 -0
- package/src/plugins/builtin/notes/ticker-notes-tab.test.tsx +38 -68
- package/src/plugins/builtin/notes/ticker-notes-tab.tsx +60 -13
- package/src/plugins/builtin/options/analytics.test.ts +65 -0
- package/src/plugins/builtin/options/analytics.ts +62 -23
- package/src/plugins/builtin/options/calc-seed.test.ts +15 -3
- package/src/plugins/builtin/options/calc-seed.ts +18 -6
- package/src/plugins/builtin/options/chain-integrity.test.tsx +251 -0
- package/src/plugins/builtin/options/expiry-catalogue.ts +43 -0
- package/src/plugins/builtin/options/expiry-selection.test.tsx +317 -0
- package/src/plugins/builtin/options/footer.test.ts +38 -1
- package/src/plugins/builtin/options/footer.ts +69 -3
- package/src/plugins/builtin/options/live-quotes.test.ts +18 -4
- package/src/plugins/builtin/options/live-quotes.ts +7 -2
- package/src/plugins/builtin/options/market-reference.test.ts +36 -0
- package/src/plugins/builtin/options/market-reference.ts +70 -0
- package/src/plugins/builtin/options/quote-context.tsx +29 -0
- package/src/plugins/builtin/options/table.test.ts +100 -0
- package/src/plugins/builtin/options/table.ts +41 -11
- package/src/plugins/builtin/options/types.ts +1 -0
- package/src/plugins/builtin/options/view.test.tsx +271 -43
- package/src/plugins/builtin/options/view.tsx +137 -65
- package/src/plugins/builtin/options-calculator/boundary-integrity.test.tsx +112 -0
- package/src/plugins/builtin/options-calculator/index.tsx +1 -1
- package/src/plugins/builtin/options-calculator/model.test.ts +70 -0
- package/src/plugins/builtin/options-calculator/model.ts +52 -6
- package/src/plugins/builtin/options-calculator/pane.test.tsx +44 -12
- package/src/plugins/builtin/options-calculator/pane.tsx +59 -61
- package/src/plugins/builtin/plugin-marketplace/ids.ts +2 -0
- package/src/plugins/builtin/plugin-marketplace/model.test.ts +238 -19
- package/src/plugins/builtin/plugin-marketplace/model.ts +219 -17
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +426 -198
- package/src/plugins/builtin/plugin-marketplace/store.ts +56 -6
- package/src/plugins/builtin/plugin-module.ts +9 -6
- package/src/plugins/builtin/portfolio-list/account-metrics.test.ts +20 -0
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +3 -4
- package/src/plugins/builtin/portfolio-list/bond-price-basis.test.ts +120 -0
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +1 -1
- package/src/plugins/builtin/portfolio-list/cli/render.test.ts +261 -0
- package/src/plugins/builtin/portfolio-list/cli/render.ts +81 -27
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +1 -1
- package/src/plugins/builtin/portfolio-list/column-values.ts +87 -123
- package/src/plugins/builtin/portfolio-list/command-bar.ts +1 -1
- package/src/plugins/builtin/portfolio-list/grid.tsx +3 -1
- package/src/plugins/builtin/portfolio-list/header.tsx +7 -41
- package/src/plugins/builtin/portfolio-list/metrics.test.ts +133 -1
- package/src/plugins/builtin/portfolio-list/mutations.test.ts +13 -0
- package/src/plugins/builtin/portfolio-list/mutations.ts +7 -1
- package/src/plugins/builtin/portfolio-list/pane/data.ts +4 -0
- package/src/plugins/builtin/portfolio-list/pane/index.test.tsx +153 -88
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +43 -10
- package/src/plugins/builtin/portfolio-list/pane/streaming.ts +22 -8
- package/src/plugins/builtin/portfolio-list/position-cost-integrity.test.ts +101 -0
- package/src/plugins/builtin/portfolio-list/position-metrics.ts +166 -90
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +31 -3
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +71 -31
- package/src/plugins/builtin/portfolio-list/table.tsx +15 -1
- package/src/plugins/builtin/portfolio-list/use-cursor-neighbor-prefetch.test.tsx +96 -0
- package/src/plugins/builtin/portfolio-list/use-cursor-neighbor-prefetch.ts +87 -0
- package/src/plugins/builtin/portfolio-list/use-throttled-cursor-symbol.test.tsx +8 -5
- package/src/plugins/builtin/portfolio-list/use-throttled-cursor-symbol.ts +4 -1
- package/src/plugins/builtin/research/analyst-headless.test.ts +28 -0
- package/src/plugins/builtin/research/analyst-headless.ts +26 -22
- package/src/plugins/builtin/research/analyst-model.test.ts +36 -0
- package/src/plugins/builtin/research/analyst-model.ts +61 -17
- package/src/plugins/builtin/research/analyst-pane.test.tsx +120 -0
- package/src/plugins/builtin/research/analyst-pane.tsx +15 -7
- package/src/plugins/builtin/research/corporate-actions-pane.test.tsx +68 -0
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +122 -29
- package/src/plugins/builtin/research/equity-diagnostic-pane.test.tsx +17 -46
- package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +13 -24
- package/src/plugins/builtin/research/event-model.test.ts +137 -0
- package/src/plugins/builtin/research/event-model.ts +173 -33
- package/src/plugins/builtin/research/events-headless.test.ts +11 -0
- package/src/plugins/builtin/research/events-headless.ts +36 -19
- package/src/plugins/builtin/research/headless-schema.ts +16 -0
- package/src/plugins/builtin/research/headless.test.ts +18 -0
- package/src/plugins/builtin/research/headless.ts +19 -8
- package/src/plugins/builtin/research/index.test.ts +73 -5
- package/src/plugins/builtin/research/index.tsx +3 -0
- package/src/plugins/builtin/research/relative-valuation-headless.test.ts +192 -0
- package/src/plugins/builtin/research/relative-valuation-headless.ts +51 -0
- package/src/plugins/builtin/research/relative-valuation-model.ts +54 -0
- package/src/plugins/builtin/research/relative-valuation-pane.test.tsx +98 -0
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +72 -71
- package/src/plugins/builtin/research-search/document-view.tsx +15 -28
- package/src/plugins/builtin/research-search/pane.test.tsx +11 -20
- package/src/plugins/builtin/research-search/pane.tsx +5 -9
- package/src/plugins/builtin/risk-factors/data.test.ts +53 -0
- package/src/plugins/builtin/risk-factors/data.ts +117 -0
- package/src/plugins/builtin/risk-factors/headless.test.ts +40 -0
- package/src/plugins/builtin/risk-factors/headless.ts +70 -0
- package/src/plugins/builtin/risk-factors/index.tsx +63 -0
- package/src/plugins/builtin/risk-factors/pane.test.tsx +52 -0
- package/src/plugins/builtin/risk-factors/pane.tsx +310 -0
- package/src/plugins/builtin/risk-factors/test-fixtures.ts +4 -0
- package/src/plugins/builtin/scanner/denied.tsx +7 -7
- package/src/plugins/builtin/scanner/feed.ts +2 -2
- package/src/plugins/builtin/scanner/flow-pane.tsx +17 -8
- package/src/plugins/builtin/scanner/hilo-pane.tsx +21 -7
- package/src/plugins/builtin/sec/filing-content.test.ts +16 -0
- package/src/plugins/builtin/sec/filing-content.ts +46 -5
- package/src/plugins/builtin/sec/filing-display.tsx +13 -7
- package/src/plugins/builtin/sec/filing-documents.ts +10 -0
- package/src/plugins/builtin/sec/headless.test.ts +27 -0
- package/src/plugins/builtin/sec/headless.ts +4 -2
- package/src/plugins/builtin/sec/index.tsx +125 -29
- package/src/plugins/builtin/sec/model.ts +41 -3
- package/src/plugins/builtin/sec/pane.test.tsx +152 -0
- package/src/plugins/builtin/sectors/client.test.ts +211 -0
- package/src/plugins/builtin/sectors/client.ts +89 -18
- package/src/plugins/builtin/sectors/headless.test.ts +59 -0
- package/src/plugins/builtin/sectors/headless.ts +20 -1
- package/src/plugins/builtin/sectors/index.tsx +21 -22
- package/src/plugins/builtin/sectors/pane-cache.test.tsx +78 -0
- package/src/plugins/builtin/sectors/sector-model.test.ts +59 -0
- package/src/plugins/builtin/sectors/sector-model.ts +89 -24
- package/src/plugins/builtin/shared/cloud-upgrade.ts +49 -15
- package/src/plugins/builtin/shared/headless-market-data.ts +40 -0
- package/src/plugins/builtin/shared/headless-options.ts +33 -0
- package/src/plugins/builtin/shared/pane-footer.ts +4 -6
- package/src/plugins/builtin/shared/research-cloud-session.test.tsx +143 -0
- package/src/plugins/builtin/shared/research-cloud-session.ts +16 -0
- package/src/plugins/builtin/shared/screener-live-quotes.test.ts +13 -0
- package/src/plugins/builtin/shared/screener-live-quotes.ts +10 -9
- package/src/plugins/builtin/shared/series-cache.test.ts +106 -0
- package/src/plugins/builtin/shared/series-cache.ts +94 -49
- package/src/plugins/builtin/shared/table-pane.ts +4 -1
- package/src/plugins/builtin/shared/ticker-request.test.tsx +137 -0
- package/src/plugins/builtin/shared/ticker-request.ts +11 -46
- package/src/plugins/builtin/shared/ticker-surface.test.ts +1 -1
- package/src/plugins/builtin/shared/ticker-surface.ts +4 -3
- package/src/plugins/builtin/shared/use-quote-board.test.tsx +73 -6
- package/src/plugins/builtin/shared/use-quote-board.ts +18 -10
- package/src/plugins/builtin/short-interest/client.test.ts +47 -0
- package/src/plugins/builtin/short-interest/client.ts +5 -10
- package/src/plugins/builtin/short-interest/model.ts +13 -4
- package/src/plugins/builtin/short-interest/pane.test.tsx +57 -0
- package/src/plugins/builtin/short-interest/pane.tsx +21 -69
- package/src/plugins/builtin/thirteenf/api.test.ts +91 -0
- package/src/plugins/builtin/thirteenf/api.ts +78 -88
- package/src/plugins/builtin/thirteenf/data.test.ts +177 -1
- package/src/plugins/builtin/thirteenf/data.ts +118 -38
- package/src/plugins/builtin/thirteenf/format.ts +2 -0
- package/src/plugins/builtin/thirteenf/headless.test.ts +36 -0
- package/src/plugins/builtin/thirteenf/headless.ts +27 -8
- package/src/plugins/builtin/thirteenf/model.test.ts +90 -24
- package/src/plugins/builtin/thirteenf/model.ts +129 -82
- package/src/plugins/builtin/thirteenf/pane.test.tsx +27 -92
- package/src/plugins/builtin/thirteenf/pane.tsx +55 -33
- package/src/plugins/builtin/thirteenf/table.ts +2 -3
- package/src/plugins/builtin/thirteenf/types.ts +13 -1
- package/src/plugins/builtin/ticker-detail/chart-tab-switch.test.tsx +17 -50
- package/src/plugins/builtin/ticker-detail/data-panes/historical-price-precision.test.tsx +120 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.test.tsx +41 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +36 -13
- package/src/plugins/builtin/ticker-detail/financials/aggregation.test.ts +79 -0
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +90 -13
- package/src/plugins/builtin/ticker-detail/financials/model.test.ts +152 -0
- package/src/plugins/builtin/ticker-detail/financials/model.ts +139 -22
- package/src/plugins/builtin/ticker-detail/financials/period-integrity.test.tsx +77 -0
- package/src/plugins/builtin/ticker-detail/financials/schema.ts +3 -3
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +71 -49
- package/src/plugins/builtin/ticker-detail/fund-profile.test.tsx +118 -0
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +59 -0
- package/src/plugins/builtin/ticker-detail/headless.test.ts +165 -0
- package/src/plugins/builtin/ticker-detail/headless.ts +150 -0
- package/src/plugins/builtin/ticker-detail/index.tsx +34 -22
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +21 -22
- package/src/plugins/builtin/ticker-detail/overview/model.test.ts +118 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -43
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/overview/types.ts +2 -0
- package/src/plugins/builtin/ticker-detail/overview-return-coverage.test.tsx +71 -0
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +92 -80
- package/src/plugins/builtin/ticker-detail/pane.tsx +42 -19
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +28 -0
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +18 -9
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.test.tsx +21 -29
- package/src/plugins/builtin/ticker-detail/quote-monitor/retained-status.test.tsx +134 -0
- package/src/plugins/builtin/ticker-detail/quote-status.test.tsx +116 -0
- package/src/plugins/builtin/ticker-detail/quote-time-integrity.test.ts +42 -0
- package/src/plugins/builtin/ticker-research-plugin.ts +8 -0
- package/src/plugins/builtin/treasury-auctions/cache.test.ts +43 -1
- package/src/plugins/builtin/treasury-auctions/cache.ts +29 -67
- package/src/plugins/builtin/treasury-auctions/client.test.ts +26 -8
- package/src/plugins/builtin/treasury-auctions/client.ts +28 -4
- package/src/plugins/builtin/treasury-auctions/headless.ts +2 -0
- package/src/plugins/builtin/treasury-auctions/model.test.ts +22 -0
- package/src/plugins/builtin/treasury-auctions/model.ts +28 -25
- package/src/plugins/builtin/treasury-auctions/pane.test.tsx +7 -22
- package/src/plugins/builtin/treasury-auctions/pane.tsx +32 -37
- package/src/plugins/builtin/treasury-auctions/types.ts +2 -2
- package/src/plugins/builtin/volatility/index.tsx +18 -47
- package/src/plugins/builtin/world-indices/headless.ts +4 -3
- package/src/plugins/builtin/world-indices/index.tsx +12 -5
- package/src/plugins/builtin/world-indices/pane.test.tsx +55 -15
- package/src/plugins/builtin/world-indices/table.tsx +3 -3
- package/src/plugins/builtin/world-venue-map/map.desktop.test.tsx +12 -73
- package/src/plugins/builtin/world-venue-map/pane.tsx +5 -7
- package/src/plugins/builtin/yield-curve/chart.test.ts +32 -0
- package/src/plugins/builtin/yield-curve/chart.ts +37 -0
- package/src/plugins/builtin/yield-curve/headless.test.ts +23 -7
- package/src/plugins/builtin/yield-curve/headless.ts +24 -7
- package/src/plugins/builtin/yield-curve/history.test.ts +124 -0
- package/src/plugins/builtin/yield-curve/history.ts +89 -0
- package/src/plugins/builtin/yield-curve/index.tsx +112 -97
- package/src/plugins/builtin/yield-curve/pane.test.tsx +137 -0
- package/src/plugins/builtin/yield-curve/treasury-data.test.ts +15 -5
- package/src/plugins/builtin/yield-curve/treasury-data.ts +25 -17
- package/src/plugins/bundle.test.ts +44 -1
- package/src/plugins/bundle.ts +59 -7
- package/src/plugins/catalog-backend.test.ts +1 -1
- package/src/plugins/catalog-backend.ts +0 -2
- package/src/plugins/catalog-browser.test.ts +9 -3
- package/src/plugins/catalog-browser.ts +37 -2
- package/src/plugins/catalog-manifest.ts +1 -3
- package/src/plugins/catalog-ui.ts +2 -6
- package/src/plugins/current-target.ts +17 -0
- package/src/plugins/external-runtime.ts +70 -0
- package/src/plugins/health.ts +21 -0
- package/src/plugins/host-contract.ts +26 -0
- package/src/plugins/host-link.test.ts +133 -0
- package/src/plugins/host-link.ts +49 -10
- package/src/plugins/host-module-imports.test.ts +94 -0
- package/src/plugins/host-module-imports.ts +73 -0
- package/src/plugins/host-modules.ts +2 -51
- package/src/plugins/host-resolver.test.ts +96 -0
- package/src/plugins/host-resolver.ts +102 -0
- package/src/plugins/host-smoke.ts +103 -0
- package/src/plugins/launch-layout.test.ts +131 -0
- package/src/plugins/launch-layout.ts +148 -0
- package/src/plugins/loader.test.ts +54 -0
- package/src/plugins/loader.ts +138 -36
- package/src/plugins/manager-node.ts +41 -0
- package/src/plugins/ownership.ts +4 -3
- package/src/plugins/pane-manager/dock-tree.ts +4 -2
- package/src/plugins/pane-manager/layout-state.ts +11 -4
- package/src/plugins/pane-manager/queries.ts +5 -4
- package/src/plugins/pane-manager.test.ts +22 -0
- package/src/plugins/pane-state.ts +48 -0
- package/src/plugins/plugin-names.ts +32 -0
- package/src/plugins/registry/contributions.ts +65 -126
- package/src/plugins/registry/index.test.ts +71 -5
- package/src/plugins/registry/index.ts +181 -102
- package/src/plugins/registry/pane-settings.ts +20 -14
- package/src/plugins/registry/plugin-state.ts +5 -20
- package/src/plugins/registry/setup-command.test.ts +62 -0
- package/src/plugins/registry/setup-command.ts +93 -0
- package/src/plugins/registry/shared.ts +1 -3
- package/src/plugins/registry/slots.ts +1 -1
- package/src/plugins/runtime/context.tsx +1 -0
- package/src/plugins/runtime/index.tsx +15 -49
- package/src/plugins/runtime/state.ts +28 -47
- package/src/plugins/seed.test.ts +57 -4
- package/src/plugins/seed.ts +28 -9
- package/src/plugins/team-state.ts +70 -0
- package/src/plugins/ticker-navigation.ts +5 -0
- package/src/plugins/web-bundled.ts +42 -0
- package/src/public/i18n.ts +17 -0
- package/src/public/layout.ts +12 -0
- package/src/public/market-data.ts +19 -0
- package/src/public/pane-hooks.ts +8 -1
- package/src/public/public-api.test.ts +39 -282
- package/src/public/quotes.ts +50 -0
- package/src/public/react.ts +44 -0
- package/src/public/remote.ts +23 -0
- package/src/public/test-support.ts +46 -1
- package/src/public/tickers.ts +40 -0
- package/src/public/time-series.ts +5 -0
- package/src/public/utils.ts +38 -2
- package/src/react/async-resource.test.tsx +106 -0
- package/src/react/async-resource.ts +65 -0
- package/src/react/plugins/plugin-slot.tsx +2 -10
- package/src/react/use-throttled-commit-value.ts +18 -1
- package/src/remote/app-host.tsx +17 -2
- package/src/remote/controller.test.ts +109 -3
- package/src/remote/controller.ts +44 -2
- package/src/remote/schema.ts +15 -0
- package/src/remote/semantic-tree.tsx +15 -7
- package/src/renderers/browser/app-services.ts +19 -52
- package/src/renderers/browser/bundled-plugins.test.ts +41 -0
- package/src/renderers/browser/bundled-plugins.ts +60 -0
- package/src/renderers/browser/cloud-transport.ts +8 -2
- package/src/renderers/browser/config-host.test.ts +70 -0
- package/src/renderers/browser/config-host.ts +75 -11
- package/src/renderers/browser/deeplink-bridge.test.ts +8 -4
- package/src/renderers/browser/deeplink-bridge.ts +18 -0
- package/src/renderers/browser/http-proxy-transport.test.ts +98 -0
- package/src/renderers/browser/http-proxy-transport.ts +83 -0
- package/src/renderers/browser/main.tsx +18 -2
- package/src/renderers/browser/research-entry.test.ts +24 -0
- package/src/renderers/browser/research-entry.ts +16 -2
- package/src/renderers/browser/storage.test.ts +7 -7
- package/src/renderers/cloudflare/http-proxy.test.ts +122 -0
- package/src/renderers/cloudflare/http-proxy.ts +197 -0
- package/src/renderers/cloudflare/worker.ts +7 -0
- package/src/renderers/electrobun/bun/core-capabilities.ts +0 -160
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +4 -0
- package/src/renderers/electrobun/bun/external-plugins.ts +178 -63
- package/src/renderers/electrobun/bun/index.ts +49 -9
- package/src/renderers/electrobun/shared/protocol.ts +40 -4
- package/src/renderers/electrobun/view/app-services.ts +36 -90
- package/src/renderers/electrobun/view/backend-rpc.ts +12 -2
- package/src/renderers/electrobun/view/build-assets.ts +0 -1
- package/src/renderers/electrobun/view/capability-stream-client.ts +51 -0
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +232 -416
- package/src/renderers/electrobun/view/cli-pane-shot-frame.test.tsx +67 -0
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +39 -0
- package/src/renderers/electrobun/view/data-table/dom.ts +3 -0
- package/src/renderers/electrobun/view/data-table/frozen-column.test.tsx +73 -0
- package/src/renderers/electrobun/view/data-table/frozen-column.ts +22 -0
- package/src/renderers/electrobun/view/data-table/horizontal-navigation.test.tsx +77 -0
- package/src/renderers/electrobun/view/data-table/index.test.tsx +125 -0
- package/src/renderers/electrobun/view/data-table/index.tsx +48 -6
- package/src/renderers/electrobun/view/data-table/row.tsx +32 -3
- package/src/renderers/electrobun/view/desktop/control-styles.ts +7 -0
- package/src/renderers/electrobun/view/desktop/controls.test.tsx +141 -48
- package/src/renderers/electrobun/view/desktop/controls.tsx +86 -39
- package/src/renderers/electrobun/view/desktop/list-view.tsx +44 -9
- package/src/renderers/electrobun/view/dom-ui-host.tsx +4 -2
- package/src/renderers/electrobun/view/external-plugins.test.ts +13 -1
- package/src/renderers/electrobun/view/external-plugins.ts +47 -35
- package/src/renderers/electrobun/view/host/block-glyph-canvas.tsx +115 -0
- package/src/renderers/electrobun/view/host/box.test.tsx +50 -89
- package/src/renderers/electrobun/view/host/input.tsx +7 -1
- package/src/renderers/electrobun/view/host/media-surface.tsx +1 -2
- package/src/renderers/electrobun/view/host/scroll-box.desktop.test.tsx +26 -0
- package/src/renderers/electrobun/view/host/scroll-box.tsx +14 -6
- package/src/renderers/electrobun/view/host/text.tsx +28 -0
- package/src/renderers/electrobun/view/http-fetch.ts +3 -14
- package/src/renderers/electrobun/view/input-host.test.tsx +11 -47
- package/src/renderers/electrobun/view/input-host.tsx +1 -1
- package/src/renderers/electrobun/view/main.tsx +38 -6
- package/src/renderers/electrobun/view/native-stubs/native-stubs.test.ts +2 -7
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +2 -0
- package/src/renderers/electrobun/view/remote/persistence.ts +2 -2
- package/src/renderers/electrobun/view/remote/quote-subscription-registry.ts +6 -1
- package/src/renderers/electrobun/view/rpc-codec.test.ts +64 -0
- package/src/renderers/electrobun/view/rpc-codec.ts +35 -0
- package/src/renderers/electrobun/view/screenshot-watermark.test.ts +48 -0
- package/src/renderers/electrobun/view/screenshot-watermark.ts +105 -0
- package/src/renderers/electrobun/view/styles.css +16 -0
- package/src/renderers/electrobun/view/test-utils.tsx +76 -0
- package/src/renderers/electrobun/view/toast-host.test.tsx +8 -25
- package/src/renderers/electrobun/view/ui-host.tsx +0 -3
- package/src/renderers/electrobun/view/window-fullscreen.ts +57 -0
- package/src/renderers/opentui/interaction-performance.ts +29 -3
- package/src/renderers/opentui/scrollbox-layout.ts +35 -0
- package/src/renderers/opentui/start.tsx +7 -40
- package/src/renderers/opentui/test-utils.tsx +117 -6
- package/src/renderers/opentui/ui-host.tsx +1 -1
- package/src/renderers/share/chart.test.ts +52 -0
- package/src/renderers/share/chart.ts +74 -0
- package/src/renderers/share/main.tsx +10 -2
- package/src/renderers/share/styles.css +29 -0
- package/src/renderers/share/view.test.tsx +20 -0
- package/src/renderers/share/view.tsx +24 -15
- package/src/shares/api.test.ts +15 -0
- package/src/shares/live.ts +27 -0
- package/src/shares/pane.ts +3 -0
- package/src/shares/payload.ts +35 -3
- package/src/sources/gloomberb-cloud/history-coverage.test.ts +119 -0
- package/src/sources/gloomberb-cloud/index.test.ts +307 -20
- package/src/sources/gloomberb-cloud/index.ts +176 -62
- package/src/sources/gloomberb-cloud/news.ts +11 -3
- package/src/sources/gloomberb-cloud/normalizers.test.ts +27 -1
- package/src/sources/gloomberb-cloud/normalizers.ts +29 -8
- package/src/sources/gloomberb-cloud/quote-metadata.test.ts +50 -0
- package/src/sources/gloomberb-cloud/valuation-observations.ts +29 -0
- package/src/sources/history-coverage.test.ts +40 -0
- package/src/sources/history-coverage.ts +97 -0
- package/src/sources/listing-history.ts +52 -0
- package/src/sources/listing-target.ts +41 -0
- package/src/sources/provider-router/arca-cache.test.ts +97 -0
- package/src/sources/provider-router/batches.ts +21 -5
- package/src/sources/provider-router/broker-session.test.ts +52 -0
- package/src/sources/provider-router/brokers.ts +1 -0
- package/src/sources/provider-router/cache.test.ts +133 -0
- package/src/sources/provider-router/cache.ts +113 -8
- package/src/sources/provider-router/cached-financials.test.ts +104 -14
- package/src/sources/provider-router/cached-routes.test.ts +212 -0
- package/src/sources/provider-router/cached-routes.ts +223 -0
- package/src/sources/provider-router/connection-health.ts +1 -0
- package/src/sources/provider-router/financial-routes.ts +90 -26
- package/src/sources/provider-router/financials.test.ts +97 -1
- package/src/sources/provider-router/financials.ts +217 -44
- package/src/sources/provider-router/fixtures/quarterly-source-disagreements.json +438 -0
- package/src/sources/provider-router/history-boundary-cache.test.ts +72 -0
- package/src/sources/provider-router/history-gap-cache.test.ts +84 -0
- package/src/sources/provider-router/history-gaps.test.ts +141 -0
- package/src/sources/provider-router/history.test.ts +124 -3
- package/src/sources/provider-router/history.ts +156 -46
- package/src/sources/provider-router/index.test.ts +19 -13
- package/src/sources/provider-router/index.ts +83 -18
- package/src/sources/provider-router/listing-history.test.ts +139 -0
- package/src/sources/provider-router/listing-identity.test.ts +128 -0
- package/src/sources/provider-router/non-company-metadata.test.ts +95 -0
- package/src/sources/provider-router/o-income-basis.test.ts +64 -0
- package/src/sources/provider-router/primary.ts +44 -8
- package/src/sources/provider-router/profile-enrichment.test.ts +171 -0
- package/src/sources/provider-router/quote-completion.test.ts +62 -0
- package/src/sources/provider-router/quote-domain.test.ts +92 -0
- package/src/sources/provider-router/routing.ts +2 -30
- package/src/sources/provider-router/search.ts +2 -11
- package/src/sources/provider-router/shell-history-cache.test.ts +131 -0
- package/src/sources/provider-router/statement-history.test.ts +71 -0
- package/src/sources/provider-router/statement-history.ts +15 -0
- package/src/sources/provider-router/statement-observations.test.ts +126 -0
- package/src/sources/provider-router/streaming.ts +1 -1
- package/src/sources/provider-router/supplemental.ts +2 -389
- package/src/sources/provider-router/valuation-retractions.test.ts +280 -0
- package/src/sources/sec-edgar-shares.fixture.json +188 -0
- package/src/sources/sec-edgar-shares.test.ts +66 -0
- package/src/sources/sec-edgar.test.ts +146 -0
- package/src/sources/sec-edgar.ts +136 -37
- package/src/sources/sec-income-attribution.test.ts +93 -0
- package/src/sources/yahoo-finance/financials.ts +23 -23
- package/src/sources/yahoo-finance/mappers.test.ts +95 -1
- package/src/sources/yahoo-finance/mappers.ts +104 -43
- package/src/sources/yahoo-finance/options.test.ts +13 -0
- package/src/sources/yahoo-finance/options.ts +4 -2
- package/src/sources/yahoo-finance/quote-summary.ts +25 -12
- package/src/sources/yahoo-finance/requests.test.ts +37 -0
- package/src/sources/yahoo-finance/requests.ts +9 -2
- package/src/sources/yahoo-finance/snapshots.test.ts +140 -0
- package/src/sources/yahoo-finance/snapshots.ts +21 -11
- package/src/sources/yahoo-finance/symbols.test.ts +8 -0
- package/src/sources/yahoo-finance/symbols.ts +60 -11
- package/src/sources/yahoo-finance/types.ts +8 -0
- package/src/sources/yahoo-finance/yahoo-chart-interval.ts +18 -0
- package/src/sources/yahoo-finance.test.ts +20 -0
- package/src/sources/yahoo-finance.ts +54 -20
- package/src/state/app/bootstrap.test.ts +124 -0
- package/src/state/app/bootstrap.ts +106 -130
- package/src/state/app/context/index.test.tsx +56 -0
- package/src/state/app/context/index.tsx +101 -31
- package/src/state/app/context/selector.test.tsx +38 -2
- package/src/state/config-save-scheduler.ts +16 -4
- package/src/state/hooks/inline-ticker-failures.test.ts +77 -0
- package/src/state/hooks/inline-ticker-failures.ts +100 -0
- package/src/state/hooks/inline-tickers.test.tsx +47 -11
- package/src/state/hooks/inline-tickers.ts +254 -85
- package/src/state/hooks/quote-streaming.ts +6 -13
- package/src/state/hooks/session-snapshot.ts +9 -5
- package/src/state/persist-scheduler.test.ts +54 -1
- package/src/state/persist-scheduler.ts +36 -3
- package/src/state/session-persistence.test.ts +46 -0
- package/src/sync/core-contributors.test.ts +35 -6
- package/src/sync/core-contributors.ts +30 -27
- package/src/test-support/market-session.ts +12 -0
- package/src/test-support/pane.tsx +52 -0
- package/src/test-support/plugin-runtime.ts +5 -0
- package/src/theme/color-utils.ts +90 -33
- package/src/tickers/instrument-label.ts +10 -0
- package/src/tickers/list.test.ts +1 -0
- package/src/tickers/list.ts +1 -1
- package/src/tickers/metadata.ts +4 -1
- package/src/tickers/open-target.test.ts +86 -0
- package/src/tickers/open-target.ts +48 -9
- package/src/tickers/search/identity.ts +19 -0
- package/src/tickers/search/index.test.ts +263 -8
- package/src/tickers/search/index.ts +164 -29
- package/src/tickers/search/ranking.ts +85 -9
- package/src/tickers/search/types.ts +5 -1
- package/src/tickers/search/upsert.ts +14 -6
- package/src/tickers/search-contract-context.test.tsx +161 -0
- package/src/tickers/search-contract-templates.test.ts +83 -0
- package/src/tickers/selection.ts +21 -0
- package/src/time-series/alignment.ts +11 -3
- package/src/time-series/bond-price-history.test.ts +52 -0
- package/src/time-series/chart-data.test.ts +44 -12
- package/src/time-series/chart-data.ts +36 -8
- package/src/time-series/economic.test.ts +44 -0
- package/src/time-series/economic.ts +42 -0
- package/src/time-series/field-catalog.ts +3 -2
- package/src/time-series/financial-history-request.test.ts +20 -0
- package/src/time-series/financial-period-coverage.test.ts +37 -0
- package/src/time-series/financial-period-coverage.ts +59 -0
- package/src/time-series/financial-period-gaps.test.ts +128 -0
- package/src/time-series/fixtures/q4-reported-common-income.json +394 -0
- package/src/time-series/fixtures/q4-reported-per-share.json +305 -0
- package/src/time-series/forward-valuation.test.ts +131 -0
- package/src/time-series/forward-valuation.ts +247 -0
- package/src/time-series/fundamentals.test.ts +111 -24
- package/src/time-series/fundamentals.ts +260 -131
- package/src/time-series/hooks.ts +7 -3
- package/src/time-series/legacy-contract-live.test.ts +23 -0
- package/src/time-series/live-quotes.test.ts +5 -2
- package/src/time-series/live-quotes.ts +23 -29
- package/src/time-series/market-price-units.test.ts +75 -0
- package/src/time-series/market.ts +55 -15
- package/src/time-series/price-comparison.test.ts +233 -0
- package/src/time-series/price-comparison.ts +133 -0
- package/src/time-series/price-history-integrity-window.test.ts +137 -0
- package/src/time-series/price-history-integrity.test.ts +195 -0
- package/src/time-series/q4-common-income.test.ts +63 -0
- package/src/time-series/q4-per-share.test.ts +144 -0
- package/src/time-series/reporting-currency.test.ts +99 -0
- package/src/time-series/reporting-currency.ts +37 -0
- package/src/time-series/reporting.ts +38 -2
- package/src/time-series/resolve.test.ts +528 -366
- package/src/time-series/resolve.ts +322 -76
- package/src/time-series/sec-eps-research.test.ts +55 -0
- package/src/time-series/session-history-domain.test.ts +160 -0
- package/src/{cli/pane-functions/intraday-shot.ts → time-series/session-history.ts} +96 -42
- package/src/time-series/spec-studies.test.ts +177 -6
- package/src/time-series/studies.ts +173 -38
- package/src/time-series/transforms.test.ts +38 -2
- package/src/time-series/transforms.ts +5 -1
- package/src/time-series/types.ts +30 -0
- package/src/time-series/use-chart-resolution.test.tsx +72 -4
- package/src/time-series/use-chart-resolution.ts +45 -28
- package/src/time-series/valuation-currency.test.ts +127 -0
- package/src/time-series/valuation-currency.ts +46 -0
- package/src/time-series/valuation-denominator.test.ts +240 -0
- package/src/time-series/valuation-live-status.test.ts +63 -0
- package/src/time-series/valuation-price.test.ts +264 -0
- package/src/time-series/valuation-price.ts +68 -0
- package/src/types/broker.ts +2 -1
- package/src/types/config.test.ts +31 -0
- package/src/types/config.ts +49 -10
- package/src/types/data-provider.ts +43 -0
- package/src/types/exchange-rate.ts +13 -0
- package/src/types/financials.ts +164 -2
- package/src/types/headless.ts +23 -0
- package/src/types/instrument.ts +11 -0
- package/src/types/plugin.ts +108 -2
- package/src/types/ticker.ts +10 -2
- package/src/ui/context-menu.test.ts +2 -1
- package/src/ui/context-menu.tsx +3 -3
- package/src/ui/host.tsx +6 -2
- package/src/ui/index.tsx +3 -4
- package/src/updater.test.ts +17 -1
- package/src/updater.ts +4 -2
- package/src/utils/dom-screenshot.test.ts +52 -0
- package/src/utils/dom-screenshot.ts +70 -15
- package/src/utils/exchange-rate-snapshot.test.ts +22 -0
- package/src/utils/exchange-rate-snapshot.ts +62 -0
- package/src/utils/exchanges.test.ts +24 -0
- package/src/utils/exchanges.ts +22 -11
- package/src/utils/financial-statements.test.ts +74 -1
- package/src/utils/financial-statements.ts +119 -14
- package/src/utils/format.test.ts +21 -1
- package/src/utils/format.ts +56 -23
- package/src/utils/fundamentals.ts +15 -0
- package/src/utils/fx-status.test.ts +16 -0
- package/src/utils/fx-status.ts +46 -0
- package/src/utils/http-proxy-response.ts +44 -0
- package/src/utils/http-transport.ts +21 -1
- package/src/utils/income-statement.ts +46 -0
- package/src/utils/instrument-identity.test.ts +26 -0
- package/src/utils/instrument-identity.ts +35 -0
- package/src/utils/latest-financial-period.test.ts +19 -0
- package/src/utils/latest-financial-period.ts +26 -0
- package/src/utils/market-capitalization-consumers.test.ts +59 -0
- package/src/utils/market-capitalization.test.ts +38 -0
- package/src/utils/market-capitalization.ts +58 -0
- package/src/utils/options.test.ts +20 -0
- package/src/utils/options.ts +4 -4
- package/src/utils/perf-marks.ts +26 -0
- package/src/utils/plugin-proxy-hosts.json +16 -0
- package/src/utils/plugin-proxy-hosts.ts +25 -0
- package/src/utils/price-earnings.test.ts +39 -0
- package/src/utils/price-earnings.ts +13 -0
- package/src/utils/price-history-integrity.ts +61 -0
- package/src/utils/price-history.test.ts +41 -3
- package/src/utils/price-history.ts +90 -6
- package/src/utils/reported-money.test.ts +25 -0
- package/src/utils/reported-money.ts +31 -0
- package/src/utils/screenshot-watermark.ts +27 -0
- package/src/utils/sec-eps-basis.test.ts +82 -0
- package/src/utils/sec-eps-basis.ts +152 -0
- package/src/utils/sec.test.ts +12 -10
- package/src/utils/sec.ts +4 -3
- package/src/utils/semver.test.ts +31 -0
- package/src/utils/semver.ts +48 -0
- package/src/utils/sort-values.test.ts +11 -0
- package/src/utils/sort-values.ts +2 -0
- package/src/utils/statement-observations.ts +121 -0
- package/src/cli/commands/automation.test.ts +0 -211
- package/src/components/chart/native/surface/sync.ts +0 -34
- package/src/components/command-bar/panel/body.tsx +0 -301
- package/src/components/onboarding/account-step/chooser-panel.tsx +0 -51
- package/src/plugins/builtin/ai/agent-history.ts +0 -143
- package/src/plugins/builtin/ai/ask-ai-detail-tab.tsx +0 -466
- package/src/plugins/builtin/ai/ask-ai.test.tsx +0 -365
- package/src/plugins/builtin/ai/index.test.ts +0 -302
- package/src/plugins/builtin/ai/index.tsx +0 -440
- package/src/plugins/builtin/ai/pane-settings.test.ts +0 -155
- package/src/plugins/builtin/ai/pane-settings.ts +0 -319
- package/src/plugins/builtin/ai/pi/credential-store.test.ts +0 -80
- package/src/plugins/builtin/ai/pi/credential-store.ts +0 -138
- package/src/plugins/builtin/ai/pi/file-store.ts +0 -138
- package/src/plugins/builtin/ai/pi/host.test.ts +0 -500
- package/src/plugins/builtin/ai/pi/host.ts +0 -565
- package/src/plugins/builtin/ai/pi/index.ts +0 -5
- package/src/plugins/builtin/ai/pi/models-store.test.ts +0 -44
- package/src/plugins/builtin/ai/pi/models-store.ts +0 -141
- package/src/plugins/builtin/ai/pi/providers.ts +0 -68
- package/src/plugins/builtin/ai/pi/runtime.test.ts +0 -240
- package/src/plugins/builtin/ai/pi/runtime.ts +0 -636
- package/src/plugins/builtin/ai/providers.test.ts +0 -68
- package/src/plugins/builtin/ai/providers.ts +0 -191
- package/src/plugins/builtin/ai/runner-selection.test.ts +0 -174
- package/src/plugins/builtin/ai/runner-selection.ts +0 -193
- package/src/plugins/builtin/ai/runner-selector.tsx +0 -153
- package/src/plugins/builtin/ai/runner.test.ts +0 -198
- package/src/plugins/builtin/ai/runner.ts +0 -316
- package/src/plugins/builtin/ai/screener/contract.test.ts +0 -70
- package/src/plugins/builtin/ai/screener/contract.ts +0 -136
- package/src/plugins/builtin/ai/screener/editor-runtime.ts +0 -160
- package/src/plugins/builtin/ai/screener/editor.tsx +0 -131
- package/src/plugins/builtin/ai/screener/footer.ts +0 -104
- package/src/plugins/builtin/ai/screener/keyboard.ts +0 -106
- package/src/plugins/builtin/ai/screener/market-runtime.ts +0 -101
- package/src/plugins/builtin/ai/screener/model.test.ts +0 -24
- package/src/plugins/builtin/ai/screener/model.ts +0 -113
- package/src/plugins/builtin/ai/screener/pane.test.tsx +0 -479
- package/src/plugins/builtin/ai/screener/pane.tsx +0 -438
- package/src/plugins/builtin/ai/screener/results-view.tsx +0 -144
- package/src/plugins/builtin/ai/screener/results.ts +0 -139
- package/src/plugins/builtin/ai/screener/runner.ts +0 -164
- package/src/plugins/builtin/ai/screener/tabs-bar.tsx +0 -65
- package/src/plugins/builtin/ai/settings.ts +0 -81
- package/src/plugins/builtin/ai/ticker-context.ts +0 -65
- package/src/plugins/builtin/ai/use-runtime-providers.ts +0 -28
- package/src/plugins/builtin/ai/workspace/model.test.ts +0 -227
- package/src/plugins/builtin/ai/workspace/model.ts +0 -283
- package/src/plugins/builtin/ai/workspace/pane.test.tsx +0 -197
- package/src/plugins/builtin/ai/workspace/pane.tsx +0 -907
- package/src/plugins/builtin/chat/message/action-chip.tsx +0 -39
- package/src/plugins/builtin/cloud/askg/verify.ts +0 -130
- package/src/plugins/builtin/earnings/data/data.test.ts +0 -90
- package/src/plugins/builtin/earnings/data/data.ts +0 -115
- package/src/plugins/builtin/fear-greed/cache.test.ts +0 -90
- package/src/plugins/builtin/fear-greed/cache.ts +0 -154
- package/src/plugins/builtin/fear-greed/charts.tsx +0 -305
- package/src/plugins/builtin/fear-greed/data.test.ts +0 -72
- package/src/plugins/builtin/fear-greed/data.ts +0 -375
- package/src/plugins/builtin/fear-greed/format.ts +0 -87
- package/src/plugins/builtin/fear-greed/headless.test.ts +0 -53
- package/src/plugins/builtin/fear-greed/headless.ts +0 -84
- package/src/plugins/builtin/fear-greed/index.tsx +0 -43
- package/src/plugins/builtin/fear-greed/pane.tsx +0 -169
- package/src/plugins/builtin/ipo-calendar/cache.ts +0 -101
- package/src/plugins/builtin/ipo-calendar/client.test.ts +0 -31
- package/src/plugins/builtin/ipo-calendar/client.ts +0 -311
- package/src/plugins/builtin/ipo-calendar/headless.test.ts +0 -89
- package/src/plugins/builtin/ipo-calendar/headless.ts +0 -127
- package/src/plugins/builtin/ipo-calendar/index.tsx +0 -68
- package/src/plugins/builtin/ipo-calendar/model.ts +0 -133
- package/src/plugins/builtin/ipo-calendar/pane.tsx +0 -328
- package/src/plugins/builtin/ipo-calendar/types.ts +0 -19
- package/src/plugins/builtin/market-halts/client.ts +0 -114
- package/src/plugins/builtin/market-halts/index.tsx +0 -30
- package/src/plugins/builtin/market-halts/model.test.ts +0 -187
- package/src/plugins/builtin/market-halts/model.ts +0 -291
- package/src/plugins/builtin/market-halts/pane.tsx +0 -256
- package/src/plugins/builtin/market-heatmap/data.test.ts +0 -122
- package/src/plugins/builtin/market-heatmap/data.ts +0 -305
- package/src/plugins/builtin/market-heatmap/index.tsx +0 -400
- package/src/plugins/builtin/market-valuation/model.ts +0 -8
- package/src/plugins/builtin/notes/sync.test.ts +0 -49
- package/src/plugins/builtin/notes/sync.ts +0 -98
- package/src/plugins/builtin/polls/client.ts +0 -57
- package/src/plugins/builtin/polls/hooks.ts +0 -20
- package/src/plugins/builtin/polls/index.tsx +0 -35
- package/src/plugins/builtin/polls/normalize.test.ts +0 -230
- package/src/plugins/builtin/polls/normalize.ts +0 -319
- package/src/plugins/builtin/polls/pane.tsx +0 -722
- package/src/plugins/builtin/polls/types.ts +0 -77
- package/src/plugins/builtin/scanner/waiting.tsx +0 -11
- package/src/plugins/builtin/shared/public-share.ts +0 -23
- package/src/plugins/builtin/tv/channels.ts +0 -27
- package/src/plugins/builtin/tv/index.tsx +0 -40
- package/src/plugins/builtin/tv/pane.tsx +0 -346
- package/src/plugins/builtin/tv/youtube-embed.test.ts +0 -84
- package/src/plugins/builtin/tv/youtube-embed.ts +0 -173
- package/src/plugins/builtin/tv/youtube-stream.ts +0 -125
- package/src/plugins/catalog-manifest.test.ts +0 -58
- package/src/plugins/prediction-markets/backend-plugin.ts +0 -21
- package/src/plugins/prediction-markets/cache.ts +0 -163
- package/src/plugins/prediction-markets/capability.test.ts +0 -281
- package/src/plugins/prediction-markets/capability.ts +0 -171
- package/src/plugins/prediction-markets/categories.ts +0 -213
- package/src/plugins/prediction-markets/chart.tsx +0 -158
- package/src/plugins/prediction-markets/cli.ts +0 -28
- package/src/plugins/prediction-markets/columns.ts +0 -134
- package/src/plugins/prediction-markets/controller/catalog.ts +0 -395
- package/src/plugins/prediction-markets/controller/data.ts +0 -177
- package/src/plugins/prediction-markets/controller/detail.ts +0 -247
- package/src/plugins/prediction-markets/controller/effects.ts +0 -253
- package/src/plugins/prediction-markets/controller/index.ts +0 -368
- package/src/plugins/prediction-markets/controller/keyboard.ts +0 -245
- package/src/plugins/prediction-markets/controller/live-updates.ts +0 -86
- package/src/plugins/prediction-markets/controller/selection.ts +0 -59
- package/src/plugins/prediction-markets/controller/status.ts +0 -104
- package/src/plugins/prediction-markets/detail/book.tsx +0 -144
- package/src/plugins/prediction-markets/detail/outcomes.tsx +0 -101
- package/src/plugins/prediction-markets/detail/overview.tsx +0 -84
- package/src/plugins/prediction-markets/detail/pane.tsx +0 -344
- package/src/plugins/prediction-markets/detail/rules.tsx +0 -31
- package/src/plugins/prediction-markets/detail/shared.tsx +0 -49
- package/src/plugins/prediction-markets/detail/trades.tsx +0 -101
- package/src/plugins/prediction-markets/detail.test.tsx +0 -94
- package/src/plugins/prediction-markets/headless.test.ts +0 -119
- package/src/plugins/prediction-markets/headless.ts +0 -255
- package/src/plugins/prediction-markets/index.tsx +0 -117
- package/src/plugins/prediction-markets/keyboard.ts +0 -65
- package/src/plugins/prediction-markets/launch.test.ts +0 -126
- package/src/plugins/prediction-markets/launch.ts +0 -275
- package/src/plugins/prediction-markets/metrics.ts +0 -328
- package/src/plugins/prediction-markets/navigation.ts +0 -77
- package/src/plugins/prediction-markets/outcome-order.ts +0 -19
- package/src/plugins/prediction-markets/pane.test.tsx +0 -562
- package/src/plugins/prediction-markets/pane.tsx +0 -347
- package/src/plugins/prediction-markets/plugin.test.tsx +0 -645
- package/src/plugins/prediction-markets/rows.ts +0 -229
- package/src/plugins/prediction-markets/services/fetch.ts +0 -121
- package/src/plugins/prediction-markets/services/kalshi/adapter.ts +0 -398
- package/src/plugins/prediction-markets/services/kalshi/normalize.ts +0 -211
- package/src/plugins/prediction-markets/services/kalshi/types.ts +0 -103
- package/src/plugins/prediction-markets/services/polymarket/adapter.ts +0 -177
- package/src/plugins/prediction-markets/services/polymarket/detail.ts +0 -356
- package/src/plugins/prediction-markets/services/polymarket/normalize.ts +0 -239
- package/src/plugins/prediction-markets/services/polymarket/types.ts +0 -66
- package/src/plugins/prediction-markets/services/polymarket/ws.ts +0 -128
- package/src/plugins/prediction-markets/settings.ts +0 -163
- package/src/plugins/prediction-markets/test-helpers.tsx +0 -591
- package/src/plugins/prediction-markets/types.ts +0 -179
- package/src/plugins/registry/context.ts +0 -218
- package/src/renderers/electrobun/bun/desktop/media.ts +0 -17
- package/src/renderers/electrobun/view/ai-host.ts +0 -198
- package/src/renderers/electrobun/view/native-stubs/chart/surface-sync.ts +0 -1
- package/src/renderers/electrobun/view/resource-store.test.ts +0 -44
- package/src/shares/chart-snapshot.test.ts +0 -34
- package/src/shares/chart-snapshot.ts +0 -28
- package/src/sources/provider-router/document-routes.ts +0 -203
- package/src/types/media.ts +0 -19
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, jest, test } from "bun:test";
|
|
2
|
-
import type { AppNotificationRequest } from "../../../types/plugin";
|
|
3
|
-
import { MemoryPluginPersistence as MemoryPersistence } from "../../../test-support/plugin-persistence";
|
|
4
2
|
import {
|
|
5
3
|
apiClient,
|
|
6
4
|
type ChatChannel,
|
|
@@ -9,9 +7,30 @@ import {
|
|
|
9
7
|
type ChatStateResponse,
|
|
10
8
|
} from "../../../api-client";
|
|
11
9
|
import { ApiRequestError } from "../../../api-client/errors";
|
|
10
|
+
import { MemoryPluginPersistence as MemoryPersistence } from "../../../test-support/plugin-persistence";
|
|
11
|
+
import type { AppNotificationRequest } from "../../../types/plugin";
|
|
12
12
|
import { ChatController } from "./controller";
|
|
13
13
|
import { SESSION_RETRY_MS } from "./controller/state";
|
|
14
14
|
|
|
15
|
+
const testControllers = new Set<ChatController>();
|
|
16
|
+
|
|
17
|
+
function createController(): ChatController {
|
|
18
|
+
const controller = new ChatController();
|
|
19
|
+
testControllers.add(controller);
|
|
20
|
+
return controller;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function persistSession(persistence: MemoryPersistence, user: Record<string, unknown> = {}) {
|
|
24
|
+
persistence.setState("session", {
|
|
25
|
+
sessionToken: "token-123",
|
|
26
|
+
user: { id: "u1", username: "vince", ...user },
|
|
27
|
+
}, { schemaVersion: 1 });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function chatMessage(input: Pick<ChatMessage, "id" | "content" | "createdAt"> & Partial<ChatMessage>): ChatMessage {
|
|
31
|
+
return { channelId: "everyone", replyToId: null, user: { id: "u1", username: "vince", displayName: "Vince" }, ...input };
|
|
32
|
+
}
|
|
33
|
+
|
|
15
34
|
const TRANSCRIPT_KIND = "channel-transcript";
|
|
16
35
|
const TRANSCRIPT_KEY = "everyone";
|
|
17
36
|
const TRANSCRIPT_SOURCE = "server";
|
|
@@ -100,6 +119,8 @@ beforeEach(() => {
|
|
|
100
119
|
});
|
|
101
120
|
|
|
102
121
|
afterEach(() => {
|
|
122
|
+
for (const controller of testControllers) controller.dispose();
|
|
123
|
+
testControllers.clear();
|
|
103
124
|
jest.useRealTimers();
|
|
104
125
|
apiClient.dispose();
|
|
105
126
|
apiClient.setSessionToken(null);
|
|
@@ -121,20 +142,14 @@ afterEach(() => {
|
|
|
121
142
|
describe("ChatController", () => {
|
|
122
143
|
test("hydrates cached session, draft, and transcript from plugin persistence", () => {
|
|
123
144
|
const persistence = new MemoryPersistence();
|
|
124
|
-
const controller =
|
|
125
|
-
const message: ChatMessage = {
|
|
145
|
+
const controller = createController();
|
|
146
|
+
const message: ChatMessage = chatMessage({
|
|
126
147
|
id: "m1",
|
|
127
|
-
channelId: "everyone",
|
|
128
148
|
content: "hello",
|
|
129
|
-
replyToId: null,
|
|
130
149
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
131
|
-
|
|
132
|
-
};
|
|
150
|
+
});
|
|
133
151
|
|
|
134
|
-
persistence
|
|
135
|
-
sessionToken: "token-123",
|
|
136
|
-
user: { id: "u1", username: "vince" },
|
|
137
|
-
}, { schemaVersion: 1 });
|
|
152
|
+
persistSession(persistence);
|
|
138
153
|
persistence.setState("channel:everyone", {
|
|
139
154
|
draft: "cached draft",
|
|
140
155
|
replyToId: "m1",
|
|
@@ -161,7 +176,7 @@ describe("ChatController", () => {
|
|
|
161
176
|
|
|
162
177
|
test("uses a browser cookie session without exposing its token", async () => {
|
|
163
178
|
const persistence = new MemoryPersistence();
|
|
164
|
-
const controller =
|
|
179
|
+
const controller = createController();
|
|
165
180
|
const sentMessages: string[] = [];
|
|
166
181
|
|
|
167
182
|
apiClient.setCookieSessionMode(true);
|
|
@@ -201,7 +216,7 @@ describe("ChatController", () => {
|
|
|
201
216
|
});
|
|
202
217
|
|
|
203
218
|
test("rejects unknown shortcut channels after the server list loads", async () => {
|
|
204
|
-
const controller =
|
|
219
|
+
const controller = createController();
|
|
205
220
|
apiClient.getChannels = async () => SERVER_CHAT_CHANNELS;
|
|
206
221
|
|
|
207
222
|
await expect(controller.resolveRequiredChannelId("help")).resolves.toBe("help");
|
|
@@ -212,24 +227,28 @@ describe("ChatController", () => {
|
|
|
212
227
|
|
|
213
228
|
test("keeps private channels when a public refresh finishes after chat state", async () => {
|
|
214
229
|
const persistence = new MemoryPersistence();
|
|
215
|
-
const controller =
|
|
230
|
+
const controller = createController();
|
|
216
231
|
const directChannel: ChatChannel = {
|
|
217
232
|
id: "dm:u2",
|
|
218
233
|
name: "u2",
|
|
219
234
|
kind: "direct",
|
|
220
235
|
created_at: "2026-03-28T00:00:00.000Z",
|
|
221
236
|
};
|
|
237
|
+
const teamChannel: ChatChannel = {
|
|
238
|
+
id: "team:org-1:trades",
|
|
239
|
+
name: "trades",
|
|
240
|
+
kind: "team",
|
|
241
|
+
teamId: "org-1",
|
|
242
|
+
created_at: "2026-09-14T00:00:00.000Z",
|
|
243
|
+
};
|
|
222
244
|
let resolvePublicChannels: ((channels: ChatChannel[]) => void) | undefined;
|
|
223
245
|
|
|
224
|
-
persistence
|
|
225
|
-
sessionToken: "token-123",
|
|
226
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
227
|
-
}, { schemaVersion: 1 });
|
|
246
|
+
persistSession(persistence, { emailVerified: true });
|
|
228
247
|
apiClient.getChannels = () => new Promise((resolve) => {
|
|
229
248
|
resolvePublicChannels = resolve;
|
|
230
249
|
});
|
|
231
250
|
apiClient.getChatState = async () => ({
|
|
232
|
-
channels: [...SERVER_CHAT_CHANNELS, directChannel],
|
|
251
|
+
channels: [...SERVER_CHAT_CHANNELS, directChannel, teamChannel],
|
|
233
252
|
onlineCount: 0,
|
|
234
253
|
channelStates: [],
|
|
235
254
|
notifications: [],
|
|
@@ -239,21 +258,20 @@ describe("ChatController", () => {
|
|
|
239
258
|
const publicRefresh = controller.refreshChannels();
|
|
240
259
|
await controller.refreshChatState();
|
|
241
260
|
expect(controller.getChannels().map((channel) => channel.id)).toContain(directChannel.id);
|
|
261
|
+
expect(controller.getChannels().map((channel) => channel.id)).toContain(teamChannel.id);
|
|
242
262
|
|
|
243
263
|
resolvePublicChannels!(SERVER_CHAT_CHANNELS);
|
|
244
264
|
await publicRefresh;
|
|
245
265
|
|
|
246
266
|
expect(controller.getChannels().map((channel) => channel.id)).toContain(directChannel.id);
|
|
267
|
+
expect(controller.getChannels().map((channel) => channel.id)).toContain(teamChannel.id);
|
|
247
268
|
});
|
|
248
269
|
|
|
249
270
|
test("hydrates a cached verified user into the api client for offline use", async () => {
|
|
250
271
|
const persistence = new MemoryPersistence();
|
|
251
|
-
const controller =
|
|
272
|
+
const controller = createController();
|
|
252
273
|
|
|
253
|
-
persistence
|
|
254
|
-
sessionToken: "token-123",
|
|
255
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
256
|
-
}, { schemaVersion: 1 });
|
|
274
|
+
persistSession(persistence, { emailVerified: true });
|
|
257
275
|
|
|
258
276
|
controller.attachPersistence(persistence);
|
|
259
277
|
|
|
@@ -271,7 +289,7 @@ describe("ChatController", () => {
|
|
|
271
289
|
|
|
272
290
|
test("does not restore persisted websocket tokens", () => {
|
|
273
291
|
const persistence = new MemoryPersistence();
|
|
274
|
-
const controller =
|
|
292
|
+
const controller = createController();
|
|
275
293
|
|
|
276
294
|
persistence.setState("session", {
|
|
277
295
|
sessionToken: "token-123",
|
|
@@ -292,12 +310,9 @@ describe("ChatController", () => {
|
|
|
292
310
|
|
|
293
311
|
test("reset clears persisted chat state and session token", () => {
|
|
294
312
|
const persistence = new MemoryPersistence();
|
|
295
|
-
const controller =
|
|
313
|
+
const controller = createController();
|
|
296
314
|
|
|
297
|
-
persistence
|
|
298
|
-
sessionToken: "token-123",
|
|
299
|
-
user: { id: "u1", username: "vince" },
|
|
300
|
-
}, { schemaVersion: 1 });
|
|
315
|
+
persistSession(persistence);
|
|
301
316
|
persistence.setState("channel:everyone", {
|
|
302
317
|
draft: "cached draft",
|
|
303
318
|
replyToId: null,
|
|
@@ -325,7 +340,7 @@ describe("ChatController", () => {
|
|
|
325
340
|
|
|
326
341
|
test("defers draft persistence and subscriber sync until the user pauses or leaves", () => {
|
|
327
342
|
const persistence = new TrackingPersistence();
|
|
328
|
-
const controller =
|
|
343
|
+
const controller = createController();
|
|
329
344
|
const draftSnapshots: string[] = [];
|
|
330
345
|
|
|
331
346
|
controller.attachPersistence(persistence);
|
|
@@ -352,7 +367,7 @@ describe("ChatController", () => {
|
|
|
352
367
|
});
|
|
353
368
|
|
|
354
369
|
test("pauses verification polling while the app is backgrounded", () => {
|
|
355
|
-
const controller =
|
|
370
|
+
const controller = createController();
|
|
356
371
|
|
|
357
372
|
apiClient.setSessionToken("token-123");
|
|
358
373
|
(controller as any).session.sessionToken = "token-123";
|
|
@@ -369,7 +384,7 @@ describe("ChatController", () => {
|
|
|
369
384
|
});
|
|
370
385
|
|
|
371
386
|
test("dispose stops verification polling and closes the live connection", () => {
|
|
372
|
-
const controller =
|
|
387
|
+
const controller = createController();
|
|
373
388
|
let closed = false;
|
|
374
389
|
|
|
375
390
|
apiClient.setSessionToken("token-123");
|
|
@@ -398,7 +413,7 @@ describe("ChatController", () => {
|
|
|
398
413
|
|
|
399
414
|
test("runs a quiet safety refresh while the live connection is active", async () => {
|
|
400
415
|
const persistence = new MemoryPersistence();
|
|
401
|
-
const controller =
|
|
416
|
+
const controller = createController();
|
|
402
417
|
const originalSetInterval = globalThis.setInterval;
|
|
403
418
|
const originalClearInterval = globalThis.clearInterval;
|
|
404
419
|
const intervalCallbacks: Array<() => void> = [];
|
|
@@ -407,10 +422,7 @@ describe("ChatController", () => {
|
|
|
407
422
|
let getMessagesCalls = 0;
|
|
408
423
|
const loadingSnapshots: boolean[] = [];
|
|
409
424
|
|
|
410
|
-
persistence
|
|
411
|
-
sessionToken: "token-123",
|
|
412
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
413
|
-
}, { schemaVersion: 1 });
|
|
425
|
+
persistSession(persistence, { emailVerified: true });
|
|
414
426
|
|
|
415
427
|
(globalThis as any).setInterval = (callback: () => void, timeout: number) => {
|
|
416
428
|
expect(timeout).toBe(30_000);
|
|
@@ -466,7 +478,7 @@ describe("ChatController", () => {
|
|
|
466
478
|
|
|
467
479
|
test("validates a persisted native session through protected chat state", async () => {
|
|
468
480
|
const persistence = new MemoryPersistence();
|
|
469
|
-
const controller =
|
|
481
|
+
const controller = createController();
|
|
470
482
|
const directChannel: ChatChannel = {
|
|
471
483
|
id: "dm:u2",
|
|
472
484
|
name: "u2",
|
|
@@ -474,10 +486,7 @@ describe("ChatController", () => {
|
|
|
474
486
|
created_at: "2026-03-28T00:00:00.000Z",
|
|
475
487
|
};
|
|
476
488
|
|
|
477
|
-
persistence
|
|
478
|
-
sessionToken: "token-123",
|
|
479
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
480
|
-
}, { schemaVersion: 1 });
|
|
489
|
+
persistSession(persistence, { emailVerified: true });
|
|
481
490
|
|
|
482
491
|
controller.attachPersistence(persistence);
|
|
483
492
|
apiClient.getSession = async () => {
|
|
@@ -513,7 +522,7 @@ describe("ChatController", () => {
|
|
|
513
522
|
|
|
514
523
|
test("clears an expired persisted session when protected chat rejects it", async () => {
|
|
515
524
|
const persistence = new MemoryPersistence();
|
|
516
|
-
const controller =
|
|
525
|
+
const controller = createController();
|
|
517
526
|
|
|
518
527
|
persistence.setState("session", {
|
|
519
528
|
sessionToken: "expired-token",
|
|
@@ -543,7 +552,7 @@ describe("ChatController", () => {
|
|
|
543
552
|
|
|
544
553
|
test("clears an expired persisted session for an unverified user", async () => {
|
|
545
554
|
const persistence = new MemoryPersistence();
|
|
546
|
-
const controller =
|
|
555
|
+
const controller = createController();
|
|
547
556
|
let profileRequests = 0;
|
|
548
557
|
|
|
549
558
|
persistence.setState("session", {
|
|
@@ -572,12 +581,9 @@ describe("ChatController", () => {
|
|
|
572
581
|
|
|
573
582
|
test("downgrades stale verification state when protected chat rejects it", async () => {
|
|
574
583
|
const persistence = new MemoryPersistence();
|
|
575
|
-
const controller =
|
|
584
|
+
const controller = createController();
|
|
576
585
|
|
|
577
|
-
persistence
|
|
578
|
-
sessionToken: "token-123",
|
|
579
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
580
|
-
}, { schemaVersion: 1 });
|
|
586
|
+
persistSession(persistence, { emailVerified: true });
|
|
581
587
|
|
|
582
588
|
controller.attachPersistence(persistence);
|
|
583
589
|
apiClient.getSession = async () => {
|
|
@@ -602,7 +608,7 @@ describe("ChatController", () => {
|
|
|
602
608
|
|
|
603
609
|
test("does not let a stale validation failure clear a replacement session", async () => {
|
|
604
610
|
const persistence = new MemoryPersistence();
|
|
605
|
-
const controller =
|
|
611
|
+
const controller = createController();
|
|
606
612
|
let rejectProbe: ((error: Error) => void) | null = null;
|
|
607
613
|
let markProbeStarted: (() => void) | null = null;
|
|
608
614
|
const probeStarted = new Promise<void>((resolve) => {
|
|
@@ -649,7 +655,7 @@ describe("ChatController", () => {
|
|
|
649
655
|
|
|
650
656
|
test("does not apply stale chat state after a replacement session", async () => {
|
|
651
657
|
const persistence = new MemoryPersistence();
|
|
652
|
-
const controller =
|
|
658
|
+
const controller = createController();
|
|
653
659
|
let resolveProbe: ((state: ChatStateResponse) => void) | null = null;
|
|
654
660
|
let markProbeStarted: (() => void) | null = null;
|
|
655
661
|
const probeStarted = new Promise<void>((resolve) => {
|
|
@@ -701,12 +707,9 @@ describe("ChatController", () => {
|
|
|
701
707
|
test("revalidates a persisted session after an offline validation probe", async () => {
|
|
702
708
|
jest.useFakeTimers();
|
|
703
709
|
const persistence = new MemoryPersistence();
|
|
704
|
-
const controller =
|
|
710
|
+
const controller = createController();
|
|
705
711
|
|
|
706
|
-
persistence
|
|
707
|
-
sessionToken: "token-123",
|
|
708
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
709
|
-
}, { schemaVersion: 1 });
|
|
712
|
+
persistSession(persistence, { emailVerified: true });
|
|
710
713
|
|
|
711
714
|
controller.attachPersistence(persistence);
|
|
712
715
|
apiClient.getSession = async () => {
|
|
@@ -739,7 +742,7 @@ describe("ChatController", () => {
|
|
|
739
742
|
|
|
740
743
|
test("signs out when get-session returns no user and no token is stored", async () => {
|
|
741
744
|
const persistence = new MemoryPersistence();
|
|
742
|
-
const controller =
|
|
745
|
+
const controller = createController();
|
|
743
746
|
|
|
744
747
|
persistence.setState("session", {
|
|
745
748
|
sessionToken: null,
|
|
@@ -758,12 +761,9 @@ describe("ChatController", () => {
|
|
|
758
761
|
|
|
759
762
|
test("keeps the cached session when session refresh fails transiently", async () => {
|
|
760
763
|
const persistence = new MemoryPersistence();
|
|
761
|
-
const controller =
|
|
764
|
+
const controller = createController();
|
|
762
765
|
|
|
763
|
-
persistence
|
|
764
|
-
sessionToken: "token-123",
|
|
765
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
766
|
-
}, { schemaVersion: 1 });
|
|
766
|
+
persistSession(persistence, { emailVerified: true });
|
|
767
767
|
|
|
768
768
|
controller.attachPersistence(persistence);
|
|
769
769
|
apiClient.getSession = async () => {
|
|
@@ -790,15 +790,12 @@ describe("ChatController", () => {
|
|
|
790
790
|
|
|
791
791
|
test("refreshes the public transcript without requiring a session", async () => {
|
|
792
792
|
const persistence = new MemoryPersistence();
|
|
793
|
-
const controller =
|
|
794
|
-
const message: ChatMessage = {
|
|
793
|
+
const controller = createController();
|
|
794
|
+
const message: ChatMessage = chatMessage({
|
|
795
795
|
id: "m1",
|
|
796
|
-
channelId: "everyone",
|
|
797
796
|
content: "hello from the lobby",
|
|
798
|
-
replyToId: null,
|
|
799
797
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
800
|
-
|
|
801
|
-
};
|
|
798
|
+
});
|
|
802
799
|
|
|
803
800
|
controller.attachPersistence(persistence);
|
|
804
801
|
apiClient.getMessages = async () => [message];
|
|
@@ -816,23 +813,19 @@ describe("ChatController", () => {
|
|
|
816
813
|
|
|
817
814
|
test("keeps per-channel drafts and transcripts isolated", () => {
|
|
818
815
|
const persistence = new MemoryPersistence();
|
|
819
|
-
const controller =
|
|
820
|
-
const everyoneMessage: ChatMessage = {
|
|
816
|
+
const controller = createController();
|
|
817
|
+
const everyoneMessage: ChatMessage = chatMessage({
|
|
821
818
|
id: "m1",
|
|
822
|
-
channelId: "everyone",
|
|
823
819
|
content: "general",
|
|
824
|
-
replyToId: null,
|
|
825
820
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
const optionsMessage: ChatMessage = {
|
|
821
|
+
});
|
|
822
|
+
const optionsMessage: ChatMessage = chatMessage({
|
|
829
823
|
id: "m2",
|
|
830
824
|
channelId: "options",
|
|
831
825
|
content: "options note",
|
|
832
|
-
replyToId: null,
|
|
833
826
|
createdAt: "2026-03-28T00:01:00.000Z",
|
|
834
827
|
user: { id: "u2", username: "bob", displayName: "Bob" },
|
|
835
|
-
};
|
|
828
|
+
});
|
|
836
829
|
|
|
837
830
|
persistence.setState("channel:everyone", {
|
|
838
831
|
draft: "general draft",
|
|
@@ -868,23 +861,18 @@ describe("ChatController", () => {
|
|
|
868
861
|
|
|
869
862
|
test("stores the latest message id as the incremental cursor", async () => {
|
|
870
863
|
const persistence = new MemoryPersistence();
|
|
871
|
-
const controller =
|
|
872
|
-
const initial: ChatMessage = {
|
|
864
|
+
const controller = createController();
|
|
865
|
+
const initial: ChatMessage = chatMessage({
|
|
873
866
|
id: "m1",
|
|
874
|
-
channelId: "everyone",
|
|
875
867
|
content: "hello",
|
|
876
|
-
replyToId: null,
|
|
877
868
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
const next: ChatMessage = {
|
|
869
|
+
});
|
|
870
|
+
const next: ChatMessage = chatMessage({
|
|
881
871
|
id: "m2",
|
|
882
|
-
channelId: "everyone",
|
|
883
872
|
content: "new message",
|
|
884
|
-
replyToId: null,
|
|
885
873
|
createdAt: "2026-03-28T00:01:00.000Z",
|
|
886
874
|
user: { id: "u2", username: "bob", displayName: "Bob" },
|
|
887
|
-
};
|
|
875
|
+
});
|
|
888
876
|
|
|
889
877
|
persistence.setState("channel:everyone", {
|
|
890
878
|
draft: "",
|
|
@@ -924,31 +912,24 @@ describe("ChatController", () => {
|
|
|
924
912
|
|
|
925
913
|
test("recovers a message the cursor already moved past", async () => {
|
|
926
914
|
const persistence = new MemoryPersistence();
|
|
927
|
-
const controller =
|
|
928
|
-
const asked: ChatMessage = {
|
|
915
|
+
const controller = createController();
|
|
916
|
+
const asked: ChatMessage = chatMessage({
|
|
929
917
|
id: "m1",
|
|
930
|
-
channelId: "everyone",
|
|
931
918
|
content: "why is the chart glitching",
|
|
932
|
-
replyToId: null,
|
|
933
919
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
const missed: ChatMessage = {
|
|
920
|
+
});
|
|
921
|
+
const missed: ChatMessage = chatMessage({
|
|
937
922
|
id: "m2",
|
|
938
|
-
channelId: "everyone",
|
|
939
923
|
content: "charts open with GP",
|
|
940
924
|
replyToId: "m1",
|
|
941
925
|
createdAt: "2026-03-28T00:01:00.000Z",
|
|
942
926
|
user: { id: "u2", username: "gloombot", displayName: "Gloombot" },
|
|
943
|
-
};
|
|
944
|
-
const acknowledged: ChatMessage = {
|
|
927
|
+
});
|
|
928
|
+
const acknowledged: ChatMessage = chatMessage({
|
|
945
929
|
id: "m3",
|
|
946
|
-
channelId: "everyone",
|
|
947
930
|
content: "got it",
|
|
948
|
-
replyToId: null,
|
|
949
931
|
createdAt: "2026-03-28T00:02:00.000Z",
|
|
950
|
-
|
|
951
|
-
};
|
|
932
|
+
});
|
|
952
933
|
|
|
953
934
|
// The cursor already sits on m3, so an incremental fetch can never ask for
|
|
954
935
|
// m2 again even though the server still has it.
|
|
@@ -979,21 +960,16 @@ describe("ChatController", () => {
|
|
|
979
960
|
|
|
980
961
|
test("hydrates missing transcript cache without marking history unread", async () => {
|
|
981
962
|
const persistence = new MemoryPersistence();
|
|
982
|
-
const controller =
|
|
963
|
+
const controller = createController();
|
|
983
964
|
const notifications: AppNotificationRequest[] = [];
|
|
984
|
-
const history: ChatMessage = {
|
|
965
|
+
const history: ChatMessage = chatMessage({
|
|
985
966
|
id: "m1",
|
|
986
|
-
channelId: "everyone",
|
|
987
967
|
content: "already seen",
|
|
988
|
-
replyToId: null,
|
|
989
968
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
990
969
|
user: { id: "u2", username: "bob", displayName: "Bob" },
|
|
991
|
-
};
|
|
970
|
+
});
|
|
992
971
|
|
|
993
|
-
persistence
|
|
994
|
-
sessionToken: "token-123",
|
|
995
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
996
|
-
}, { schemaVersion: 1 });
|
|
972
|
+
persistSession(persistence, { emailVerified: true });
|
|
997
973
|
persistence.setState("channel:everyone", {
|
|
998
974
|
draft: "",
|
|
999
975
|
replyToId: null,
|
|
@@ -1027,23 +1003,18 @@ describe("ChatController", () => {
|
|
|
1027
1003
|
|
|
1028
1004
|
test("backfills from cached transcript when persisted cursor is ahead of the cache", async () => {
|
|
1029
1005
|
const persistence = new MemoryPersistence();
|
|
1030
|
-
const controller =
|
|
1031
|
-
const cached: ChatMessage = {
|
|
1006
|
+
const controller = createController();
|
|
1007
|
+
const cached: ChatMessage = chatMessage({
|
|
1032
1008
|
id: "m1",
|
|
1033
|
-
channelId: "everyone",
|
|
1034
1009
|
content: "cached",
|
|
1035
|
-
replyToId: null,
|
|
1036
1010
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
const fresh: ChatMessage = {
|
|
1011
|
+
});
|
|
1012
|
+
const fresh: ChatMessage = chatMessage({
|
|
1040
1013
|
id: "m2",
|
|
1041
|
-
channelId: "everyone",
|
|
1042
1014
|
content: "fresh",
|
|
1043
|
-
replyToId: null,
|
|
1044
1015
|
createdAt: "2026-03-28T00:01:00.000Z",
|
|
1045
1016
|
user: { id: "u2", username: "bob", displayName: "Bob" },
|
|
1046
|
-
};
|
|
1017
|
+
});
|
|
1047
1018
|
|
|
1048
1019
|
persistence.setState("channel:everyone", {
|
|
1049
1020
|
draft: "",
|
|
@@ -1083,29 +1054,22 @@ describe("ChatController", () => {
|
|
|
1083
1054
|
|
|
1084
1055
|
test("shows a pending message immediately and replaces it when the send succeeds", async () => {
|
|
1085
1056
|
const persistence = new MemoryPersistence();
|
|
1086
|
-
const controller =
|
|
1087
|
-
const replyTarget: ChatMessage = {
|
|
1057
|
+
const controller = createController();
|
|
1058
|
+
const replyTarget: ChatMessage = chatMessage({
|
|
1088
1059
|
id: "m1",
|
|
1089
|
-
channelId: "everyone",
|
|
1090
1060
|
content: "first",
|
|
1091
|
-
replyToId: null,
|
|
1092
1061
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
1093
1062
|
user: { id: "u2", username: "bob", displayName: "Bob" },
|
|
1094
|
-
};
|
|
1095
|
-
const sentMessage: ChatMessage = {
|
|
1063
|
+
});
|
|
1064
|
+
const sentMessage: ChatMessage = chatMessage({
|
|
1096
1065
|
id: "m2",
|
|
1097
|
-
channelId: "everyone",
|
|
1098
1066
|
content: "hello",
|
|
1099
1067
|
replyToId: "m1",
|
|
1100
1068
|
createdAt: "2026-03-28T00:01:00.000Z",
|
|
1101
|
-
user: { id: "u1", username: "vince", displayName: "Vince" },
|
|
1102
1069
|
replyTo: { content: "first", user: { username: "bob" } },
|
|
1103
|
-
};
|
|
1070
|
+
});
|
|
1104
1071
|
|
|
1105
|
-
persistence
|
|
1106
|
-
sessionToken: "token-123",
|
|
1107
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1108
|
-
}, { schemaVersion: 1 });
|
|
1072
|
+
persistSession(persistence, { emailVerified: true });
|
|
1109
1073
|
persistence.setState("channel:everyone", {
|
|
1110
1074
|
draft: "hello",
|
|
1111
1075
|
replyToId: "m1",
|
|
@@ -1154,13 +1118,10 @@ describe("ChatController", () => {
|
|
|
1154
1118
|
|
|
1155
1119
|
test("sends one idempotency key while the same message is pending", () => {
|
|
1156
1120
|
const persistence = new MemoryPersistence();
|
|
1157
|
-
const controller =
|
|
1121
|
+
const controller = createController();
|
|
1158
1122
|
const clientMessageIds: Array<string | undefined> = [];
|
|
1159
1123
|
|
|
1160
|
-
persistence
|
|
1161
|
-
sessionToken: "token-123",
|
|
1162
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1163
|
-
}, { schemaVersion: 1 });
|
|
1124
|
+
persistSession(persistence, { emailVerified: true });
|
|
1164
1125
|
|
|
1165
1126
|
controller.attachPersistence(persistence);
|
|
1166
1127
|
apiClient.getMessages = async () => [];
|
|
@@ -1188,20 +1149,14 @@ describe("ChatController", () => {
|
|
|
1188
1149
|
|
|
1189
1150
|
test("edits the latest message from the current user", async () => {
|
|
1190
1151
|
const persistence = new MemoryPersistence();
|
|
1191
|
-
const controller =
|
|
1192
|
-
const original: ChatMessage = {
|
|
1152
|
+
const controller = createController();
|
|
1153
|
+
const original: ChatMessage = chatMessage({
|
|
1193
1154
|
id: "m1",
|
|
1194
|
-
channelId: "everyone",
|
|
1195
1155
|
content: "helo",
|
|
1196
|
-
replyToId: null,
|
|
1197
1156
|
createdAt: recentChatTimestamp(),
|
|
1198
|
-
|
|
1199
|
-
};
|
|
1157
|
+
});
|
|
1200
1158
|
|
|
1201
|
-
persistence
|
|
1202
|
-
sessionToken: "token-123",
|
|
1203
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1204
|
-
}, { schemaVersion: 1 });
|
|
1159
|
+
persistSession(persistence, { emailVerified: true });
|
|
1205
1160
|
persistence.setResource(TRANSCRIPT_KIND, TRANSCRIPT_KEY, {
|
|
1206
1161
|
messages: [original],
|
|
1207
1162
|
}, {
|
|
@@ -1230,21 +1185,15 @@ describe("ChatController", () => {
|
|
|
1230
1185
|
|
|
1231
1186
|
test("refuses to edit after the edit window expires", async () => {
|
|
1232
1187
|
const persistence = new MemoryPersistence();
|
|
1233
|
-
const controller =
|
|
1188
|
+
const controller = createController();
|
|
1234
1189
|
const notifications: AppNotificationRequest[] = [];
|
|
1235
|
-
const original: ChatMessage = {
|
|
1190
|
+
const original: ChatMessage = chatMessage({
|
|
1236
1191
|
id: "m1",
|
|
1237
|
-
channelId: "everyone",
|
|
1238
1192
|
content: "old typo",
|
|
1239
|
-
replyToId: null,
|
|
1240
1193
|
createdAt: recentChatTimestamp(16 * 60_000),
|
|
1241
|
-
|
|
1242
|
-
};
|
|
1194
|
+
});
|
|
1243
1195
|
|
|
1244
|
-
persistence
|
|
1245
|
-
sessionToken: "token-123",
|
|
1246
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1247
|
-
}, { schemaVersion: 1 });
|
|
1196
|
+
persistSession(persistence, { emailVerified: true });
|
|
1248
1197
|
persistence.setResource(TRANSCRIPT_KIND, TRANSCRIPT_KEY, {
|
|
1249
1198
|
messages: [original],
|
|
1250
1199
|
}, {
|
|
@@ -1266,31 +1215,22 @@ describe("ChatController", () => {
|
|
|
1266
1215
|
|
|
1267
1216
|
test("refuses to edit an older message from the current user", async () => {
|
|
1268
1217
|
const persistence = new MemoryPersistence();
|
|
1269
|
-
const controller =
|
|
1218
|
+
const controller = createController();
|
|
1270
1219
|
const notifications: AppNotificationRequest[] = [];
|
|
1271
1220
|
const messages: ChatMessage[] = [
|
|
1272
|
-
{
|
|
1221
|
+
chatMessage({
|
|
1273
1222
|
id: "m1",
|
|
1274
|
-
channelId: "everyone",
|
|
1275
1223
|
content: "older",
|
|
1276
|
-
replyToId: null,
|
|
1277
1224
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
{
|
|
1225
|
+
}),
|
|
1226
|
+
chatMessage({
|
|
1281
1227
|
id: "m2",
|
|
1282
|
-
channelId: "everyone",
|
|
1283
1228
|
content: "newer",
|
|
1284
|
-
replyToId: null,
|
|
1285
1229
|
createdAt: "2026-03-28T00:01:00.000Z",
|
|
1286
|
-
|
|
1287
|
-
},
|
|
1230
|
+
}),
|
|
1288
1231
|
];
|
|
1289
1232
|
|
|
1290
|
-
persistence
|
|
1291
|
-
sessionToken: "token-123",
|
|
1292
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1293
|
-
}, { schemaVersion: 1 });
|
|
1233
|
+
persistSession(persistence, { emailVerified: true });
|
|
1294
1234
|
persistence.setResource(TRANSCRIPT_KIND, TRANSCRIPT_KEY, {
|
|
1295
1235
|
messages,
|
|
1296
1236
|
}, {
|
|
@@ -1312,13 +1252,10 @@ describe("ChatController", () => {
|
|
|
1312
1252
|
|
|
1313
1253
|
test("marks a pending message as failed when sending errors", async () => {
|
|
1314
1254
|
const persistence = new MemoryPersistence();
|
|
1315
|
-
const controller =
|
|
1255
|
+
const controller = createController();
|
|
1316
1256
|
const notifications: AppNotificationRequest[] = [];
|
|
1317
1257
|
|
|
1318
|
-
persistence
|
|
1319
|
-
sessionToken: "token-123",
|
|
1320
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1321
|
-
}, { schemaVersion: 1 });
|
|
1258
|
+
persistSession(persistence, { emailVerified: true });
|
|
1322
1259
|
|
|
1323
1260
|
controller.setNotifier((notification) => {
|
|
1324
1261
|
notifications.push(notification);
|
|
@@ -1347,21 +1284,16 @@ describe("ChatController", () => {
|
|
|
1347
1284
|
|
|
1348
1285
|
test("tracks unread mentions from fetched messages without issuing local notifications", () => {
|
|
1349
1286
|
const persistence = new MemoryPersistence();
|
|
1350
|
-
const controller =
|
|
1287
|
+
const controller = createController();
|
|
1351
1288
|
const notifications: AppNotificationRequest[] = [];
|
|
1352
|
-
const message: ChatMessage = {
|
|
1289
|
+
const message: ChatMessage = chatMessage({
|
|
1353
1290
|
id: "m1",
|
|
1354
|
-
channelId: "everyone",
|
|
1355
1291
|
content: "hey @Vince can you take a look?",
|
|
1356
|
-
replyToId: null,
|
|
1357
1292
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
1358
1293
|
user: { id: "u2", username: "bob", displayName: "Bob" },
|
|
1359
|
-
};
|
|
1294
|
+
});
|
|
1360
1295
|
|
|
1361
|
-
persistence
|
|
1362
|
-
sessionToken: "token-123",
|
|
1363
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1364
|
-
}, { schemaVersion: 1 });
|
|
1296
|
+
persistSession(persistence, { emailVerified: true });
|
|
1365
1297
|
|
|
1366
1298
|
controller.setNotifier((notification) => {
|
|
1367
1299
|
notifications.push(notification);
|
|
@@ -1380,14 +1312,11 @@ describe("ChatController", () => {
|
|
|
1380
1312
|
|
|
1381
1313
|
test("delivers background notifications while the focused chat stays unread", async () => {
|
|
1382
1314
|
const persistence = new MemoryPersistence();
|
|
1383
|
-
const controller =
|
|
1315
|
+
const controller = createController();
|
|
1384
1316
|
const notifications: AppNotificationRequest[] = [];
|
|
1385
1317
|
const deliveredIds: string[][] = [];
|
|
1386
1318
|
|
|
1387
|
-
persistence
|
|
1388
|
-
sessionToken: "token-123",
|
|
1389
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1390
|
-
}, { schemaVersion: 1 });
|
|
1319
|
+
persistSession(persistence, { emailVerified: true });
|
|
1391
1320
|
|
|
1392
1321
|
controller.setNotifier((notification) => {
|
|
1393
1322
|
notifications.push(notification);
|
|
@@ -1421,15 +1350,12 @@ describe("ChatController", () => {
|
|
|
1421
1350
|
|
|
1422
1351
|
test("keeps undeliverable background notifications pending for email fallback", () => {
|
|
1423
1352
|
const persistence = new MemoryPersistence();
|
|
1424
|
-
const controller =
|
|
1353
|
+
const controller = createController();
|
|
1425
1354
|
const deliveredIds: string[][] = [];
|
|
1426
1355
|
let desktopAvailable = false;
|
|
1427
1356
|
let presentationCount = 0;
|
|
1428
1357
|
|
|
1429
|
-
persistence
|
|
1430
|
-
sessionToken: "token-123",
|
|
1431
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1432
|
-
}, { schemaVersion: 1 });
|
|
1358
|
+
persistSession(persistence, { emailVerified: true });
|
|
1433
1359
|
controller.setNotifier(() => {
|
|
1434
1360
|
presentationCount += 1;
|
|
1435
1361
|
return { toastVisible: false, desktopRequested: desktopAvailable };
|
|
@@ -1456,21 +1382,16 @@ describe("ChatController", () => {
|
|
|
1456
1382
|
|
|
1457
1383
|
test("marks mentions viewed when a chat view opens", () => {
|
|
1458
1384
|
const persistence = new MemoryPersistence();
|
|
1459
|
-
const controller =
|
|
1385
|
+
const controller = createController();
|
|
1460
1386
|
const notifications: AppNotificationRequest[] = [];
|
|
1461
|
-
const message: ChatMessage = {
|
|
1387
|
+
const message: ChatMessage = chatMessage({
|
|
1462
1388
|
id: "m1",
|
|
1463
|
-
channelId: "everyone",
|
|
1464
1389
|
content: "hey @vince",
|
|
1465
|
-
replyToId: null,
|
|
1466
1390
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
1467
1391
|
user: { id: "u2", username: "bob", displayName: "Bob" },
|
|
1468
|
-
};
|
|
1392
|
+
});
|
|
1469
1393
|
|
|
1470
|
-
persistence
|
|
1471
|
-
sessionToken: "token-123",
|
|
1472
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1473
|
-
}, { schemaVersion: 1 });
|
|
1394
|
+
persistSession(persistence, { emailVerified: true });
|
|
1474
1395
|
|
|
1475
1396
|
controller.setNotifier((notification) => {
|
|
1476
1397
|
notifications.push(notification);
|
|
@@ -1493,14 +1414,11 @@ describe("ChatController", () => {
|
|
|
1493
1414
|
|
|
1494
1415
|
test("keeps focused foreground notifications read without presenting an alert", () => {
|
|
1495
1416
|
const persistence = new MemoryPersistence();
|
|
1496
|
-
const controller =
|
|
1417
|
+
const controller = createController();
|
|
1497
1418
|
const notifications: AppNotificationRequest[] = [];
|
|
1498
1419
|
const deliveredIds: string[][] = [];
|
|
1499
1420
|
|
|
1500
|
-
persistence
|
|
1501
|
-
sessionToken: "token-123",
|
|
1502
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1503
|
-
}, { schemaVersion: 1 });
|
|
1421
|
+
persistSession(persistence, { emailVerified: true });
|
|
1504
1422
|
|
|
1505
1423
|
controller.setNotifier((notification) => {
|
|
1506
1424
|
notifications.push(notification);
|
|
@@ -1526,14 +1444,11 @@ describe("ChatController", () => {
|
|
|
1526
1444
|
|
|
1527
1445
|
test("keeps an unfocused foreground chat unread while presenting an in-app alert", () => {
|
|
1528
1446
|
const persistence = new MemoryPersistence();
|
|
1529
|
-
const controller =
|
|
1447
|
+
const controller = createController();
|
|
1530
1448
|
const notifications: AppNotificationRequest[] = [];
|
|
1531
1449
|
const deliveredIds: string[][] = [];
|
|
1532
1450
|
|
|
1533
|
-
persistence
|
|
1534
|
-
sessionToken: "token-123",
|
|
1535
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1536
|
-
}, { schemaVersion: 1 });
|
|
1451
|
+
persistSession(persistence, { emailVerified: true });
|
|
1537
1452
|
controller.setNotifier((notification) => {
|
|
1538
1453
|
notifications.push(notification);
|
|
1539
1454
|
return { toastVisible: true, desktopRequested: false };
|
|
@@ -1559,14 +1474,11 @@ describe("ChatController", () => {
|
|
|
1559
1474
|
|
|
1560
1475
|
test("loads server chat state, pending reply notifications, and acks delivery", async () => {
|
|
1561
1476
|
const persistence = new MemoryPersistence();
|
|
1562
|
-
const controller =
|
|
1477
|
+
const controller = createController();
|
|
1563
1478
|
const notifications: AppNotificationRequest[] = [];
|
|
1564
1479
|
const deliveredIds: string[][] = [];
|
|
1565
1480
|
|
|
1566
|
-
persistence
|
|
1567
|
-
sessionToken: "token-123",
|
|
1568
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1569
|
-
}, { schemaVersion: 1 });
|
|
1481
|
+
persistSession(persistence, { emailVerified: true });
|
|
1570
1482
|
apiClient.getSession = async () => ({
|
|
1571
1483
|
id: "u1",
|
|
1572
1484
|
name: "Vince",
|
|
@@ -1592,7 +1504,7 @@ describe("ChatController", () => {
|
|
|
1592
1504
|
channelId: "options",
|
|
1593
1505
|
messageId: "m2",
|
|
1594
1506
|
createdAt: "2026-03-28T00:02:00.000Z",
|
|
1595
|
-
message: {
|
|
1507
|
+
message: chatMessage({
|
|
1596
1508
|
id: "m2",
|
|
1597
1509
|
channelId: "options",
|
|
1598
1510
|
content: "answering you",
|
|
@@ -1600,7 +1512,7 @@ describe("ChatController", () => {
|
|
|
1600
1512
|
createdAt: "2026-03-28T00:02:00.000Z",
|
|
1601
1513
|
user: { id: "u2", username: "bob", displayName: "Bob" },
|
|
1602
1514
|
replyTo: { content: "question", user: { id: "u1", username: "vince" } },
|
|
1603
|
-
},
|
|
1515
|
+
}),
|
|
1604
1516
|
}],
|
|
1605
1517
|
});
|
|
1606
1518
|
apiClient.markChatNotificationsDelivered = async (ids) => {
|
|
@@ -1638,13 +1550,10 @@ describe("ChatController", () => {
|
|
|
1638
1550
|
|
|
1639
1551
|
test("toggles channel notifications optimistically and keeps the channel connected", async () => {
|
|
1640
1552
|
const persistence = new MemoryPersistence();
|
|
1641
|
-
const controller =
|
|
1553
|
+
const controller = createController();
|
|
1642
1554
|
const connectedChannels: string[] = [];
|
|
1643
1555
|
|
|
1644
|
-
persistence
|
|
1645
|
-
sessionToken: "token-123",
|
|
1646
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1647
|
-
}, { schemaVersion: 1 });
|
|
1556
|
+
persistSession(persistence, { emailVerified: true });
|
|
1648
1557
|
apiClient.updateChatChannelState = async (channelId, body) => ({
|
|
1649
1558
|
channelId,
|
|
1650
1559
|
notificationsEnabled: body.notificationsEnabled === true,
|
|
@@ -1673,7 +1582,7 @@ describe("ChatController", () => {
|
|
|
1673
1582
|
|
|
1674
1583
|
test("dedupes reply notifications by message id", () => {
|
|
1675
1584
|
const persistence = new MemoryPersistence();
|
|
1676
|
-
const controller =
|
|
1585
|
+
const controller = createController();
|
|
1677
1586
|
const notifications: AppNotificationRequest[] = [];
|
|
1678
1587
|
const notification: ChatNotification = {
|
|
1679
1588
|
id: "n1",
|
|
@@ -1681,21 +1590,17 @@ describe("ChatController", () => {
|
|
|
1681
1590
|
channelId: "everyone",
|
|
1682
1591
|
messageId: "m2",
|
|
1683
1592
|
createdAt: "2026-03-28T00:02:00.000Z",
|
|
1684
|
-
message: {
|
|
1593
|
+
message: chatMessage({
|
|
1685
1594
|
id: "m2",
|
|
1686
|
-
channelId: "everyone",
|
|
1687
1595
|
content: "same reply",
|
|
1688
1596
|
replyToId: "m1",
|
|
1689
1597
|
createdAt: "2026-03-28T00:02:00.000Z",
|
|
1690
1598
|
user: { id: "u2", username: "bob", displayName: "Bob" },
|
|
1691
1599
|
replyTo: { content: "question", user: { id: "u1", username: "vince" } },
|
|
1692
|
-
},
|
|
1600
|
+
}),
|
|
1693
1601
|
};
|
|
1694
1602
|
|
|
1695
|
-
persistence
|
|
1696
|
-
sessionToken: "token-123",
|
|
1697
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1698
|
-
}, { schemaVersion: 1 });
|
|
1603
|
+
persistSession(persistence, { emailVerified: true });
|
|
1699
1604
|
controller.setNotifier((entry) => {
|
|
1700
1605
|
notifications.push(entry);
|
|
1701
1606
|
return { toastVisible: true, desktopRequested: false };
|
|
@@ -1710,22 +1615,18 @@ describe("ChatController", () => {
|
|
|
1710
1615
|
|
|
1711
1616
|
test("opens a server-issued channel notification at its exact message", () => {
|
|
1712
1617
|
const persistence = new MemoryPersistence();
|
|
1713
|
-
const controller =
|
|
1618
|
+
const controller = createController();
|
|
1714
1619
|
const notifications: AppNotificationRequest[] = [];
|
|
1715
1620
|
const openedMessages: string[] = [];
|
|
1716
|
-
const message: ChatMessage = {
|
|
1621
|
+
const message: ChatMessage = chatMessage({
|
|
1717
1622
|
id: "m1",
|
|
1718
1623
|
channelId: "options",
|
|
1719
1624
|
content: "new option flow",
|
|
1720
|
-
replyToId: null,
|
|
1721
1625
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
1722
1626
|
user: { id: "u2", username: "bob", displayName: "Bob" },
|
|
1723
|
-
};
|
|
1627
|
+
});
|
|
1724
1628
|
|
|
1725
|
-
persistence
|
|
1726
|
-
sessionToken: "token-123",
|
|
1727
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1728
|
-
}, { schemaVersion: 1 });
|
|
1629
|
+
persistSession(persistence, { emailVerified: true });
|
|
1729
1630
|
controller.setNotifier((entry) => {
|
|
1730
1631
|
notifications.push(entry);
|
|
1731
1632
|
}, (channelId, messageId) => {
|
|
@@ -1755,7 +1656,7 @@ describe("ChatController", () => {
|
|
|
1755
1656
|
|
|
1756
1657
|
test("uses direct channel labels in server-issued notification titles", async () => {
|
|
1757
1658
|
const persistence = new MemoryPersistence();
|
|
1758
|
-
const controller =
|
|
1659
|
+
const controller = createController();
|
|
1759
1660
|
const notifications: AppNotificationRequest[] = [];
|
|
1760
1661
|
const directChannel: ChatChannel = {
|
|
1761
1662
|
id: "dm:u2",
|
|
@@ -1764,14 +1665,13 @@ describe("ChatController", () => {
|
|
|
1764
1665
|
created_at: "2026-03-28T00:00:00.000Z",
|
|
1765
1666
|
dmUser: { id: "u2", username: "bob", displayName: "Bob" },
|
|
1766
1667
|
};
|
|
1767
|
-
const message: ChatMessage = {
|
|
1668
|
+
const message: ChatMessage = chatMessage({
|
|
1768
1669
|
id: "m1",
|
|
1769
1670
|
channelId: directChannel.id,
|
|
1770
1671
|
content: "ping",
|
|
1771
|
-
replyToId: null,
|
|
1772
1672
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
1773
1673
|
user: { id: "u2", username: "bob", displayName: "Bob" },
|
|
1774
|
-
};
|
|
1674
|
+
});
|
|
1775
1675
|
|
|
1776
1676
|
apiClient.getChatState = async () => ({
|
|
1777
1677
|
channels: [...SERVER_CHAT_CHANNELS, directChannel],
|
|
@@ -1784,10 +1684,7 @@ describe("ChatController", () => {
|
|
|
1784
1684
|
})),
|
|
1785
1685
|
notifications: [],
|
|
1786
1686
|
});
|
|
1787
|
-
persistence
|
|
1788
|
-
sessionToken: "token-123",
|
|
1789
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1790
|
-
}, { schemaVersion: 1 });
|
|
1687
|
+
persistSession(persistence, { emailVerified: true });
|
|
1791
1688
|
controller.setNotifier((entry) => {
|
|
1792
1689
|
notifications.push(entry);
|
|
1793
1690
|
});
|
|
@@ -1813,20 +1710,16 @@ describe("ChatController", () => {
|
|
|
1813
1710
|
|
|
1814
1711
|
test("tracks unread channel messages and clears them when the channel opens", () => {
|
|
1815
1712
|
const persistence = new MemoryPersistence();
|
|
1816
|
-
const controller =
|
|
1817
|
-
const message: ChatMessage = {
|
|
1713
|
+
const controller = createController();
|
|
1714
|
+
const message: ChatMessage = chatMessage({
|
|
1818
1715
|
id: "m1",
|
|
1819
1716
|
channelId: "options",
|
|
1820
1717
|
content: "new option flow",
|
|
1821
|
-
replyToId: null,
|
|
1822
1718
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
1823
1719
|
user: { id: "u2", username: "bob", displayName: "Bob" },
|
|
1824
|
-
};
|
|
1720
|
+
});
|
|
1825
1721
|
|
|
1826
|
-
persistence
|
|
1827
|
-
sessionToken: "token-123",
|
|
1828
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1829
|
-
}, { schemaVersion: 1 });
|
|
1722
|
+
persistSession(persistence, { emailVerified: true });
|
|
1830
1723
|
controller.attachPersistence(persistence);
|
|
1831
1724
|
|
|
1832
1725
|
(controller as any).mergeMessages("options", [message]);
|
|
@@ -1845,9 +1738,9 @@ describe("ChatController", () => {
|
|
|
1845
1738
|
|
|
1846
1739
|
test("server reply notifications fire even when channel notifications are disabled", () => {
|
|
1847
1740
|
const persistence = new MemoryPersistence();
|
|
1848
|
-
const controller =
|
|
1741
|
+
const controller = createController();
|
|
1849
1742
|
const notifications: AppNotificationRequest[] = [];
|
|
1850
|
-
const message: ChatMessage = {
|
|
1743
|
+
const message: ChatMessage = chatMessage({
|
|
1851
1744
|
id: "m2",
|
|
1852
1745
|
channelId: "options",
|
|
1853
1746
|
content: "reply without channel notify",
|
|
@@ -1855,12 +1748,9 @@ describe("ChatController", () => {
|
|
|
1855
1748
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
1856
1749
|
user: { id: "u2", username: "bob", displayName: "Bob" },
|
|
1857
1750
|
replyTo: { content: "question", user: { id: "u1", username: "vince" } },
|
|
1858
|
-
};
|
|
1751
|
+
});
|
|
1859
1752
|
|
|
1860
|
-
persistence
|
|
1861
|
-
sessionToken: "token-123",
|
|
1862
|
-
user: { id: "u1", username: "vince", emailVerified: true },
|
|
1863
|
-
}, { schemaVersion: 1 });
|
|
1753
|
+
persistSession(persistence, { emailVerified: true });
|
|
1864
1754
|
controller.setNotifier((notification) => {
|
|
1865
1755
|
notifications.push(notification);
|
|
1866
1756
|
});
|
|
@@ -1885,25 +1775,20 @@ describe("ChatController", () => {
|
|
|
1885
1775
|
|
|
1886
1776
|
test("recovers from a legacy timestamp cursor by falling back to a full transcript fetch", async () => {
|
|
1887
1777
|
const persistence = new MemoryPersistence();
|
|
1888
|
-
const controller =
|
|
1889
|
-
const cached: ChatMessage = {
|
|
1778
|
+
const controller = createController();
|
|
1779
|
+
const cached: ChatMessage = chatMessage({
|
|
1890
1780
|
id: "m1",
|
|
1891
|
-
channelId: "everyone",
|
|
1892
1781
|
content: "cached",
|
|
1893
|
-
replyToId: null,
|
|
1894
1782
|
createdAt: "2026-03-28T00:00:00.000Z",
|
|
1895
|
-
|
|
1896
|
-
};
|
|
1783
|
+
});
|
|
1897
1784
|
const fullTranscript: ChatMessage[] = [
|
|
1898
1785
|
cached,
|
|
1899
|
-
{
|
|
1786
|
+
chatMessage({
|
|
1900
1787
|
id: "m2",
|
|
1901
|
-
channelId: "everyone",
|
|
1902
1788
|
content: "fresh",
|
|
1903
|
-
replyToId: null,
|
|
1904
1789
|
createdAt: "2026-03-28T00:01:00.000Z",
|
|
1905
1790
|
user: { id: "u2", username: "bob", displayName: "Bob" },
|
|
1906
|
-
},
|
|
1791
|
+
}),
|
|
1907
1792
|
];
|
|
1908
1793
|
|
|
1909
1794
|
persistence.setState("channel:everyone", {
|
|
@@ -1942,42 +1827,34 @@ describe("ChatController", () => {
|
|
|
1942
1827
|
|
|
1943
1828
|
test("loads older messages before the oldest cached message without moving the latest cursor", async () => {
|
|
1944
1829
|
const persistence = new MemoryPersistence();
|
|
1945
|
-
const controller =
|
|
1830
|
+
const controller = createController();
|
|
1946
1831
|
const cached: ChatMessage[] = [
|
|
1947
|
-
{
|
|
1832
|
+
chatMessage({
|
|
1948
1833
|
id: "m3",
|
|
1949
|
-
channelId: "everyone",
|
|
1950
1834
|
content: "cached older",
|
|
1951
|
-
replyToId: null,
|
|
1952
1835
|
createdAt: "2026-03-28T00:03:00.000Z",
|
|
1953
1836
|
user: { id: "u3", username: "cara", displayName: "Cara" },
|
|
1954
|
-
},
|
|
1955
|
-
{
|
|
1837
|
+
}),
|
|
1838
|
+
chatMessage({
|
|
1956
1839
|
id: "m4",
|
|
1957
|
-
channelId: "everyone",
|
|
1958
1840
|
content: "cached newer",
|
|
1959
|
-
replyToId: null,
|
|
1960
1841
|
createdAt: "2026-03-28T00:04:00.000Z",
|
|
1961
1842
|
user: { id: "u4", username: "drew", displayName: "Drew" },
|
|
1962
|
-
},
|
|
1843
|
+
}),
|
|
1963
1844
|
];
|
|
1964
1845
|
const older: ChatMessage[] = [
|
|
1965
|
-
{
|
|
1846
|
+
chatMessage({
|
|
1966
1847
|
id: "m1",
|
|
1967
|
-
channelId: "everyone",
|
|
1968
1848
|
content: "oldest",
|
|
1969
|
-
replyToId: null,
|
|
1970
1849
|
createdAt: "2026-03-28T00:01:00.000Z",
|
|
1971
1850
|
user: { id: "u1", username: "alice", displayName: "Alice" },
|
|
1972
|
-
},
|
|
1973
|
-
{
|
|
1851
|
+
}),
|
|
1852
|
+
chatMessage({
|
|
1974
1853
|
id: "m2",
|
|
1975
|
-
channelId: "everyone",
|
|
1976
1854
|
content: "older",
|
|
1977
|
-
replyToId: null,
|
|
1978
1855
|
createdAt: "2026-03-28T00:02:00.000Z",
|
|
1979
1856
|
user: { id: "u2", username: "bob", displayName: "Bob" },
|
|
1980
|
-
},
|
|
1857
|
+
}),
|
|
1981
1858
|
];
|
|
1982
1859
|
|
|
1983
1860
|
persistence.setState("channel:everyone", {
|