gloomberb 0.16.4 → 0.16.5
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 +14 -91
- package/package.json +4 -1
- package/src/{plugins/builtin/cloud → account}/auth-form.tsx +9 -9
- package/src/{plugins/builtin/cloud → account}/auth-model.ts +4 -4
- package/src/account/billing.ts +57 -0
- package/src/{plugins/builtin/cloud → account}/device-signin-dialog.tsx +18 -12
- package/src/{plugins/builtin/cloud → account}/device-signin.ts +2 -2
- package/src/{plugins/builtin/cloud → account}/email-auth-attempt.ts +2 -2
- package/src/account/session.ts +16 -0
- package/src/{plugins/builtin/cloud → account}/upgrade-dialog.tsx +16 -15
- package/src/{plugins/builtin/cloud → account}/upgrade-personalization.ts +7 -7
- package/src/{plugins/builtin/cloud → account}/upgrade-tickers.ts +6 -6
- package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
- package/src/api-client/data.ts +24 -2
- package/src/api-client/earnings.ts +6 -0
- package/src/api-client/futures-curve.ts +56 -0
- package/src/api-client/index.ts +4 -1
- package/src/api-client/market-discovery.ts +10 -1
- package/src/api-client/paths.ts +7 -0
- package/src/api-client/research-activity.ts +15 -10
- package/src/api-client/types.ts +17 -1
- package/src/api-client/yield-curves.ts +8 -0
- package/src/app/global-shortcuts.ts +15 -1
- package/src/app/pane-runtime/ticker-open-runtime.ts +7 -3
- package/src/architecture/core-builtin-allowlist.json +4 -13
- package/src/brokers/signed-in/sign-in-dialog.tsx +11 -5
- package/src/capabilities/chart-series.ts +11 -1
- package/src/cli/commands/crypto-hints.ts +7 -0
- package/src/cli/commands/fred-series.ts +61 -0
- package/src/cli/commands/market.ts +407 -104
- package/src/cli/commands/news-hints.ts +62 -0
- package/src/cli/commands/news-search.ts +53 -0
- package/src/cli/commands/options-leaps.ts +5 -2
- package/src/cli/commands/overview.ts +93 -20
- package/src/cli/commands/remote.ts +2 -1
- package/src/cli/commands/search.ts +82 -9
- package/src/cli/commands/system.ts +55 -8
- package/src/cli/commands/ticker.ts +88 -11
- package/src/cli/context.ts +45 -14
- package/src/cli/desktop-pane-shot.ts +59 -7
- package/src/cli/earnings-calendar.ts +71 -0
- package/src/cli/freshness.ts +18 -7
- package/src/cli/glossary.ts +429 -0
- package/src/cli/history-rows.ts +48 -7
- package/src/cli/index-roots.ts +7 -0
- package/src/cli/index.ts +21 -7
- package/src/cli/known-gaps.ts +27 -0
- package/src/cli/listing-arg.ts +417 -56
- package/src/cli/not-a-ticker.ts +12 -5
- package/src/cli/pane-functions/access-gate.ts +5 -0
- package/src/cli/pane-functions/capabilities.ts +3 -2
- package/src/cli/pane-functions/catalog.ts +35 -5
- package/src/cli/pane-functions/data.ts +12 -8
- package/src/cli/pane-functions/discovery.ts +1 -0
- package/src/cli/pane-functions/dom.ts +20 -6
- package/src/cli/pane-functions/freshness.ts +363 -43
- package/src/cli/pane-functions/function-help.ts +12 -5
- package/src/cli/pane-functions/headless.ts +45 -17
- package/src/cli/pane-functions/index.ts +63 -10
- package/src/cli/pane-functions/market-session.ts +22 -8
- package/src/cli/pane-functions/options.ts +63 -22
- package/src/cli/pane-functions/report-notices.ts +25 -7
- package/src/cli/pane-functions/report.ts +15 -8
- package/src/cli/pane-functions/resolver.ts +49 -12
- package/src/cli/pane-functions/screenshot.ts +110 -23
- package/src/cli/report-tables.ts +3 -0
- package/src/cli/result.ts +4 -1
- package/src/cli/staged-tickers.ts +52 -0
- package/src/cli/symbol-args.ts +9 -0
- package/src/cli/symbol-list.ts +172 -0
- package/src/cli/ticker-resolution.ts +223 -30
- package/src/cli/types.ts +5 -0
- package/src/components/chart/composite/axis-overlays.tsx +6 -2
- package/src/components/chart/composite/composite-chart.tsx +40 -6
- package/src/components/chart/composite/legend.tsx +49 -2
- package/src/components/chart/composite/panel-surface.tsx +44 -17
- package/src/components/chart/composite/price-axis-labels.tsx +3 -1
- package/src/components/command-bar/panel/index.tsx +11 -3
- package/src/components/command-bar/panel/runtime.ts +3 -0
- package/src/components/command-bar/panel/types.ts +2 -0
- package/src/components/command-bar/routes/root/provider-search.ts +4 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +12 -11
- package/src/components/command-bar/routes/ticker-search/route.ts +4 -3
- package/src/components/command-bar/workflow/tickers.ts +23 -4
- package/src/components/layout/detached-pane-shell.tsx +9 -0
- package/src/components/layout/floating-pane.tsx +3 -0
- package/src/components/layout/header.tsx +20 -5
- package/src/components/layout/pane/content.tsx +7 -13
- package/src/components/layout/pane/footer/index.tsx +6 -2
- package/src/components/layout/pane/footer/model.ts +35 -1
- package/src/components/layout/pane/header.tsx +24 -1
- package/src/components/layout/pane/index.tsx +12 -2
- package/src/components/layout/pane/sidebar.tsx +78 -10
- package/src/components/layout/shell/active-drag.ts +21 -5
- package/src/components/layout/shell/drag/index.ts +39 -9
- package/src/components/layout/shell/drag/live.ts +61 -51
- package/src/components/layout/shell/drag/runtime.ts +54 -12
- package/src/components/layout/shell/index.tsx +25 -7
- package/src/components/layout/shell/menu.ts +5 -0
- package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
- package/src/components/layout/shell/pane/layers.tsx +192 -45
- package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
- package/src/components/markdown-text.tsx +62 -20
- package/src/components/metric-treemap/heat-surface.tsx +10 -1
- package/src/components/onboarding/account-step/form-panel.tsx +1 -1
- package/src/components/onboarding/account-step/index.tsx +1 -1
- package/src/components/onboarding/account-step/qr-panel.tsx +1 -1
- package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
- package/src/components/onboarding/onboarding-keyboard.ts +1 -1
- package/src/components/onboarding/onboarding-wizard.tsx +2 -2
- package/src/components/onboarding/use-onboarding-upgrade.ts +3 -3
- package/src/components/onboarding/wizard-account.ts +2 -2
- package/src/components/pane-template-wizard.tsx +9 -1
- package/src/components/price-selector-dialog.tsx +11 -2
- package/src/components/sign-in-gate.tsx +3 -3
- package/src/components/ticker/list-table-view.tsx +24 -1
- package/src/components/ui/action-row.tsx +2 -1
- package/src/components/ui/button.tsx +7 -1
- package/src/components/ui/choice-dialog.tsx +6 -4
- package/src/components/ui/confirm-dialog.tsx +28 -18
- package/src/components/ui/data-table/index.tsx +17 -6
- package/src/components/ui/data-table/opentui/index.tsx +37 -6
- package/src/components/ui/data-table/types.ts +12 -0
- package/src/components/ui/dialog-actions.tsx +64 -0
- package/src/components/ui/display.tsx +17 -3
- package/src/components/ui/frame.tsx +35 -2
- package/src/components/ui/icon.tsx +2 -0
- package/src/components/ui/text-prompt-dialog.tsx +11 -9
- package/src/data/cached-query.ts +2 -0
- package/src/data/config/store/normalize.ts +7 -2
- package/src/data/ticker-repository.ts +5 -0
- package/src/data/ticker-store.ts +15 -0
- package/src/docs/content.ts +215 -0
- package/src/docs/load.ts +139 -0
- package/src/docs/requests.ts +39 -0
- package/src/docs/snapshot.chunk.ts +8 -0
- package/src/docs/snapshot.json +7416 -0
- package/src/docs/topics.ts +216 -0
- package/src/i18n/es.ts +61 -4
- package/src/i18n/ja.ts +61 -4
- package/src/i18n/ko.ts +61 -4
- package/src/i18n/zh-cn.ts +61 -4
- package/src/i18n/zh-tw.ts +61 -4
- package/src/layout/desks.ts +1 -1
- package/src/layout/pane-manager/dock-tree.ts +18 -0
- package/src/layout/pane-manager/index.ts +1 -0
- package/src/market-data/coordinator/chart.ts +10 -4
- package/src/market-data/coordinator/index.ts +6 -3
- package/src/{plugins/builtin/futures/contracts.ts → market-data/futures-board.ts} +81 -28
- package/src/market-data/futures-contract.ts +151 -0
- package/src/market-data/hooks.tsx +10 -2
- package/src/market-data/market/format.ts +39 -21
- package/src/market-data/market/freshness.ts +81 -18
- package/src/market-data/market/status.ts +19 -23
- package/src/market-data/published-apac-sessions.ts +23 -1
- package/src/market-data/quotes/contributions.ts +3 -0
- package/src/market-data/quotes/metadata.ts +7 -24
- package/src/market-data/quotes/resolution.ts +2 -0
- package/src/market-data/quotes/screener-live-quotes.ts +5 -4
- package/src/market-data/result-types.ts +2 -0
- package/src/plugins/builtin/account-management/model.ts +1 -56
- package/src/plugins/builtin/account-management/pane.tsx +6 -4
- package/src/plugins/builtin/account-management/password-dialog.tsx +1 -1
- package/src/plugins/builtin/alerts/cli.ts +313 -47
- package/src/plugins/builtin/alerts/events-pane.tsx +45 -7
- package/src/plugins/builtin/alerts/events.ts +23 -2
- package/src/plugins/builtin/alerts/history-pane.tsx +7 -2
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +41 -9
- package/src/plugins/builtin/alerts/pane.tsx +8 -0
- package/src/plugins/builtin/alerts/research-builder.ts +8 -3
- package/src/plugins/builtin/alerts/research-rules.ts +18 -2
- package/src/plugins/builtin/alerts/scheduled-check.ts +122 -0
- package/src/plugins/builtin/alerts/scheduled-sources.ts +25 -0
- package/src/plugins/builtin/alerts/scheduled.ts +254 -0
- package/src/plugins/builtin/alerts/targets.ts +92 -0
- package/src/plugins/builtin/analytics/index.tsx +4 -2
- package/src/plugins/builtin/analytics/risk-headless.ts +30 -12
- package/src/plugins/builtin/analytics/risk-math.ts +91 -27
- package/src/plugins/builtin/analytics/risk-model.ts +35 -5
- package/src/plugins/builtin/analytics/risk-pane.tsx +15 -8
- package/src/plugins/builtin/attention/index.tsx +2 -0
- package/src/plugins/builtin/attention/pane.tsx +3 -1
- package/src/plugins/builtin/attention/series.ts +26 -0
- package/src/plugins/builtin/awards/index.tsx +2 -0
- package/src/plugins/builtin/awards/pane.tsx +3 -1
- package/src/plugins/builtin/awards/series.ts +29 -0
- package/src/plugins/builtin/bond-calculator/model.ts +2 -1
- package/src/plugins/builtin/catalysts/pane.tsx +3 -1
- package/src/plugins/builtin/cds/client.ts +70 -13
- package/src/plugins/builtin/cds/headless.ts +116 -19
- package/src/plugins/builtin/cds/index.tsx +3 -1
- package/src/plugins/builtin/cds/model.ts +193 -31
- package/src/plugins/builtin/cds/pane.tsx +56 -14
- package/src/plugins/builtin/cds/series.ts +19 -0
- package/src/plugins/builtin/central-bank-rates/index.tsx +2 -0
- package/src/plugins/builtin/central-bank-rates/series.ts +42 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +192 -255
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +84 -46
- package/src/plugins/builtin/chart-composer/editor.tsx +5 -4
- package/src/plugins/builtin/chart-composer/field-series.ts +40 -0
- package/src/plugins/builtin/chart-composer/headless.ts +8 -3
- package/src/plugins/builtin/chart-composer/index.tsx +9 -2
- package/src/plugins/builtin/chart-composer/series-catalog.ts +58 -50
- package/src/plugins/builtin/chart-composer/series-expression.ts +18 -10
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +59 -3
- package/src/plugins/builtin/chart-composer/user-series.ts +84 -0
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
- package/src/plugins/builtin/chat/controller/index.ts +2 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +111 -19
- package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
- package/src/plugins/builtin/cloud/askg/manifest.ts +32 -7
- package/src/plugins/builtin/cloud/askg/model.ts +27 -8
- package/src/plugins/builtin/cloud/askg/protocol.ts +10 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +3 -0
- package/src/plugins/builtin/cloud/askg/undo.ts +2 -0
- package/src/plugins/builtin/cloud/auth-actions.tsx +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +1 -1
- package/src/plugins/builtin/cloud/auth-dialog.tsx +3 -3
- package/src/plugins/builtin/cloud/company-picker.tsx +1 -1
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +3 -0
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +77 -9
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +6 -1
- package/src/plugins/builtin/cloud/terminal-relay/policy.ts +9 -0
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +35 -11
- package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
- package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
- package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
- package/src/plugins/builtin/company-attention/headless.ts +19 -5
- package/src/plugins/builtin/company-attention/index.tsx +2 -0
- package/src/plugins/builtin/company-attention/model.ts +26 -7
- package/src/plugins/builtin/company-attention/pane.tsx +12 -9
- package/src/plugins/builtin/company-attention/series.ts +52 -0
- package/src/plugins/builtin/company-kpis/pane.tsx +4 -2
- package/src/plugins/builtin/composite-plugins.ts +19 -13
- package/src/plugins/builtin/cot/index.tsx +3 -1
- package/src/plugins/builtin/cot/model.ts +40 -11
- package/src/plugins/builtin/cot/series.ts +27 -0
- package/src/plugins/builtin/credit-boards/index.tsx +2 -0
- package/src/plugins/builtin/credit-boards/series.ts +66 -0
- package/src/plugins/builtin/credit-conditions/index.tsx +2 -0
- package/src/plugins/builtin/credit-conditions/series.ts +26 -0
- package/src/plugins/builtin/credit-documents/headless.ts +31 -1
- package/src/plugins/builtin/credit-documents/pane.tsx +3 -1
- package/src/plugins/builtin/crypto-board/headless.ts +2 -3
- package/src/plugins/builtin/crypto-board/index.tsx +2 -0
- package/src/plugins/builtin/crypto-board/model.ts +12 -0
- package/src/plugins/builtin/crypto-board/pane.tsx +19 -12
- package/src/plugins/builtin/crypto-board/series.ts +48 -0
- package/src/plugins/builtin/custom-view/live-quotes.ts +2 -2
- package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
- package/src/plugins/builtin/debt-maturities/series.ts +45 -0
- package/src/plugins/builtin/dividend-yield/headless.ts +2 -2
- package/src/plugins/builtin/dividend-yield/index.tsx +2 -0
- package/src/plugins/builtin/dividend-yield/series.ts +20 -0
- package/src/plugins/builtin/docs/blocks.tsx +181 -0
- package/src/plugins/builtin/docs/index.tsx +68 -0
- package/src/plugins/builtin/docs/pane.tsx +426 -0
- package/src/plugins/builtin/docs/targets.ts +72 -0
- package/src/plugins/builtin/docs/use-docs.ts +60 -0
- package/src/plugins/builtin/doe/index.tsx +2 -0
- package/src/plugins/builtin/doe/series.ts +62 -0
- package/src/plugins/builtin/earnings/client.ts +3 -2
- package/src/plugins/builtin/earnings/format.ts +1 -5
- package/src/plugins/builtin/earnings/headless.ts +58 -6
- package/src/plugins/builtin/earnings/history-model.ts +15 -1
- package/src/plugins/builtin/earnings/history-table.ts +13 -2
- package/src/plugins/builtin/earnings/history.tsx +7 -3
- package/src/plugins/builtin/econ/fred-catalog.ts +189 -0
- package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
- package/src/plugins/builtin/econ/index.tsx +2 -0
- package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +19 -4
- package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
- package/src/plugins/builtin/exposure/holdings.ts +1 -1
- package/src/plugins/builtin/exposure/pane.tsx +3 -1
- package/src/plugins/builtin/fear-greed/index.tsx +4 -0
- package/src/plugins/builtin/fear-greed/series.ts +52 -0
- package/src/plugins/builtin/futures/index.tsx +43 -3
- package/src/plugins/builtin/futures/model.ts +1 -1
- package/src/plugins/builtin/futures/returns.ts +1 -1
- package/src/plugins/builtin/futures/series.ts +13 -0
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures/use-front-returns.ts +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +12 -3
- package/src/plugins/builtin/futures-curve/headless.ts +70 -9
- package/src/plugins/builtin/futures-curve/index.tsx +1 -1
- package/src/plugins/builtin/futures-curve/model.ts +66 -11
- package/src/plugins/builtin/futures-curve/pane.tsx +52 -18
- package/src/plugins/builtin/fx-matrix/index.tsx +1 -1
- package/src/plugins/builtin/gpu/board.tsx +13 -10
- package/src/plugins/builtin/gpu/changes.tsx +4 -4
- package/src/plugins/builtin/gpu/client.ts +19 -1
- package/src/plugins/builtin/gpu/equities.tsx +14 -10
- package/src/plugins/builtin/gpu/headless.ts +56 -25
- package/src/plugins/builtin/gpu/history.tsx +3 -3
- package/src/plugins/builtin/gpu/index.tsx +2 -0
- package/src/plugins/builtin/gpu/model.ts +101 -16
- package/src/plugins/builtin/gpu/pane.tsx +28 -12
- package/src/plugins/builtin/gpu/series.ts +38 -0
- package/src/plugins/builtin/help/function-card.tsx +25 -6
- package/src/plugins/builtin/help/index.tsx +17 -8
- package/src/plugins/builtin/holders/beneficial-model.ts +90 -3
- package/src/plugins/builtin/holders/beneficial-report.ts +57 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +55 -11
- package/src/plugins/builtin/holders/client.ts +22 -3
- package/src/plugins/builtin/holders/format.ts +18 -3
- package/src/plugins/builtin/holders/headless.ts +36 -133
- package/src/plugins/builtin/holders/pane.tsx +11 -4
- package/src/plugins/builtin/holders/report-header.ts +40 -5
- package/src/plugins/builtin/holders/report-rows.ts +240 -0
- package/src/plugins/builtin/insider/client.ts +35 -20
- package/src/plugins/builtin/insider/headless.ts +41 -11
- package/src/plugins/builtin/insider/index.tsx +26 -9
- package/src/plugins/builtin/insider/insider-data.ts +10 -0
- package/src/plugins/builtin/insider/issuer.ts +49 -0
- package/src/plugins/builtin/insider/model.ts +3 -0
- package/src/plugins/builtin/iv-history/client.ts +14 -4
- package/src/plugins/builtin/iv-history/headless.ts +7 -4
- package/src/plugins/builtin/iv-history/index.tsx +2 -0
- package/src/plugins/builtin/iv-history/model.ts +111 -7
- package/src/plugins/builtin/iv-history/screen-pane.tsx +5 -9
- package/src/plugins/builtin/iv-history/series.ts +29 -0
- package/src/plugins/builtin/jobs/headless.ts +28 -3
- package/src/plugins/builtin/jobs/index.tsx +3 -1
- package/src/plugins/builtin/jobs/series.ts +19 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +2 -1
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
- package/src/plugins/builtin/macro-day/client.ts +44 -3
- package/src/plugins/builtin/macro-day/headless.ts +13 -10
- package/src/plugins/builtin/macro-day/model.ts +56 -10
- package/src/plugins/builtin/macro-day/pane.tsx +30 -20
- package/src/plugins/builtin/market-heatmap/model.ts +19 -11
- package/src/plugins/builtin/market-heatmap/portfolio.ts +2 -2
- package/src/plugins/builtin/market-movers/client.ts +7 -5
- package/src/plugins/builtin/market-movers/index.tsx +3 -2
- package/src/plugins/builtin/market-movers/model.ts +30 -0
- package/src/plugins/builtin/market-movers/screener.ts +31 -0
- package/src/plugins/builtin/market-valuation/chart-series.ts +29 -69
- package/src/plugins/builtin/market-valuation/index.tsx +3 -3
- package/src/plugins/builtin/market-valuation/indicators.ts +0 -5
- package/src/plugins/builtin/members/headless.ts +7 -2
- package/src/plugins/builtin/members/model.ts +31 -3
- package/src/plugins/builtin/members/pane.tsx +3 -6
- package/src/plugins/builtin/mna/headless.ts +15 -3
- package/src/plugins/builtin/money-markets/index.tsx +2 -0
- package/src/plugins/builtin/money-markets/series.ts +41 -0
- package/src/plugins/builtin/notes/cli.ts +12 -7
- package/src/plugins/builtin/options/view.tsx +1 -1
- package/src/plugins/builtin/options-calculator/inputs.ts +2 -1
- package/src/plugins/builtin/options-positioning/client.ts +7 -3
- package/src/plugins/builtin/options-positioning/headless.ts +1 -0
- package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
- package/src/plugins/builtin/options-scenario/client.ts +2 -1
- package/src/plugins/builtin/options-scenario/headless.ts +1 -0
- package/src/plugins/builtin/options-scenario/hedge.ts +2 -1
- package/src/plugins/builtin/perps/client.ts +40 -6
- package/src/plugins/builtin/perps/equity-row.tsx +33 -11
- package/src/plugins/builtin/perps/freshness.ts +66 -0
- package/src/plugins/builtin/perps/headless.ts +45 -30
- package/src/plugins/builtin/perps/index.tsx +18 -1
- package/src/plugins/builtin/perps/model.ts +20 -5
- package/src/plugins/builtin/perps/pane.tsx +76 -20
- package/src/plugins/builtin/perps/series.ts +76 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +67 -61
- package/src/plugins/builtin/plugin-module.ts +3 -0
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +273 -0
- package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +331 -65
- package/src/plugins/builtin/portfolio-list/cli/render.ts +200 -31
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +24 -0
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +120 -47
- package/src/plugins/builtin/portfolio-list/column-values.ts +1 -1
- package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
- package/src/plugins/builtin/portfolio-list/headless.ts +34 -4
- package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +6 -1
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +17 -1
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +1 -1
- package/src/plugins/builtin/portfolio-list/table.tsx +7 -1
- package/src/plugins/builtin/power/client.ts +16 -0
- package/src/plugins/builtin/power/evidence.ts +6 -2
- package/src/plugins/builtin/power/headless.ts +71 -7
- package/src/plugins/builtin/power/index.tsx +4 -1
- package/src/plugins/builtin/power/model.ts +72 -1
- package/src/plugins/builtin/power/pane.tsx +32 -9
- package/src/plugins/builtin/rate-path/headless.ts +11 -3
- package/src/plugins/builtin/realized-vol/headless.ts +5 -0
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +5 -2
- package/src/plugins/builtin/research/event-model.ts +68 -24
- package/src/plugins/builtin/research/events-headless.ts +2 -1
- package/src/plugins/builtin/research/headless.ts +2 -1
- package/src/plugins/builtin/seasonality/client.ts +15 -7
- package/src/plugins/builtin/seasonality/headless.ts +36 -12
- package/src/plugins/builtin/seasonality/index.tsx +2 -2
- package/src/plugins/builtin/seasonality/model.ts +119 -0
- package/src/plugins/builtin/seasonality/pane.tsx +108 -37
- package/src/plugins/builtin/series-inventory.ts +91 -0
- package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
- package/src/plugins/builtin/shared/command-tab.ts +30 -12
- package/src/plugins/builtin/shared/earnings-report.ts +55 -0
- package/src/plugins/builtin/shared/fred-points.ts +20 -0
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +101 -0
- package/src/plugins/builtin/shared/open-description.ts +29 -0
- package/src/plugins/builtin/shared/report-freshness.ts +9 -0
- package/src/plugins/builtin/shared/series-warning.ts +5 -0
- package/src/plugins/builtin/short-interest/headless.ts +1 -0
- package/src/plugins/builtin/short-interest/index.tsx +2 -0
- package/src/plugins/builtin/short-interest/series.ts +36 -0
- package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
- package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
- package/src/plugins/builtin/short-volume/headless.ts +1 -0
- package/src/plugins/builtin/short-volume/index.tsx +2 -0
- package/src/plugins/builtin/short-volume/series.ts +23 -0
- package/src/plugins/builtin/social-mentions/index.tsx +2 -0
- package/src/plugins/builtin/social-mentions/series.ts +23 -0
- package/src/plugins/builtin/supply-chain/graph-pane.tsx +3 -2
- package/src/plugins/builtin/supply-chain/pane.tsx +3 -1
- package/src/plugins/builtin/thirteenf/api.ts +1 -0
- package/src/plugins/builtin/thirteenf/data.ts +6 -4
- package/src/plugins/builtin/thirteenf/headless.ts +217 -36
- package/src/plugins/builtin/thirteenf/model.ts +39 -1
- package/src/plugins/builtin/thirteenf/overlap.ts +75 -0
- package/src/plugins/builtin/thirteenf/pane.tsx +10 -1
- package/src/plugins/builtin/thirteenf/report-notes.ts +103 -1
- package/src/plugins/builtin/thirteenf/types.ts +2 -0
- package/src/plugins/builtin/ticker-detail/index.tsx +3 -0
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/overview/futures-contract.ts +31 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +3 -3
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +48 -4
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
- package/src/plugins/builtin/time-sales/headless.ts +1 -0
- package/src/plugins/builtin/treasury-auctions/headless.ts +16 -2
- package/src/plugins/builtin/treasury-auctions/index.tsx +1 -0
- package/src/plugins/builtin/treasury-auctions/model.ts +8 -0
- package/src/plugins/builtin/vol-surface/headless.ts +1 -0
- package/src/plugins/builtin/volatility/index.tsx +2 -0
- package/src/plugins/builtin/volatility/series.ts +84 -0
- package/src/plugins/builtin/world-venue-map/geo-series.ts +26 -1
- package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
- package/src/plugins/builtin/world-venue-map/index.ts +2 -1
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +8 -4
- package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
- package/src/plugins/builtin/yield-curve/chart.ts +2 -2
- package/src/plugins/builtin/yield-curve/curves.ts +21 -8
- package/src/plugins/builtin/yield-curve/headless.ts +71 -18
- package/src/plugins/builtin/yield-curve/index.tsx +3 -1
- package/src/plugins/builtin/yield-curve/series.ts +86 -0
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/registry/index.ts +89 -4
- package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
- package/src/portfolio/position-value.ts +40 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +7 -0
- package/src/public/time-series.ts +17 -0
- package/src/react/auto-refresh.ts +13 -3
- package/src/remote/app-host.tsx +20 -4
- package/src/remote/confirm-change.tsx +85 -0
- package/src/remote/controller-utils.ts +8 -1
- package/src/remote/controller.ts +123 -6
- package/src/remote/pane-screenshot.ts +47 -0
- package/src/remote/schema.ts +62 -0
- package/src/remote/types.ts +30 -0
- package/src/remote/watchlist.ts +306 -0
- package/src/renderers/browser/main.tsx +3 -2
- package/src/renderers/cloudflare/worker.ts +1 -1
- package/src/renderers/dom/data-table/frozen-column.ts +3 -1
- package/src/renderers/dom/data-table/index.tsx +33 -6
- package/src/renderers/dom/data-table/row.tsx +27 -1
- package/src/renderers/dom/desktop/control-styles.ts +63 -1
- package/src/renderers/dom/desktop/controls.tsx +30 -23
- package/src/renderers/dom/desktop/dialog-actions.tsx +170 -0
- package/src/renderers/dom/desktop/icons.tsx +7 -0
- package/src/renderers/dom/dom-ui-host.tsx +3 -0
- package/src/renderers/dom/host/box.tsx +3 -0
- package/src/renderers/dom/host/chart-surface.tsx +6 -2
- package/src/renderers/dom/host/live-frame.ts +6 -2
- package/src/renderers/dom/host/overflow-fade.ts +14 -1
- package/src/renderers/dom/host/size-observer.ts +26 -0
- package/src/renderers/dom/host/surface-3d.tsx +7 -2
- package/src/renderers/dom/host/text.tsx +1 -1
- package/src/renderers/dom/styles.css +61 -0
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +17 -2
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +19 -11
- package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
- package/src/renderers/electrobun/view/main.tsx +2 -0
- package/src/series/capability.ts +75 -0
- package/src/series/csv.ts +160 -0
- package/src/series/files.ts +107 -0
- package/src/series/registry.ts +198 -0
- package/src/series/resolve.ts +107 -0
- package/src/series/standalone.ts +48 -0
- package/src/series/types.ts +145 -0
- package/src/series/validate.ts +171 -0
- package/src/sources/gloomberb-cloud/index.ts +7 -7
- package/src/sources/gloomberb-cloud/normalizers.ts +1 -0
- package/src/sources/history-result.ts +1 -0
- package/src/sources/listing-symbols.ts +4 -1
- package/src/sources/provider-router/batches.ts +4 -1
- package/src/sources/provider-router/cache.ts +4 -2
- package/src/sources/provider-router/cached-routes.ts +1 -1
- package/src/sources/provider-router/financial-routes.ts +1 -0
- package/src/sources/provider-router/financials.ts +13 -0
- package/src/sources/provider-router/history.ts +43 -25
- package/src/sources/provider-router/search.ts +1 -0
- package/src/sync/core-contributors.ts +1 -0
- package/src/tickers/company-name.ts +75 -0
- package/src/tickers/instrument-kind.ts +25 -0
- package/src/tickers/open-target.ts +3 -2
- package/src/tickers/search/index.ts +45 -7
- package/src/tickers/search/ranking.ts +33 -17
- package/src/tickers/search/types.ts +7 -1
- package/src/tickers/us-listing.ts +34 -0
- package/src/time-series/hooks.ts +9 -0
- package/src/time-series/resolve.ts +95 -16
- package/src/time-series/types.ts +4 -2
- package/src/time-series/use-chart-resolution.ts +32 -0
- package/src/types/config.ts +6 -0
- package/src/types/data-provider.ts +5 -0
- package/src/types/financials.ts +52 -1
- package/src/types/headless.ts +61 -0
- package/src/types/plugin.ts +19 -0
- package/src/types/price-history.ts +7 -0
- package/src/types/ticker.ts +14 -0
- package/src/ui/host.tsx +18 -0
- package/src/ui/live-resize.ts +81 -0
- package/src/ui/live-stretch.ts +121 -0
- package/src/ui/measured-cells.ts +58 -0
- package/src/ui/pane-fill.ts +11 -0
- package/src/utils/basis-points.ts +17 -0
- package/src/utils/cli-output.ts +7 -1
- package/src/utils/concurrency.ts +25 -0
- package/src/utils/crypto-pair.ts +20 -0
- package/src/utils/currency-pair.ts +19 -0
- package/src/utils/decimal-comma.ts +19 -0
- package/src/utils/dom-screenshot-css.ts +265 -0
- package/src/utils/dom-screenshot-rasters.ts +276 -0
- package/src/utils/dom-screenshot.ts +437 -52
- package/src/utils/exchange-rate-snapshot.ts +6 -2
- package/src/utils/exchanges.ts +107 -1
- package/src/utils/format.ts +16 -3
- package/src/utils/fundamentals.ts +66 -0
- package/src/utils/futures-generic.ts +6 -12
- package/src/utils/fx-market-hours.ts +15 -5
- package/src/utils/price-history.ts +99 -42
- package/src/utils/sec-eps-basis.ts +24 -11
- package/src/utils/sec.ts +61 -7
- package/src/utils/utc-time.ts +51 -4
- package/src/plugins/builtin/fx-matrix/freshness.ts +0 -65
- /package/src/{plugins/builtin/cloud → tickers}/starter-symbols.ts +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useMemo, useState } from "react";
|
|
1
|
+
import { useEffect, useMemo, useState, useSyncExternalStore } from "react";
|
|
2
2
|
import {
|
|
3
3
|
buildTickerSearchCandidates,
|
|
4
4
|
searchTickerCandidates,
|
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
import { useOptionalAppSelector } from "../../../state/app/context";
|
|
7
7
|
import type { TickerRecord } from "../../../types/ticker";
|
|
8
8
|
import { searchChartSeriesCapabilities } from "../../../capabilities";
|
|
9
|
+
import { SERIES_CATALOG_CAPABILITY_ID } from "../../../series/capability";
|
|
10
|
+
import type { SeriesCatalogEntry } from "../../../series/types";
|
|
9
11
|
import { getSharedRegistry } from "../../registry";
|
|
10
12
|
import {
|
|
11
13
|
analyzeSeriesSearchQuery,
|
|
@@ -17,6 +19,9 @@ import {
|
|
|
17
19
|
|
|
18
20
|
const EMPTY_TICKERS: ReadonlyMap<string, TickerRecord> = new Map();
|
|
19
21
|
const EMPTY_RECENT: readonly string[] = [];
|
|
22
|
+
const EMPTY_PLUGINS: readonly string[] = [];
|
|
23
|
+
const EMPTY_ENTRIES: readonly SeriesCatalogEntry[] = [];
|
|
24
|
+
const NO_SUBSCRIPTION = () => () => {};
|
|
20
25
|
const MAX_SERIES_SUGGESTIONS = 8;
|
|
21
26
|
const DEFAULT_CATALOG_INSTRUMENTS: readonly SeriesCatalogInstrument[] = [
|
|
22
27
|
{ symbol: "AAPL", exchange: "NASDAQ", name: "Apple Inc." },
|
|
@@ -72,6 +77,56 @@ function candidateToInstrument(candidate: {
|
|
|
72
77
|
};
|
|
73
78
|
}
|
|
74
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Every registered series of the plugins that are switched on. On the
|
|
82
|
+
* desktop, series only the Bun process has (files in the profile's series
|
|
83
|
+
* folder) are asked for once and listed after the rest; elsewhere, sources
|
|
84
|
+
* that change while the app runs catch up when the catalog opens.
|
|
85
|
+
*/
|
|
86
|
+
export function useRegisteredSeries(): readonly SeriesCatalogEntry[] {
|
|
87
|
+
const registry = getSharedRegistry();
|
|
88
|
+
const series = registry?.series;
|
|
89
|
+
const version = useSyncExternalStore(
|
|
90
|
+
series ? series.subscribe.bind(series) : NO_SUBSCRIPTION,
|
|
91
|
+
() => series?.getVersion() ?? 0,
|
|
92
|
+
() => 0,
|
|
93
|
+
);
|
|
94
|
+
const disabledPlugins = useOptionalAppSelector((state) => state.config.disabledPlugins, EMPTY_PLUGINS);
|
|
95
|
+
const [remote, setRemote] = useState<readonly SeriesCatalogEntry[] | null>(null);
|
|
96
|
+
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
if (!registry || !series) return;
|
|
99
|
+
if (!registry.usesRemoteCapabilities) {
|
|
100
|
+
void series.refresh();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
let cancelled = false;
|
|
104
|
+
void registry.invokeCapability<{ entries: SeriesCatalogEntry[] }>(SERIES_CATALOG_CAPABILITY_ID, "list", {})
|
|
105
|
+
.then((result) => {
|
|
106
|
+
if (!cancelled && Array.isArray(result?.entries)) setRemote(result.entries);
|
|
107
|
+
})
|
|
108
|
+
.catch(() => {
|
|
109
|
+
// The view's own series still list; only the Bun process's extras are missing.
|
|
110
|
+
});
|
|
111
|
+
return () => { cancelled = true; };
|
|
112
|
+
}, [registry, series]);
|
|
113
|
+
|
|
114
|
+
return useMemo(() => {
|
|
115
|
+
const local = series?.catalog() ?? EMPTY_ENTRIES;
|
|
116
|
+
let entries = local;
|
|
117
|
+
if (remote?.length) {
|
|
118
|
+
const known = new Set(local.map((entry) => entry.id));
|
|
119
|
+
const extra = remote.filter((entry) => !known.has(entry.id));
|
|
120
|
+
if (extra.length) entries = [...local, ...extra];
|
|
121
|
+
}
|
|
122
|
+
if (disabledPlugins.length === 0) return entries;
|
|
123
|
+
const disabled = new Set(disabledPlugins);
|
|
124
|
+
return entries.some((entry) => disabled.has(entry.pluginId))
|
|
125
|
+
? entries.filter((entry) => !disabled.has(entry.pluginId))
|
|
126
|
+
: entries;
|
|
127
|
+
}, [disabledPlugins, remote, series, version]);
|
|
128
|
+
}
|
|
129
|
+
|
|
75
130
|
export function useCatalogUniverse(query: string): {
|
|
76
131
|
instruments: SeriesCatalogInstrument[];
|
|
77
132
|
loading: boolean;
|
|
@@ -193,6 +248,7 @@ export function useSeriesCatalogSuggestions({
|
|
|
193
248
|
enabled: boolean;
|
|
194
249
|
}): SeriesCatalogSearchResult {
|
|
195
250
|
const tickers = useOptionalAppSelector((state) => state.tickers, EMPTY_TICKERS);
|
|
251
|
+
const registered = useRegisteredSeries();
|
|
196
252
|
const analysis = useMemo(() => analyzeSeriesSearchQuery(query), [query]);
|
|
197
253
|
const [providerSearch, setProviderSearch] = useState<{
|
|
198
254
|
query: string;
|
|
@@ -298,11 +354,11 @@ export function useSeriesCatalogSuggestions({
|
|
|
298
354
|
// and they arrive well before plugin catalogs (which can take seconds), so
|
|
299
355
|
// late plugin results append below instead of pushing the list around.
|
|
300
356
|
const suggestions = useMemo(() => {
|
|
301
|
-
const builtIn = buildSeriesCatalogSuggestions(query, defaultInstrument, instruments);
|
|
357
|
+
const builtIn = buildSeriesCatalogSuggestions(query, defaultInstrument, instruments, MAX_SERIES_SUGGESTIONS, registered);
|
|
302
358
|
const provider = providerSearch.query === query.trim() ? providerSearch.suggestions : [];
|
|
303
359
|
return [...builtIn, ...provider.filter((entry) => !builtIn.some((candidate) => candidate.id === entry.id))]
|
|
304
360
|
.slice(0, MAX_SERIES_SUGGESTIONS);
|
|
305
|
-
}, [defaultInstrument, instruments, providerSearch, query]);
|
|
361
|
+
}, [defaultInstrument, instruments, providerSearch, query, registered]);
|
|
306
362
|
|
|
307
363
|
return {
|
|
308
364
|
suggestions,
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { getCurrentPluginTarget } from "../../current-target";
|
|
2
|
+
import { getSharedRegistry } from "../../registry";
|
|
3
|
+
import { listSeriesFiles, seriesFromFile } from "../../../series/files";
|
|
4
|
+
import type { SeriesDefinition } from "../../../series/types";
|
|
5
|
+
import type { GloomPluginContext } from "../../../types/plugin";
|
|
6
|
+
import type { PluginModule } from "../plugin-module";
|
|
7
|
+
|
|
8
|
+
interface RegisteredFile {
|
|
9
|
+
mtimeMs: number;
|
|
10
|
+
dispose: () => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Keeps the catalog in step with the profile's series folder: a file added,
|
|
15
|
+
* changed or removed shows up the next time the catalog opens.
|
|
16
|
+
*/
|
|
17
|
+
function watchUserSeriesFolder(ctx: GloomPluginContext): () => void {
|
|
18
|
+
const registered = new Map<string, RegisteredFile>();
|
|
19
|
+
let running: Promise<void> = Promise.resolve();
|
|
20
|
+
|
|
21
|
+
const sync = async () => {
|
|
22
|
+
const files = await listSeriesFiles(ctx.getConfig().dataDir);
|
|
23
|
+
const present = new Set(files.map((file) => file.name));
|
|
24
|
+
for (const [name, entry] of registered) {
|
|
25
|
+
if (present.has(name)) continue;
|
|
26
|
+
entry.dispose();
|
|
27
|
+
registered.delete(name);
|
|
28
|
+
}
|
|
29
|
+
for (const file of files) {
|
|
30
|
+
const existing = registered.get(file.name);
|
|
31
|
+
if (existing?.mtimeMs === file.mtimeMs) continue;
|
|
32
|
+
existing?.dispose();
|
|
33
|
+
registered.delete(file.name);
|
|
34
|
+
let definitions: SeriesDefinition[];
|
|
35
|
+
try {
|
|
36
|
+
definitions = seriesFromFile(file.name, await file.readText(), file.readText);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
ctx.log.warn("Series file skipped", { file: file.name, error: error instanceof Error ? error.message : String(error) });
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const disposers = definitions.flatMap((definition) => {
|
|
42
|
+
try {
|
|
43
|
+
return [ctx.registerSeries(definition)];
|
|
44
|
+
} catch (error) {
|
|
45
|
+
ctx.log.warn("Series skipped", { file: file.name, error: error instanceof Error ? error.message : String(error) });
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
registered.set(file.name, { mtimeMs: file.mtimeMs, dispose: () => { for (const dispose of disposers) dispose(); } });
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const refresh = () => {
|
|
53
|
+
running = running.then(sync, sync);
|
|
54
|
+
return running;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
void refresh();
|
|
58
|
+
const removeRefresher = getSharedRegistry()?.series.addRefresher(refresh);
|
|
59
|
+
return () => {
|
|
60
|
+
removeRefresher?.();
|
|
61
|
+
for (const entry of registered.values()) entry.dispose();
|
|
62
|
+
registered.clear();
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let stopWatching: (() => void) | null = null;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* CSV files in `<data dir>/series/` as catalog series, chartable against
|
|
70
|
+
* anything else. Files are read where the app can reach the disk: the
|
|
71
|
+
* terminal, and the desktop's Bun process, which lists them for its view.
|
|
72
|
+
*/
|
|
73
|
+
export const userSeriesModule: PluginModule = {
|
|
74
|
+
setup(ctx) {
|
|
75
|
+
const target = getCurrentPluginTarget();
|
|
76
|
+
if (target !== "cli" && target !== "tui") return;
|
|
77
|
+
stopWatching?.();
|
|
78
|
+
stopWatching = watchUserSeriesFolder(ctx);
|
|
79
|
+
},
|
|
80
|
+
dispose() {
|
|
81
|
+
stopWatching?.();
|
|
82
|
+
stopWatching = null;
|
|
83
|
+
},
|
|
84
|
+
};
|
|
@@ -267,9 +267,11 @@ export function NewDmDialog({
|
|
|
267
267
|
const startButton = (
|
|
268
268
|
<Button
|
|
269
269
|
label={submitting ? t("Starting") : t("Start")}
|
|
270
|
-
|
|
270
|
+
// The terminal keeps its column fixed; the desktop sizes to the label and its key.
|
|
271
|
+
width={nativePaneChrome ? undefined : submitting ? 10 : START_BUTTON_WIDTH}
|
|
271
272
|
variant="primary"
|
|
272
273
|
disabled={!canSubmit}
|
|
274
|
+
desktopShortcut="Enter"
|
|
273
275
|
stopPropagation
|
|
274
276
|
onPress={() => { void submit(); }}
|
|
275
277
|
/>
|
|
@@ -362,7 +364,13 @@ export function NewDmDialog({
|
|
|
362
364
|
pointerEvents: "auto",
|
|
363
365
|
}}
|
|
364
366
|
>
|
|
365
|
-
<DialogFrame
|
|
367
|
+
<DialogFrame
|
|
368
|
+
title="New DM"
|
|
369
|
+
onClose={onCancel}
|
|
370
|
+
footer={footer}
|
|
371
|
+
desktopFooter={items.length > 0 ? { keys: [{ key: "Tab", label: "add" }] } : null}
|
|
372
|
+
shrinkable
|
|
373
|
+
>
|
|
366
374
|
<Box flexDirection="column" flexShrink={1} minHeight={0} style={{ gap: 6 }}>
|
|
367
375
|
{field}
|
|
368
376
|
<Text fg={selectedUsernames.length > 0 ? colors.textMuted : colors.textDim} style={ELLIPSIS_STYLE}>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerAccountSession } from "../../../../account/session";
|
|
1
2
|
import type {
|
|
2
3
|
AppNotificationDelivery,
|
|
3
4
|
AppNotificationRequest,
|
|
@@ -757,3 +758,4 @@ export class ChatController {
|
|
|
757
758
|
}
|
|
758
759
|
|
|
759
760
|
export const chatController = new ChatController();
|
|
761
|
+
registerAccountSession(chatController);
|
|
@@ -4,13 +4,14 @@ import {
|
|
|
4
4
|
type ASKGToolResultOutcome,
|
|
5
5
|
type ASKGTransport,
|
|
6
6
|
} from "../../../../api-client/askg";
|
|
7
|
-
import type
|
|
7
|
+
import { toolCallRemainingMs, type ASKGToolExecutor, type ASKGToolPreview } from "./executor";
|
|
8
8
|
import {
|
|
9
9
|
activeTurn,
|
|
10
10
|
askgReducer,
|
|
11
11
|
canRateTurn,
|
|
12
12
|
EMPTY_ASKG_CONVERSATION,
|
|
13
13
|
isTurnRunning,
|
|
14
|
+
NOT_APPROVED_IN_TIME_NOTE,
|
|
14
15
|
requiresLocalConfirmation,
|
|
15
16
|
type ASKGAction,
|
|
16
17
|
type ASKGConversationState,
|
|
@@ -42,6 +43,18 @@ const MAX_HISTORY_TURNS = 8;
|
|
|
42
43
|
const DEFAULT_TURN_WALL_CLOCK_MS = 120_000;
|
|
43
44
|
/** Sessions are renegotiated a little before they expire. */
|
|
44
45
|
const SESSION_EXPIRY_GRACE_MS = 5_000;
|
|
46
|
+
/**
|
|
47
|
+
* A confirmation prompt closes this long before the server stops waiting for
|
|
48
|
+
* its call, so an approval still leaves time for the write and its result.
|
|
49
|
+
*/
|
|
50
|
+
export const CONFIRMATION_CLOSE_MARGIN_MS = 2_000;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* How a confirmation prompt ended. `expired` is this app's own deadline for
|
|
54
|
+
* the call; `abandoned` is the turn giving up on it (the call timed out on the
|
|
55
|
+
* server, the turn ended, was cancelled or lost its stream).
|
|
56
|
+
*/
|
|
57
|
+
type ConfirmationAnswer = "approved" | "declined" | "expired" | "abandoned";
|
|
45
58
|
|
|
46
59
|
export interface ASKGControllerManifest {
|
|
47
60
|
tools: ClientToolManifest[];
|
|
@@ -146,9 +159,7 @@ export class ASKGSessionController {
|
|
|
146
159
|
private session: ASKGSessionStartResponse | null = null;
|
|
147
160
|
private sessionRequest: Promise<ASKGSessionStartResponse> | null = null;
|
|
148
161
|
private manifest: ASKGControllerManifest | null = null;
|
|
149
|
-
private readonly confirmations = new Map<string, (
|
|
150
|
-
/** Calls whose turn ended while they were still waiting to be approved. */
|
|
151
|
-
private readonly abandonedCalls = new Set<string>();
|
|
162
|
+
private readonly confirmations = new Map<string, (answer: ConfirmationAnswer) => void>();
|
|
152
163
|
private readonly toolTasks = new Set<Promise<void>>();
|
|
153
164
|
private turnAbort: AbortController | null = null;
|
|
154
165
|
/** Ratings of one answer go out in the order they were made. */
|
|
@@ -286,6 +297,8 @@ export class ASKGSessionController {
|
|
|
286
297
|
signal: abort.signal,
|
|
287
298
|
onEvent: (event) => this.handleEvent(event),
|
|
288
299
|
});
|
|
300
|
+
// The stream is over, so no approval can reach this turn any more.
|
|
301
|
+
this.abandonPendingConfirmations();
|
|
289
302
|
// Tool calls delivered late in the stream may still be running.
|
|
290
303
|
await Promise.allSettled([...this.toolTasks]);
|
|
291
304
|
} catch (error) {
|
|
@@ -350,6 +363,13 @@ export class ASKGSessionController {
|
|
|
350
363
|
this.abandonPendingConfirmations();
|
|
351
364
|
return;
|
|
352
365
|
}
|
|
366
|
+
// The server reports a delegated call it gave up on (timed out, or its
|
|
367
|
+
// script ended) like one it got a result for. A prompt still open for it
|
|
368
|
+
// closes: an approval could no longer reach the turn.
|
|
369
|
+
if (event.type === "tool-executed") {
|
|
370
|
+
this.settleConfirmation(event.toolCallId, "abandoned");
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
353
373
|
if (event.type !== "tool-call") return;
|
|
354
374
|
const task = this.runToolCall(event).finally(() => {
|
|
355
375
|
this.toolTasks.delete(task);
|
|
@@ -384,12 +404,43 @@ export class ASKGSessionController {
|
|
|
384
404
|
|
|
385
405
|
try {
|
|
386
406
|
let confirmed = false;
|
|
407
|
+
let confirmedChange: string | undefined;
|
|
387
408
|
if (requiresLocalConfirmation(call)) {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
409
|
+
const preview = await this.previewCall(call, signal);
|
|
410
|
+
// The turn ended or moved on while the app looked.
|
|
411
|
+
if (signal?.aborted || this.toolRowStatus(call.toolCallId) !== "pending") return;
|
|
412
|
+
if (preview?.kind === "refusal") {
|
|
413
|
+
await this.deliver(failure(preview.message));
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
if (preview?.kind === "change") confirmedChange = preview.confirmKey;
|
|
417
|
+
// Nothing to approve: the operation re-checks and asks in the app itself if that changed.
|
|
418
|
+
if (preview?.kind === "no-change") {
|
|
419
|
+
confirmed = true;
|
|
420
|
+
} else {
|
|
421
|
+
this.dispatch({
|
|
422
|
+
type: "tool-awaiting-confirmation",
|
|
423
|
+
toolCallId: call.toolCallId,
|
|
424
|
+
...(preview?.kind === "change" ? { preview: preview.summary } : {}),
|
|
425
|
+
});
|
|
426
|
+
const answer = await this.awaitConfirmation(
|
|
427
|
+
call.toolCallId,
|
|
428
|
+
startedAt + toolCallRemainingMs(call, startedAt),
|
|
429
|
+
);
|
|
430
|
+
if (answer === "abandoned") return;
|
|
431
|
+
if (answer === "expired") {
|
|
432
|
+
await this.deliver({
|
|
433
|
+
turnId: call.turnId,
|
|
434
|
+
toolCallId: call.toolCallId,
|
|
435
|
+
status: "timeout",
|
|
436
|
+
truncated: false,
|
|
437
|
+
elapsedMs: Math.max(0, this.now() - startedAt),
|
|
438
|
+
note: NOT_APPROVED_IN_TIME_NOTE,
|
|
439
|
+
});
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
confirmed = answer === "approved";
|
|
443
|
+
}
|
|
393
444
|
if (!confirmed) {
|
|
394
445
|
await this.deliver({
|
|
395
446
|
turnId: call.turnId,
|
|
@@ -413,6 +464,7 @@ export class ASKGSessionController {
|
|
|
413
464
|
}
|
|
414
465
|
const payload = await executor.execute(call, {
|
|
415
466
|
confirmed: confirmed || !requiresLocalConfirmation(call),
|
|
467
|
+
...(confirmedChange ? { confirmedChange } : {}),
|
|
416
468
|
...(signal ? { signal } : {}),
|
|
417
469
|
});
|
|
418
470
|
await this.deliver(payload);
|
|
@@ -425,6 +477,28 @@ export class ASKGSessionController {
|
|
|
425
477
|
}
|
|
426
478
|
}
|
|
427
479
|
|
|
480
|
+
/**
|
|
481
|
+
* The operation's own account of a call that needs approval, when it has
|
|
482
|
+
* one. Null keeps the server's description.
|
|
483
|
+
*/
|
|
484
|
+
private async previewCall(call: ASKGToolCallEvent, signal?: AbortSignal): Promise<ASKGToolPreview | null> {
|
|
485
|
+
try {
|
|
486
|
+
const manifest = this.manifest ?? await this.options.loadManifest();
|
|
487
|
+
this.manifest = manifest;
|
|
488
|
+
return await this.options.getExecutor(manifest)?.preview?.(call, signal) ?? null;
|
|
489
|
+
} catch {
|
|
490
|
+
return null;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
private toolRowStatus(toolCallId: string): string | undefined {
|
|
495
|
+
for (const turn of this.state.turns) {
|
|
496
|
+
const row = turn.tools.find((entry) => entry.toolCallId === toolCallId);
|
|
497
|
+
if (row) return row.status;
|
|
498
|
+
}
|
|
499
|
+
return undefined;
|
|
500
|
+
}
|
|
501
|
+
|
|
428
502
|
/** Records a tool result locally, then posts it to the turn loop. */
|
|
429
503
|
private async deliver(payload: ToolResultPayload): Promise<void> {
|
|
430
504
|
this.dispatch({ type: "tool-result", payload });
|
|
@@ -444,25 +518,43 @@ export class ASKGSessionController {
|
|
|
444
518
|
}
|
|
445
519
|
}
|
|
446
520
|
|
|
447
|
-
/**
|
|
448
|
-
|
|
521
|
+
/**
|
|
522
|
+
* Waits for the person's answer to one call. The prompt closes on its own
|
|
523
|
+
* a little before the server stops waiting (`deadlineAt`, by this clock),
|
|
524
|
+
* so an approval always has time to land; an older server that waits less
|
|
525
|
+
* than the call declared says so in the frame, and is honoured the same way.
|
|
526
|
+
*/
|
|
527
|
+
private awaitConfirmation(toolCallId: string, deadlineAt: number): Promise<ConfirmationAnswer> {
|
|
528
|
+
return new Promise<ConfirmationAnswer>((resolve) => {
|
|
529
|
+
const timer = setTimeout(
|
|
530
|
+
() => this.settleConfirmation(toolCallId, "expired"),
|
|
531
|
+
Math.max(0, deadlineAt - CONFIRMATION_CLOSE_MARGIN_MS - this.now()),
|
|
532
|
+
);
|
|
533
|
+
this.confirmations.set(toolCallId, (answer) => {
|
|
534
|
+
clearTimeout(timer);
|
|
535
|
+
resolve(answer);
|
|
536
|
+
});
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/** Ends one prompt. Only the first answer counts; a later one does nothing. */
|
|
541
|
+
private settleConfirmation(toolCallId: string, answer: ConfirmationAnswer): void {
|
|
449
542
|
const resolve = this.confirmations.get(toolCallId);
|
|
450
543
|
if (!resolve) return;
|
|
451
544
|
this.confirmations.delete(toolCallId);
|
|
452
|
-
resolve(
|
|
545
|
+
resolve(answer);
|
|
453
546
|
}
|
|
454
547
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
resolve(false);
|
|
459
|
-
}
|
|
548
|
+
/** Answers a `user-data` or `broker` confirmation prompt. */
|
|
549
|
+
resolveConfirmation(toolCallId: string, approved: boolean): void {
|
|
550
|
+
this.settleConfirmation(toolCallId, approved ? "approved" : "declined");
|
|
460
551
|
}
|
|
461
552
|
|
|
462
553
|
/** Drops confirmations whose answer can no longer reach the turn. */
|
|
463
554
|
private abandonPendingConfirmations(): void {
|
|
464
|
-
for (const toolCallId of this.confirmations.keys())
|
|
465
|
-
|
|
555
|
+
for (const toolCallId of [...this.confirmations.keys()]) {
|
|
556
|
+
this.settleConfirmation(toolCallId, "abandoned");
|
|
557
|
+
}
|
|
466
558
|
}
|
|
467
559
|
|
|
468
560
|
/**
|
|
@@ -32,6 +32,7 @@ import { describeTrimmedLists, fitResultToBytes } from "./result-budget";
|
|
|
32
32
|
import {
|
|
33
33
|
remoteRequestForTool,
|
|
34
34
|
resolveRemoteToolBinding,
|
|
35
|
+
toolExecutionTimeoutMs,
|
|
35
36
|
} from "./manifest";
|
|
36
37
|
import {
|
|
37
38
|
ASKGUndoManager,
|
|
@@ -67,16 +68,38 @@ export interface ASKGToolExecutorDependencies {
|
|
|
67
68
|
interface ASKGToolExecutionOptions {
|
|
68
69
|
signal?: AbortSignal;
|
|
69
70
|
confirmed?: boolean;
|
|
71
|
+
/** The confirmKey of the preview the person approved, so the app does not ask again. */
|
|
72
|
+
confirmedChange?: string;
|
|
70
73
|
}
|
|
71
74
|
|
|
75
|
+
/**
|
|
76
|
+
* What a call needing approval will change, from the operation's own dry run:
|
|
77
|
+
* the list and listing it resolved rather than the arguments as sent.
|
|
78
|
+
*/
|
|
79
|
+
export type ASKGToolPreview =
|
|
80
|
+
| { kind: "change"; summary: string; confirmKey: string }
|
|
81
|
+
/**
|
|
82
|
+
* Nothing would change (already on the list), so there is nothing to
|
|
83
|
+
* approve. The operation checks again when it runs and asks in the app
|
|
84
|
+
* itself if that is no longer so.
|
|
85
|
+
*/
|
|
86
|
+
| { kind: "no-change" }
|
|
87
|
+
/** The app refuses the call as asked. */
|
|
88
|
+
| { kind: "refusal"; message: string };
|
|
89
|
+
|
|
72
90
|
export interface ASKGToolExecutor {
|
|
73
91
|
execute(
|
|
74
92
|
call: ASKGToolCallEvent,
|
|
75
93
|
options?: ASKGToolExecutionOptions,
|
|
76
94
|
): Promise<ToolResultPayload>;
|
|
95
|
+
/** Null when the call has no dry run that says more than its arguments. */
|
|
96
|
+
preview?(call: ASKGToolCallEvent, signal?: AbortSignal): Promise<ASKGToolPreview | null>;
|
|
77
97
|
undo(token: string, signal?: AbortSignal): Promise<AppliedUndo>;
|
|
78
98
|
}
|
|
79
99
|
|
|
100
|
+
/** A dry run answers from local state and at most one search. */
|
|
101
|
+
const PREVIEW_TIMEOUT_MS = 3_000;
|
|
102
|
+
|
|
80
103
|
interface ExecutionValue {
|
|
81
104
|
status: ToolResultStatus;
|
|
82
105
|
result?: unknown;
|
|
@@ -214,7 +237,11 @@ function inferRemoteRowCount(value: unknown): number | undefined {
|
|
|
214
237
|
return 1;
|
|
215
238
|
}
|
|
216
239
|
|
|
217
|
-
|
|
240
|
+
/**
|
|
241
|
+
* How much longer the server waits for this call, by its frame: its timeout,
|
|
242
|
+
* and never past the time it expires.
|
|
243
|
+
*/
|
|
244
|
+
export function toolCallRemainingMs(call: ASKGToolCallEvent, now: number): number {
|
|
218
245
|
const declared = Math.max(0, call.timeoutMs);
|
|
219
246
|
const expiresAt = Date.parse(call.expiresAt);
|
|
220
247
|
if (!Number.isFinite(expiresAt)) return declared;
|
|
@@ -346,7 +373,7 @@ export function createASKGToolExecutor(
|
|
|
346
373
|
return base({ status: "denied", note: "This tool call requires local confirmation." });
|
|
347
374
|
}
|
|
348
375
|
|
|
349
|
-
const timeoutMs = Math.min(manifest
|
|
376
|
+
const timeoutMs = Math.min(toolExecutionTimeoutMs(manifest), toolCallRemainingMs(call, now()));
|
|
350
377
|
try {
|
|
351
378
|
const value = await runWithDeadline(async (signal): Promise<ExecutionValue> => {
|
|
352
379
|
if (manifest.source === "headless") {
|
|
@@ -375,7 +402,10 @@ export function createASKGToolExecutor(
|
|
|
375
402
|
}
|
|
376
403
|
}
|
|
377
404
|
|
|
378
|
-
const response = await dependencies.remoteHandler(remoteRequestForTool(binding, call.args)
|
|
405
|
+
const response = await dependencies.remoteHandler(remoteRequestForTool(binding, call.args), {
|
|
406
|
+
signal,
|
|
407
|
+
...(options.confirmed && options.confirmedChange ? { confirmed: options.confirmedChange } : {}),
|
|
408
|
+
});
|
|
379
409
|
if (!response.ok) {
|
|
380
410
|
return {
|
|
381
411
|
status: "error",
|
|
@@ -413,8 +443,32 @@ export function createASKGToolExecutor(
|
|
|
413
443
|
}
|
|
414
444
|
};
|
|
415
445
|
|
|
446
|
+
const preview = async (call: ASKGToolCallEvent, signal?: AbortSignal): Promise<ASKGToolPreview | null> => {
|
|
447
|
+
const manifest = manifests.get(call.name);
|
|
448
|
+
if (!manifest || manifest.source !== "remote-op" || manifest.confirm !== "always") return null;
|
|
449
|
+
const binding = resolveRemoteToolBinding(call.name);
|
|
450
|
+
if (binding?.kind !== "operation") return null;
|
|
451
|
+
try {
|
|
452
|
+
const response = await runWithDeadline(
|
|
453
|
+
() => dependencies.remoteHandler({ type: "call", operation: binding.operation, input: call.args, dryRun: true, include: [] }),
|
|
454
|
+
PREVIEW_TIMEOUT_MS,
|
|
455
|
+
signal,
|
|
456
|
+
);
|
|
457
|
+
if (!response.ok) return { kind: "refusal", message: response.error.message };
|
|
458
|
+
const data = response.data as { summary?: unknown; confirmKey?: unknown; changes?: unknown } | null;
|
|
459
|
+
if (typeof data?.summary !== "string" || typeof data.confirmKey !== "string") return null;
|
|
460
|
+
return data.changes === false
|
|
461
|
+
? { kind: "no-change" }
|
|
462
|
+
: { kind: "change", summary: data.summary, confirmKey: data.confirmKey };
|
|
463
|
+
} catch {
|
|
464
|
+
// The person still approves the call as the server described it.
|
|
465
|
+
return null;
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
|
|
416
469
|
return {
|
|
417
470
|
execute,
|
|
471
|
+
preview,
|
|
418
472
|
undo: (token, signal) => undoManager.undo(token, signal),
|
|
419
473
|
};
|
|
420
474
|
}
|
|
@@ -25,6 +25,12 @@ import {
|
|
|
25
25
|
|
|
26
26
|
const HEADLESS_TOOL_TIMEOUT_MS = 30_000;
|
|
27
27
|
const REMOTE_TOOL_TIMEOUT_MS = 10_000;
|
|
28
|
+
/**
|
|
29
|
+
* A tool that asks first waits for a person to read the prompt and click, so
|
|
30
|
+
* the server holds the call this long: the minute the terminal relay gives a
|
|
31
|
+
* confirmation. A server from before the window holds it 10 s.
|
|
32
|
+
*/
|
|
33
|
+
const CONFIRM_TOOL_TIMEOUT_MS = 60_000;
|
|
28
34
|
const REMOTE_RESOURCE_TOOL_NAME = "app.get_resource";
|
|
29
35
|
|
|
30
36
|
const TOOL_NAME_REGEX = new RegExp(TOOL_NAME_PATTERN);
|
|
@@ -166,11 +172,14 @@ function headlessCandidates(registry: PaneFunctionCatalog): ManifestCandidate[]
|
|
|
166
172
|
return candidates;
|
|
167
173
|
}
|
|
168
174
|
|
|
175
|
+
/** Ask Gloom's tool results are text, so an operation that answers with a PNG is not offered there. */
|
|
176
|
+
const ASKG_REMOTE_OPERATIONS = REMOTE_OPERATIONS.filter((operation) => !operation.returnsImage);
|
|
177
|
+
|
|
169
178
|
function remoteCandidates(): ManifestCandidate[] {
|
|
170
|
-
const descriptors = remoteOperationDescriptors();
|
|
171
179
|
const operationsByName = new Map(
|
|
172
|
-
|
|
180
|
+
ASKG_REMOTE_OPERATIONS.map((operation) => [remoteOperationToolName(operation.id), operation]),
|
|
173
181
|
);
|
|
182
|
+
const descriptors = remoteOperationDescriptors().filter((descriptor) => operationsByName.has(descriptor.name));
|
|
174
183
|
const candidates = descriptors.map((descriptor): ManifestCandidate => ({
|
|
175
184
|
token: descriptor.name,
|
|
176
185
|
identity: `operation:${operationsByName.get(descriptor.name)?.id ?? descriptor.name}`,
|
|
@@ -181,10 +190,7 @@ function remoteCandidates(): ManifestCandidate[] {
|
|
|
181
190
|
description: descriptor.description,
|
|
182
191
|
writeTier: descriptor.writeTier,
|
|
183
192
|
inputSchema: descriptor.inputSchema,
|
|
184
|
-
|
|
185
|
-
? "always"
|
|
186
|
-
: "never",
|
|
187
|
-
timeoutMs: REMOTE_TOOL_TIMEOUT_MS,
|
|
193
|
+
...remoteConfirmation(descriptor.writeTier),
|
|
188
194
|
},
|
|
189
195
|
}));
|
|
190
196
|
|
|
@@ -217,6 +223,25 @@ function remoteCandidates(): ManifestCandidate[] {
|
|
|
217
223
|
return candidates;
|
|
218
224
|
}
|
|
219
225
|
|
|
226
|
+
/** Account and broker writes ask first, and get the minute that takes. */
|
|
227
|
+
function remoteConfirmation(writeTier: ClientToolManifest["writeTier"]): Pick<ClientToolManifest, "confirm" | "timeoutMs"> {
|
|
228
|
+
return writeTier === "user-data" || writeTier === "broker"
|
|
229
|
+
? { confirm: "always", timeoutMs: CONFIRM_TOOL_TIMEOUT_MS }
|
|
230
|
+
: { confirm: "never", timeoutMs: REMOTE_TOOL_TIMEOUT_MS };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* How long a call may run once it starts. A tool that asks first declares the
|
|
235
|
+
* window for the person and the write together; the write itself keeps the
|
|
236
|
+
* budget of every app action, counted from the approval rather than from the
|
|
237
|
+
* call. The server's deadline for the call still bounds it.
|
|
238
|
+
*/
|
|
239
|
+
export function toolExecutionTimeoutMs(manifest: Pick<ClientToolManifest, "confirm" | "timeoutMs">): number {
|
|
240
|
+
return manifest.confirm === "always"
|
|
241
|
+
? Math.min(manifest.timeoutMs, REMOTE_TOOL_TIMEOUT_MS)
|
|
242
|
+
: manifest.timeoutMs;
|
|
243
|
+
}
|
|
244
|
+
|
|
220
245
|
function compareManifests(left: ClientToolManifest, right: ClientToolManifest): number {
|
|
221
246
|
return compareText(left.name, right.name) || compareText(left.source, right.source);
|
|
222
247
|
}
|
|
@@ -314,7 +339,7 @@ export async function buildASKGClientManifest(
|
|
|
314
339
|
|
|
315
340
|
export function resolveRemoteToolBinding(name: string): RemoteToolBinding | null {
|
|
316
341
|
if (name === REMOTE_RESOURCE_TOOL_NAME) return { kind: "resource" };
|
|
317
|
-
const operation =
|
|
342
|
+
const operation = ASKG_REMOTE_OPERATIONS.find((entry) => remoteOperationToolName(entry.id) === name);
|
|
318
343
|
return operation ? { kind: "operation", operation: operation.id } : null;
|
|
319
344
|
}
|
|
320
345
|
|