opencandle 0.5.0 → 0.6.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 +164 -187
- package/dist/analysts/contracts.d.ts +1 -3
- package/dist/analysts/contracts.js +1 -11
- package/dist/analysts/contracts.js.map +1 -1
- package/dist/analysts/orchestrator.d.ts +1 -3
- package/dist/analysts/orchestrator.js +1 -26
- package/dist/analysts/orchestrator.js.map +1 -1
- package/dist/cli.js +30 -7
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +3 -3
- package/dist/config.js +12 -5
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/infra/browser.js +3 -1
- package/dist/infra/browser.js.map +1 -1
- package/dist/infra/cache.d.ts +8 -11
- package/dist/infra/cache.js +17 -15
- package/dist/infra/cache.js.map +1 -1
- package/dist/infra/http-client.d.ts +4 -1
- package/dist/infra/http-client.js +59 -6
- package/dist/infra/http-client.js.map +1 -1
- package/dist/infra/index.d.ts +3 -3
- package/dist/infra/index.js +3 -3
- package/dist/infra/index.js.map +1 -1
- package/dist/infra/native-dependencies.js +2 -2
- package/dist/infra/native-dependencies.js.map +1 -1
- package/dist/infra/node-version.js.map +1 -1
- package/dist/infra/opencandle-paths.d.ts +0 -3
- package/dist/infra/opencandle-paths.js +4 -11
- package/dist/infra/opencandle-paths.js.map +1 -1
- package/dist/infra/rate-limiter.js +12 -9
- package/dist/infra/rate-limiter.js.map +1 -1
- package/dist/market-state/alert-conditions.d.ts +34 -0
- package/dist/market-state/alert-conditions.js +23 -0
- package/dist/market-state/alert-conditions.js.map +1 -0
- package/dist/market-state/alert-runner.d.ts +55 -0
- package/dist/market-state/alert-runner.js +634 -0
- package/dist/market-state/alert-runner.js.map +1 -0
- package/dist/market-state/daily-report.d.ts +26 -0
- package/dist/market-state/daily-report.js +179 -0
- package/dist/market-state/daily-report.js.map +1 -0
- package/dist/market-state/local-automation-service.d.ts +25 -0
- package/dist/market-state/local-automation-service.js +119 -0
- package/dist/market-state/local-automation-service.js.map +1 -0
- package/dist/market-state/notification-delivery.d.ts +14 -0
- package/dist/market-state/notification-delivery.js +139 -0
- package/dist/market-state/notification-delivery.js.map +1 -0
- package/dist/market-state/resolve-for-mutation.d.ts +10 -0
- package/dist/market-state/resolve-for-mutation.js +15 -0
- package/dist/market-state/resolve-for-mutation.js.map +1 -0
- package/dist/market-state/resolve.d.ts +14 -0
- package/dist/market-state/resolve.js +89 -0
- package/dist/market-state/resolve.js.map +1 -0
- package/dist/market-state/service.d.ts +527 -0
- package/dist/market-state/service.js +1099 -0
- package/dist/market-state/service.js.map +1 -0
- package/dist/memory/index.d.ts +7 -7
- package/dist/memory/index.js +6 -6
- package/dist/memory/index.js.map +1 -1
- package/dist/memory/manager.js +11 -11
- package/dist/memory/manager.js.map +1 -1
- package/dist/memory/retrieval.js +7 -4
- package/dist/memory/retrieval.js.map +1 -1
- package/dist/memory/sqlite.js +385 -3
- package/dist/memory/sqlite.js.map +1 -1
- package/dist/memory/storage.js +1 -2
- package/dist/memory/storage.js.map +1 -1
- package/dist/memory/tool-defaults.js +64 -28
- package/dist/memory/tool-defaults.js.map +1 -1
- package/dist/memory/types.js.map +1 -1
- package/dist/monitor.d.ts +2 -0
- package/dist/monitor.js +104 -0
- package/dist/monitor.js.map +1 -0
- package/dist/onboarding/connect.js +4 -6
- package/dist/onboarding/connect.js.map +1 -1
- package/dist/onboarding/credential-interceptor.js +1 -1
- package/dist/onboarding/credential-interceptor.js.map +1 -1
- package/dist/onboarding/degradation-accumulator.js +1 -3
- package/dist/onboarding/degradation-accumulator.js.map +1 -1
- package/dist/onboarding/providers.js +3 -16
- package/dist/onboarding/providers.js.map +1 -1
- package/dist/onboarding/state.js.map +1 -1
- package/dist/onboarding/tool-helpers.js +1 -1
- package/dist/onboarding/tool-helpers.js.map +1 -1
- package/dist/onboarding/tool-tags.js +6 -4
- package/dist/onboarding/tool-tags.js.map +1 -1
- package/dist/onboarding/validation.js +1 -1
- package/dist/onboarding/validation.js.map +1 -1
- package/dist/pi/opencandle-extension.d.ts +8 -0
- package/dist/pi/opencandle-extension.js +412 -28
- package/dist/pi/opencandle-extension.js.map +1 -1
- package/dist/pi/session.d.ts +1 -1
- package/dist/pi/session.js +3 -1
- package/dist/pi/session.js.map +1 -1
- package/dist/pi/setup.js +8 -3
- package/dist/pi/setup.js.map +1 -1
- package/dist/pi/tool-adapter.js +5 -2
- package/dist/pi/tool-adapter.js.map +1 -1
- package/dist/prompts/context-builder.d.ts +1 -1
- package/dist/prompts/context-builder.js +19 -6
- package/dist/prompts/context-builder.js.map +1 -1
- package/dist/prompts/policy-cards.d.ts +1 -1
- package/dist/prompts/policy-cards.js +1 -1
- package/dist/prompts/policy-cards.js.map +1 -1
- package/dist/prompts/sections.d.ts +1 -1
- package/dist/prompts/symbol-preflight.d.ts +20 -0
- package/dist/prompts/symbol-preflight.js +49 -0
- package/dist/prompts/symbol-preflight.js.map +1 -0
- package/dist/prompts/workflow-prompts.d.ts +1 -1
- package/dist/prompts/workflow-prompts.js +54 -16
- package/dist/prompts/workflow-prompts.js.map +1 -1
- package/dist/providers/alpha-vantage.d.ts +1 -1
- package/dist/providers/alpha-vantage.js +26 -7
- package/dist/providers/alpha-vantage.js.map +1 -1
- package/dist/providers/coingecko.js +1 -1
- package/dist/providers/coingecko.js.map +1 -1
- package/dist/providers/errors.d.ts +5 -0
- package/dist/providers/errors.js +11 -0
- package/dist/providers/errors.js.map +1 -0
- package/dist/providers/exa-search.d.ts +2 -2
- package/dist/providers/exa-search.js +19 -11
- package/dist/providers/exa-search.js.map +1 -1
- package/dist/providers/fear-greed.js +1 -1
- package/dist/providers/fear-greed.js.map +1 -1
- package/dist/providers/finnhub.js +3 -5
- package/dist/providers/finnhub.js.map +1 -1
- package/dist/providers/fred.js +2 -2
- package/dist/providers/fred.js.map +1 -1
- package/dist/providers/index.d.ts +7 -6
- package/dist/providers/index.js +6 -5
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/reddit.js +2 -2
- package/dist/providers/reddit.js.map +1 -1
- package/dist/providers/sec-edgar.d.ts +1 -0
- package/dist/providers/sec-edgar.js +12 -4
- package/dist/providers/sec-edgar.js.map +1 -1
- package/dist/providers/tradingview.d.ts +47 -0
- package/dist/providers/tradingview.js +275 -0
- package/dist/providers/tradingview.js.map +1 -0
- package/dist/providers/twitter.js +6 -8
- package/dist/providers/twitter.js.map +1 -1
- package/dist/providers/web-search.js +26 -12
- package/dist/providers/web-search.js.map +1 -1
- package/dist/providers/with-fallback.js +4 -2
- package/dist/providers/with-fallback.js.map +1 -1
- package/dist/providers/wrap-provider.d.ts +2 -3
- package/dist/providers/wrap-provider.js +14 -8
- package/dist/providers/wrap-provider.js.map +1 -1
- package/dist/providers/yahoo-finance.d.ts +1 -1
- package/dist/providers/yahoo-finance.js +101 -17
- package/dist/providers/yahoo-finance.js.map +1 -1
- package/dist/routing/classify-intent.d.ts +6 -0
- package/dist/routing/classify-intent.js +78 -7
- package/dist/routing/classify-intent.js.map +1 -1
- package/dist/routing/defaults.d.ts +1 -1
- package/dist/routing/entity-extractor.d.ts +1 -0
- package/dist/routing/entity-extractor.js +234 -29
- package/dist/routing/entity-extractor.js.map +1 -1
- package/dist/routing/fund-symbols.d.ts +2 -0
- package/dist/routing/fund-symbols.js +55 -0
- package/dist/routing/fund-symbols.js.map +1 -0
- package/dist/routing/horizon.d.ts +1 -0
- package/dist/routing/horizon.js +10 -0
- package/dist/routing/horizon.js.map +1 -0
- package/dist/routing/index.d.ts +10 -10
- package/dist/routing/index.js +6 -6
- package/dist/routing/index.js.map +1 -1
- package/dist/routing/planning.d.ts +1 -1
- package/dist/routing/planning.js +65 -34
- package/dist/routing/planning.js.map +1 -1
- package/dist/routing/route-manifest.d.ts +2 -2
- package/dist/routing/route-manifest.js +25 -4
- package/dist/routing/route-manifest.js.map +1 -1
- package/dist/routing/router-llm-client.js.map +1 -1
- package/dist/routing/router-prompt.js +7 -9
- package/dist/routing/router-prompt.js.map +1 -1
- package/dist/routing/router-types.d.ts +1 -0
- package/dist/routing/router.js +137 -22
- package/dist/routing/router.js.map +1 -1
- package/dist/routing/slot-resolver.d.ts +1 -1
- package/dist/routing/slot-resolver.js +2 -4
- package/dist/routing/slot-resolver.js.map +1 -1
- package/dist/routing/symbol-disambiguator.d.ts +11 -0
- package/dist/routing/symbol-disambiguator.js +52 -0
- package/dist/routing/symbol-disambiguator.js.map +1 -0
- package/dist/routing/turn-context.d.ts +1 -1
- package/dist/routing/turn-context.js +1 -1
- package/dist/routing/turn-context.js.map +1 -1
- package/dist/routing/types.d.ts +2 -0
- package/dist/runtime/answer-contracts.js +36 -8
- package/dist/runtime/answer-contracts.js.map +1 -1
- package/dist/runtime/artifact-contracts.js.map +1 -1
- package/dist/runtime/planning-evidence.js +47 -26
- package/dist/runtime/planning-evidence.js.map +1 -1
- package/dist/runtime/prompt-step.d.ts +1 -9
- package/dist/runtime/prompt-step.js +0 -10
- package/dist/runtime/prompt-step.js.map +1 -1
- package/dist/runtime/run-context.d.ts +5 -2
- package/dist/runtime/run-context.js +8 -1
- package/dist/runtime/run-context.js.map +1 -1
- package/dist/runtime/session-coordinator.d.ts +13 -5
- package/dist/runtime/session-coordinator.js +160 -20
- package/dist/runtime/session-coordinator.js.map +1 -1
- package/dist/runtime/session-title.d.ts +14 -0
- package/dist/runtime/session-title.js +50 -0
- package/dist/runtime/session-title.js.map +1 -0
- package/dist/runtime/tool-defaults-wrapper.js +1 -3
- package/dist/runtime/tool-defaults-wrapper.js.map +1 -1
- package/dist/runtime/validation.js.map +1 -1
- package/dist/runtime/workflow-events.js.map +1 -1
- package/dist/runtime/workflow-runner.d.ts +3 -3
- package/dist/runtime/workflow-runner.js +1 -1
- package/dist/runtime/workflow-runner.js.map +1 -1
- package/dist/sentiment/adapters/finnhub.d.ts +1 -1
- package/dist/sentiment/adapters/finnhub.js +6 -1
- package/dist/sentiment/adapters/finnhub.js.map +1 -1
- package/dist/sentiment/adapters/reddit.d.ts +2 -2
- package/dist/sentiment/adapters/twitter.d.ts +1 -1
- package/dist/sentiment/adapters/web.d.ts +1 -1
- package/dist/sentiment/index.d.ts +9 -11
- package/dist/sentiment/index.js +9 -20
- package/dist/sentiment/index.js.map +1 -1
- package/dist/sentiment/keywords.js +26 -4
- package/dist/sentiment/keywords.js.map +1 -1
- package/dist/sentiment/pipeline.d.ts +2 -2
- package/dist/sentiment/pipeline.js +1 -1
- package/dist/sentiment/pipeline.js.map +1 -1
- package/dist/sentiment/scorer.js +1 -1
- package/dist/sentiment/store.d.ts +1 -1
- package/dist/sentiment/store.js +1 -1
- package/dist/sentiment/store.js.map +1 -1
- package/dist/sentiment/trends.d.ts +1 -1
- package/dist/sentiment/trends.js.map +1 -1
- package/dist/sentiment/types.js.map +1 -1
- package/dist/system-prompt.js +3 -2
- package/dist/system-prompt.js.map +1 -1
- package/dist/tool-kit.d.ts +7 -7
- package/dist/tool-kit.js +4 -4
- package/dist/tool-kit.js.map +1 -1
- package/dist/tools/fundamentals/company-overview.js +11 -6
- package/dist/tools/fundamentals/company-overview.js.map +1 -1
- package/dist/tools/fundamentals/comps.js +18 -9
- package/dist/tools/fundamentals/comps.js.map +1 -1
- package/dist/tools/fundamentals/dcf.js +23 -11
- package/dist/tools/fundamentals/dcf.js.map +1 -1
- package/dist/tools/fundamentals/earnings.js +8 -3
- package/dist/tools/fundamentals/earnings.js.map +1 -1
- package/dist/tools/fundamentals/financials.js +8 -3
- package/dist/tools/fundamentals/financials.js.map +1 -1
- package/dist/tools/fundamentals/sec-filings.js +21 -6
- package/dist/tools/fundamentals/sec-filings.js.map +1 -1
- package/dist/tools/index.d.ts +23 -19
- package/dist/tools/index.js +51 -39
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/interaction/ask-user.js +15 -3
- package/dist/tools/interaction/ask-user.js.map +1 -1
- package/dist/tools/interaction/twitter-login.js +13 -3
- package/dist/tools/interaction/twitter-login.js.map +1 -1
- package/dist/tools/macro/fear-greed.js.map +1 -1
- package/dist/tools/macro/fred-data.d.ts +1 -1
- package/dist/tools/macro/fred-data.js +17 -6
- package/dist/tools/macro/fred-data.js.map +1 -1
- package/dist/tools/market/crypto-history.js +3 -1
- package/dist/tools/market/crypto-history.js.map +1 -1
- package/dist/tools/market/crypto-price.js +3 -1
- package/dist/tools/market/crypto-price.js.map +1 -1
- package/dist/tools/market/screen-stocks.d.ts +18 -0
- package/dist/tools/market/screen-stocks.js +252 -0
- package/dist/tools/market/screen-stocks.js.map +1 -0
- package/dist/tools/market/search-ticker.js +160 -8
- package/dist/tools/market/search-ticker.js.map +1 -1
- package/dist/tools/market/stock-history.d.ts +2 -2
- package/dist/tools/market/stock-history.js +26 -7
- package/dist/tools/market/stock-history.js.map +1 -1
- package/dist/tools/market/stock-quote.js +5 -3
- package/dist/tools/market/stock-quote.js.map +1 -1
- package/dist/tools/options/greeks.js +1 -1
- package/dist/tools/options/greeks.js.map +1 -1
- package/dist/tools/options/option-chain.js +19 -6
- package/dist/tools/options/option-chain.js.map +1 -1
- package/dist/tools/portfolio/alerts.d.ts +15 -0
- package/dist/tools/portfolio/alerts.js +357 -0
- package/dist/tools/portfolio/alerts.js.map +1 -0
- package/dist/tools/portfolio/correlation.d.ts +1 -1
- package/dist/tools/portfolio/correlation.js +33 -13
- package/dist/tools/portfolio/correlation.js.map +1 -1
- package/dist/tools/portfolio/daily-report.d.ts +8 -0
- package/dist/tools/portfolio/daily-report.js +83 -0
- package/dist/tools/portfolio/daily-report.js.map +1 -0
- package/dist/tools/portfolio/holdings-overlap.js +10 -3
- package/dist/tools/portfolio/holdings-overlap.js.map +1 -1
- package/dist/tools/portfolio/notifications.d.ts +7 -0
- package/dist/tools/portfolio/notifications.js +43 -0
- package/dist/tools/portfolio/notifications.js.map +1 -0
- package/dist/tools/portfolio/predictions.d.ts +12 -6
- package/dist/tools/portfolio/predictions.js +337 -87
- package/dist/tools/portfolio/predictions.js.map +1 -1
- package/dist/tools/portfolio/risk-analysis.d.ts +1 -1
- package/dist/tools/portfolio/risk-analysis.js +45 -6
- package/dist/tools/portfolio/risk-analysis.js.map +1 -1
- package/dist/tools/portfolio/tracker.d.ts +4 -3
- package/dist/tools/portfolio/tracker.js +246 -101
- package/dist/tools/portfolio/tracker.js.map +1 -1
- package/dist/tools/portfolio/watchlist.d.ts +6 -4
- package/dist/tools/portfolio/watchlist.js +208 -108
- package/dist/tools/portfolio/watchlist.js.map +1 -1
- package/dist/tools/sentiment/reddit-sentiment.js +23 -10
- package/dist/tools/sentiment/reddit-sentiment.js.map +1 -1
- package/dist/tools/sentiment/sentiment-summary.js +15 -13
- package/dist/tools/sentiment/sentiment-summary.js.map +1 -1
- package/dist/tools/sentiment/sentiment-trend.d.ts +1 -1
- package/dist/tools/sentiment/sentiment-trend.js +12 -2
- package/dist/tools/sentiment/sentiment-trend.js.map +1 -1
- package/dist/tools/sentiment/twitter-sentiment.js +12 -5
- package/dist/tools/sentiment/twitter-sentiment.js.map +1 -1
- package/dist/tools/sentiment/untrusted-text.d.ts +2 -0
- package/dist/tools/sentiment/untrusted-text.js +17 -0
- package/dist/tools/sentiment/untrusted-text.js.map +1 -0
- package/dist/tools/sentiment/web-search.js +9 -13
- package/dist/tools/sentiment/web-search.js.map +1 -1
- package/dist/tools/sentiment/web-sentiment.js +15 -3
- package/dist/tools/sentiment/web-sentiment.js.map +1 -1
- package/dist/tools/technical/backtest.d.ts +1 -1
- package/dist/tools/technical/backtest.js +27 -20
- package/dist/tools/technical/backtest.js.map +1 -1
- package/dist/tools/technical/indicators.js +23 -5
- package/dist/tools/technical/indicators.js.map +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.js.map +1 -1
- package/dist/types/market.d.ts +1 -0
- package/dist/types/portfolio.d.ts +14 -4
- package/dist/workflows/compare-assets.d.ts +0 -3
- package/dist/workflows/compare-assets.js +20 -11
- package/dist/workflows/compare-assets.js.map +1 -1
- package/dist/workflows/index.d.ts +3 -4
- package/dist/workflows/index.js +3 -3
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/options-screener.d.ts +0 -3
- package/dist/workflows/options-screener.js +4 -11
- package/dist/workflows/options-screener.js.map +1 -1
- package/dist/workflows/portfolio-builder.d.ts +0 -3
- package/dist/workflows/portfolio-builder.js +0 -8
- package/dist/workflows/portfolio-builder.js.map +1 -1
- package/gui/server/ask-user-bridge.ts +1 -1
- package/gui/server/automation-heartbeat.ts +97 -0
- package/gui/server/background-quotes.ts +97 -1
- package/gui/server/chat-event-adapter.ts +32 -10
- package/gui/server/chat-run-session.ts +16 -0
- package/gui/server/invoke-tool.ts +144 -1
- package/gui/server/live-chat-event-adapter.ts +21 -6
- package/gui/server/market-state-api.ts +315 -0
- package/gui/server/model-setup.ts +149 -2
- package/gui/server/private-api-access.ts +62 -0
- package/gui/server/projector.ts +12 -7
- package/gui/server/prompt-observation.ts +4 -7
- package/gui/server/quote-snapshot-store.ts +50 -0
- package/gui/server/server.ts +200 -451
- package/gui/server/session-actions.ts +186 -1
- package/gui/server/shutdown.ts +47 -0
- package/gui/server/tool-invoke-ack.ts +49 -0
- package/gui/server/tool-metadata.ts +23 -10
- package/gui/server/websocket.ts +13 -3
- package/gui/server/writer-lock.ts +6 -2
- package/gui/server/ws-hub.ts +292 -0
- package/gui/shared/chat-events.ts +16 -1
- package/gui/shared/event-reducer.ts +24 -6
- package/gui/web/dist/assets/CatalogOverlay-eJ2cBk33.js +1 -0
- package/gui/web/dist/assets/index-2KZtKBmu.css +1 -0
- package/gui/web/dist/assets/index-CveNgtDg.js +69 -0
- package/gui/web/dist/index.html +2 -2
- package/package.json +5 -1
- package/src/analysts/contracts.ts +10 -23
- package/src/analysts/orchestrator.ts +8 -43
- package/src/cli.ts +35 -12
- package/src/config.ts +17 -9
- package/src/index.ts +1 -1
- package/src/infra/browser.ts +3 -1
- package/src/infra/cache.ts +41 -30
- package/src/infra/http-client.ts +72 -6
- package/src/infra/index.ts +7 -10
- package/src/infra/native-dependencies.ts +8 -3
- package/src/infra/node-version.ts +3 -1
- package/src/infra/opencandle-paths.ts +3 -14
- package/src/infra/rate-limiter.ts +22 -19
- package/src/market-state/alert-conditions.ts +82 -0
- package/src/market-state/alert-runner.ts +863 -0
- package/src/market-state/daily-report.ts +247 -0
- package/src/market-state/local-automation-service.ts +162 -0
- package/src/market-state/notification-delivery.ts +158 -0
- package/src/market-state/resolve-for-mutation.ts +24 -0
- package/src/market-state/resolve.ts +112 -0
- package/src/market-state/service.ts +2344 -0
- package/src/memory/index.ts +7 -7
- package/src/memory/manager.ts +14 -16
- package/src/memory/retrieval.ts +8 -7
- package/src/memory/sqlite.ts +407 -6
- package/src/memory/storage.ts +5 -15
- package/src/memory/tool-defaults.ts +60 -39
- package/src/memory/types.ts +3 -3
- package/src/monitor.ts +121 -0
- package/src/onboarding/connect.ts +10 -33
- package/src/onboarding/credential-interceptor.ts +3 -15
- package/src/onboarding/degradation-accumulator.ts +1 -3
- package/src/onboarding/providers.ts +9 -40
- package/src/onboarding/state.ts +4 -15
- package/src/onboarding/tool-helpers.ts +2 -9
- package/src/onboarding/tool-tags.ts +6 -6
- package/src/onboarding/validation.ts +14 -20
- package/src/pi/opencandle-extension.ts +529 -85
- package/src/pi/session.ts +7 -5
- package/src/pi/setup.ts +61 -43
- package/src/pi/tool-adapter.ts +5 -2
- package/src/prompts/context-builder.ts +23 -12
- package/src/prompts/policy-cards.ts +2 -2
- package/src/prompts/sections.ts +1 -1
- package/src/prompts/symbol-preflight.ts +80 -0
- package/src/prompts/workflow-prompts.ts +77 -28
- package/src/providers/alpha-vantage.ts +58 -39
- package/src/providers/coingecko.ts +2 -5
- package/src/providers/errors.ts +9 -0
- package/src/providers/exa-search.ts +24 -22
- package/src/providers/fear-greed.ts +1 -1
- package/src/providers/finnhub.ts +7 -6
- package/src/providers/fred.ts +3 -3
- package/src/providers/index.ts +14 -6
- package/src/providers/reddit.ts +17 -6
- package/src/providers/sec-edgar.ts +20 -6
- package/src/providers/tradingview.ts +399 -0
- package/src/providers/twitter.ts +6 -8
- package/src/providers/web-search.ts +30 -20
- package/src/providers/with-fallback.ts +8 -7
- package/src/providers/wrap-provider.ts +15 -10
- package/src/providers/yahoo-finance.ts +140 -35
- package/src/routing/classify-intent.ts +101 -10
- package/src/routing/defaults.ts +1 -1
- package/src/routing/entity-extractor.ts +287 -38
- package/src/routing/fund-symbols.ts +58 -0
- package/src/routing/horizon.ts +7 -0
- package/src/routing/index.ts +48 -48
- package/src/routing/planning.ts +144 -53
- package/src/routing/route-manifest.ts +37 -15
- package/src/routing/router-llm-client.ts +4 -4
- package/src/routing/router-prompt.ts +15 -19
- package/src/routing/router-types.ts +2 -5
- package/src/routing/router.ts +251 -53
- package/src/routing/slot-resolver.ts +34 -11
- package/src/routing/symbol-disambiguator.ts +72 -0
- package/src/routing/turn-context.ts +6 -9
- package/src/routing/types.ts +2 -0
- package/src/runtime/answer-contracts.ts +82 -43
- package/src/runtime/artifact-contracts.ts +2 -1
- package/src/runtime/planning-evidence.ts +157 -66
- package/src/runtime/prompt-step.ts +1 -16
- package/src/runtime/run-context.ts +12 -2
- package/src/runtime/session-coordinator.ts +238 -63
- package/src/runtime/session-title.ts +60 -0
- package/src/runtime/tool-defaults-wrapper.ts +1 -3
- package/src/runtime/validation.ts +1 -4
- package/src/runtime/workflow-events.ts +7 -7
- package/src/runtime/workflow-runner.ts +5 -11
- package/src/sentiment/adapters/finnhub.ts +7 -2
- package/src/sentiment/adapters/reddit.ts +2 -2
- package/src/sentiment/adapters/twitter.ts +1 -1
- package/src/sentiment/adapters/web.ts +1 -1
- package/src/sentiment/index.ts +16 -26
- package/src/sentiment/keywords.ts +26 -4
- package/src/sentiment/pipeline.ts +15 -4
- package/src/sentiment/scorer.ts +1 -1
- package/src/sentiment/store.ts +2 -2
- package/src/sentiment/trends.ts +9 -3
- package/src/sentiment/types.ts +5 -4
- package/src/system-prompt.ts +3 -2
- package/src/tool-kit.ts +10 -9
- package/src/tools/fundamentals/company-overview.ts +19 -9
- package/src/tools/fundamentals/comps.ts +68 -55
- package/src/tools/fundamentals/dcf.ts +145 -95
- package/src/tools/fundamentals/earnings.ts +16 -6
- package/src/tools/fundamentals/financials.ts +16 -7
- package/src/tools/fundamentals/sec-filings.ts +37 -16
- package/src/tools/index.ts +51 -39
- package/src/tools/interaction/ask-user.ts +22 -10
- package/src/tools/interaction/twitter-login.ts +17 -5
- package/src/tools/macro/fear-greed.ts +1 -1
- package/src/tools/macro/fred-data.ts +58 -46
- package/src/tools/market/crypto-history.ts +8 -3
- package/src/tools/market/crypto-price.ts +6 -6
- package/src/tools/market/screen-stocks.ts +279 -0
- package/src/tools/market/search-ticker.ts +218 -17
- package/src/tools/market/stock-history.ts +37 -12
- package/src/tools/market/stock-quote.ts +10 -7
- package/src/tools/options/greeks.ts +5 -5
- package/src/tools/options/option-chain.ts +41 -17
- package/src/tools/portfolio/alerts.ts +457 -0
- package/src/tools/portfolio/correlation.ts +47 -20
- package/src/tools/portfolio/daily-report.ts +101 -0
- package/src/tools/portfolio/holdings-overlap.ts +31 -15
- package/src/tools/portfolio/notifications.ts +45 -0
- package/src/tools/portfolio/predictions.ts +406 -106
- package/src/tools/portfolio/risk-analysis.ts +46 -7
- package/src/tools/portfolio/tracker.ts +270 -109
- package/src/tools/portfolio/watchlist.ts +250 -121
- package/src/tools/sentiment/reddit-sentiment.ts +50 -24
- package/src/tools/sentiment/sentiment-summary.ts +62 -41
- package/src/tools/sentiment/sentiment-trend.ts +24 -7
- package/src/tools/sentiment/twitter-sentiment.ts +22 -15
- package/src/tools/sentiment/untrusted-text.ts +21 -0
- package/src/tools/sentiment/web-search.ts +21 -18
- package/src/tools/sentiment/web-sentiment.ts +26 -10
- package/src/tools/technical/backtest.ts +32 -22
- package/src/tools/technical/indicators.ts +39 -14
- package/src/types/index.ts +8 -3
- package/src/types/market.ts +1 -0
- package/src/types/portfolio.ts +14 -4
- package/src/types/sentiment.ts +2 -2
- package/src/workflows/compare-assets.ts +33 -21
- package/src/workflows/index.ts +3 -4
- package/src/workflows/options-screener.ts +27 -29
- package/src/workflows/portfolio-builder.ts +34 -27
- package/dist/workflows/types.d.ts +0 -4
- package/dist/workflows/types.js +0 -2
- package/dist/workflows/types.js.map +0 -1
- package/gui/web/dist/assets/CatalogOverlay-Bmp6Knu7.js +0 -1
- package/gui/web/dist/assets/index-Bxt9QpLX.css +0 -1
- package/gui/web/dist/assets/index-CZ9DHZYy.js +0 -67
- package/src/workflows/types.ts +0 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Type } from "@sinclair/typebox";
|
|
2
1
|
import type { AgentTool } from "@earendil-works/pi-agent-core";
|
|
3
|
-
import {
|
|
2
|
+
import { Type } from "@sinclair/typebox";
|
|
4
3
|
import { wrapProvider } from "../../providers/wrap-provider.js";
|
|
4
|
+
import { getHistory } from "../../providers/yahoo-finance.js";
|
|
5
5
|
import type { OHLCV } from "../../types/market.js";
|
|
6
6
|
|
|
7
7
|
// --- Volume-based indicators ---
|
|
@@ -52,7 +52,12 @@ export const technicalIndicatorsTool: AgentTool<typeof params> = {
|
|
|
52
52
|
const result = await wrapProvider("yahoo", () => getHistory(symbol, range, "1d"));
|
|
53
53
|
if (result.status === "unavailable") {
|
|
54
54
|
return {
|
|
55
|
-
content: [
|
|
55
|
+
content: [
|
|
56
|
+
{
|
|
57
|
+
type: "text",
|
|
58
|
+
text: `⚠ Technical indicators unavailable for ${symbol} (${result.reason}).`,
|
|
59
|
+
},
|
|
60
|
+
],
|
|
56
61
|
details: null as any,
|
|
57
62
|
};
|
|
58
63
|
}
|
|
@@ -61,7 +66,12 @@ export const technicalIndicatorsTool: AgentTool<typeof params> = {
|
|
|
61
66
|
|
|
62
67
|
if (closes.length < 26) {
|
|
63
68
|
return {
|
|
64
|
-
content: [
|
|
69
|
+
content: [
|
|
70
|
+
{
|
|
71
|
+
type: "text",
|
|
72
|
+
text: `Insufficient data for ${symbol} (need 26+ bars, got ${closes.length})`,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
65
75
|
details: null,
|
|
66
76
|
};
|
|
67
77
|
}
|
|
@@ -79,9 +89,12 @@ export const technicalIndicatorsTool: AgentTool<typeof params> = {
|
|
|
79
89
|
const latestMacd = macd[macd.length - 1];
|
|
80
90
|
const latestBB = bb[bb.length - 1];
|
|
81
91
|
const latestVwap = vwap[vwap.length - 1];
|
|
82
|
-
const obvTrend =
|
|
83
|
-
|
|
84
|
-
|
|
92
|
+
const obvTrend =
|
|
93
|
+
obv.length >= 20
|
|
94
|
+
? obv[obv.length - 1] > obv[obv.length - 20]
|
|
95
|
+
? "Rising"
|
|
96
|
+
: "Falling"
|
|
97
|
+
: "N/A";
|
|
85
98
|
|
|
86
99
|
const lines = [
|
|
87
100
|
`**${symbol} Technical Analysis** (${bars[0].date} to ${bars[bars.length - 1].date})`,
|
|
@@ -103,7 +116,13 @@ export const technicalIndicatorsTool: AgentTool<typeof params> = {
|
|
|
103
116
|
range,
|
|
104
117
|
prices: closes,
|
|
105
118
|
dates: bars.map((b) => b.date),
|
|
106
|
-
sma20,
|
|
119
|
+
sma20,
|
|
120
|
+
sma50,
|
|
121
|
+
rsi,
|
|
122
|
+
macd,
|
|
123
|
+
bb,
|
|
124
|
+
obv,
|
|
125
|
+
vwap,
|
|
107
126
|
},
|
|
108
127
|
};
|
|
109
128
|
},
|
|
@@ -241,16 +260,22 @@ function trendSummary(
|
|
|
241
260
|
|
|
242
261
|
if (latestSma20 && price > latestSma20) signals.push("Price above SMA(20) — short-term bullish");
|
|
243
262
|
if (latestSma20 && price < latestSma20) signals.push("Price below SMA(20) — short-term bearish");
|
|
244
|
-
if (latestSma20 && latestSma50 && latestSma20 > latestSma50)
|
|
245
|
-
|
|
263
|
+
if (latestSma20 && latestSma50 && latestSma20 > latestSma50)
|
|
264
|
+
signals.push("Golden cross pattern (SMA20 > SMA50)");
|
|
265
|
+
if (latestSma20 && latestSma50 && latestSma20 < latestSma50)
|
|
266
|
+
signals.push("Death cross pattern (SMA20 < SMA50)");
|
|
246
267
|
if (rsi != null && rsi >= 70) signals.push("RSI overbought — potential reversal");
|
|
247
268
|
if (rsi != null && rsi <= 30) signals.push("RSI oversold — potential bounce");
|
|
248
269
|
if (macd && macd.histogram > 0) signals.push("MACD bullish (histogram positive)");
|
|
249
270
|
if (macd && macd.histogram < 0) signals.push("MACD bearish (histogram negative)");
|
|
250
|
-
if (obvTrend === "Rising" && price > (latestSma20 ?? 0))
|
|
251
|
-
|
|
252
|
-
if (
|
|
253
|
-
|
|
271
|
+
if (obvTrend === "Rising" && price > (latestSma20 ?? 0))
|
|
272
|
+
signals.push("Volume confirming price advance (OBV rising)");
|
|
273
|
+
if (obvTrend === "Falling" && price < (latestSma20 ?? Infinity))
|
|
274
|
+
signals.push("Volume confirming price decline (OBV falling)");
|
|
275
|
+
if (vwap != null && price > vwap)
|
|
276
|
+
signals.push("Price above cumulative VWAP — bullish volume-weighted bias");
|
|
277
|
+
if (vwap != null && price < vwap)
|
|
278
|
+
signals.push("Price below cumulative VWAP — bearish volume-weighted bias");
|
|
254
279
|
|
|
255
280
|
return signals.length > 0 ? "Signals: " + signals.join(" | ") : "No strong signals";
|
|
256
281
|
}
|
package/src/types/index.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
export type { StockQuote, OHLCV, CryptoPrice } from "./market.js";
|
|
2
1
|
export type { CompanyOverview, EarningsData, FinancialStatement } from "./fundamentals.js";
|
|
3
2
|
export type { FredObservation, FredSeries } from "./macro.js";
|
|
4
3
|
export { FRED_SERIES } from "./macro.js";
|
|
4
|
+
export type { CryptoPrice, OHLCV, StockQuote } from "./market.js";
|
|
5
5
|
export type { Greeks, OptionContract, OptionsChain } from "./options.js";
|
|
6
|
-
export type {
|
|
7
|
-
export type {
|
|
6
|
+
export type { PortfolioSummary, Position, RiskMetrics, TechnicalIndicators } from "./portfolio.js";
|
|
7
|
+
export type {
|
|
8
|
+
FearGreedData,
|
|
9
|
+
RedditSentimentResult,
|
|
10
|
+
WebSearchEnvelope,
|
|
11
|
+
WebSearchResult,
|
|
12
|
+
} from "./sentiment.js";
|
|
8
13
|
|
|
9
14
|
/**
|
|
10
15
|
* Handler for `ask_user` tool invocations in non-UI contexts (e.g. test harness).
|
package/src/types/market.ts
CHANGED
package/src/types/portfolio.ts
CHANGED
|
@@ -2,23 +2,33 @@ export interface Position {
|
|
|
2
2
|
symbol: string;
|
|
3
3
|
shares: number;
|
|
4
4
|
avgCost: number;
|
|
5
|
+
currency: string;
|
|
5
6
|
addedAt: string;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
export interface PortfolioSummary {
|
|
9
10
|
positions: Array<
|
|
10
11
|
Position & {
|
|
11
|
-
currentPrice: number;
|
|
12
|
-
marketValue: number;
|
|
12
|
+
currentPrice: number | null;
|
|
13
|
+
marketValue: number | null;
|
|
13
14
|
totalCost: number;
|
|
14
|
-
pnl: number;
|
|
15
|
-
pnlPercent: number;
|
|
15
|
+
pnl: number | null;
|
|
16
|
+
pnlPercent: number | null;
|
|
17
|
+
includedInTotals: boolean;
|
|
18
|
+
quoteStatus?: "ok" | "unavailable";
|
|
19
|
+
exclusionReason?: string;
|
|
16
20
|
}
|
|
17
21
|
>;
|
|
22
|
+
baseCurrency: string;
|
|
18
23
|
totalValue: number;
|
|
19
24
|
totalCost: number;
|
|
20
25
|
totalPnl: number;
|
|
21
26
|
totalPnlPercent: number;
|
|
27
|
+
excludedFromTotals: Array<{
|
|
28
|
+
symbol: string;
|
|
29
|
+
currency: string;
|
|
30
|
+
reason: string;
|
|
31
|
+
}>;
|
|
22
32
|
}
|
|
23
33
|
|
|
24
34
|
export interface RiskMetrics {
|
package/src/types/sentiment.ts
CHANGED
|
@@ -23,7 +23,7 @@ export interface TwitterSentimentResult {
|
|
|
23
23
|
query: string;
|
|
24
24
|
tweetCount: number;
|
|
25
25
|
tweets: TwitterTweet[];
|
|
26
|
-
sentimentScore: number;
|
|
26
|
+
sentimentScore: number; // -1.0 (fully bearish) to +1.0 (fully bullish)
|
|
27
27
|
bullishCount: number;
|
|
28
28
|
bearishCount: number;
|
|
29
29
|
topMentions: string[];
|
|
@@ -63,7 +63,7 @@ export interface RedditSentimentResult {
|
|
|
63
63
|
created: string;
|
|
64
64
|
}>;
|
|
65
65
|
topMentions: string[];
|
|
66
|
-
sentimentScore: number;
|
|
66
|
+
sentimentScore: number; // -1.0 (fully bearish) to +1.0 (fully bullish)
|
|
67
67
|
bullishCount: number;
|
|
68
68
|
bearishCount: number;
|
|
69
69
|
fetchedAt: string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { CompareAssetsSlots, SlotResolution } from "../routing/types.js";
|
|
2
1
|
import { buildCompareAssetsPrompt } from "../prompts/workflow-prompts.js";
|
|
3
|
-
import
|
|
2
|
+
import { areLikelyFundOrIndexSymbols, isFundOrIndexAssetScope } from "../routing/fund-symbols.js";
|
|
3
|
+
import { isLongInvestmentHorizon } from "../routing/horizon.js";
|
|
4
|
+
import type { CompareAssetsSlots, SlotResolution } from "../routing/types.js";
|
|
4
5
|
import type { WorkflowDefinition } from "../runtime/prompt-step.js";
|
|
5
6
|
import { promptStep } from "../runtime/prompt-step.js";
|
|
6
7
|
|
|
@@ -12,11 +13,18 @@ export function buildCompareAssetsWorkflowDefinition(
|
|
|
12
13
|
const isMacroHedge = resolution.resolved.metrics?.includes("macro_hedge") ?? false;
|
|
13
14
|
const isInterestRateSensitive = resolution.resolved.metrics?.includes("interest_rates") ?? false;
|
|
14
15
|
const isOverlapComparison = resolution.resolved.metrics?.includes("overlap") ?? false;
|
|
16
|
+
const hasFundContext =
|
|
17
|
+
isFundOrIndexAssetScope(resolution.resolved.assetScope) ||
|
|
18
|
+
areLikelyFundOrIndexSymbols(resolution.resolved.symbols);
|
|
19
|
+
const shouldProbeFundOverlap =
|
|
20
|
+
!isOverlapComparison && isLongInvestmentHorizon(timeHorizon) && hasFundContext;
|
|
15
21
|
const evidenceList = resolution.resolved.metrics?.includes("sentiment")
|
|
16
22
|
? "price, technical, risk, and sentiment data"
|
|
17
23
|
: isOverlapComparison
|
|
18
24
|
? "quote, holdings-overlap, and correlation data"
|
|
19
|
-
|
|
25
|
+
: shouldProbeFundOverlap
|
|
26
|
+
? "price, technical, risk, correlation, and holdings-overlap data when applicable"
|
|
27
|
+
: "price, technical, and risk data";
|
|
20
28
|
const horizonGuidance = timeHorizon
|
|
21
29
|
? `
|
|
22
30
|
- Start by directly answering whether these assets are reasonable to compare for a ${timeHorizon} horizon.
|
|
@@ -40,10 +48,20 @@ export function buildCompareAssetsWorkflowDefinition(
|
|
|
40
48
|
- For ETF overlap prompts, synthesize the holdings-overlap and shared-exposure evidence first, with correlation only as supporting diversification context.
|
|
41
49
|
- State the diversification implication directly: deliberate factor tilt, accidental duplication, or genuinely differentiated exposure.
|
|
42
50
|
- If provider holdings coverage was partial or unavailable, say that before giving the practical next step.`
|
|
43
|
-
:
|
|
51
|
+
: shouldProbeFundOverlap
|
|
52
|
+
? `
|
|
53
|
+
- If these assets are ETFs, funds, or index products, synthesize holdings-overlap and shared-exposure evidence before correlation when that provider evidence is available.
|
|
54
|
+
- Compare fund role, broad style or sector tilt, dividend/income versus growth tradeoffs, taxable-account dividend drag, and any fetched expense ratio, yield, or AUM evidence.
|
|
55
|
+
- If expense ratio, yield, AUM, or constituent detail is unavailable, name that verification gap instead of filling it with approximate fund facts.
|
|
56
|
+
- If provider holdings coverage was partial or unavailable, say that before giving the practical next step.`
|
|
57
|
+
: "";
|
|
44
58
|
const verdictInstruction = isOverlapComparison
|
|
45
59
|
? "End with a concise verdict on whether the added fund improves diversification or mostly duplicates existing exposure."
|
|
46
|
-
:
|
|
60
|
+
: shouldProbeFundOverlap
|
|
61
|
+
? "End with a concise verdict tied to the user's horizon, fund roles, and diversification needs rather than short-term timing."
|
|
62
|
+
: timeHorizon
|
|
63
|
+
? `End with a concise verdict on which asset best fits the ${timeHorizon} horizon and why.`
|
|
64
|
+
: "End with a concise verdict on which asset looks strongest right now and why.";
|
|
47
65
|
|
|
48
66
|
return {
|
|
49
67
|
workflowType: "compare_assets",
|
|
@@ -52,24 +70,18 @@ export function buildCompareAssetsWorkflowDefinition(
|
|
|
52
70
|
requiredInputs: ["symbols"],
|
|
53
71
|
expectedOutputs: ["asset_data"],
|
|
54
72
|
}),
|
|
55
|
-
promptStep(
|
|
73
|
+
promptStep(
|
|
74
|
+
"compare_and_present",
|
|
75
|
+
"Present side-by-side comparison",
|
|
76
|
+
`Now present the side-by-side comparison for ${symbols}:
|
|
56
77
|
- Keep any unavailable fundamentals marked as unavailable instead of retrying the same failed provider calls.
|
|
57
78
|
- Use the ${evidenceList} you already fetched to finish the comparison even if some fundamentals are missing.
|
|
58
|
-
- ${verdictInstruction}${horizonGuidance}${macroHedgeGuidance}${interestRateGuidance}${overlapGuidance}`,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
79
|
+
- ${verdictInstruction}${horizonGuidance}${macroHedgeGuidance}${interestRateGuidance}${overlapGuidance}`,
|
|
80
|
+
{
|
|
81
|
+
requiredInputs: ["asset_data"],
|
|
82
|
+
expectedOutputs: ["comparison_summary"],
|
|
83
|
+
},
|
|
84
|
+
),
|
|
62
85
|
],
|
|
63
86
|
};
|
|
64
87
|
}
|
|
65
|
-
|
|
66
|
-
/** @deprecated Use buildCompareAssetsWorkflowDefinition instead */
|
|
67
|
-
export function buildCompareAssetsWorkflow(
|
|
68
|
-
resolution: SlotResolution<CompareAssetsSlots>,
|
|
69
|
-
): WorkflowPlan {
|
|
70
|
-
const def = buildCompareAssetsWorkflowDefinition(resolution);
|
|
71
|
-
return {
|
|
72
|
-
initialPrompt: def.steps[0].prompt,
|
|
73
|
-
followUps: def.steps.slice(1).map((s) => s.prompt),
|
|
74
|
-
};
|
|
75
|
-
}
|
package/src/workflows/index.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
4
|
-
export type { WorkflowPlan } from "./types.js";
|
|
1
|
+
export { buildCompareAssetsWorkflowDefinition } from "./compare-assets.js";
|
|
2
|
+
export { buildOptionsScreenerWorkflowDefinition } from "./options-screener.js";
|
|
3
|
+
export { buildPortfolioWorkflowDefinition } from "./portfolio-builder.js";
|
|
@@ -1,32 +1,34 @@
|
|
|
1
|
-
import type { OptionsScreenerSlots, SlotResolution } from "../routing/types.js";
|
|
2
1
|
import { buildOptionsScreenerPrompt } from "../prompts/workflow-prompts.js";
|
|
3
|
-
import type {
|
|
2
|
+
import type { OptionsScreenerSlots, SlotResolution } from "../routing/types.js";
|
|
4
3
|
import type { WorkflowDefinition } from "../runtime/prompt-step.js";
|
|
5
4
|
import { promptStep } from "../runtime/prompt-step.js";
|
|
6
5
|
|
|
7
|
-
export function buildOptionsScreenerWorkflowDefinition(
|
|
6
|
+
export function buildOptionsScreenerWorkflowDefinition(
|
|
7
|
+
resolution: SlotResolution<OptionsScreenerSlots>,
|
|
8
|
+
): WorkflowDefinition {
|
|
8
9
|
const s = resolution.resolved;
|
|
9
10
|
const isProtectivePutContext = s.optionStrategy === "protective_put";
|
|
10
11
|
const contractType = s.direction === "bullish" && !isProtectivePutContext ? "calls" : "puts";
|
|
11
12
|
const horizonPhrase = describeDteTarget(s.dteTarget);
|
|
12
|
-
const isCoveredCallContext =
|
|
13
|
-
|
|
14
|
-
s.
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
const isCoveredCallContext =
|
|
14
|
+
!isProtectivePutContext &&
|
|
15
|
+
(s.optionStrategy === "covered_call" ||
|
|
16
|
+
s.costBasis !== undefined ||
|
|
17
|
+
(s.catalystSymbols?.length ?? 0) > 0);
|
|
17
18
|
const rankingInstruction = isProtectivePutContext
|
|
18
19
|
? "Rank by protection per dollar of premium, expiration fit, moneyness, hedge floor, live liquidity, and premium as a percent of the stock position."
|
|
19
20
|
: isCoveredCallContext
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const maxPremiumInstruction =
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
? "Rank by premium collected, strike above cost basis, assignment risk, event risk, live liquidity, and probability of expiring out of the money."
|
|
22
|
+
: `Rank by ${s.objective}: balance premium cost, delta exposure, and probability of profit. Only include contracts with |delta| >= 0.20.`;
|
|
23
|
+
const maxPremiumInstruction =
|
|
24
|
+
s.maxPremium !== undefined
|
|
25
|
+
? ` Do not rank contracts above the user's max premium of $${s.maxPremium.toLocaleString("en-US")} unless no contracts under that cap are liquid; if so, say the cap could not be met.`
|
|
26
|
+
: "";
|
|
25
27
|
const riskInstruction = isProtectivePutContext
|
|
26
28
|
? "Include protective-put hedge risks: premium decay/cost, imperfect hedge before the strike, liquidity, and opportunity cost. Long protective puts do not have short-option assignment risk."
|
|
27
29
|
: isCoveredCallContext
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
? "Include covered-call sale risks: assignment risk, upside is capped at the strike plus premium, share-price downside in the owned stock less premium received, IV/event risk, and exit liquidity. Do not say max loss = premium or describe max loss as the option premium paid."
|
|
31
|
+
: "Include risk caveats: max loss = premium, IV crush risk, time decay (theta).";
|
|
30
32
|
const coveredCallFallback = isCoveredCallContext
|
|
31
33
|
? `
|
|
32
34
|
Covered-call fallback:
|
|
@@ -77,7 +79,10 @@ Protective-put requirements:
|
|
|
77
79
|
requiredInputs: ["symbol"],
|
|
78
80
|
expectedOutputs: ["option_chain"],
|
|
79
81
|
}),
|
|
80
|
-
promptStep(
|
|
82
|
+
promptStep(
|
|
83
|
+
"rank_and_present",
|
|
84
|
+
"Rank and present top contracts",
|
|
85
|
+
`Now rank and present the top ${contractType} for ${s.symbol}. You MUST produce a final text response — never end this turn with only tool calls.
|
|
81
86
|
|
|
82
87
|
1. From the option chain data already fetched, select the top 3-5 contracts matching: ${s.moneynessPreference} strikes, DTE near ${s.dteTarget}, with ${s.liquidityMinimum}.
|
|
83
88
|
2. ${rankingInstruction}${maxPremiumInstruction}
|
|
@@ -97,10 +102,12 @@ ${protectivePutFallback}
|
|
|
97
102
|
Length constraints:
|
|
98
103
|
- Max 1 sentence explaining the #1 pick.
|
|
99
104
|
- Risk section: max 3 bullets.
|
|
100
|
-
- Keep total response under 30 lines.`,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
105
|
+
- Keep total response under 30 lines.`,
|
|
106
|
+
{
|
|
107
|
+
requiredInputs: ["option_chain"],
|
|
108
|
+
expectedOutputs: ["ranked_contracts"],
|
|
109
|
+
},
|
|
110
|
+
),
|
|
104
111
|
],
|
|
105
112
|
};
|
|
106
113
|
}
|
|
@@ -116,12 +123,3 @@ function describeDteTarget(dteTarget: string): string {
|
|
|
116
123
|
if (plus) return `${plus[1]}+ day horizon`;
|
|
117
124
|
return `${dteTarget} horizon`;
|
|
118
125
|
}
|
|
119
|
-
|
|
120
|
-
/** @deprecated Use buildOptionsScreenerWorkflowDefinition instead */
|
|
121
|
-
export function buildOptionsScreenerWorkflow(resolution: SlotResolution<OptionsScreenerSlots>): WorkflowPlan {
|
|
122
|
-
const def = buildOptionsScreenerWorkflowDefinition(resolution);
|
|
123
|
-
return {
|
|
124
|
-
initialPrompt: def.steps[0].prompt,
|
|
125
|
-
followUps: def.steps.slice(1).map((s) => s.prompt),
|
|
126
|
-
};
|
|
127
|
-
}
|
|
@@ -1,30 +1,44 @@
|
|
|
1
|
-
import type { PortfolioSlots, SlotResolution } from "../routing/types.js";
|
|
2
1
|
import { buildPortfolioPrompt } from "../prompts/workflow-prompts.js";
|
|
3
|
-
import type {
|
|
2
|
+
import type { PortfolioSlots, SlotResolution } from "../routing/types.js";
|
|
4
3
|
import type { WorkflowDefinition } from "../runtime/prompt-step.js";
|
|
5
4
|
import { promptStep } from "../runtime/prompt-step.js";
|
|
6
5
|
|
|
7
|
-
export function buildPortfolioWorkflowDefinition(
|
|
6
|
+
export function buildPortfolioWorkflowDefinition(
|
|
7
|
+
resolution: SlotResolution<PortfolioSlots>,
|
|
8
|
+
): WorkflowDefinition {
|
|
8
9
|
const s = resolution.resolved;
|
|
9
10
|
|
|
10
11
|
return {
|
|
11
12
|
workflowType: "portfolio_builder",
|
|
12
13
|
steps: [
|
|
13
|
-
promptStep(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
promptStep(
|
|
15
|
+
"fetch_candidates",
|
|
16
|
+
"Fetch market data and select candidates",
|
|
17
|
+
buildPortfolioPrompt(resolution),
|
|
18
|
+
{
|
|
19
|
+
requiredInputs: ["symbols"],
|
|
20
|
+
expectedOutputs: ["candidate_positions"],
|
|
21
|
+
},
|
|
22
|
+
),
|
|
23
|
+
promptStep(
|
|
24
|
+
"risk_review",
|
|
25
|
+
"Review risk and diversification",
|
|
26
|
+
`Now review the risk and diversification of this draft portfolio:
|
|
18
27
|
1. Use analyze_correlation across all ${s.positionCount} candidates to check for concentration risk.
|
|
19
28
|
2. Use analyze_risk on each position for volatility and max drawdown.
|
|
20
29
|
3. If correlation is too high (>0.7 between any pair), suggest a replacement to improve diversification.
|
|
21
30
|
4. If any position's risk metrics undermine its intended role, lower its allocation, replace it with a role-equivalent candidate, or explicitly justify why it remains.
|
|
22
|
-
5. Confirm the portfolio fits a ${s.riskProfile} risk profile with ${s.timeHorizon} horizon.`,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
5. Confirm the portfolio fits a ${s.riskProfile} risk profile with ${s.timeHorizon} horizon.`,
|
|
32
|
+
{
|
|
33
|
+
skippable: true,
|
|
34
|
+
requiredInputs: ["candidate_positions"],
|
|
35
|
+
expectedOutputs: ["risk_assessment"],
|
|
36
|
+
},
|
|
37
|
+
),
|
|
38
|
+
promptStep(
|
|
39
|
+
"synthesize",
|
|
40
|
+
"Present final portfolio draft",
|
|
41
|
+
`Present the final portfolio draft as a structured summary:
|
|
28
42
|
- State all assumptions at the top (which parameters were defaults vs user-specified vs saved preferences).
|
|
29
43
|
- Commit to the allocation: concrete percentages per position, not ranges.
|
|
30
44
|
- Present an allocation table: symbol, allocation %, dollar amount ($${s.budget.toLocaleString("en-US")} total), current price used, estimated shares, role, and one-line analyst rationale per position.
|
|
@@ -38,19 +52,12 @@ Length constraints:
|
|
|
38
52
|
- Risk summary: max 3 bullet points.
|
|
39
53
|
- Implementation notes: max 3 bullets.
|
|
40
54
|
- Growth/safety suggestions: max 2 bullet points each.
|
|
41
|
-
- Keep total response under 40 lines.`,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
55
|
+
- Keep total response under 40 lines.`,
|
|
56
|
+
{
|
|
57
|
+
requiredInputs: ["risk_assessment"],
|
|
58
|
+
expectedOutputs: ["portfolio_summary"],
|
|
59
|
+
},
|
|
60
|
+
),
|
|
45
61
|
],
|
|
46
62
|
};
|
|
47
63
|
}
|
|
48
|
-
|
|
49
|
-
/** @deprecated Use buildPortfolioWorkflowDefinition instead */
|
|
50
|
-
export function buildPortfolioWorkflow(resolution: SlotResolution<PortfolioSlots>): WorkflowPlan {
|
|
51
|
-
const def = buildPortfolioWorkflowDefinition(resolution);
|
|
52
|
-
return {
|
|
53
|
-
initialPrompt: def.steps[0].prompt,
|
|
54
|
-
followUps: def.steps.slice(1).map((s) => s.prompt),
|
|
55
|
-
};
|
|
56
|
-
}
|
package/dist/workflows/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/workflows/types.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{_ as e,a as t,c as n,d as r,f as i,g as a,h as o,i as s,l as c,m as l,n as u,o as d,p as f,r as p,s as m,t as h,u as g,v as _}from"./index-CZ9DHZYy.js";var v=o(`arrow-right`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]),y=o(`chevron-left`,[[`path`,{d:`m15 18-6-6 6-6`,key:`1wnfg3`}]]),ee=o(`eye-off`,[[`path`,{d:`M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49`,key:`ct8e1f`}],[`path`,{d:`M14.084 14.158a3 3 0 0 1-4.242-4.242`,key:`151rxh`}],[`path`,{d:`M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143`,key:`13bj9a`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}]]),b=o(`eye`,[[`path`,{d:`M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0`,key:`1nclc0`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]),x=o(`play`,[[`path`,{d:`M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z`,key:`10ikf1`}]]),S=o(`sparkles`,[[`path`,{d:`M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z`,key:`1s2grr`}],[`path`,{d:`M20 2v4`,key:`1rf3ol`}],[`path`,{d:`M22 4h-4`,key:`gwowj6`}],[`circle`,{cx:`4`,cy:`20`,r:`2`,key:`6kqj1y`}]]),C=_(e(),1),w=a();function T({label:e,hint:t,required:n=!1,children:r,className:i}){return(0,w.jsxs)(`label`,{className:d(`grid gap-1.5`,i),children:[(0,w.jsxs)(`span`,{className:`flex items-baseline justify-between gap-3 text-xs font-medium text-foreground`,children:[(0,w.jsxs)(`span`,{children:[e,n?(0,w.jsx)(`span`,{className:`text-foreground/40`,"aria-hidden":`true`,children:` *`}):null]}),t?(0,w.jsx)(`span`,{className:`text-[11px] font-normal text-muted-foreground`,children:t}):null]}),r]})}function te({value:e,onChange:t,options:n,ariaLabel:r}){return(0,w.jsx)(`div`,{role:`radiogroup`,"aria-label":r,className:`inline-flex h-9 items-center rounded-md border border-border bg-card p-0.5`,children:n.map(n=>{let r=n.value===e;return(0,w.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":r,onClick:()=>t(n.value),className:d(`inline-flex h-8 min-w-9 items-center justify-center rounded-[4px] px-2.5 text-xs font-medium tabular-nums transition-colors`,r?`bg-foreground text-background`:`text-muted-foreground hover:text-foreground`),children:n.label},n.value)})})}function E({value:e,onChange:t,options:n,placeholder:r,ariaLabel:i}){return(0,w.jsxs)(`div`,{className:`relative`,children:[(0,w.jsxs)(`select`,{"aria-label":i,value:e??``,onChange:e=>t(e.target.value||void 0),className:`h-9 w-full appearance-none rounded-md border border-border bg-card px-3 pr-9 text-sm text-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background`,children:[r?(0,w.jsx)(`option`,{value:``,disabled:!0,hidden:!0,children:r}):null,n.map(e=>(0,w.jsx)(`option`,{value:e.value,children:e.label},e.value))]}),(0,w.jsx)(f,{"aria-hidden":`true`,className:`pointer-events-none absolute right-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground`})]})}function D({value:e,onChange:t,presets:n,suffix:r,min:i,max:a,step:o=1,placeholder:s}){let c=n.some(t=>t.value===e);return(0,w.jsxs)(`div`,{className:`grid gap-2`,children:[(0,w.jsx)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:n.map(n=>(0,w.jsx)(`button`,{type:`button`,onClick:()=>t(n.value),className:d(`inline-flex h-7 items-center rounded-full border px-2.5 text-xs font-medium tabular-nums transition-colors`,n.value===e?`border-foreground bg-foreground text-background`:`border-border bg-card text-muted-foreground hover:border-border hover:text-foreground`),children:n.label},String(n.value)))}),(0,w.jsxs)(`div`,{className:`relative w-32`,children:[(0,w.jsx)(p,{type:`number`,inputMode:`numeric`,value:c?``:e??``,min:i,max:a,step:o,placeholder:s??`Custom`,onChange:e=>{t(e.target.value===``?void 0:Number(e.target.value))},className:`h-8 pr-8 text-xs tabular-nums`}),r?(0,w.jsx)(`span`,{className:`pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 text-[11px] text-muted-foreground`,children:r}):null]})]})}function ne({value:e,onChange:t,lookup:n,placeholder:r=`AAPL`,ariaLabel:i}){let[a,o]=(0,C.useState)(!1),[s,c]=(0,C.useState)([]),[l,u]=(0,C.useState)(!1),d=(0,C.useRef)(null);return(0,C.useEffect)(()=>{if(!n)return;let t=String(e||``).trim();if(t.length<1){c([]);return}return d.current&&clearTimeout(d.current),d.current=setTimeout(async()=>{u(!0);try{c((await n(t)).slice(0,6))}catch{c([])}finally{u(!1)}},180),()=>{d.current&&clearTimeout(d.current)}},[e,n]),(0,w.jsxs)(`div`,{className:`relative`,children:[(0,w.jsx)(p,{"aria-label":i,value:e??``,placeholder:r,onChange:e=>t(e.target.value.toUpperCase()),onFocus:()=>o(!0),onBlur:()=>setTimeout(()=>o(!1),120),className:`h-9 tabular-nums`,autoCapitalize:`characters`}),a&&s.length>0?(0,w.jsx)(`div`,{className:`absolute left-0 right-0 top-full z-20 mt-1 max-h-60 overflow-auto rounded-md border border-border bg-card shadow-subtle-sm`,children:s.map(e=>(0,w.jsxs)(`button`,{type:`button`,onMouseDown:e=>e.preventDefault(),onClick:()=>{t(e.symbol),o(!1)},className:`flex w-full items-center justify-between gap-3 px-3 py-2 text-left text-sm hover:bg-secondary`,children:[(0,w.jsx)(`span`,{className:`font-medium tabular-nums text-foreground`,children:e.symbol}),(0,w.jsx)(`span`,{className:`truncate text-xs text-muted-foreground`,children:e.name})]},e.symbol))}):null,l?(0,w.jsx)(`span`,{className:`absolute right-3 top-1/2 -translate-y-1/2 text-[10px] uppercase tracking-wider text-muted-foreground`,children:`…`}):null]})}function re({value:e=[],onChange:n,placeholder:r=`Add ticker`,min:i,max:a}){let[o,s]=(0,C.useState)(``),c=a!=null&&e.length>=a,l=()=>{let t=o.trim().toUpperCase();if(t){if(e.includes(t)){s(``);return}c||(n([...e,t]),s(``))}},u=t=>n(e.filter(e=>e!==t));return(0,w.jsxs)(`div`,{children:[(0,w.jsxs)(`div`,{className:`flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border border-border bg-card px-2 py-1.5 focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 focus-within:ring-offset-background`,children:[e.map(e=>(0,w.jsxs)(`span`,{className:`inline-flex items-center gap-1 rounded-md border border-border bg-secondary px-1.5 py-0.5 text-xs font-medium tabular-nums text-foreground`,children:[e,(0,w.jsx)(`button`,{type:`button`,"aria-label":`Remove ${e}`,onClick:()=>u(e),className:`text-muted-foreground hover:text-foreground`,children:(0,w.jsx)(m,{className:`h-3 w-3`})})]},e)),(0,w.jsx)(`input`,{value:o,onChange:e=>s(e.target.value.toUpperCase()),onKeyDown:t=>{t.key===`Enter`||t.key===`,`?(t.preventDefault(),l()):t.key===`Backspace`&&!o&&e.length>0&&(t.preventDefault(),n(e.slice(0,-1)))},placeholder:e.length===0?r:``,disabled:c,className:`min-w-[80px] flex-1 bg-transparent py-1 text-xs tabular-nums text-foreground outline-none placeholder:text-muted-foreground disabled:opacity-40`,autoCapitalize:`characters`}),o.trim()?(0,w.jsx)(t,{type:`button`,variant:`ghost`,size:`icon-xs`,"aria-label":`Add ticker`,onClick:l,children:(0,w.jsx)(g,{})}):null]}),i!=null&&e.length<i?(0,w.jsxs)(`p`,{className:`mt-1 text-[11px] text-muted-foreground`,children:[`Add at least `,i,` symbol`,i===1?``:`s`,`.`]}):null,a==null?null:(0,w.jsxs)(`p`,{className:`mt-1 text-[11px] text-muted-foreground tabular-nums`,children:[e.length,`/`,a]})]})}function ie({value:e=[],onChange:t,options:n}){let r=n=>{e.includes(n)?t(e.filter(e=>e!==n)):t([...e,n])};return(0,w.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:n.map(t=>{let n=e.includes(t.value);return(0,w.jsxs)(`button`,{type:`button`,onClick:()=>r(t.value),className:d(`inline-flex h-7 items-center gap-1 rounded-full border px-2.5 text-xs font-medium transition-colors`,n?`border-foreground bg-foreground text-background`:`border-border bg-card text-muted-foreground hover:text-foreground`),children:[n?(0,w.jsx)(l,{className:`h-3 w-3`,"aria-hidden":`true`}):null,t.label]},t.value)})})}function ae({value:e,onChange:t,min:n,max:r,placeholder:i=`YYYY-MM-DD`}){return(0,w.jsx)(p,{type:`date`,value:e??``,min:n,max:r,placeholder:i,onChange:e=>t(e.target.value||void 0),className:`h-9 tabular-nums`})}function oe({value:e,onChange:t,placeholder:n,rows:r=3,maxLength:i}){return(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`textarea`,{value:e??``,onChange:e=>t(e.target.value),placeholder:n,maxLength:i,rows:r,className:`block w-full resize-y rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background`}),i?(0,w.jsxs)(`div`,{className:`mt-1 text-right text-[11px] tabular-nums text-muted-foreground`,children:[(e||``).length,`/`,i]}):null]})}function O({value:e,onChange:t,currency:n=`USD`,min:r=0,placeholder:i=`0`}){let[a,o]=(0,C.useState)(!1),[s,c]=(0,C.useState)(k(e,!1));(0,C.useEffect)(()=>{a||c(k(e,!1))},[e,a]);let l=se(n),u=e=>{if(o(!1),!e||!e.replace(/[^0-9.]/g,``)){t(void 0),c(``);return}let n=Number(e.replace(/[^0-9.]/g,``));Number.isFinite(n)&&(t(n),c(k(n,!1)))};return(0,w.jsxs)(`div`,{className:`relative`,children:[(0,w.jsx)(`span`,{className:`pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground`,children:l}),(0,w.jsx)(p,{value:a?s:k(e,!1),inputMode:`decimal`,placeholder:i,onChange:e=>c(e.target.value.replace(/[^0-9.]/g,``)),onFocus:()=>{o(!0),c(e==null?``:String(e))},onBlur:e=>u(e.target.value),min:r,className:`h-9 pl-7 tabular-nums`})]})}function k(e,t){if(e==null||e===``)return``;let n=Number(e);return Number.isFinite(n)?t?String(n):n.toLocaleString(`en-US`):String(e)}function se(e){return!e||e===`USD`||e===`CAD`||e===`AUD`?`$`:e===`EUR`?`€`:e===`GBP`?`£`:e===`JPY`?`¥`:e}function ce({value:e,onChange:t,min:n,max:r,step:i=.5,placeholder:a}){return(0,w.jsxs)(`div`,{className:`relative`,children:[(0,w.jsx)(p,{type:`number`,inputMode:`decimal`,value:e==null||e===``?``:String(Number((Number(e)*100).toFixed(4))),placeholder:a,min:n,max:r,step:i,onChange:e=>{let n=e.target.value;if(n===``){t(void 0);return}let r=Number(n);Number.isFinite(r)&&t(r/100)},className:`h-9 pr-7 tabular-nums`}),(0,w.jsx)(`span`,{className:`pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground`,children:`%`})]})}function le({suggestions:e,onPick:t,label:n=`Suggestions`}){return e?.length?(0,w.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,w.jsx)(`span`,{className:`text-[11px] font-medium uppercase tracking-wider text-muted-foreground`,children:n}),(0,w.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:e.map(e=>(0,w.jsx)(`button`,{type:`button`,onClick:()=>t(e.value||e.label),className:`inline-flex h-7 items-center rounded-full border border-border bg-card px-2.5 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground`,children:e.label},e.value||e.label))})]}):null}var ue={DAYS_PRESETS:[{value:7,label:`7d`},{value:30,label:`30d`},{value:90,label:`90d`},{value:180,label:`6M`},{value:365,label:`1Y`}],HOURS_PRESETS:[{value:6,label:`6h`},{value:24,label:`24h`},{value:72,label:`3d`},{value:168,label:`7d`}],RANGE_OPTIONS:[{value:`1mo`,label:`1M`},{value:`3mo`,label:`3M`},{value:`6mo`,label:`6M`},{value:`1y`,label:`1Y`},{value:`2y`,label:`2Y`},{value:`5y`,label:`5Y`},{value:`max`,label:`Max`}],PERIOD_OPTIONS:[{value:`6mo`,label:`6M`},{value:`1y`,label:`1Y`},{value:`2y`,label:`2Y`}],FRESHNESS_OPTIONS:[{value:`hours`,label:`Hours`},{value:`day`,label:`Day`},{value:`week`,label:`Week`},{value:`month`,label:`Month`}]};function A(e){return typeof e==`string`?ue[e]??[]:e??[]}function j({field:e,value:t,onChange:n,lookupSymbol:r}){let i=t=>n(e.name,t);switch(e.label,e.required,e.helper&&e.helper,e.kind){case`symbol`:return(0,w.jsx)(T,{label:e.label,hint:e.helper,required:e.required,children:(0,w.jsx)(ne,{value:t,onChange:i,lookup:r,placeholder:e.placeholder,ariaLabel:e.label})});case`symbols`:return(0,w.jsx)(T,{label:e.label,hint:e.helper,required:e.required,children:(0,w.jsx)(re,{value:t||[],onChange:i,min:e.min,max:e.max,placeholder:e.placeholder})});case`segmented`:return(0,w.jsx)(T,{label:e.label,hint:e.helper,required:e.required,children:(0,w.jsx)(te,{value:t,onChange:i,options:A(e.options),ariaLabel:e.label})});case`select`:return(0,w.jsx)(T,{label:e.label,hint:e.helper,required:e.required,children:(0,w.jsx)(E,{value:t,onChange:i,options:A(e.options),placeholder:e.placeholder,ariaLabel:e.label})});case`number-chips`:return(0,w.jsx)(T,{label:e.label,hint:e.helper,required:e.required,children:(0,w.jsx)(D,{value:t,onChange:i,presets:A(e.presets),suffix:e.suffix,min:e.min,max:e.max,step:e.step,placeholder:e.placeholder})});case`multi-chips`:return(0,w.jsx)(T,{label:e.label,hint:e.helper,required:e.required,children:(0,w.jsx)(ie,{value:t||[],onChange:i,options:A(e.options)})});case`date`:return(0,w.jsx)(T,{label:e.label,hint:e.helper,required:e.required,children:(0,w.jsx)(ae,{value:t,onChange:i,min:e.min,max:e.max})});case`freetext`:return(0,w.jsx)(T,{label:e.label,hint:e.helper,required:e.required,children:(0,w.jsx)(oe,{value:t,onChange:i,placeholder:e.placeholder,maxLength:e.maxLength,rows:e.rows})});case`money`:return(0,w.jsx)(T,{label:e.label,hint:e.helper,required:e.required,children:(0,w.jsx)(O,{value:t,onChange:i,currency:e.currency,placeholder:e.placeholder})});case`percent`:return(0,w.jsx)(T,{label:e.label,hint:e.helper,required:e.required,children:(0,w.jsx)(ce,{value:t,onChange:i,min:e.min,max:e.max,step:e.step,placeholder:e.placeholder})});default:return(0,w.jsxs)(T,{label:e.label,hint:e.helper,required:e.required,children:[(0,w.jsx)(p,{value:t??``,placeholder:e.placeholder,onChange:e=>i(e.target.value),className:`h-9`}),e.suggestions?.length?(0,w.jsx)(`div`,{className:`mt-2`,children:(0,w.jsx)(le,{suggestions:e.suggestions,onPick:i,label:`Try`})}):null]})}}function M(e){let t={};for(let n of e)n.default!==void 0&&(t[n.name]=n.default);return t}function N(e,t){let n=[];for(let r of e){if(!r.required)continue;let e=t[r.name];if(e==null||e===``){n.push(`${r.label} is required.`);continue}Array.isArray(e)&&(e.length===0?n.push(`${r.label} is required.`):r.min!=null&&e.length<r.min&&n.push(`${r.label} needs at least ${r.min} entr${r.min===1?`y`:`ies`}.`))}return n}var P=(e={})=>({name:`symbol`,kind:`symbol`,label:`Symbol`,required:!0,default:`NVDA`,placeholder:`AAPL`,...e}),F=(e={})=>({name:`query`,kind:`text`,label:`Ticker or topic`,required:!0,placeholder:`AAPL or AI infrastructure`,...e}),I={search_ticker:[{name:`query`,kind:`text`,label:`Search query`,required:!0,placeholder:`apple, AAPL, ethereum…`,helper:`Company name, ticker, or crypto. Returns the best matches.`}],get_stock_quote:[P()],get_stock_history:[P(),{name:`range`,kind:`segmented`,label:`Range`,default:`6mo`,options:`RANGE_OPTIONS`},{name:`interval`,kind:`select`,label:`Interval`,default:`1d`,options:[{value:`1d`,label:`Daily`},{value:`1wk`,label:`Weekly`},{value:`1mo`,label:`Monthly`},{value:`1h`,label:`Hourly`},{value:`5m`,label:`5 min`}]}],get_crypto_price:[{name:`id`,kind:`text`,label:`Coin ID`,required:!0,default:`bitcoin`,placeholder:`bitcoin, ethereum, solana`,helper:`CoinGecko coin id (lowercase, hyphenated).`}],get_crypto_history:[{name:`id`,kind:`text`,label:`Coin ID`,required:!0,default:`bitcoin`,placeholder:`bitcoin`,helper:`CoinGecko coin id.`},{name:`days`,kind:`number-chips`,label:`History window`,default:180,presets:`DAYS_PRESETS`,suffix:`days`,helper:`1, 7, 14, 30, 90, 180, 365, or 'max'.`}],get_company_overview:[P()],get_financials:[P(),{name:`statement`,kind:`select`,label:`Statement`,default:`income`,options:[{value:`income`,label:`Income statement`},{value:`balance`,label:`Balance sheet`},{value:`cashflow`,label:`Cash flow`}]}],get_earnings:[P()],calculate_dcf:[P(),{name:`growth_rate`,kind:`percent`,label:`FCF growth rate`,helper:`Annual. Estimated from history if blank.`},{name:`discount_rate`,kind:`percent`,label:`Discount rate (WACC)`,default:.1,helper:`Default 10%.`},{name:`terminal_growth`,kind:`percent`,label:`Terminal growth`,default:.03,helper:`Default 3%.`},{name:`projection_years`,kind:`number-chips`,label:`Projection years`,default:5,presets:[{value:3,label:`3y`},{value:5,label:`5y`},{value:7,label:`7y`},{value:10,label:`10y`}],suffix:`yrs`}],compare_companies:[{name:`symbols`,kind:`symbols`,label:`Tickers`,required:!0,min:2,max:6,default:[`AAPL`,`MSFT`,`GOOGL`],helper:`Pick 2 to 6 tickers to compare side by side.`}],get_sec_filings:[P(),{name:`form_types`,kind:`multi-chips`,label:`Filing types`,default:[`10-K`,`10-Q`,`8-K`],options:[{value:`10-K`,label:`10-K (annual)`},{value:`10-Q`,label:`10-Q (quarterly)`},{value:`8-K`,label:`8-K (material)`},{value:`S-1`,label:`S-1`},{value:`DEF 14A`,label:`Proxy (DEF 14A)`}]},{name:`limit`,kind:`number-chips`,label:`Max results`,default:10,presets:[{value:5,label:`5`},{value:10,label:`10`},{value:25,label:`25`},{value:50,label:`50`}]}],get_economic_data:[{name:`series_id`,kind:`text`,label:`FRED series`,required:!0,default:`CPIAUCSL`,placeholder:`CPIAUCSL`,helper:`Common: CPIAUCSL (CPI), DGS10 (10Y), UNRATE (unemployment), FEDFUNDS.`,suggestions:[{value:`CPIAUCSL`,label:`CPI`},{value:`DGS10`,label:`10Y Treasury`},{value:`UNRATE`,label:`Unemployment`},{value:`FEDFUNDS`,label:`Fed Funds`},{value:`GDP`,label:`GDP`}]},{name:`limit`,kind:`number-chips`,label:`Observations`,default:30,presets:[{value:12,label:`12`},{value:30,label:`30`},{value:60,label:`60`},{value:120,label:`120`}]}],get_fear_greed:[],get_technical_indicators:[P(),{name:`range`,kind:`segmented`,label:`Range`,default:`1y`,options:[{value:`3mo`,label:`3M`},{value:`6mo`,label:`6M`},{value:`1y`,label:`1Y`},{value:`2y`,label:`2Y`}]}],backtest_strategy:[P(),{name:`strategy`,kind:`select`,label:`Strategy`,required:!0,default:`sma_crossover`,options:[{value:`sma_crossover`,label:`SMA crossover (20/50)`},{value:`rsi_mean_reversion`,label:`RSI mean reversion (30/70)`}]},{name:`period`,kind:`segmented`,label:`Lookback`,default:`2y`,options:[{value:`1y`,label:`1Y`},{value:`2y`,label:`2Y`},{value:`5y`,label:`5Y`}]}],manage_portfolio:[{name:`action`,kind:`segmented`,label:`Action`,required:!0,default:`check`,options:[{value:`add`,label:`Add`},{value:`remove`,label:`Remove`},{value:`check`,label:`Check`},{value:`list`,label:`List`}]},P({required:!1,helper:`Required for add/remove.`}),{name:`shares`,kind:`number-chips`,label:`Shares`,presets:[{value:10,label:`10`},{value:100,label:`100`},{value:500,label:`500`}],helper:`Required when adding a position.`},{name:`avg_cost`,kind:`money`,label:`Average cost basis`,helper:`Per share, in your portfolio currency.`}],watchlist:[{name:`action`,kind:`segmented`,label:`Action`,required:!0,default:`check`,options:[{value:`add`,label:`Add`},{value:`remove`,label:`Remove`},{value:`check`,label:`Check`}]},P({required:!1}),{name:`target_price`,kind:`money`,label:`Target (alert ↑)`},{name:`stop_price`,kind:`money`,label:`Stop (alert ↓)`}],analyze_correlation:[{name:`symbols`,kind:`symbols`,label:`Tickers`,required:!0,min:2,max:12,default:[`SPY`,`QQQ`,`TLT`],helper:`2 or more tickers.`},{name:`period`,kind:`segmented`,label:`Window`,default:`1y`,options:`PERIOD_OPTIONS`}],analyze_risk:[P(),{name:`period`,kind:`segmented`,label:`Window`,default:`1y`,options:`PERIOD_OPTIONS`}],predict_returns:[{name:`symbols`,kind:`symbols`,label:`Tickers`,required:!0,min:1,max:8,default:[`NVDA`,`AAPL`],helper:`Forecast 1-week and 1-month return ranges.`}],get_option_chain:[P(),{name:`expiration`,kind:`date`,label:`Expiration`,helper:`Defaults to nearest expiration.`},{name:`type`,kind:`segmented`,label:`Type`,options:[{value:``,label:`Both`},{value:`call`,label:`Calls`},{value:`put`,label:`Puts`}]}],get_reddit_sentiment:[{name:`subreddit`,kind:`text`,label:`Subreddit`,placeholder:`wallstreetbets, stocks, all`,helper:`Leave blank to search defaults.`},{name:`query`,kind:`text`,label:`Filter query`,placeholder:`AAPL or 'rate cuts'`}],get_twitter_sentiment:[F(),{name:`limit`,kind:`number-chips`,label:`Tweets`,default:50,presets:[{value:25,label:`25`},{value:50,label:`50`},{value:100,label:`100`},{value:200,label:`200`}]},{name:`hours`,kind:`number-chips`,label:`Lookback`,default:24,presets:`HOURS_PRESETS`,suffix:`hr`}],get_web_search:[F({label:`Search query`}),{name:`category`,kind:`segmented`,label:`Category`,default:`news`,options:[{value:`news`,label:`News`},{value:`general`,label:`General`}]},{name:`freshness`,kind:`segmented`,label:`Freshness`,default:`day`,options:`FRESHNESS_OPTIONS`}],get_web_sentiment:[F(),{name:`freshness`,kind:`segmented`,label:`Freshness`,default:`day`,options:`FRESHNESS_OPTIONS`},{name:`limit`,kind:`number-chips`,label:`Articles`,default:10,presets:[{value:5,label:`5`},{value:10,label:`10`},{value:20,label:`20`}]}],get_sentiment_trend:[F(),{name:`days`,kind:`number-chips`,label:`Days of history`,default:7,presets:[{value:3,label:`3d`},{value:7,label:`7d`},{value:14,label:`14d`},{value:30,label:`30d`}]},{name:`source`,kind:`select`,label:`Source`,placeholder:`All sources`,options:[{value:`twitter`,label:`Twitter`},{value:`reddit`,label:`Reddit`},{value:`web`,label:`Web`},{value:`finnhub`,label:`Finnhub`}]}],get_sentiment_summary:[F(),{name:`hours`,kind:`number-chips`,label:`Lookback`,default:24,presets:`HOURS_PRESETS`,suffix:`hr`}]},L={market:`Market`,fundamentals:`Fundamentals`,options:`Options`,portfolio:`Portfolio`,technical:`Technical`,sentiment:`Sentiment`,macro:`Macro`,interaction:`Interaction`};function R(e){return I[e]??null}var z={comprehensive_analysis:{headline:`Comprehensive analysis`,description:`Run market, fundamentals, technical, sentiment, and macro analysts on one ticker, then synthesize.`,fields:[{name:`symbol`,kind:`symbol`,label:`Symbol`,required:!0,default:`NVDA`},{name:`depth`,kind:`segmented`,label:`Depth`,default:`standard`,options:[{value:`fast`,label:`Fast`},{value:`standard`,label:`Standard`},{value:`deep`,label:`Deep`}],helper:`Fast: market + fundamentals only. Deep: includes options + macro.`}],buildPrompt:e=>{let t=e.depth&&e.depth!==`standard`?` (${e.depth} depth)`:``;return`/analyze ${e.symbol}${t}`}},portfolio_builder:{headline:`Portfolio builder`,description:`Build a draft portfolio from goals and constraints. The agent will fetch candidates, check correlation, and present an allocation table.`,fields:[{name:`objective`,kind:`freetext`,label:`Objective`,required:!0,placeholder:`Long-term growth with US tech exposure`,maxLength:200,helper:`One or two sentences describing what the portfolio is for.`},{name:`budget`,kind:`money`,label:`Budget`,default:1e5,helper:`Total amount to allocate.`},{name:`riskProfile`,kind:`segmented`,label:`Risk profile`,default:`balanced`,options:[{value:`conservative`,label:`Conservative`},{value:`balanced`,label:`Balanced`},{value:`aggressive`,label:`Aggressive`}]},{name:`timeHorizon`,kind:`segmented`,label:`Time horizon`,default:`5y`,options:[{value:`1y`,label:`1Y`},{value:`3y`,label:`3Y`},{value:`5y`,label:`5Y`},{value:`10y`,label:`10Y+`}]},{name:`assetScope`,kind:`segmented`,label:`Asset scope`,default:`stocks`,options:[{value:`stocks`,label:`Stocks`},{value:`stocks_etfs`,label:`Stocks + ETFs`},{value:`stocks_crypto`,label:`Stocks + Crypto`}]},{name:`positionCount`,kind:`number-chips`,label:`Positions`,default:8,presets:[{value:5,label:`5`},{value:8,label:`8`},{value:12,label:`12`},{value:20,label:`20`}]},{name:`maxSinglePositionPct`,kind:`percent`,label:`Max single position`,default:.15,helper:`Concentration cap, e.g. 15%.`},{name:`excludeSectors`,kind:`multi-chips`,label:`Exclude sectors`,advanced:!0,options:[{value:`energy`,label:`Energy`},{value:`financials`,label:`Financials`},{value:`consumer_discretionary`,label:`Consumer Discr.`},{value:`healthcare`,label:`Healthcare`},{value:`tech`,label:`Technology`},{value:`real_estate`,label:`Real Estate`},{value:`utilities`,label:`Utilities`}]},{name:`incomeVsGrowth`,kind:`segmented`,label:`Tilt`,advanced:!0,options:[{value:`income`,label:`Income`},{value:`balanced`,label:`Balanced`},{value:`growth`,label:`Growth`}]}],buildPrompt:e=>{let t=[`${U(e.budget)} budget`,e.riskProfile&&`${e.riskProfile} risk`,e.timeHorizon&&`${e.timeHorizon} horizon`,e.assetScope&&B(e.assetScope),e.positionCount&&`${e.positionCount} positions`,e.maxSinglePositionPct!=null&&`max ${(e.maxSinglePositionPct*100).toFixed(0)}% per position`,e.incomeVsGrowth&&`${e.incomeVsGrowth} tilt`,e.excludeSectors?.length&&`exclude ${e.excludeSectors.join(`, `)}`].filter(Boolean).join(`, `);return`Build me a portfolio for ${String(e.objective||``).trim()}. Constraints: ${t}.`}},options_screener:{headline:`Options screener`,description:`Pick contracts from a single ticker's chain that match your direction, DTE, and liquidity preferences.`,fields:[{name:`symbol`,kind:`symbol`,label:`Underlying`,required:!0,default:`NVDA`},{name:`direction`,kind:`segmented`,label:`Direction`,required:!0,default:`bullish`,options:[{value:`bullish`,label:`Bullish (calls)`},{value:`bearish`,label:`Bearish (puts)`}]},{name:`dteTarget`,kind:`segmented`,label:`Days to expiry`,required:!0,default:`30-45`,options:[{value:`0-7`,label:`0–7`},{value:`14-30`,label:`14–30`},{value:`30-45`,label:`30–45`},{value:`45-90`,label:`45–90`},{value:`90+`,label:`90+`}]},{name:`moneynessPreference`,kind:`segmented`,label:`Moneyness`,required:!0,default:`atm`,options:[{value:`itm`,label:`ITM`},{value:`atm`,label:`ATM`},{value:`otm`,label:`OTM`}]},{name:`liquidityMinimum`,kind:`segmented`,label:`Liquidity floor`,required:!0,default:`tight_spreads`,options:[{value:`any`,label:`Any`},{value:`tight_spreads`,label:`Tight spreads`},{value:`high_oi`,label:`High open interest`}]},{name:`objective`,kind:`select`,label:`Objective`,required:!0,default:`directional_leverage`,options:[{value:`directional_leverage`,label:`Directional leverage`},{value:`hedge`,label:`Hedge existing position`},{value:`income`,label:`Income (sell premium)`},{value:`speculative`,label:`Speculative (cheap convexity)`}]},{name:`maxPremium`,kind:`money`,label:`Max premium per contract`,advanced:!0},{name:`ivPreference`,kind:`segmented`,label:`IV preference`,advanced:!0,options:[{value:`any`,label:`Any`},{value:`low`,label:`Low IV`},{value:`high`,label:`High IV`}]}],buildPrompt:e=>{let t=[e.dteTarget&&`DTE ${e.dteTarget}`,e.moneynessPreference&&`${e.moneynessPreference.toUpperCase()} strikes`,e.liquidityMinimum&&V(e.liquidityMinimum),e.objective&&H(e.objective),e.maxPremium!=null&&`max premium ${U(e.maxPremium)}`,e.ivPreference&&e.ivPreference!==`any`&&`${e.ivPreference} IV`].filter(Boolean).join(`, `);return`Screen options for ${e.symbol} (${e.direction||`bullish`}). ${t?`Filters: ${t}.`:``}`.trim()}},compare_assets:{headline:`Compare assets`,description:`Side-by-side comparison of two or more tickers across price, technicals, fundamentals, and risk.`,fields:[{name:`symbols`,kind:`symbols`,label:`Tickers`,required:!0,min:2,max:6,default:[`NVDA`,`AMD`],helper:`2 to 6 symbols.`},{name:`metrics`,kind:`multi-chips`,label:`Focus on`,advanced:!0,options:[{value:`valuation`,label:`Valuation`},{value:`growth`,label:`Growth`},{value:`profitability`,label:`Profitability`},{value:`momentum`,label:`Momentum`},{value:`risk`,label:`Risk`}]}],buildPrompt:e=>`Compare ${(e.symbols||[]).join(` vs `)} side by side.${e.metrics?.length?` Focus on ${e.metrics.join(`, `)}.`:``}`}};function B(e){return e===`stocks_etfs`?`stocks and ETFs`:e===`stocks_crypto`?`stocks and crypto`:`stocks only`}function V(e){return e===`tight_spreads`?`tight bid-ask spreads`:e===`high_oi`?`high open interest`:`any liquidity`}function H(e){return e===`directional_leverage`?`directional leverage`:e===`hedge`?`hedge an existing position`:e===`income`?`income via short premium`:e===`speculative`?`speculative cheap convexity`:e}function U(e){if(e==null)return``;let t=Number(e);return Number.isFinite(t)?`$${t.toLocaleString(`en-US`)}`:String(e)}function de(e){return z[e]??null}var fe=[{id:`workflows`,label:`Workflows`,icon:S},{id:`tools`,label:`Tools`,icon:n},{id:`providers`,label:`Providers`,icon:r}],W=`workflows`;function pe({open:e,initialTab:t,catalog:n,onClose:r,send:i,setToast:a,startChatRun:o,fillComposer:s}){let[c,l]=(0,C.useState)(t??W),[d,f]=(0,C.useState)(``),[p,m]=(0,C.useState)(null),g=(0,C.useRef)(null);(0,C.useEffect)(()=>{e&&(l(t??W),f(``),m(null))},[e,t]),(0,C.useEffect)(()=>{g.current&&(g.current.scrollTop=0)},[p,c]);let _=(0,C.useCallback)(()=>{m(null),f(``),r()},[r]);return(0,w.jsx)(h,{open:e,onOpenChange:e=>{e||_()},children:(0,w.jsx)(u,{width:`xl`,handleLabel:`Catalog`,className:`bg-card p-0`,children:(0,w.jsxs)(`div`,{className:`grid min-h-0 flex-1 grid-rows-[auto_minmax(0,1fr)]`,children:[p?(0,w.jsx)(ye,{selection:p,catalog:n,onBack:()=>m(null)}):(0,w.jsx)(G,{tab:c,setTab:l,query:d,setQuery:f,counts:{workflows:n?.workflows?.length??0,tools:n?.tools?.length??0,providers:n?.providers?.length??0}}),(0,w.jsx)(`div`,{ref:g,className:`min-h-0 overflow-y-auto overscroll-contain`,children:p?(0,w.jsx)(be,{selection:p,catalog:n,send:i,setToast:a,startChatRun:o,fillComposer:s,onClose:_,lookupSymbol:void 0}):(0,w.jsx)(he,{tab:c,query:d,catalog:n,onSelect:e=>m(e)})})]})})})}function G({tab:e,setTab:n,query:r,setQuery:i,counts:a}){return(0,w.jsxs)(`div`,{className:`border-b border-border`,children:[(0,w.jsx)(`div`,{className:`px-3 pt-2 sm:px-4`,children:(0,w.jsx)(`div`,{className:`flex w-full items-center gap-0.5 rounded-md bg-secondary p-0.5`,children:fe.map(t=>{let r=t.icon,i=e===t.id;return(0,w.jsxs)(`button`,{type:`button`,onClick:()=>n(t.id),"aria-pressed":i,className:d(`inline-flex h-8 min-w-0 flex-1 items-center justify-center gap-1.5 rounded-[5px] px-2 text-xs font-medium transition-colors`,i?`bg-card text-foreground shadow-subtle-xs`:`text-muted-foreground hover:text-foreground`),children:[(0,w.jsx)(r,{className:`hidden h-3.5 w-3.5 sm:inline`,"aria-hidden":`true`}),(0,w.jsx)(`span`,{className:`truncate`,children:t.label}),(0,w.jsx)(`span`,{className:d(`hidden rounded-full px-1.5 text-[10px] tabular-nums sm:inline`,i?`bg-secondary text-muted-foreground`:`text-muted-foreground/70`),children:a[t.id]??0})]},t.id)})})}),(0,w.jsxs)(`div`,{className:`flex items-center gap-2 px-3 py-2 sm:px-4`,children:[(0,w.jsx)(c,{"aria-hidden":`true`,className:`h-4 w-4 shrink-0 text-muted-foreground`}),(0,w.jsx)(p,{variant:`ghost`,value:r,onChange:e=>i(e.target.value),placeholder:me(e),autoFocus:!0,className:`h-8 px-0 text-sm shadow-none`}),r?(0,w.jsx)(t,{variant:`ghost`,size:`icon-xs`,"aria-label":`Clear search`,onClick:()=>i(``),children:(0,w.jsx)(m,{})}):null]})]})}function me(e){return e===`workflows`?`Search workflows`:e===`providers`?`Search providers`:`Search tools by name, label, or domain`}function he({tab:e,query:t,catalog:n,onSelect:r}){if(e===`workflows`){let e=Me(n?.workflows??[],t);return e.length===0?(0,w.jsx)(K,{query:t,kind:`workflows`}):(0,w.jsx)(`ul`,{className:`grid divide-y divide-border`,children:e.map(e=>(0,w.jsx)(ge,{workflow:e,onSelect:r},e.id))})}if(e===`providers`){let e=Ne(n?.providers??[],t);return e.length===0?(0,w.jsx)(K,{query:t,kind:`providers`}):(0,w.jsx)(`ul`,{className:`grid divide-y divide-border`,children:e.map(e=>(0,w.jsx)(ve,{provider:e,onSelect:r},e.id))})}let i=je(n?.tools??[],t);if(i.length===0)return(0,w.jsx)(K,{query:t,kind:`tools`});let a=Pe(i,e=>e.domain??`tool`),o=[`market`,`fundamentals`,`options`,`portfolio`,`technical`,`sentiment`,`macro`,`interaction`];return(0,w.jsx)(`div`,{className:`grid`,children:[...a.keys()].sort((e,t)=>{let n=o.indexOf(e),r=o.indexOf(t);return(n===-1?999:n)-(r===-1?999:r)}).map((e,t)=>(0,w.jsxs)(`section`,{className:d(t===0?``:`mt-2`),children:[(0,w.jsx)(`h4`,{className:`px-4 pb-1 pt-3 text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground`,children:L[e]??e}),(0,w.jsx)(`ul`,{className:`grid divide-y divide-border border-y border-border`,children:a.get(e).map(e=>(0,w.jsx)(_e,{tool:e,onSelect:r},e.name))})]},e))})}function ge({workflow:e,onSelect:t}){return(0,w.jsx)(`li`,{children:(0,w.jsxs)(`button`,{type:`button`,onClick:()=>t({kind:`workflow`,id:e.id}),className:`group flex w-full items-start gap-3 px-4 py-3 text-left transition-colors hover:bg-secondary`,children:[(0,w.jsx)(S,{"aria-hidden":`true`,className:`mt-0.5 h-4 w-4 shrink-0 text-foreground`}),(0,w.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,w.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,w.jsx)(`span`,{className:`text-sm font-semibold text-foreground`,children:e.name})}),(0,w.jsx)(`p`,{className:`mt-0.5 line-clamp-2 text-xs text-muted-foreground`,children:e.description})]}),(0,w.jsx)(v,{"aria-hidden":`true`,className:`mt-1 h-4 w-4 shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100`})]})})}function _e({tool:e,onSelect:t}){let r=e.enabled===!1;return(0,w.jsx)(`li`,{children:(0,w.jsxs)(`button`,{type:`button`,onClick:()=>t({kind:`tool`,id:e.name}),className:d(`group flex w-full items-start gap-3 px-4 py-2.5 text-left transition-colors hover:bg-secondary`,r&&`opacity-60`),children:[(0,w.jsx)(n,{"aria-hidden":`true`,className:`mt-0.5 h-3.5 w-3.5 shrink-0 text-muted-foreground`}),(0,w.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,w.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,w.jsx)(`span`,{className:`text-sm font-medium text-foreground`,children:e.label||Y(e.name)}),(0,w.jsx)(`code`,{className:`hidden truncate text-[11px] tabular-nums text-muted-foreground/70 sm:inline`,children:e.name}),r?(0,w.jsx)(s,{variant:`outline`,className:`h-5 px-1.5 text-[10px]`,children:`disabled`}):null]}),(0,w.jsx)(`p`,{className:`mt-0.5 line-clamp-1 text-xs text-muted-foreground`,children:e.description})]}),(0,w.jsx)(v,{"aria-hidden":`true`,className:`mt-1 h-4 w-4 shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100`})]})})}function ve({provider:e,onSelect:t}){let n=X(e);return(0,w.jsx)(`li`,{children:(0,w.jsxs)(`button`,{type:`button`,onClick:()=>t({kind:`provider`,id:e.id}),className:`group flex w-full items-start gap-3 px-4 py-3 text-left transition-colors hover:bg-secondary`,children:[(0,w.jsx)(r,{"aria-hidden":`true`,className:`mt-0.5 h-4 w-4 shrink-0 text-muted-foreground`}),(0,w.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,w.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,w.jsx)(`span`,{className:`text-sm font-medium text-foreground`,children:e.displayName}),(0,w.jsx)(Z,{status:n}),(0,w.jsx)(`span`,{className:d(`text-[11px]`,$(n)),children:Q(n)})]}),(0,w.jsx)(`p`,{className:`mt-0.5 line-clamp-2 text-xs text-muted-foreground`,children:(e.unlocks||[]).join(` · `)})]}),(0,w.jsx)(v,{"aria-hidden":`true`,className:`mt-1 h-4 w-4 shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100`})]})})}function K({query:e,kind:t}){return(0,w.jsxs)(`div`,{className:`grid gap-2 p-12 text-center`,children:[(0,w.jsx)(c,{className:`mx-auto h-5 w-5 text-muted-foreground`,"aria-hidden":`true`}),(0,w.jsx)(`p`,{className:`text-sm font-medium text-foreground`,children:e?`No ${t} match "${e}"`:`No ${t} available`}),(0,w.jsx)(`p`,{className:`mx-auto max-w-xs text-xs text-muted-foreground`,children:e?`Try a shorter query or check spelling.`:`OpenCandle did not return entries for this section.`})]})}function ye({selection:e,catalog:i,onBack:a}){let o=J(e,i);return(0,w.jsxs)(`div`,{className:`flex items-center gap-2 border-b border-border px-3 py-2 sm:px-4`,children:[(0,w.jsx)(t,{variant:`ghost`,size:`icon-sm`,"aria-label":`Back to catalog`,onClick:a,children:(0,w.jsx)(y,{})}),(0,w.jsxs)(`div`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[e.kind===`workflow`?(0,w.jsx)(S,{className:`h-4 w-4 text-foreground`,"aria-hidden":`true`}):null,e.kind===`tool`?(0,w.jsx)(n,{className:`h-4 w-4 text-muted-foreground`,"aria-hidden":`true`}):null,e.kind===`provider`?(0,w.jsx)(r,{className:`h-4 w-4 text-muted-foreground`,"aria-hidden":`true`}):null,(0,w.jsx)(`h2`,{className:`truncate text-sm font-semibold text-foreground`,children:we(e,o)}),e.kind===`tool`&&o?.domain?(0,w.jsx)(s,{variant:`outline`,className:`hidden h-5 px-1.5 text-[10px] sm:inline-flex`,children:L[o.domain]??o.domain}):null]})]})}function be({selection:e,catalog:t,send:n,setToast:r,startChatRun:i,fillComposer:a,onClose:o,lookupSymbol:s}){let c=J(e,t);return c?e.kind===`workflow`?(0,w.jsx)(xe,{workflow:c,startChatRun:i,fillComposer:a,onClose:o,setToast:r,lookupSymbol:s}):e.kind===`tool`?(0,w.jsx)(Se,{tool:c,send:n,startChatRun:i,fillComposer:a,onClose:o,setToast:r,lookupSymbol:s}):(0,w.jsx)(Ce,{provider:c,send:n,setToast:r}):(0,w.jsxs)(`div`,{className:`grid gap-2 p-12 text-center`,children:[(0,w.jsx)(`p`,{className:`text-sm font-medium text-foreground`,children:`Selection no longer available`}),(0,w.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`The catalog refreshed while you were viewing this entry.`})]})}function xe({workflow:e,startChatRun:n,fillComposer:r,onClose:i,setToast:a,lookupSymbol:o}){let s=de(e.id),[c,l]=(0,C.useState)(()=>s?M(s.fields):{}),[u,f]=(0,C.useState)(!1);if(!s)return(0,w.jsxs)(`div`,{className:`p-6`,children:[(0,w.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[`No builder defined for "`,e.name,`". The agent will use its default planner.`]}),(0,w.jsx)(`div`,{className:`mt-4 flex gap-2`,children:(0,w.jsx)(t,{variant:`brand`,onClick:()=>{n(e.prompt||e.name),i()},children:`Run with defaults`})})]});let p=(0,C.useCallback)((e,t)=>l(n=>({...n,[e]:t})),[]),m=N(s.fields,c),h=(0,C.useMemo)(()=>Ae(s,c),[s,c]),g=s.fields.filter(e=>!e.advanced),_=s.fields.filter(e=>e.advanced),y=e=>{if(m.length>0){a?.(m[0]);return}if(e===`send`){n(h),i();return}r?.(h),a?.(`Draft loaded — edit and send when ready.`),i()};return(0,w.jsxs)(`div`,{className:`grid animate-fade-in-once gap-5 px-4 py-4 sm:px-5`,children:[(0,w.jsx)(`p`,{className:`text-sm leading-5 text-muted-foreground`,children:s.description}),(0,w.jsx)(`div`,{className:`grid gap-3.5`,children:g.map(e=>(0,w.jsx)(j,{field:e,value:c[e.name],onChange:p,lookupSymbol:o},e.name))}),_.length>0?(0,w.jsxs)(`div`,{className:`grid gap-3.5 border-t border-border pt-4`,children:[(0,w.jsxs)(`button`,{type:`button`,onClick:()=>f(e=>!e),className:`inline-flex w-fit items-center gap-1.5 text-[11px] font-medium uppercase tracking-wider text-muted-foreground hover:text-foreground`,children:[(0,w.jsxs)(`span`,{children:[u?`Hide`:`Show`,` advanced`]}),(0,w.jsx)(v,{"aria-hidden":`true`,className:d(`h-3 w-3 transition-transform`,u&&`rotate-90`)})]}),u?_.map(e=>(0,w.jsx)(j,{field:e,value:c[e.name],onChange:p,lookupSymbol:o},e.name)):null]}):null,(0,w.jsx)(q,{prompt:h}),(0,w.jsxs)(`div`,{className:`sticky bottom-0 -mx-4 flex flex-wrap items-center justify-end gap-2 border-t border-border bg-card px-4 py-3 sm:-mx-5 sm:px-5`,children:[(0,w.jsx)(t,{variant:`bordered`,onClick:()=>y(`draft`),disabled:!h,children:`Edit in chat`}),(0,w.jsx)(t,{variant:`brand`,onClick:()=>y(`send`),disabled:!h,prefixIcon:x,children:`Run workflow`})]})]})}function Se({tool:e,send:n,startChatRun:r,fillComposer:i,onClose:a,setToast:o,lookupSymbol:s}){let c=(0,C.useMemo)(()=>R(e.name)??Te(e),[e]),[l,u]=(0,C.useState)(()=>M(c)),d=(0,C.useCallback)((e,t)=>u(n=>({...n,[e]:t})),[]),f=N(c,l),p=(0,C.useMemo)(()=>De(l),[l]),m=(0,C.useMemo)(()=>`Use ${e.name}${Oe(p)}`,[e,p]),h=t=>{if(f.length>0){o?.(f[0]);return}if(t===`send`){r(m),a();return}if(t===`draft`){i?.(m),o?.(`Draft loaded — edit and send when ready.`),a();return}t===`run`&&n?.(`tool.invoke`,{toolName:e.name,args:p})&&(o?.(`Running ${e.label||e.name}…`),a())};return(0,w.jsxs)(`div`,{className:`grid animate-fade-in-once gap-5 px-4 py-4 sm:px-5`,children:[(0,w.jsx)(`p`,{className:`text-sm leading-5 text-muted-foreground`,children:e.description}),c.length===0?(0,w.jsx)(`div`,{className:`rounded-md border border-dashed border-border bg-secondary px-3 py-2.5 text-xs text-muted-foreground`,children:`This tool takes no inputs.`}):(0,w.jsx)(`div`,{className:`grid gap-3.5`,children:c.map(e=>(0,w.jsx)(j,{field:e,value:l[e.name],onChange:d,lookupSymbol:s},e.name))}),(0,w.jsx)(q,{prompt:m,title:`Chat preview`}),(0,w.jsxs)(`div`,{className:`sticky bottom-0 -mx-4 flex flex-wrap items-center justify-end gap-2 border-t border-border bg-card px-4 py-3 sm:-mx-5 sm:px-5`,children:[(0,w.jsx)(t,{variant:`bordered`,size:`sm`,onClick:()=>h(`draft`),children:`Edit in chat`}),(0,w.jsx)(t,{variant:`brand`,size:`sm`,prefixIcon:x,onClick:()=>h(`run`),children:`Run now`})]})]})}function Ce({provider:e,send:n,setToast:r}){let[a,o]=(0,C.useState)(e.apiKey||``),[s,c]=(0,C.useState)(!1),l=X(e),u=l===`env`,f=a.trim(),m=!u&&f.length>0;(0,C.useEffect)(()=>{o(e.apiKey||``),c(!1)},[e.id,e.apiKey]);let h=()=>{if(u){r?.(`${e.displayName} is set via ${e.envVar}. Unset it to override here.`);return}f&&(r?.(`Verifying ${e.displayName} key…`),n?.(`provider.save_api_key`,{providerId:e.id,apiKey:f})&&o(``))};return(0,w.jsxs)(`div`,{className:`grid animate-fade-in-once gap-5 px-4 py-4 sm:px-5`,children:[(0,w.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,w.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,w.jsx)(Z,{status:l}),(0,w.jsx)(`span`,{className:d(`text-xs font-medium`,$(l)),children:Q(l)}),u?(0,w.jsxs)(`code`,{className:`text-[11px] text-muted-foreground`,children:[`env: `,e.envVar]}):null]}),(0,w.jsx)(`p`,{className:`text-sm leading-5 text-muted-foreground`,children:e.fallbackDescription?(0,w.jsxs)(w.Fragment,{children:[`If absent: `,e.fallbackDescription,`.`]}):(0,w.jsxs)(w.Fragment,{children:[`Required for: `,(e.unlocks||[]).join(`, `)||`this provider's tools`,`.`]})})]}),(0,w.jsxs)(`div`,{className:`grid gap-2`,children:[(0,w.jsx)(`span`,{className:`text-[11px] font-medium uppercase tracking-wider text-muted-foreground`,children:`Unlocks`}),(0,w.jsx)(`ul`,{className:`grid gap-1`,children:(e.unlocks||[]).map(e=>(0,w.jsxs)(`li`,{className:`flex items-baseline gap-2 text-sm text-foreground`,children:[(0,w.jsx)(`span`,{"aria-hidden":`true`,className:`mt-1 h-1 w-1 rounded-full bg-foreground/40`}),(0,w.jsx)(`span`,{children:e})]},e))})]}),(0,w.jsxs)(`div`,{className:`grid gap-2`,children:[(0,w.jsx)(`label`,{htmlFor:`provider-api-key-${e.id}`,className:`text-xs font-medium text-foreground`,children:`API key`}),(0,w.jsxs)(`div`,{className:`relative`,children:[(0,w.jsx)(p,{id:`provider-api-key-${e.id}`,type:s?`text`:`password`,value:a,onChange:e=>o(e.target.value),placeholder:`Paste your ${e.displayName} key`,disabled:u,className:`pr-10 font-mono`,autoCapitalize:`none`,autoComplete:`off`,spellCheck:!1,onKeyDown:e=>{e.key===`Enter`&&m&&(e.preventDefault(),h())}}),(0,w.jsx)(t,{type:`button`,variant:`ghost`,size:`icon-xs`,className:`absolute right-1 top-1/2 -translate-y-1/2`,"aria-label":s?`Hide API key`:`Show API key`,tooltip:s?`Hide API key`:`Show API key`,onClick:()=>c(e=>!e),disabled:!a,children:s?(0,w.jsx)(ee,{}):(0,w.jsx)(b,{})})]}),(0,w.jsx)(`p`,{className:`text-[11px] leading-4 text-muted-foreground`,children:u?`Currently set via ${e.envVar}. Unset that variable to manage the key here.`:l===`file`?`Saved to ~/.opencandle/config.json. Paste a new key to replace.`:e.instructionsHint||`Saved to ~/.opencandle/config.json.`})]}),(0,w.jsxs)(`div`,{className:`sticky bottom-0 -mx-4 flex flex-wrap items-center justify-end gap-2 border-t border-border bg-card px-4 py-3 sm:-mx-5 sm:px-5`,children:[e.signupUrl?(0,w.jsx)(t,{variant:`ghost`,size:`sm`,suffixIcon:i,onClick:()=>window.open(e.signupUrl,`_blank`,`noreferrer`),children:`Get a key`}):null,(0,w.jsx)(t,{variant:`brand`,size:`sm`,onClick:h,disabled:!m,children:l===`file`?`Replace key`:`Save key`})]})]})}function q({prompt:e,title:t=`Chat prompt`}){return(0,w.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,w.jsx)(`span`,{className:`text-[11px] font-medium uppercase tracking-wider text-muted-foreground`,children:t}),(0,w.jsx)(`pre`,{className:`overflow-auto whitespace-pre-wrap rounded-md border border-border bg-secondary px-3 py-2 font-mono text-xs leading-5 text-foreground`,children:e||`Fill the required fields to preview the chat prompt.`})]})}function J(e,t){return!e||!t?null:e.kind===`workflow`?t.workflows?.find(t=>t.id===e.id)??null:e.kind===`tool`?t.tools?.find(t=>t.name===e.id)??null:e.kind===`provider`?t.providers?.find(t=>t.id===e.id)??null:null}function we(e,t){return t?e.kind===`workflow`?t.name:e.kind===`tool`?t.label||Y(t.name):e.kind===`provider`?t.displayName:`Catalog`:`Catalog`}function Y(e){return String(e||``).replace(/^get_/,``).replace(/_/g,` `)}function Te(e){let t=e.parameters?.properties||{};return Object.entries(t).map(([t,n])=>{let r=String(n.description||``);return{name:t,kind:n.type===`number`?`text`:n.type===`boolean`?`select`:`text`,label:Ee(t),placeholder:n.examples?.[0],helper:r.length>80?r.slice(0,80)+`…`:r,required:e.parameters?.required?.includes?.(t)??!1}})}function Ee(e){return e.replace(/_/g,` `).replace(/\b\w/g,e=>e.toUpperCase())}function De(e){let t={};for(let[n,r]of Object.entries(e))r===void 0||r===``||Array.isArray(r)&&r.length===0||(t[n]=r);return t}function Oe(e){let t=Object.entries(e);return t.length===0?``:` with ${t.map(([e,t])=>`${e}=${ke(t)}`).join(`, `)}`}function ke(e){return Array.isArray(e)?e.join(`,`):typeof e==`string`&&e.includes(` `)?JSON.stringify(e):String(e)}function Ae(e,t){try{return e.buildPrompt(t)||``}catch{return``}}function je(e,t){if(!t.trim())return e;let n=t.toLowerCase();return e.filter(e=>[e.name,e.label,e.description,e.domain].some(e=>String(e||``).toLowerCase().includes(n)))}function Me(e,t){if(!t.trim())return e;let n=t.toLowerCase();return e.filter(e=>[e.id,e.name,e.description].some(e=>String(e||``).toLowerCase().includes(n)))}function Ne(e,t){if(!t.trim())return e;let n=t.toLowerCase();return e.filter(e=>[e.id,e.displayName,e.envVar,...e.unlocks||[]].some(e=>String(e||``).toLowerCase().includes(n)))}function Pe(e,t){let n=new Map;for(let r of e){let e=t(r);n.has(e)||n.set(e,[]),n.get(e).push(r)}return n}function X(e){return e.source??`absent`}function Z({status:e}){return(0,w.jsx)(`span`,{"aria-hidden":`true`,className:d(`inline-block h-1.5 w-1.5 rounded-full`,e===`file`?`bg-success`:e===`env`?`bg-info`:`bg-warning`)})}function Q(e){return e===`file`?`Configured`:e===`env`?`From environment`:`Not configured`}function $(e){return e===`file`?`text-success`:e===`env`?`text-info`:`text-warning`}export{pe as CatalogOverlay};
|