opencandle 0.4.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/LICENSE +1 -1
- package/README.md +186 -117
- 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 +32 -8
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +19 -3
- package/dist/config.js +69 -3
- 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.d.ts +1 -3
- package/dist/infra/browser.js +4 -2
- 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.d.ts +4 -0
- package/dist/infra/rate-limiter.js +17 -10
- 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.d.ts +9 -0
- package/dist/memory/manager.js +39 -22
- 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.d.ts +3 -2
- 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 +4 -0
- 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 +637 -59
- 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 +17 -2
- 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 +18 -3
- package/dist/prompts/context-builder.js +117 -18
- package/dist/prompts/context-builder.js.map +1 -1
- package/dist/prompts/disclaimer.js +1 -1
- package/dist/prompts/disclaimer.js.map +1 -1
- package/dist/prompts/policy-cards.d.ts +13 -0
- package/dist/prompts/policy-cards.js +197 -0
- package/dist/prompts/policy-cards.js.map +1 -0
- package/dist/prompts/sections.d.ts +1 -1
- package/dist/prompts/sections.js +3 -3
- package/dist/prompts/sections.js.map +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 +209 -19
- package/dist/prompts/workflow-prompts.js.map +1 -1
- package/dist/providers/alpha-vantage.d.ts +1 -1
- package/dist/providers/alpha-vantage.js +49 -8
- 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 +9 -1
- package/dist/providers/sec-edgar.js +181 -6
- 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 +3 -1
- package/dist/providers/yahoo-finance.js +226 -11
- package/dist/providers/yahoo-finance.js.map +1 -1
- package/dist/routing/classify-intent.d.ts +9 -0
- package/dist/routing/classify-intent.js +153 -3
- package/dist/routing/classify-intent.js.map +1 -1
- package/dist/routing/defaults.d.ts +1 -1
- package/dist/routing/defaults.js +3 -3
- package/dist/routing/defaults.js.map +1 -1
- package/dist/routing/entity-extractor.d.ts +2 -0
- package/dist/routing/entity-extractor.js +377 -26
- 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 +12 -6
- package/dist/routing/index.js +8 -4
- package/dist/routing/index.js.map +1 -1
- package/dist/routing/legacy-rule-router.d.ts +9 -0
- package/dist/routing/legacy-rule-router.js +12 -0
- package/dist/routing/legacy-rule-router.js.map +1 -0
- package/dist/routing/planning.d.ts +54 -0
- package/dist/routing/planning.js +562 -0
- package/dist/routing/planning.js.map +1 -0
- package/dist/routing/route-manifest.d.ts +35 -0
- package/dist/routing/route-manifest.js +242 -0
- package/dist/routing/route-manifest.js.map +1 -0
- package/dist/routing/router-llm-client.js.map +1 -1
- package/dist/routing/router-prompt.js +46 -45
- package/dist/routing/router-prompt.js.map +1 -1
- package/dist/routing/router-types.d.ts +10 -0
- package/dist/routing/router.d.ts +1 -0
- package/dist/routing/router.js +572 -13
- package/dist/routing/router.js.map +1 -1
- package/dist/routing/slot-resolver.d.ts +1 -1
- package/dist/routing/slot-resolver.js +45 -7
- 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 +44 -0
- package/dist/routing/turn-context.js +45 -0
- package/dist/routing/turn-context.js.map +1 -0
- package/dist/routing/types.d.ts +15 -1
- package/dist/runtime/answer-contracts.d.ts +82 -0
- package/dist/runtime/answer-contracts.js +442 -0
- package/dist/runtime/answer-contracts.js.map +1 -0
- package/dist/runtime/artifact-contracts.d.ts +14 -0
- package/dist/runtime/artifact-contracts.js +57 -0
- package/dist/runtime/artifact-contracts.js.map +1 -0
- package/dist/runtime/planning-evidence.d.ts +99 -0
- package/dist/runtime/planning-evidence.js +466 -0
- package/dist/runtime/planning-evidence.js.map +1 -0
- 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 +29 -3
- package/dist/runtime/session-coordinator.js +204 -31
- 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 +7 -3
- 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 +12 -7
- package/dist/tools/fundamentals/company-overview.js.map +1 -1
- package/dist/tools/fundamentals/comps.js +19 -10
- package/dist/tools/fundamentals/comps.js.map +1 -1
- package/dist/tools/fundamentals/dcf.js +24 -12
- package/dist/tools/fundamentals/dcf.js.map +1 -1
- package/dist/tools/fundamentals/earnings.js +9 -4
- package/dist/tools/fundamentals/earnings.js.map +1 -1
- package/dist/tools/fundamentals/financials.js +9 -4
- package/dist/tools/fundamentals/financials.js.map +1 -1
- package/dist/tools/fundamentals/sec-filings.d.ts +1 -0
- package/dist/tools/fundamentals/sec-filings.js +36 -4
- package/dist/tools/fundamentals/sec-filings.js.map +1 -1
- package/dist/tools/index.d.ts +23 -18
- package/dist/tools/index.js +53 -38
- 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 +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 +44 -9
- package/dist/tools/macro/fred-data.js.map +1 -1
- package/dist/tools/market/crypto-history.js +21 -3
- package/dist/tools/market/crypto-history.js.map +1 -1
- package/dist/tools/market/crypto-price.js +4 -2
- 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 +161 -9
- 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 +27 -8
- package/dist/tools/market/stock-history.js.map +1 -1
- package/dist/tools/market/stock-quote.js +6 -4
- package/dist/tools/market/stock-quote.js.map +1 -1
- package/dist/tools/options/greeks.js +1 -2
- package/dist/tools/options/greeks.js.map +1 -1
- package/dist/tools/options/option-chain.js +27 -9
- 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 +34 -14
- 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.d.ts +8 -0
- package/dist/tools/portfolio/holdings-overlap.js +112 -0
- package/dist/tools/portfolio/holdings-overlap.js.map +1 -0
- 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 +338 -88
- 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 +46 -7
- 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 +247 -102
- package/dist/tools/portfolio/tracker.js.map +1 -1
- package/dist/tools/portfolio/watchlist.d.ts +6 -4
- package/dist/tools/portfolio/watchlist.js +209 -101
- package/dist/tools/portfolio/watchlist.js.map +1 -1
- package/dist/tools/sentiment/reddit-sentiment.js +24 -11
- package/dist/tools/sentiment/reddit-sentiment.js.map +1 -1
- package/dist/tools/sentiment/sentiment-summary.js +71 -14
- 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 +13 -6
- 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 +37 -12
- package/dist/tools/sentiment/web-search.js.map +1 -1
- package/dist/tools/sentiment/web-sentiment.js +16 -4
- package/dist/tools/sentiment/web-sentiment.js.map +1 -1
- package/dist/tools/technical/backtest.d.ts +3 -3
- package/dist/tools/technical/backtest.js +65 -44
- package/dist/tools/technical/backtest.js.map +1 -1
- package/dist/tools/technical/indicators.js +24 -8
- 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/options.d.ts +10 -0
- package/dist/types/portfolio.d.ts +41 -4
- package/dist/workflows/compare-assets.d.ts +0 -3
- package/dist/workflows/compare-assets.js +55 -10
- 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 +88 -14
- package/dist/workflows/options-screener.js.map +1 -1
- package/dist/workflows/portfolio-builder.d.ts +0 -3
- package/dist/workflows/portfolio-builder.js +7 -11
- package/dist/workflows/portfolio-builder.js.map +1 -1
- package/gui/server/ask-user-bridge.ts +82 -0
- 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/gui-session-manager.ts +5 -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 +58 -11
- package/gui/server/prompt-observation.ts +58 -0
- package/gui/server/quote-snapshot-store.ts +50 -0
- package/gui/server/server.ts +236 -376
- package/gui/server/session-actions.ts +186 -1
- package/gui/server/session-entry-wait.ts +81 -0
- 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 +22 -12
- package/src/analysts/contracts.ts +10 -23
- package/src/analysts/orchestrator.ts +8 -43
- package/src/cli.ts +37 -13
- package/src/config.ts +99 -7
- package/src/index.ts +1 -1
- package/src/infra/browser.ts +4 -2
- 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 +32 -20
- 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 +57 -26
- package/src/memory/retrieval.ts +8 -7
- package/src/memory/sqlite.ts +407 -6
- package/src/memory/storage.ts +8 -17
- package/src/memory/tool-defaults.ts +60 -39
- package/src/memory/types.ts +7 -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 +795 -120
- package/src/pi/session.ts +7 -5
- package/src/pi/setup.ts +61 -33
- package/src/pi/tool-adapter.ts +5 -2
- package/src/prompts/context-builder.ts +143 -21
- package/src/prompts/disclaimer.ts +1 -1
- package/src/prompts/policy-cards.ts +220 -0
- package/src/prompts/sections.ts +4 -4
- package/src/prompts/symbol-preflight.ts +80 -0
- package/src/prompts/workflow-prompts.ts +231 -28
- package/src/providers/alpha-vantage.ts +82 -40
- 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 +235 -5
- 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 +292 -20
- package/src/routing/classify-intent.ts +186 -4
- package/src/routing/defaults.ts +4 -4
- package/src/routing/entity-extractor.ts +428 -28
- package/src/routing/fund-symbols.ts +58 -0
- package/src/routing/horizon.ts +7 -0
- package/src/routing/index.ts +60 -16
- package/src/routing/legacy-rule-router.ts +13 -0
- package/src/routing/planning.ts +823 -0
- package/src/routing/route-manifest.ts +309 -0
- package/src/routing/router-llm-client.ts +4 -4
- package/src/routing/router-prompt.ts +52 -52
- package/src/routing/router-types.ts +18 -0
- package/src/routing/router.ts +717 -20
- package/src/routing/slot-resolver.ts +75 -14
- package/src/routing/symbol-disambiguator.ts +72 -0
- package/src/routing/turn-context.ts +108 -0
- package/src/routing/types.ts +15 -1
- package/src/runtime/answer-contracts.ts +672 -0
- package/src/runtime/artifact-contracts.ts +77 -0
- package/src/runtime/planning-evidence.ts +682 -0
- package/src/runtime/prompt-step.ts +1 -16
- package/src/runtime/run-context.ts +12 -2
- package/src/runtime/session-coordinator.ts +297 -56
- 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 +7 -3
- package/src/tool-kit.ts +10 -9
- package/src/tools/fundamentals/company-overview.ts +20 -10
- package/src/tools/fundamentals/comps.ts +69 -56
- package/src/tools/fundamentals/dcf.ts +146 -96
- package/src/tools/fundamentals/earnings.ts +17 -7
- package/src/tools/fundamentals/financials.ts +17 -8
- package/src/tools/fundamentals/sec-filings.ts +52 -8
- package/src/tools/index.ts +53 -38
- 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 +2 -2
- package/src/tools/macro/fred-data.ts +80 -42
- package/src/tools/market/crypto-history.ts +25 -4
- package/src/tools/market/crypto-price.ts +7 -7
- package/src/tools/market/screen-stocks.ts +279 -0
- package/src/tools/market/search-ticker.ts +219 -18
- package/src/tools/market/stock-history.ts +38 -13
- package/src/tools/market/stock-quote.ts +11 -8
- package/src/tools/options/greeks.ts +5 -6
- package/src/tools/options/option-chain.ts +47 -18
- package/src/tools/portfolio/alerts.ts +457 -0
- package/src/tools/portfolio/correlation.ts +48 -21
- package/src/tools/portfolio/daily-report.ts +101 -0
- package/src/tools/portfolio/holdings-overlap.ts +139 -0
- package/src/tools/portfolio/notifications.ts +45 -0
- package/src/tools/portfolio/predictions.ts +407 -107
- package/src/tools/portfolio/risk-analysis.ts +47 -8
- package/src/tools/portfolio/tracker.ts +271 -110
- package/src/tools/portfolio/watchlist.ts +251 -116
- package/src/tools/sentiment/reddit-sentiment.ts +51 -25
- package/src/tools/sentiment/sentiment-summary.ts +116 -35
- package/src/tools/sentiment/sentiment-trend.ts +24 -7
- package/src/tools/sentiment/twitter-sentiment.ts +23 -16
- package/src/tools/sentiment/untrusted-text.ts +21 -0
- package/src/tools/sentiment/web-search.ts +52 -16
- package/src/tools/sentiment/web-sentiment.ts +27 -11
- package/src/tools/technical/backtest.ts +78 -47
- package/src/tools/technical/indicators.ts +40 -17
- package/src/types/index.ts +8 -3
- package/src/types/market.ts +1 -0
- package/src/types/options.ts +17 -0
- package/src/types/portfolio.ts +46 -4
- package/src/types/sentiment.ts +2 -2
- package/src/workflows/compare-assets.ts +67 -19
- package/src/workflows/index.ts +3 -4
- package/src/workflows/options-screener.ts +98 -22
- package/src/workflows/portfolio-builder.ts +40 -29
- package/dist/runtime/index.d.ts +0 -16
- package/dist/runtime/index.js +0 -10
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/provider-ids.d.ts +0 -14
- package/dist/runtime/provider-ids.js +0 -14
- package/dist/runtime/provider-ids.js.map +0 -1
- 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-D1ImSJTe.js +0 -1
- package/gui/web/dist/assets/index-DBrWq43L.css +0 -1
- package/gui/web/dist/assets/index-RflHaj0y.js +0 -67
- package/src/runtime/index.ts +0 -55
- package/src/runtime/provider-ids.ts +0 -15
- package/src/workflows/types.ts +0 -4
package/src/pi/session.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import "../infra/node-version.js";
|
|
2
2
|
import {
|
|
3
3
|
type AuthStorage,
|
|
4
|
+
type CreateAgentSessionResult,
|
|
4
5
|
createAgentSession,
|
|
5
6
|
DefaultResourceLoader,
|
|
7
|
+
getAgentDir,
|
|
6
8
|
type ModelRegistry,
|
|
7
|
-
type CreateAgentSessionResult,
|
|
8
|
-
type SettingsManager,
|
|
9
9
|
type SessionManager,
|
|
10
|
-
|
|
10
|
+
type SettingsManager,
|
|
11
11
|
} from "@earendil-works/pi-coding-agent";
|
|
12
12
|
import { loadEnv } from "../config.js";
|
|
13
|
-
import openCandleExtension from "./opencandle-extension.js";
|
|
14
13
|
import type { AskUserHandler } from "../types/index.js";
|
|
14
|
+
import openCandleExtension from "./opencandle-extension.js";
|
|
15
15
|
|
|
16
16
|
export interface CreateOpenCandleSessionOptions {
|
|
17
17
|
cwd?: string;
|
|
@@ -38,7 +38,9 @@ export async function createOpenCandleSession(
|
|
|
38
38
|
cwd,
|
|
39
39
|
agentDir,
|
|
40
40
|
settingsManager: options.settingsManager,
|
|
41
|
-
extensionFactories: [
|
|
41
|
+
extensionFactories: [
|
|
42
|
+
(pi) => openCandleExtension(pi, { askUserHandler: options.askUserHandler }),
|
|
43
|
+
],
|
|
42
44
|
})
|
|
43
45
|
: undefined;
|
|
44
46
|
|
package/src/pi/setup.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Model } from "@earendil-works/pi-ai";
|
|
2
2
|
import {
|
|
3
|
-
LoginDialogComponent,
|
|
4
3
|
type ExtensionAPI,
|
|
5
4
|
type ExtensionContext,
|
|
5
|
+
LoginDialogComponent,
|
|
6
6
|
} from "@earendil-works/pi-coding-agent";
|
|
7
7
|
|
|
8
8
|
type SetupMode = "startup" | "manual";
|
|
@@ -54,14 +54,18 @@ function getAvailableModels(ctx: ExtensionContext, preferredProvider?: string):
|
|
|
54
54
|
return sortModels(ctx.modelRegistry.getAvailable(), preferredProvider);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
export function getLlmSetupRequirement(
|
|
57
|
+
export function getLlmSetupRequirement(
|
|
58
|
+
ctx: Pick<ExtensionContext, "model" | "modelRegistry">,
|
|
59
|
+
): SetupRequirement {
|
|
58
60
|
if (ctx.model && ctx.modelRegistry.hasConfiguredAuth(ctx.model)) {
|
|
59
61
|
return "ready";
|
|
60
62
|
}
|
|
61
63
|
return ctx.modelRegistry.getAvailable().length > 0 ? "select_model" : "connect_auth";
|
|
62
64
|
}
|
|
63
65
|
|
|
64
|
-
async function selectProviderForApiKey(
|
|
66
|
+
async function selectProviderForApiKey(
|
|
67
|
+
ctx: ExtensionContext,
|
|
68
|
+
): Promise<ApiKeyProviderId | undefined> {
|
|
65
69
|
const choice = await ctx.ui.select("Connect an AI model", [
|
|
66
70
|
"Google Gemini API",
|
|
67
71
|
"OpenAI API",
|
|
@@ -79,7 +83,9 @@ async function selectProviderForApiKey(ctx: ExtensionContext): Promise<ApiKeyPro
|
|
|
79
83
|
}
|
|
80
84
|
}
|
|
81
85
|
|
|
82
|
-
async function selectProviderForLogin(
|
|
86
|
+
async function selectProviderForLogin(
|
|
87
|
+
ctx: ExtensionContext,
|
|
88
|
+
): Promise<OAuthProviderChoice | undefined> {
|
|
83
89
|
const choice = await ctx.ui.select("Connect an AI model", [
|
|
84
90
|
"Google",
|
|
85
91
|
"OpenAI",
|
|
@@ -112,7 +118,9 @@ async function selectAdvancedOAuthProvider(ctx: ExtensionContext): Promise<strin
|
|
|
112
118
|
}
|
|
113
119
|
|
|
114
120
|
async function runLoginDialog(ctx: ExtensionContext, providerId: string): Promise<boolean> {
|
|
115
|
-
const provider = ctx.modelRegistry.authStorage
|
|
121
|
+
const provider = ctx.modelRegistry.authStorage
|
|
122
|
+
.getOAuthProviders()
|
|
123
|
+
.find((item) => item.id === providerId);
|
|
116
124
|
const providerName = provider?.name ?? providerId;
|
|
117
125
|
const usesCallbackServer = provider?.usesCallbackServer ?? false;
|
|
118
126
|
|
|
@@ -136,33 +144,49 @@ async function runLoginDialog(ctx: ExtensionContext, providerId: string): Promis
|
|
|
136
144
|
});
|
|
137
145
|
|
|
138
146
|
// Cast required: advanced providers return dynamic IDs outside the SDK's static union type
|
|
139
|
-
void ctx.modelRegistry.authStorage
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
147
|
+
void ctx.modelRegistry.authStorage
|
|
148
|
+
.login(providerId as any, {
|
|
149
|
+
onAuth: (info) => {
|
|
150
|
+
dialog.showAuth(info.url, info.instructions);
|
|
151
|
+
if (usesCallbackServer) {
|
|
152
|
+
void dialog
|
|
153
|
+
.showManualInput("Paste redirect URL below, or complete login in your browser:")
|
|
154
|
+
.then((value) => {
|
|
155
|
+
if (value && manualCodeResolve) {
|
|
156
|
+
manualCodeResolve(value);
|
|
157
|
+
manualCodeResolve = undefined;
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
.catch(() => {
|
|
161
|
+
if (manualCodeReject) {
|
|
162
|
+
manualCodeReject(new Error("Login cancelled"));
|
|
163
|
+
manualCodeReject = undefined;
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
} else if (providerId === "github-copilot") {
|
|
167
|
+
dialog.showWaiting("Waiting for browser authentication...");
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
onDeviceCode: (info) => {
|
|
171
|
+
dialog.showDeviceCode(info);
|
|
172
|
+
dialog.showWaiting("Waiting for authentication...");
|
|
173
|
+
},
|
|
174
|
+
onPrompt: async (prompt) => dialog.showPrompt(prompt.message, prompt.placeholder),
|
|
175
|
+
onProgress: (message) => dialog.showProgress(message),
|
|
176
|
+
onSelect: async (prompt) => {
|
|
177
|
+
const options = prompt.options
|
|
178
|
+
.map((option, index) => `${index + 1}. ${option.label}`)
|
|
179
|
+
.join("\n");
|
|
180
|
+
const answer = await dialog.showPrompt(
|
|
181
|
+
`${prompt.message}\n\n${options}`,
|
|
182
|
+
"Enter a number",
|
|
183
|
+
);
|
|
184
|
+
const selectedIndex = Number.parseInt(answer.trim(), 10) - 1;
|
|
185
|
+
return prompt.options[selectedIndex]?.id;
|
|
186
|
+
},
|
|
187
|
+
onManualCodeInput: () => manualCodePromise,
|
|
188
|
+
signal: dialog.signal,
|
|
189
|
+
})
|
|
166
190
|
.then(() => finish(true))
|
|
167
191
|
.catch((error) => {
|
|
168
192
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -238,7 +262,11 @@ async function activateDefaultModel(
|
|
|
238
262
|
return true;
|
|
239
263
|
}
|
|
240
264
|
|
|
241
|
-
async function selectModel(
|
|
265
|
+
async function selectModel(
|
|
266
|
+
api: ExtensionAPI,
|
|
267
|
+
ctx: ExtensionContext,
|
|
268
|
+
preferredProvider?: string,
|
|
269
|
+
): Promise<boolean> {
|
|
242
270
|
const models = getAvailableModels(ctx, preferredProvider);
|
|
243
271
|
if (models.length === 0) {
|
|
244
272
|
ctx.ui.notify("No available models found yet. Connect a provider first.", "warning");
|
package/src/pi/tool-adapter.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { AgentTool } from "@earendil-works/pi-agent-core";
|
|
2
2
|
import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
import type { TSchema } from "@sinclair/typebox";
|
|
4
|
-
import { getAllTools } from "../tools/index.js";
|
|
5
4
|
import { getDefaults } from "../memory/tool-defaults.js";
|
|
6
5
|
import { wrapWithDefaults } from "../runtime/tool-defaults-wrapper.js";
|
|
6
|
+
import { getAllTools } from "../tools/index.js";
|
|
7
7
|
|
|
8
8
|
export function agentToolToPiTool<TParams extends TSchema, TDetails>(
|
|
9
9
|
tool: AgentTool<TParams, TDetails>,
|
|
@@ -24,7 +24,10 @@ export function getOpenCandleToolDefinitions(): ToolDefinition[] {
|
|
|
24
24
|
return getAllTools()
|
|
25
25
|
.map((tool) => ({ tool, defaults: safeGetDefaults(tool.name) }))
|
|
26
26
|
.filter(({ defaults }) => defaults.__enabled !== false)
|
|
27
|
-
.map(({ tool, defaults }) =>
|
|
27
|
+
.map(({ tool, defaults }) => {
|
|
28
|
+
const { __enabled: _enabled, ...paramDefaults } = defaults;
|
|
29
|
+
return agentToolToPiTool(wrapWithDefaults(tool, paramDefaults));
|
|
30
|
+
});
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
function safeGetDefaults(toolName: string): Record<string, unknown> {
|
|
@@ -1,5 +1,21 @@
|
|
|
1
|
+
import type { ResolvedTurnContext } from "../routing/turn-context.js";
|
|
2
|
+
import { renderPolicyCardForPlanning } from "./policy-cards.js";
|
|
1
3
|
import type { PromptSection, SectionName } from "./sections.js";
|
|
2
|
-
import {
|
|
4
|
+
import { DEFAULT_BUDGETS, SECTION_ORDER, truncateTobudget } from "./sections.js";
|
|
5
|
+
|
|
6
|
+
export interface PromptSectionReport {
|
|
7
|
+
name: SectionName;
|
|
8
|
+
originalLength: number;
|
|
9
|
+
renderedLength: number;
|
|
10
|
+
characterBudget: number;
|
|
11
|
+
truncated: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface PromptBuildReport {
|
|
15
|
+
prompt: string;
|
|
16
|
+
sections: PromptSectionReport[];
|
|
17
|
+
truncationMarkers: number;
|
|
18
|
+
}
|
|
3
19
|
|
|
4
20
|
/** Options for building prompt context. */
|
|
5
21
|
export interface PromptContextOptions {
|
|
@@ -15,6 +31,7 @@ export interface PromptContextOptions {
|
|
|
15
31
|
* if both are set, `workflowInstructions` wins (rule-path compatibility).
|
|
16
32
|
*/
|
|
17
33
|
fallbackContext?: FallbackContext;
|
|
34
|
+
resolvedTurnContext?: ResolvedTurnContext;
|
|
18
35
|
}
|
|
19
36
|
|
|
20
37
|
export interface FallbackContext {
|
|
@@ -51,21 +68,36 @@ export class PromptContextBuilder {
|
|
|
51
68
|
return this;
|
|
52
69
|
}
|
|
53
70
|
|
|
54
|
-
/** Get a section by name. */
|
|
55
|
-
getSection(name: SectionName): PromptSection | undefined {
|
|
56
|
-
return this.sections.get(name);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
71
|
/** Build the complete system prompt. */
|
|
60
72
|
build(): string {
|
|
73
|
+
return this.buildWithReport().prompt;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Build the complete prompt and report section size/truncation metadata. */
|
|
77
|
+
buildWithReport(): PromptBuildReport {
|
|
61
78
|
const parts: string[] = [];
|
|
79
|
+
const report: PromptSectionReport[] = [];
|
|
80
|
+
let truncationMarkers = 0;
|
|
62
81
|
for (const name of SECTION_ORDER) {
|
|
63
82
|
const section = this.sections.get(name)!;
|
|
64
83
|
if (!section.content) continue;
|
|
65
84
|
const truncated = truncateTobudget(section.content, section.characterBudget);
|
|
85
|
+
const wasTruncated = truncated.includes("[...truncated]");
|
|
86
|
+
if (wasTruncated) truncationMarkers += 1;
|
|
87
|
+
report.push({
|
|
88
|
+
name,
|
|
89
|
+
originalLength: section.content.length,
|
|
90
|
+
renderedLength: truncated.length,
|
|
91
|
+
characterBudget: section.characterBudget,
|
|
92
|
+
truncated: wasTruncated,
|
|
93
|
+
});
|
|
66
94
|
parts.push(truncated);
|
|
67
95
|
}
|
|
68
|
-
return
|
|
96
|
+
return {
|
|
97
|
+
prompt: parts.join("\n\n"),
|
|
98
|
+
sections: report,
|
|
99
|
+
truncationMarkers,
|
|
100
|
+
};
|
|
69
101
|
}
|
|
70
102
|
|
|
71
103
|
/**
|
|
@@ -74,14 +106,23 @@ export class PromptContextBuilder {
|
|
|
74
106
|
populateFromOptions(options: PromptContextOptions): this {
|
|
75
107
|
this.setSection("base-role", BASE_ROLE);
|
|
76
108
|
this.setSection("safety-rules", SAFETY_RULES);
|
|
77
|
-
this.setSection(
|
|
109
|
+
this.setSection(
|
|
110
|
+
"tool-catalog",
|
|
111
|
+
options.resolvedTurnContext && options.resolvedTurnContext.activeToolNames.length === 0
|
|
112
|
+
? "## Available Tools\nNo finance tools are needed for this turn. Answer from general finance knowledge without naming OpenCandle tool functions."
|
|
113
|
+
: buildToolCatalog(options.addonToolDescriptions),
|
|
114
|
+
);
|
|
78
115
|
if (options.workflowInstructions) {
|
|
79
116
|
this.setSection("workflow-instructions", options.workflowInstructions);
|
|
80
|
-
} else if (options.
|
|
117
|
+
} else if (options.resolvedTurnContext) {
|
|
118
|
+
const routePlaybook = buildRoutePlaybook(options.resolvedTurnContext);
|
|
119
|
+
const policyCard = renderPolicyCardForPlanning(options.resolvedTurnContext.planning);
|
|
81
120
|
this.setSection(
|
|
82
121
|
"workflow-instructions",
|
|
83
|
-
|
|
122
|
+
policyCard ? `${policyCard}\n\n${routePlaybook}` : routePlaybook,
|
|
84
123
|
);
|
|
124
|
+
} else if (options.fallbackContext) {
|
|
125
|
+
this.setSection("workflow-instructions", buildFallbackPlaybook(options.fallbackContext));
|
|
85
126
|
}
|
|
86
127
|
if (options.memoryContext) {
|
|
87
128
|
this.setSection("memory-context", formatMemorySection(options.memoryContext));
|
|
@@ -101,6 +142,76 @@ export class PromptContextBuilder {
|
|
|
101
142
|
* are missing. Contains NO refusal or hedging language.
|
|
102
143
|
*/
|
|
103
144
|
export function buildFallbackPlaybook(ctx: FallbackContext): string {
|
|
145
|
+
return buildAgentTaskPlaybook(ctx);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function buildRoutePlaybook(ctx: ResolvedTurnContext): string {
|
|
149
|
+
const assumptionsBlock = buildResolvedAssumptionsBlock(ctx);
|
|
150
|
+
const droppedSymbols = ctx.diagnostics
|
|
151
|
+
.filter((diagnostic) => diagnostic.code === "symbol_dropped")
|
|
152
|
+
.map((diagnostic) => diagnostic.details?.token)
|
|
153
|
+
.filter((token): token is string => typeof token === "string" && token.length > 0);
|
|
154
|
+
const dropContext =
|
|
155
|
+
droppedSymbols.length > 0
|
|
156
|
+
? `Dropped ambiguous ticker-like tokens: ${droppedSymbols.join(", ")}.`
|
|
157
|
+
: undefined;
|
|
158
|
+
const extraContext = [
|
|
159
|
+
ctx.entities.symbols.length > 0
|
|
160
|
+
? `Router-extracted symbols: ${ctx.entities.symbols.join(", ")}. Route kind: ${ctx.routeKind}. Tool bundles: ${ctx.toolBundles.join(", ") || "(none)"}.`
|
|
161
|
+
: `Route kind: ${ctx.routeKind}. Tool bundles: ${ctx.toolBundles.join(", ") || "(none)"}.`,
|
|
162
|
+
dropContext,
|
|
163
|
+
]
|
|
164
|
+
.filter((part): part is string => Boolean(part))
|
|
165
|
+
.join(" ");
|
|
166
|
+
const fallbackContext: FallbackContext = {
|
|
167
|
+
assumptionsBlock,
|
|
168
|
+
missingRequired: ctx.missingRequired,
|
|
169
|
+
extraContext,
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
if (ctx.routeKind === "clarification") {
|
|
173
|
+
return buildClarificationPlaybook(fallbackContext);
|
|
174
|
+
}
|
|
175
|
+
if (ctx.routeKind === "pass_through") {
|
|
176
|
+
return `## Pass-Through Playbook
|
|
177
|
+
This turn is outside OpenCandle's finance task surface. Answer normally without invoking finance tools. If the user clarifies into an investment, trading, portfolio, macro, or market-data task, ask a concise follow-up or proceed under the analyst stance.
|
|
178
|
+
|
|
179
|
+
## Assumptions Context
|
|
180
|
+
${assumptionsBlock}`;
|
|
181
|
+
}
|
|
182
|
+
if (ctx.routeKind === "workflow_dispatch") {
|
|
183
|
+
return `## Workflow Dispatch Context
|
|
184
|
+
The router selected workflow dispatch${ctx.workflow ? ` for ${ctx.workflow}` : ""}. Use the workflow instructions as authoritative when present, and use this context only for slot provenance and missing required fields.
|
|
185
|
+
|
|
186
|
+
${ctx.missingRequired.length > 0 ? `## Missing Required Information\nThe following slots are required but not yet filled: ${ctx.missingRequired.join(", ")}. Call the \`ask_user\` tool before committing to analysis.\n\n` : ""}## Assumptions Context
|
|
187
|
+
${assumptionsBlock}`;
|
|
188
|
+
}
|
|
189
|
+
return buildAgentTaskPlaybook(fallbackContext);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function buildClarificationPlaybook(ctx: FallbackContext): string {
|
|
193
|
+
const missing = ctx.missingRequired.join(", ") || "required information";
|
|
194
|
+
return `## Clarification Playbook
|
|
195
|
+
The router found that analysis is blocked by missing required information: ${missing}. Call the \`ask_user\` tool before committing to financial analysis. Keep the question specific and collect only the missing slots.
|
|
196
|
+
|
|
197
|
+
${ctx.extraContext ? `## Additional Context\n${ctx.extraContext}\n\n` : ""}## Assumptions Context
|
|
198
|
+
${ctx.assumptionsBlock}`;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function buildResolvedAssumptionsBlock(ctx: ResolvedTurnContext): string {
|
|
202
|
+
const lines: string[] = [];
|
|
203
|
+
lines.push("Assumptions Context:");
|
|
204
|
+
if (Object.keys(ctx.slots).length === 0) {
|
|
205
|
+
lines.push(" (none)");
|
|
206
|
+
return lines.join("\n");
|
|
207
|
+
}
|
|
208
|
+
for (const [key, slot] of Object.entries(ctx.slots)) {
|
|
209
|
+
lines.push(` ${key}: ${String(slot.value)} (${slot.source})`);
|
|
210
|
+
}
|
|
211
|
+
return lines.join("\n");
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function buildAgentTaskPlaybook(ctx: FallbackContext): string {
|
|
104
215
|
const missingLine =
|
|
105
216
|
ctx.missingRequired.length > 0
|
|
106
217
|
? `\n## Missing Required Information\nThe following slots are required but not yet filled: ${ctx.missingRequired.join(", ")}. Call the \`ask_user\` tool to collect each one BEFORE committing to a final answer. Do not guess or assume these values.`
|
|
@@ -108,17 +219,21 @@ export function buildFallbackPlaybook(ctx: FallbackContext): string {
|
|
|
108
219
|
const extraLine = ctx.extraContext ? `\n## Additional Context\n${ctx.extraContext}` : "";
|
|
109
220
|
|
|
110
221
|
return `## Fallback Playbook
|
|
111
|
-
This turn did not match a structured workflow, but you still
|
|
222
|
+
This turn did not match a structured workflow, but you still answer under the analyst stance. Keep this fallback generic: task-specific behavior belongs in policy cards, workflow prompts, tool/evidence normalization, answer contracts, or structured checks. Do not add task-specific instructions here.${missingLine}${extraLine}
|
|
112
223
|
|
|
113
224
|
1. Tool-first: fetch relevant data with your available tools before stating prices, levels, or metrics.
|
|
114
|
-
2.
|
|
115
|
-
3. Commit
|
|
116
|
-
4. Attach reasoning, a confidence band, and an invalidation condition to every committal response
|
|
225
|
+
2. Use the Assumptions Context below only as internal routing context. Do not quote it, label it, or start the answer with it unless the user explicitly asked for assumptions.
|
|
226
|
+
3. Commit to a concrete, specific answer when the user asks for a view, recommendation, allocation, target, explanation, or next step. Low confidence is valid; refusal-shaped hedging is not.
|
|
227
|
+
4. Attach reasoning, a confidence band, and an invalidation condition to every committal response.
|
|
228
|
+
5. Label data gaps, stale provider output, unavailable tools, and unverified current facts. If web search returns no results or a provider soft-degrades, continue with the best supported answer when the gap is not blocking, lower confidence where appropriate, and name what live fact would change the view.
|
|
229
|
+
6. If required slots are missing, call ask_user before committing. Otherwise do not ask a generic follow-up instead of answering.
|
|
230
|
+
7. Do not add task-specific instructions here. Add them to the selected policy card, workflow prompt, tool result normalization, answer contract, or structured check.
|
|
117
231
|
|
|
232
|
+
## Assumptions Context
|
|
118
233
|
${ctx.assumptionsBlock}
|
|
119
234
|
|
|
120
235
|
Response format:
|
|
121
|
-
-
|
|
236
|
+
- Lead with the answer or view, not the assumptions context.
|
|
122
237
|
- Commit to specifics. Present numeric data in tables when comparing multiple values.
|
|
123
238
|
- Flag downside and risks loudly; never downplay them.`;
|
|
124
239
|
}
|
|
@@ -128,12 +243,19 @@ Response format:
|
|
|
128
243
|
const BASE_ROLE = `You are OpenCandle, a research analyst for investors and traders.
|
|
129
244
|
|
|
130
245
|
## Your Role
|
|
131
|
-
You are an analyst, not a fiduciary advisor. When asked for entry levels, price targets, stops, position sizes, or allocations, you COMMIT to specific numbers backed by the data you fetched. Uncertainty is expressed as a confidence band and an invalidation level — never as refusal. Refusal-shaped hedges are wrong for this product; users are here for an analyst's view. Frame views as analyst opinion ("our read", "the data suggests", "analyst view"), never as personalised fiduciary guidance ("tailored to your situation", "given your full financial picture").`;
|
|
246
|
+
You are an analyst, not a fiduciary advisor. When asked for entry levels, price targets, stops, position sizes, or allocations, you COMMIT to specific numbers backed by the data you fetched. Uncertainty is expressed as a confidence band and an invalidation level — never as refusal. Refusal-shaped hedges are wrong for this product; users are here for an analyst's view. For conceptual education questions, teach the concept directly, do not name tool functions, and do not append analyst-view, confidence-band, or invalidation boilerplate. For valuation-metric education, start with "Bottom line", immediately follow it with a one-sentence paragraph beginning "Core mental model:", use a heading exactly named "Practical workflow" with numbered question-driven application steps, explain where the metric misleads as common traps to avoid, include a compact cross-check table with why/when each metric helps, include relevant trailing, forward, normalized, or cyclically adjusted variants when useful, and end with a heading exactly named "Quick checklist". Frame views as analyst opinion ("our read", "the data suggests", "analyst view"), never as personalised fiduciary guidance ("tailored to your situation", "given your full financial picture").`;
|
|
132
247
|
|
|
133
248
|
const SAFETY_RULES = `## Guidelines
|
|
134
249
|
- Always fetch data with tools before stating prices, ratios, or metrics. Never guess financial numbers. Every substantive response should be backed by at least one tool call — if you find yourself writing a response with zero tool calls, stop and think about what data would make it better.
|
|
250
|
+
- For current single-stock recommendations, state the quote or tool-output date; preserve market-closed, delayed, or last available quote notes. If DCF/fundamentals are unavailable, do not let that tool failure or missing fundamentals become the main thesis. Use available quote, earnings, technicals, sentiment/news, fallback valuation lenses, structural business risks, position sizing, and entry strategy.
|
|
251
|
+
- For crypto position-sizing prompts, start with a concrete allocation range and dollar amount, then show drawdown impact on the user's portfolio, a sleep test, dollar-cost averaging, rebalancing rules, position caps, tax tracking, reputable custody/exchange considerations, and emergency-fund/high-interest-debt prerequisites. Cite the crypto tool-output date or history period and label sparse or unavailable history instead of implying unsupported precision.
|
|
252
|
+
- For rate-cut market-pricing questions, use get_economic_data for the current Fed funds backdrop and search_web for CME FedWatch / Federal Funds futures probabilities before naming what the market is pricing. Distinguish historical Fed rates from futures-implied expectations.
|
|
253
|
+
- For backtest_strategy results, report strategy return, buy-and-hold return, outperformance, trade count, win rate, and max drawdown. Include risk-adjusted metrics such as Sharpe or Sortino when available; otherwise say they were unavailable. Explain why the strategy worked or failed in the tested regime and discuss trading costs/slippage when the user asks whether the edge is practical. Do not reduce a backtest answer to return-only.
|
|
254
|
+
- For sentiment-only prompts, final answer must include the direction and strength of the sentiment signal, the score scale when available, missing sources, why those missing sources matter for the user's question, the source-coverage risk, low sample counts, and how those gaps downgrade confidence. For ticker-specific sentiment prompts, call get_stock_quote before the final answer and state whether sentiment diverges from price action.
|
|
135
255
|
- Commit to specifics when asked for entries, targets, stops, allocations, or position sizes. Refusal is not an acceptable output shape.
|
|
136
256
|
- Each committal response carries FOUR things: the specific number or range, a reasoning chain naming the data points you used, a confidence band, and an invalidation level (what would break the thesis).
|
|
257
|
+
- Conceptual education prompts are not committal responses. Do not append "Analyst View", "Commitment", "Reasoning Chain", "Confidence Band", or "Invalidation Level" sections when the user asked for an explanation, definition, or learning framework rather than a trade, allocation, or recommendation.
|
|
258
|
+
- If no active finance tool exists for brokerage, account, fund-platform, financial-product selection, or conceptual education, do not refuse or apologize for missing tools. Answer from durable public finance knowledge, name facts the user should verify, and keep any current-data caveat brief.
|
|
137
259
|
- For options analysis, use get_option_chain to see the full chain with Greeks. Pay attention to put/call ratio, unusual volume, and IV levels.
|
|
138
260
|
- Present numerical data in tables when comparing multiple securities.
|
|
139
261
|
- Include data timestamps so users know how fresh the information is.
|
|
@@ -151,7 +273,7 @@ Use the ask_user tool BEFORE proceeding when:
|
|
|
151
273
|
- Risk tolerance is unclear for portfolio or options recommendations
|
|
152
274
|
|
|
153
275
|
Do NOT ask clarifying questions when:
|
|
154
|
-
- The request is clear and specific
|
|
276
|
+
- The request is clear and specific about the asset or market to analyze
|
|
155
277
|
- You can reasonably infer the intent from context or prior conversation
|
|
156
278
|
- A reasonable default exists and can be disclosed in the Assumptions block instead
|
|
157
279
|
- The user explicitly asks you to use your judgment
|
|
@@ -162,14 +284,14 @@ Keep questions concise and offer specific options when possible. Prefer select-t
|
|
|
162
284
|
CRITICAL: After ask_user answers come back, your NEXT action MUST be tool calls — not a text response. You are a data agent, not a chatbot. Never respond with generic investment categories or tell the user to come back with tickers. YOU pick the relevant assets and indicators based on what you learned, then fetch the data.`;
|
|
163
285
|
|
|
164
286
|
const TOOL_CATALOG = `## Available Tools
|
|
165
|
-
- **Market Data**: get_stock_quote, get_stock_history, get_crypto_price, get_crypto_history —
|
|
287
|
+
- **Market Data**: screen_stocks, get_stock_quote, get_stock_history, get_crypto_price, get_crypto_history — use screen_stocks for breadth and screening prompts such as large-cap lists, oversold stocks, market movers, and filtered market scans; use get_stock_quote/get_stock_history for a single-security quote or historical OHLCV
|
|
166
288
|
- **Fundamentals**: get_company_overview, get_financials, get_earnings, compute_dcf, compare_companies, get_sec_filings — company financials, valuation metrics, DCF intrinsic value, peer comparison, and SEC EDGAR filings (10-K, 10-Q, 8-K)
|
|
167
289
|
- **Technical Analysis**: get_technical_indicators, backtest_strategy — SMA, EMA, RSI, MACD, Bollinger Bands, OBV, VWAP computed from price data, plus simple strategy backtesting
|
|
168
290
|
- **Macro**: get_economic_data, get_fear_greed — FRED economic indicators and market sentiment
|
|
169
291
|
- **Sentiment**: get_reddit_sentiment, get_twitter_sentiment, get_web_sentiment, get_sentiment_trend, get_sentiment_summary — retail and news sentiment from Reddit, Twitter/X, and web sources with historical trends and cross-source divergence detection
|
|
170
|
-
- **Web Search**: search_web — breaking news, earnings context, company events, regulatory developments. When a dedicated tool can answer the question (quotes, fundamentals, earnings, macro, SEC filings, sentiment), use that tool instead — do not add search_web as a supplementary source for data available through dedicated tools
|
|
292
|
+
- **Web Search**: search_web — breaking news, earnings context, company events, regulatory developments. Supported freshness values are hours, day, week, and month; use category general with freshness month for broad industry context; never pass unsupported values such as all, year, 3mo, quarter, or custom date ranges. When a dedicated tool can answer the question (quotes, fundamentals, earnings, macro, SEC filings, sentiment), use that tool instead — do not add search_web as a supplementary source for data available through dedicated tools
|
|
171
293
|
- **Options**: get_option_chain — full options chain with strikes, bids/asks, volume, OI, IV, and computed Greeks (delta, gamma, theta, vega, rho)
|
|
172
|
-
- **Portfolio**: track_portfolio, analyze_risk, manage_watchlist, analyze_correlation, track_prediction — position tracking, P&L, Sharpe ratio, VaR, watchlist
|
|
294
|
+
- **Portfolio**: track_portfolio, analyze_risk, manage_watchlist, analyze_correlation, analyze_holdings_overlap, track_prediction, manage_alerts, daily_watchlist_report, manage_notifications — position tracking, P&L, Sharpe ratio, VaR, watchlist tracking, durable local alerts, daily watchlist reports, notification history, correlation matrix, ETF/fund holdings overlap, and prediction tracking with accuracy scoring
|
|
173
295
|
- **User Interaction**: ask_user — ask the user a clarification question when their request is ambiguous or missing key details`;
|
|
174
296
|
|
|
175
297
|
function buildToolCatalog(addonDescriptions?: string[]): string {
|
|
@@ -201,4 +323,4 @@ Every committal response MUST carry four elements:
|
|
|
201
323
|
- **Invalidation level** — what would change your view, stated concretely ("thesis breaks if quarterly revenue growth falls below 15%", "invalidated on a daily close below $120 with expanding volume").
|
|
202
324
|
|
|
203
325
|
## Assumption Disclosure
|
|
204
|
-
|
|
326
|
+
Structured workflow prompts may include a pre-rendered "Assumptions" block with correct source attribution (user-specified, saved preference, or default). Start with that block only when the workflow instructions explicitly say to. Fallback prompts include "Assumptions Context" only for internal routing context; do not reproduce that context unless the user explicitly asks for assumptions. Do NOT independently relabel any value's source anywhere in your response. When an assumptions block is shown, it is the single authoritative provenance representation.`;
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
* longer steers model behavior but still surfaces on every assistant turn.
|
|
5
5
|
*/
|
|
6
6
|
export const DISCLAIMER_TEXT =
|
|
7
|
-
"OpenCandle is a research and analysis tool, not a fiduciary financial advisor. " +
|
|
7
|
+
"OpenCandle is a research and analysis tool, not financial advice or a fiduciary financial advisor. " +
|
|
8
8
|
"Views, targets, and allocations are informational analyst output — not personalized recommendations. " +
|
|
9
9
|
"Verify independently before acting.";
|