opencandle 0.2.0 → 0.3.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.
Files changed (154) hide show
  1. package/README.md +110 -87
  2. package/dist/analysts/orchestrator.js +1 -2
  3. package/dist/analysts/orchestrator.js.map +1 -1
  4. package/dist/config.d.ts +25 -5
  5. package/dist/config.js +16 -8
  6. package/dist/config.js.map +1 -1
  7. package/dist/infra/cache.d.ts +4 -0
  8. package/dist/infra/cache.js +4 -0
  9. package/dist/infra/cache.js.map +1 -1
  10. package/dist/infra/rate-limiter.js +6 -0
  11. package/dist/infra/rate-limiter.js.map +1 -1
  12. package/dist/onboarding/connect.d.ts +23 -0
  13. package/dist/onboarding/connect.js +107 -0
  14. package/dist/onboarding/connect.js.map +1 -0
  15. package/dist/onboarding/credential-interceptor.d.ts +44 -0
  16. package/dist/onboarding/credential-interceptor.js +72 -0
  17. package/dist/onboarding/credential-interceptor.js.map +1 -0
  18. package/dist/onboarding/degradation-accumulator.d.ts +21 -0
  19. package/dist/onboarding/degradation-accumulator.js +55 -0
  20. package/dist/onboarding/degradation-accumulator.js.map +1 -0
  21. package/dist/onboarding/prompt-user.d.ts +23 -0
  22. package/dist/onboarding/prompt-user.js +61 -0
  23. package/dist/onboarding/prompt-user.js.map +1 -0
  24. package/dist/onboarding/providers.d.ts +109 -0
  25. package/dist/onboarding/providers.js +236 -0
  26. package/dist/onboarding/providers.js.map +1 -0
  27. package/dist/onboarding/state.d.ts +31 -2
  28. package/dist/onboarding/state.js +141 -13
  29. package/dist/onboarding/state.js.map +1 -1
  30. package/dist/onboarding/tool-helpers.d.ts +34 -0
  31. package/dist/onboarding/tool-helpers.js +80 -0
  32. package/dist/onboarding/tool-helpers.js.map +1 -0
  33. package/dist/onboarding/tool-tags.d.ts +37 -0
  34. package/dist/onboarding/tool-tags.js +149 -0
  35. package/dist/onboarding/tool-tags.js.map +1 -0
  36. package/dist/onboarding/validation.d.ts +19 -0
  37. package/dist/onboarding/validation.js +117 -0
  38. package/dist/onboarding/validation.js.map +1 -0
  39. package/dist/pi/opencandle-extension.js +303 -4
  40. package/dist/pi/opencandle-extension.js.map +1 -1
  41. package/dist/pi/setup.d.ts +0 -1
  42. package/dist/pi/setup.js +66 -119
  43. package/dist/pi/setup.js.map +1 -1
  44. package/dist/prompts/context-builder.js +2 -1
  45. package/dist/prompts/context-builder.js.map +1 -1
  46. package/dist/providers/alpha-vantage.js +20 -1
  47. package/dist/providers/alpha-vantage.js.map +1 -1
  48. package/dist/providers/exa-search.d.ts +39 -0
  49. package/dist/providers/exa-search.js +276 -0
  50. package/dist/providers/exa-search.js.map +1 -0
  51. package/dist/providers/finnhub.d.ts +17 -0
  52. package/dist/providers/finnhub.js +94 -0
  53. package/dist/providers/finnhub.js.map +1 -0
  54. package/dist/providers/fred.js +13 -1
  55. package/dist/providers/fred.js.map +1 -1
  56. package/dist/providers/index.d.ts +2 -0
  57. package/dist/providers/index.js +1 -0
  58. package/dist/providers/index.js.map +1 -1
  59. package/dist/providers/provider-credential-error.d.ts +8 -0
  60. package/dist/providers/provider-credential-error.js +22 -0
  61. package/dist/providers/provider-credential-error.js.map +1 -0
  62. package/dist/providers/reddit.d.ts +8 -0
  63. package/dist/providers/reddit.js +36 -9
  64. package/dist/providers/reddit.js.map +1 -1
  65. package/dist/providers/twitter.js +2 -8
  66. package/dist/providers/twitter.js.map +1 -1
  67. package/dist/providers/web-search.d.ts +17 -0
  68. package/dist/providers/web-search.js +224 -0
  69. package/dist/providers/web-search.js.map +1 -0
  70. package/dist/providers/wrap-provider.d.ts +7 -0
  71. package/dist/providers/wrap-provider.js +15 -0
  72. package/dist/providers/wrap-provider.js.map +1 -1
  73. package/dist/routing/classify-intent.js +22 -0
  74. package/dist/routing/classify-intent.js.map +1 -1
  75. package/dist/runtime/session-coordinator.d.ts +0 -1
  76. package/dist/runtime/session-coordinator.js.map +1 -1
  77. package/dist/sentiment/adapters/finnhub.d.ts +7 -0
  78. package/dist/sentiment/adapters/finnhub.js +39 -0
  79. package/dist/sentiment/adapters/finnhub.js.map +1 -0
  80. package/dist/sentiment/adapters/reddit.d.ts +11 -0
  81. package/dist/sentiment/adapters/reddit.js +54 -0
  82. package/dist/sentiment/adapters/reddit.js.map +1 -0
  83. package/dist/sentiment/adapters/twitter.d.ts +9 -0
  84. package/dist/sentiment/adapters/twitter.js +32 -0
  85. package/dist/sentiment/adapters/twitter.js.map +1 -0
  86. package/dist/sentiment/adapters/web.d.ts +9 -0
  87. package/dist/sentiment/adapters/web.js +40 -0
  88. package/dist/sentiment/adapters/web.js.map +1 -0
  89. package/dist/sentiment/index.d.ts +16 -0
  90. package/dist/sentiment/index.js +44 -0
  91. package/dist/sentiment/index.js.map +1 -0
  92. package/dist/sentiment/keywords.d.ts +2 -0
  93. package/dist/sentiment/keywords.js +9 -0
  94. package/dist/sentiment/keywords.js.map +1 -0
  95. package/dist/sentiment/pipeline.d.ts +9 -0
  96. package/dist/sentiment/pipeline.js +57 -0
  97. package/dist/sentiment/pipeline.js.map +1 -0
  98. package/dist/sentiment/scorer.d.ts +9 -0
  99. package/dist/sentiment/scorer.js +64 -0
  100. package/dist/sentiment/scorer.js.map +1 -0
  101. package/dist/sentiment/store.d.ts +24 -0
  102. package/dist/sentiment/store.js +177 -0
  103. package/dist/sentiment/store.js.map +1 -0
  104. package/dist/sentiment/trends.d.ts +13 -0
  105. package/dist/sentiment/trends.js +73 -0
  106. package/dist/sentiment/trends.js.map +1 -0
  107. package/dist/sentiment/types.d.ts +66 -0
  108. package/dist/sentiment/types.js +54 -0
  109. package/dist/sentiment/types.js.map +1 -0
  110. package/dist/system-prompt.js +9 -1
  111. package/dist/system-prompt.js.map +1 -1
  112. package/dist/tools/fundamentals/company-overview.d.ts +3 -1
  113. package/dist/tools/fundamentals/company-overview.js +27 -27
  114. package/dist/tools/fundamentals/company-overview.js.map +1 -1
  115. package/dist/tools/fundamentals/comps.js +45 -45
  116. package/dist/tools/fundamentals/comps.js.map +1 -1
  117. package/dist/tools/fundamentals/dcf.js +82 -82
  118. package/dist/tools/fundamentals/dcf.js.map +1 -1
  119. package/dist/tools/fundamentals/earnings.d.ts +3 -1
  120. package/dist/tools/fundamentals/earnings.js +25 -25
  121. package/dist/tools/fundamentals/earnings.js.map +1 -1
  122. package/dist/tools/fundamentals/financials.d.ts +3 -1
  123. package/dist/tools/fundamentals/financials.js +23 -23
  124. package/dist/tools/fundamentals/financials.js.map +1 -1
  125. package/dist/tools/index.js +8 -2
  126. package/dist/tools/index.js.map +1 -1
  127. package/dist/tools/interaction/ask-user.js +28 -64
  128. package/dist/tools/interaction/ask-user.js.map +1 -1
  129. package/dist/tools/macro/fred-data.d.ts +3 -1
  130. package/dist/tools/macro/fred-data.js +26 -26
  131. package/dist/tools/macro/fred-data.js.map +1 -1
  132. package/dist/tools/sentiment/reddit-sentiment.d.ts +3 -1
  133. package/dist/tools/sentiment/reddit-sentiment.js +107 -22
  134. package/dist/tools/sentiment/reddit-sentiment.js.map +1 -1
  135. package/dist/tools/sentiment/sentiment-summary.d.ts +7 -0
  136. package/dist/tools/sentiment/sentiment-summary.js +230 -0
  137. package/dist/tools/sentiment/sentiment-summary.js.map +1 -0
  138. package/dist/tools/sentiment/sentiment-trend.d.ts +22 -0
  139. package/dist/tools/sentiment/sentiment-trend.js +39 -0
  140. package/dist/tools/sentiment/sentiment-trend.js.map +1 -0
  141. package/dist/tools/sentiment/twitter-sentiment.js +17 -0
  142. package/dist/tools/sentiment/twitter-sentiment.js.map +1 -1
  143. package/dist/tools/sentiment/web-search.d.ts +11 -0
  144. package/dist/tools/sentiment/web-search.js +115 -0
  145. package/dist/tools/sentiment/web-search.js.map +1 -0
  146. package/dist/tools/sentiment/web-sentiment.d.ts +8 -0
  147. package/dist/tools/sentiment/web-sentiment.js +66 -0
  148. package/dist/tools/sentiment/web-sentiment.js.map +1 -0
  149. package/dist/types/index.d.ts +1 -1
  150. package/dist/types/sentiment.d.ts +21 -0
  151. package/package.json +19 -3
  152. package/dist/tools/sentiment/news-sentiment.d.ts +0 -7
  153. package/dist/tools/sentiment/news-sentiment.js +0 -55
  154. package/dist/tools/sentiment/news-sentiment.js.map +0 -1
package/README.md CHANGED
@@ -1,63 +1,65 @@
1
1
  # OpenCandle
2
2
 
3
- A financial agent that talks to markets. Ask it for stock prices, options chains with Greeks, macro data, sentiment it fetches real data, computes analytics locally, and gives you actionable answers.
3
+ OpenCandle is a terminal-first financial data agent built with TypeScript and Pi. It fetches market, macro, options, fundamentals, sentiment, and portfolio data from real providers, then lets the model synthesize that data into an answer.
4
4
 
5
- ## What This Does
5
+ This repository is useful in two ways:
6
6
 
7
- OpenCandle is an AI-powered terminal agent for investors and traders. Instead of switching between Yahoo Finance, FRED, Reddit, and a spreadsheet, you ask one agent and it chains the right tools together. It computes technical indicators and options Greeks locally (Black-Scholes), so there's no API dependency for math.
7
+ - Run `opencandle` as an interactive CLI for market research
8
+ - Extend OpenCandle with new tools, providers, or Pi-compatible add-on packages
8
9
 
9
- Type `analyze TSLA` and it runs a full 5-analyst breakdown — fundamentals, technicals, options positioning, sentiment, risk — then synthesizes a verdict.
10
+ ## What You Can Use It For
10
11
 
11
- [Pi](https://pi.dev/) powers the runtime, TUI, auth, and model selection. OpenCandle keeps its own user data in `~/.opencandle/`.
12
+ - Quote and history lookups for stocks and crypto
13
+ - Options chains with locally computed Greeks
14
+ - Company fundamentals, earnings, and SEC filings
15
+ - FRED macro series and Fear & Greed data
16
+ - Reddit-based sentiment and discussion lookups
17
+ - Portfolio tracking, watchlists, correlation, and risk analysis
18
+ - Multi-step workflows such as `/analyze NVDA`
12
19
 
13
- ## Getting Started
20
+ OpenCandle is designed to fetch and format data. The model handles synthesis. Tool code should not invent financial conclusions or hardcode market numbers.
14
21
 
15
- **Requires Node.js 20.**
22
+ ## Install And Run
16
23
 
17
- ### Standalone CLI
24
+ Requires Node.js 20+.
25
+
26
+ ### CLI
18
27
 
19
28
  ```bash
20
29
  npm install -g opencandle
21
30
  opencandle
22
31
 
23
- # or run without installing globally
32
+ # or without installing globally
24
33
  npx opencandle@latest
25
34
  ```
26
35
 
27
- On first run, OpenCandle walks you through setup:
28
-
29
- 1. **Connect an AI provider** — sign in with OAuth (Google, OpenAI, Anthropic) or paste an API key
30
- 2. **Pick a model** — choose from the available models on your connected provider
31
- 3. **Optional: add market-data keys** — Alpha Vantage and FRED for fundamentals and macro data (can skip)
32
-
33
- To rerun setup later, use `/setup`.
34
-
35
36
  ### From Source
36
37
 
37
38
  ```bash
38
39
  npm install
39
40
  cp .env.example .env
40
- # Add any LLM env vars you want to use locally (for example GEMINI_API_KEY)
41
41
  npm start
42
42
  ```
43
43
 
44
- ### API Keys
44
+ On first run, OpenCandle walks you through model setup. You can rerun that flow later with `/setup`.
45
+
46
+ ## Configuration
47
+
48
+ Model access comes from Pi. Market data providers are optional and additive.
45
49
 
46
- | Key | Required | Free Tier | What It Unlocks |
47
- |-----|----------|-----------|-----------------|
48
- | `GEMINI_API_KEY` | No | Yes | Google Gemini via Pi auth/model registry |
49
- | `OPENAI_API_KEY` | No | Paid | OpenAI models via Pi auth/model registry |
50
- | `ANTHROPIC_API_KEY` | No | Paid | Anthropic models via Pi auth/model registry |
51
- | `ALPHA_VANTAGE_API_KEY` | No | 25 req/day | Company fundamentals, earnings, financials |
52
- | `FRED_API_KEY` | No | Generous | Fed rates, CPI, GDP, unemployment, yield curve |
50
+ | Key | Required | Used For |
51
+ | --- | --- | --- |
52
+ | `GEMINI_API_KEY` | No | Google models through Pi |
53
+ | `OPENAI_API_KEY` | No | OpenAI models through Pi |
54
+ | `ANTHROPIC_API_KEY` | No | Anthropic models through Pi |
55
+ | `ALPHA_VANTAGE_API_KEY` | No | Fundamentals, earnings, financial statements |
56
+ | `FRED_API_KEY` | No | Macro series such as rates, CPI, GDP, unemployment |
53
57
 
54
- Yahoo Finance, CoinGecko, Reddit, and Fear & Greed Index need no keys.
55
- Pi also supports OAuth-backed and custom providers through `~/.pi/agent/auth.json`, `/login`, `/model`, and `~/.pi/agent/models.json`.
58
+ Yahoo Finance, CoinGecko, Reddit, SEC EDGAR, and Fear & Greed data do not require keys.
56
59
 
57
- ### State and Config
60
+ OpenCandle stores its own user state in `~/.opencandle/` by default. Pi configuration stays in `.pi/` and `~/.pi/agent/`. The CLI should not depend on repo-local `.pi/extensions/`.
58
61
 
59
- - Pi runtime config and optional project overrides live in `.pi/` and `~/.pi/agent/...`.
60
- - OpenCandle finance-provider config lives in `~/.opencandle/config.json`:
62
+ Provider keys can also be stored in `~/.opencandle/config.json`:
61
63
 
62
64
  ```json
63
65
  {
@@ -72,88 +74,109 @@ Pi also supports OAuth-backed and custom providers through `~/.pi/agent/auth.jso
72
74
  }
73
75
  ```
74
76
 
75
- - Environment variables still work and override `~/.opencandle/config.json`.
76
- - Set `OPENCANDLE_HOME` to override the default `~/.opencandle/` data directory.
77
- - OpenCandle user data lives in `~/.opencandle/` (or `$OPENCANDLE_HOME`):
78
- - `~/.opencandle/watchlist.json`
79
- - `~/.opencandle/portfolio.json`
80
- - `~/.opencandle/predictions.json`
81
- - `~/.opencandle/state.db`
82
- - `~/.opencandle/logs/...`
83
- - The published CLI should work from any directory without depending on a repo-local `.pi/extensions/...` file. Project `.pi/` remains optional for user overrides.
77
+ Environment variables override values from `~/.opencandle/config.json`. Set `OPENCANDLE_HOME` if you want OpenCandle state somewhere other than `~/.opencandle/`.
84
78
 
85
- ## Usage
79
+ ## Basic Usage
86
80
 
87
- OpenCandle runs inside Pi's interactive TUI. Useful controls:
81
+ OpenCandle runs inside Pi's interactive terminal UI.
82
+
83
+ Useful commands:
88
84
 
89
85
  ```text
90
- /model Switch provider/model
91
- /login Authenticate an OAuth-backed provider
92
- /setup Rerun OpenCandle setup
93
- /analyze NVDA Run the multi-analyst workflow
86
+ /setup
87
+ /login
88
+ /model
89
+ /analyze AAPL
94
90
  ```
95
91
 
96
- Natural-language prompts still work:
92
+ Example prompts:
97
93
 
98
94
  ```text
99
- What's the price of AAPL?
95
+ What is AAPL trading at?
100
96
  Get the options chain for TSLA expiring April 24
101
97
  Show me MSFT puts with Greeks
102
- What's the Fear and Greed index?
103
98
  Get the fed funds rate from FRED
104
99
  Add 100 shares of NVDA at 120 to my portfolio, then show my portfolio
105
100
  Run risk analysis on SPY
106
- analyze AAPL
107
101
  ```
108
102
 
109
- ## Tools (23)
103
+ ## Data Sources And Tool Coverage
110
104
 
111
- | Category | Tools | Data Source |
112
- |----------|-------|------------|
113
- | **Market Data** | `search_ticker`, `get_stock_quote`, `get_stock_history`, `get_crypto_price`, `get_crypto_history` | Yahoo Finance, CoinGecko |
114
- | **Options** | `get_option_chain` — strikes, bids/asks, volume, OI, IV, computed Greeks | Yahoo Finance + Black-Scholes |
115
- | **Fundamentals** | `get_company_overview`, `get_financials`, `get_earnings`, `compute_dcf`, `compare_companies`, `get_sec_filings` | Alpha Vantage, SEC EDGAR |
116
- | **Technical** | `get_technical_indicators`, `backtest_strategy` — SMA, EMA, RSI, MACD, Bollinger Bands, backtesting | Computed locally from OHLCV |
117
- | **Macro** | `get_economic_data`, `get_fear_greed` | FRED, alternative.me |
118
- | **Sentiment** | `get_reddit_sentiment`, `get_reddit_discussions` | Reddit JSON API |
119
- | **Portfolio** | `track_portfolio`, `analyze_risk`, `manage_watchlist`, `analyze_correlation`, `track_prediction` | Yahoo Finance + local math |
105
+ | Area | Examples | Source |
106
+ | --- | --- | --- |
107
+ | Market data | quotes, history, ticker search, crypto price/history | Yahoo Finance, CoinGecko |
108
+ | Options | chains, open interest, IV, Greeks | Yahoo Finance plus local calculations |
109
+ | Fundamentals | overview, financials, earnings, DCF, company comparison | Alpha Vantage |
110
+ | Macro | economic series, Fear & Greed | FRED, alternative.me |
111
+ | Sentiment | Reddit, Twitter/X, and web sentiment with cross-source pipeline | Reddit JSON API, Twitter/X, DuckDuckGo, Brave |
112
+ | Filings | SEC filing search | SEC EDGAR |
113
+ | Portfolio | watchlist, prediction tracking, correlation, risk | Local state plus market data |
120
114
 
121
- ## How It Works
115
+ ## Engineering Notes
122
116
 
123
- Built on [Pi-mono](https://github.com/badlogic/pi-mono)'s `pi-coding-agent` SDK and TUI, with OpenCandle loaded as a bundled finance-only Pi extension. Tools are defined with [TypeBox](https://github.com/sinclairzx81/typebox) schemas and registered through Pi's extension system.
117
+ ### Project Shape
124
118
 
119
+ ```text
120
+ src/
121
+ ├── providers/ API clients
122
+ ├── tools/ Tool implementations by domain
123
+ ├── infra/ Cache, rate limiter, HTTP, browser, paths
124
+ ├── routing/ Intent classification and slot resolution
125
+ ├── workflows/ Multi-step workflow builders
126
+ ├── memory/ SQLite-backed state and retrieval
127
+ ├── analysts/ Multi-analyst orchestration
128
+ ├── pi/ Pi integration and session wiring
129
+ └── index.ts Public exports
125
130
  ```
126
- User prompt -> Pi session -> selected provider/model -> tool calls -> execute in parallel -> response
127
- ^ |
128
- |____________________ Pi session + model registry _________________|
131
+
132
+ ### Development Commands
133
+
134
+ ```bash
135
+ npm start
136
+ npm test
137
+ npm run test:watch
138
+ npm run test:e2e
139
+ npm run test:e2e:cli
140
+ npm run test:e2e:providers
129
141
  ```
130
142
 
131
- Key architectural choices:
132
- - **Local computation** over API calls for math (indicators, Greeks, risk metrics)
133
- - **Stealth browser fallback** via [Camoufox](https://github.com/daijro/camoufox) when Yahoo rate-limits Node.js `fetch`
134
- - **TTL caching + token bucket rate limiting** per provider
135
- - **Pi-native auth/model flow** via `/model`, `/login`, `auth.json`, and `models.json`
136
- - **Global OpenCandle state** under `~/.opencandle/`, separate from Pi config
137
- - **Multi-analyst orchestration** via Pi extension commands and follow-up message hooks
143
+ `npm test` is the required baseline check after changes.
144
+
145
+ ### Repository Rules That Matter
146
+
147
+ - TDD is mandatory for behavior changes
148
+ - Unit tests mock `globalThis.fetch` and use JSON fixtures
149
+ - Use `cache` and `rateLimiter` for external calls
150
+ - Tools fetch and format data; analysts and prompts synthesize
151
+ - Keep typing strict and use `.js` extensions on relative imports
152
+
153
+ ### Public Package Exports
154
+
155
+ Besides the CLI, the package exposes pieces for engineers building on top of OpenCandle:
156
+
157
+ - `opencandle`
158
+ - `opencandle/tool-kit`
159
+ - `opencandle/infra`
160
+ - `opencandle/types`
161
+ - `opencandle/providers`
138
162
 
139
- ## Test
163
+ If you want to add a new tool or publish an add-on package, start with [docs/build-a-tool.md](./docs/build-a-tool.md).
164
+
165
+ ## Testing The Agent
166
+
167
+ For end-to-end agent driving with file-based IPC:
140
168
 
141
169
  ```bash
142
- npm test # unit tests
143
- npm run test:watch # watch mode
170
+ npx tsx tests/harness/manual-run.ts /tmp/opencandle-ipc "What is AAPL trading at?"
144
171
  ```
145
172
 
146
- ## Project Docs
173
+ The harness writes status and trace files into the IPC directory. See [tests/harness/README.md](./tests/harness/README.md) for the full flow.
147
174
 
148
- - OSS launch and npm release plan: [docs/production-plan.md](https://github.com/Kahtaf/OpenCandle/blob/main/docs/production-plan.md)
149
- - Contributor guide: [CONTRIBUTING.md](https://github.com/Kahtaf/OpenCandle/blob/main/CONTRIBUTING.md)
150
- - Security policy: [SECURITY.md](https://github.com/Kahtaf/OpenCandle/blob/main/SECURITY.md)
151
- - Release history: [CHANGELOG.md](https://github.com/Kahtaf/OpenCandle/blob/main/CHANGELOG.md)
152
-
153
- ## Tech Stack
175
+ ## Project Docs
154
176
 
155
- - **Runtime**: TypeScript, Node.js
156
- - **LLM**: Pi model registry with Gemini, OpenAI, Anthropic, and custom providers
157
- - **Browser**: Camoufox (anti-detection Firefox for scraping fallback)
158
- - **Testing**: Vitest with fixture-mocked `fetch`
159
- - **No frameworks**: Raw providers, no LangChain/LlamaIndex
177
+ - [CONTRIBUTING.md](./CONTRIBUTING.md)
178
+ - [docs/build-a-tool.md](./docs/build-a-tool.md)
179
+ - [tests/harness/README.md](./tests/harness/README.md)
180
+ - [CHANGELOG.md](./CHANGELOG.md)
181
+ - [SECURITY.md](./SECURITY.md)
182
+ - [LICENSE](./LICENSE)
@@ -35,8 +35,7 @@ What is the options market pricing in that the stock price alone doesn't show?${
35
35
  contrarian: (symbol) => `**[Contrarian Analyst]** You are a Burry-style contrarian. Your job is to find what the crowd is missing. Be terse and data-driven — cite concrete numbers like "FCF yield 14.7%" or "P/E 8.3x vs sector 22x." Analyze ${symbol}:
36
36
  1. Use get_fear_greed for overall market mood — extreme readings signal opportunity.
37
37
  2. Use get_reddit_sentiment on wallstreetbets and stocks — check the sentiment score. Extreme bullishness from retail is a warning; extreme bearishness may be opportunity.
38
- 3. Use get_reddit_discussions for ${symbol} to gauge retail narrative.
39
- 4. Cross-reference: Is sentiment overly bullish while fundamentals (revenue, margins, FCF) are deteriorating? Is everyone bearish while the numbers quietly improve?
38
+ 3. Cross-reference: Is sentiment overly bullish while fundamentals (revenue, margins, FCF) are deteriorating? Is everyone bearish while the numbers quietly improve?
40
39
  5. Reuse get_company_overview or other fundamentals already fetched earlier in the session if available. If fundamentals are unavailable, say so and base the contrarian view on sentiment and price only.
41
40
  Where is the consensus wrong? What is the market over-pricing or under-pricing?${EXECUTION_GUARDRAILS}${VOTING_INSTRUCTION}`,
42
41
  risk: (symbol) => `**[Risk Manager]** You are the final check before capital is deployed. Your job is to quantify downside, not to have an opinion on direction. Analyze ${symbol}:
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/analysts/orchestrator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/analysts/orchestrator.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -1,8 +1,18 @@
1
+ export interface SentimentConfig {
2
+ retentionDays: number;
3
+ defaultSubreddits: string[];
4
+ commentsPerPost: number;
5
+ divergenceThreshold: number;
6
+ }
1
7
  export interface Config {
2
8
  alphaVantageApiKey?: string;
3
9
  fredApiKey?: string;
10
+ braveApiKey?: string;
11
+ exaApiKey?: string;
12
+ finnhubApiKey?: string;
4
13
  /** Enable adversarial bull/bear debate in comprehensive analysis. Default: true. */
5
14
  debate?: boolean;
15
+ sentiment?: SentimentConfig;
6
16
  }
7
17
  export interface OpenCandleFileConfig {
8
18
  providers?: {
@@ -12,17 +22,27 @@ export interface OpenCandleFileConfig {
12
22
  fred?: {
13
23
  apiKey?: string;
14
24
  };
25
+ brave?: {
26
+ apiKey?: string;
27
+ };
28
+ exa?: {
29
+ apiKey?: string;
30
+ };
31
+ finnhub?: {
32
+ apiKey?: string;
33
+ };
15
34
  };
16
35
  /** Enable adversarial bull/bear debate in comprehensive analysis. Default: true. */
17
36
  debate?: boolean;
18
- }
19
- export interface FinanceProviderReadiness {
20
- hasAlphaVantage: boolean;
21
- hasFred: boolean;
37
+ sentiment?: {
38
+ retentionDays?: number;
39
+ defaultSubreddits?: string[];
40
+ commentsPerPost?: number;
41
+ divergenceThreshold?: number;
42
+ };
22
43
  }
23
44
  export declare function loadEnv(path?: string): void;
24
45
  export declare function loadFileConfig(path?: string): OpenCandleFileConfig;
25
46
  export declare function saveFileConfig(config: OpenCandleFileConfig, path?: string): void;
26
- export declare function getFinanceProviderReadiness(path?: string): FinanceProviderReadiness;
27
47
  export declare function loadConfig(): Config;
28
48
  export declare function getConfig(): Config;
package/dist/config.js CHANGED
@@ -23,12 +23,28 @@ export function loadEnv(path = ".env") {
23
23
  }
24
24
  }
25
25
  let cachedConfig = null;
26
+ const SENTIMENT_DEFAULTS = {
27
+ retentionDays: 30,
28
+ defaultSubreddits: ["wallstreetbets", "stocks", "investing", "options"],
29
+ commentsPerPost: 5,
30
+ divergenceThreshold: 0.4,
31
+ };
26
32
  function resolveConfig(fileConfig) {
27
33
  const debateEnv = process.env.OPENCANDLE_DEBATE;
34
+ const fileSentiment = fileConfig.sentiment;
28
35
  return {
29
36
  alphaVantageApiKey: process.env.ALPHA_VANTAGE_API_KEY ?? fileConfig.providers?.alphaVantage?.apiKey,
30
37
  fredApiKey: process.env.FRED_API_KEY ?? fileConfig.providers?.fred?.apiKey,
38
+ braveApiKey: process.env.BRAVE_API_KEY ?? fileConfig.providers?.brave?.apiKey,
39
+ exaApiKey: process.env.EXA_API_KEY ?? fileConfig.providers?.exa?.apiKey,
40
+ finnhubApiKey: process.env.FINNHUB_API_KEY ?? fileConfig.providers?.finnhub?.apiKey,
31
41
  debate: debateEnv !== undefined ? debateEnv !== "false" && debateEnv !== "0" : fileConfig.debate ?? true,
42
+ sentiment: {
43
+ retentionDays: fileSentiment?.retentionDays ?? SENTIMENT_DEFAULTS.retentionDays,
44
+ defaultSubreddits: fileSentiment?.defaultSubreddits ?? SENTIMENT_DEFAULTS.defaultSubreddits,
45
+ commentsPerPost: fileSentiment?.commentsPerPost ?? SENTIMENT_DEFAULTS.commentsPerPost,
46
+ divergenceThreshold: fileSentiment?.divergenceThreshold ?? SENTIMENT_DEFAULTS.divergenceThreshold,
47
+ },
32
48
  };
33
49
  }
34
50
  export function loadFileConfig(path = getConfigPath()) {
@@ -56,14 +72,6 @@ export function saveFileConfig(config, path = getConfigPath()) {
56
72
  ensureParentDir(path);
57
73
  writeFileSync(path, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
58
74
  }
59
- export function getFinanceProviderReadiness(path = getConfigPath()) {
60
- loadEnv();
61
- const config = resolveConfig(loadFileConfig(path));
62
- return {
63
- hasAlphaVantage: Boolean(config.alphaVantageApiKey),
64
- hasFred: Boolean(config.fredApiKey),
65
- };
66
- }
67
75
  export function loadConfig() {
68
76
  loadEnv();
69
77
  cachedConfig = resolveConfig(loadFileConfig());
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -37,6 +37,8 @@ export declare const TTL: {
37
37
  readonly SENTIMENT: 300000;
38
38
  readonly OPTIONS_CHAIN: 120000;
39
39
  readonly CRUMB: 900000;
40
+ readonly WEB_SEARCH: 300000;
41
+ readonly FINNHUB_NEWS: 300000;
40
42
  };
41
43
  export declare const STALE_LIMIT: {
42
44
  readonly QUOTE: number;
@@ -45,4 +47,6 @@ export declare const STALE_LIMIT: {
45
47
  readonly MACRO: number;
46
48
  readonly SENTIMENT: 3600000;
47
49
  readonly OPTIONS_CHAIN: number;
50
+ readonly WEB_SEARCH: 3600000;
51
+ readonly FINNHUB_NEWS: 3600000;
48
52
  };
@@ -66,6 +66,8 @@ export const TTL = {
66
66
  SENTIMENT: 300_000, // 5 minutes
67
67
  OPTIONS_CHAIN: 120_000, // 2 minutes
68
68
  CRUMB: 900_000, // 15 minutes
69
+ WEB_SEARCH: 300_000, // 5 minutes
70
+ FINNHUB_NEWS: 300_000, // 5 minutes
69
71
  };
70
72
  // Stale limits — how long past TTL expiry a cached value is still useful as fallback
71
73
  export const STALE_LIMIT = {
@@ -75,5 +77,7 @@ export const STALE_LIMIT = {
75
77
  MACRO: 24 * 3_600_000, // 24 hours
76
78
  SENTIMENT: 3_600_000, // 1 hour
77
79
  OPTIONS_CHAIN: 30 * 60_000, // 30 minutes
80
+ WEB_SEARCH: 3_600_000, // 1 hour
81
+ FINNHUB_NEWS: 3_600_000, // 1 hour
78
82
  };
79
83
  //# sourceMappingURL=cache.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/infra/cache.ts"],"names":[],"mappings":"AAYA,MAAM,OAAO,KAAK;IACR,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;IAC/C,YAAY,GAAG,KAAK,CAAC;IACrB,iBAAiB,GAAG,CAAC,CAAC;IAE9B,GAAG,CAAI,GAAW;QAChB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAC7B,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS;YAAE,OAAO,SAAS,CAAC;QACnD,OAAO,KAAK,CAAC,KAAU,CAAC;IAC1B,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAI,GAAW,EAAE,YAAoB;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAE7B,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,QAAQ,GAAG,YAAY,EAAE,CAAC;YAC/C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC,QAAQ,CAAC;QACxC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAU,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC5E,CAAC;IAED;;;;OAIG;IACH,gBAAgB;QACd,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC9E,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;QAC3B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,GAAG,CAAI,GAAW,EAAE,KAAQ,EAAE,KAAa;QACzC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,UAAU,CAAC,OAAe;QACxB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YACpC,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF;AAED,wBAAwB;AACxB,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;AAEjC,eAAe;AACf,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,KAAK,EAAE,MAAM,EAAU,WAAW;IAClC,OAAO,EAAE,SAAS,EAAK,SAAS;IAChC,YAAY,EAAE,UAAU,EAAE,WAAW;IACrC,KAAK,EAAE,SAAS,EAAO,SAAS;IAChC,SAAS,EAAE,OAAO,EAAK,YAAY;IACnC,aAAa,EAAE,OAAO,EAAE,YAAY;IACpC,KAAK,EAAE,OAAO,EAAS,aAAa;CAC5B,CAAC;AAEX,qFAAqF;AACrF,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,KAAK,EAAE,EAAE,GAAG,MAAM,EAAc,aAAa;IAC7C,OAAO,EAAE,EAAE,GAAG,SAAS,EAAS,WAAW;IAC3C,YAAY,EAAE,CAAC,GAAG,UAAU,EAAI,SAAS;IACzC,KAAK,EAAE,EAAE,GAAG,SAAS,EAAW,WAAW;IAC3C,SAAS,EAAE,SAAS,EAAY,SAAS;IACzC,aAAa,EAAE,EAAE,GAAG,MAAM,EAAM,aAAa;CACrC,CAAC"}
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/infra/cache.ts"],"names":[],"mappings":"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"}
@@ -36,4 +36,10 @@ rateLimiter.configure("coingecko", 10, 0.167); // 10 req/min
36
36
  rateLimiter.configure("alphavantage", 5, 0.083); // 5 req/min (free tier)
37
37
  rateLimiter.configure("fred", 120, 2); // 120 req/min
38
38
  rateLimiter.configure("twitter", 5, 0.167); // 5 req, ~10 req/min
39
+ rateLimiter.configure("reddit", 5, 0.167); // 5 req, ~10 req/min
40
+ rateLimiter.configure("reddit_comments", 10, 0.5); // 10 req, ~30 req/min
41
+ rateLimiter.configure("ddg", 3, 0.1); // 3 req, ~6 req/min
42
+ rateLimiter.configure("brave_search", 5, 0.083); // 5 req, ~5 req/min
43
+ rateLimiter.configure("exa", 5, 0.1); // 5 req, ~6 req/min
44
+ rateLimiter.configure("finnhub", 60, 1); // 60 req/min (free tier)
39
45
  //# sourceMappingURL=rate-limiter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/infra/rate-limiter.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,WAAW;IACd,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE5C,SAAS,CAAC,QAAgB,EAAE,SAAiB,EAAE,UAAkB;QAC/D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE;YACzB,MAAM,EAAE,SAAS;YACjB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;YACtB,MAAM,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE;SAClC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAgB;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,sBAAsB;QAE3C,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAEpB,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACvB,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QAED,kCAAkC;QAClC,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;QACvE,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpB,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;IACrB,CAAC;IAEO,MAAM,CAAC,MAAc;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,CAAC,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;QACjD,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CACtB,MAAM,CAAC,MAAM,CAAC,SAAS,EACvB,MAAM,CAAC,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CACnD,CAAC;QACF,MAAM,CAAC,UAAU,GAAG,GAAG,CAAC;IAC1B,CAAC;CACF;AAED,+CAA+C;AAC/C,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;AAC7C,WAAW,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAW,UAAU;AAC1D,WAAW,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAE,aAAa;AAC7D,WAAW,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,wBAAwB;AACzE,WAAW,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAW,cAAc;AAC/D,WAAW,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAM,qBAAqB"}
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/infra/rate-limiter.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,WAAW;IACd,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE5C,SAAS,CAAC,QAAgB,EAAE,SAAiB,EAAE,UAAkB;QAC/D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE;YACzB,MAAM,EAAE,SAAS;YACjB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;YACtB,MAAM,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE;SAClC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAgB;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,sBAAsB;QAE3C,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAEpB,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACvB,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QAED,kCAAkC;QAClC,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;QACvE,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpB,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;IACrB,CAAC;IAEO,MAAM,CAAC,MAAc;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,CAAC,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;QACjD,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CACtB,MAAM,CAAC,MAAM,CAAC,SAAS,EACvB,MAAM,CAAC,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CACnD,CAAC;QACF,MAAM,CAAC,UAAU,GAAG,GAAG,CAAC;IAC1B,CAAC;CACF;AAED,+CAA+C;AAC/C,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;AAC7C,WAAW,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAW,UAAU;AAC1D,WAAW,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAE,aAAa;AAC7D,WAAW,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,wBAAwB;AACzE,WAAW,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAW,cAAc;AAC/D,WAAW,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAM,qBAAqB;AACtE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAU,qBAAqB;AACzE,WAAW,CAAC,SAAS,CAAC,iBAAiB,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;AACzE,WAAW,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAa,oBAAoB;AACtE,WAAW,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAE,oBAAoB;AACtE,WAAW,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAc,oBAAoB;AACvE,WAAW,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAY,yBAAyB"}
@@ -0,0 +1,23 @@
1
+ import type { ExtensionContext } from "@mariozechner/pi-coding-agent";
2
+ import { type ProviderId } from "./providers.js";
3
+ export type ConnectResult = {
4
+ status: "connected";
5
+ } | {
6
+ status: "cancelled";
7
+ } | {
8
+ status: "blocked_by_env";
9
+ } | {
10
+ status: "invalid_key";
11
+ httpStatus?: number;
12
+ message?: string;
13
+ };
14
+ /**
15
+ * Run the connect flow for a single provider.
16
+ *
17
+ * Env-precedence short-circuit: if the provider's configured credential
18
+ * already comes from an environment variable, the file-config write would
19
+ * be invisible to the next tool call (env vars win in `resolveConfig`).
20
+ * Notify the user explicitly and return `blocked_by_env` — do not open
21
+ * the browser or collect a pasted value.
22
+ */
23
+ export declare function runProviderConnect(ctx: ExtensionContext, providerId: ProviderId): Promise<ConnectResult>;
@@ -0,0 +1,107 @@
1
+ // Shared `runProviderConnect` function — the actual side-effectful flow that
2
+ // opens a browser, collects a pasted API key, validates it against the
3
+ // provider's API, persists it to `~/.opencandle/config.json`, and refreshes
4
+ // the cached Config so the next tool call sees the new credential.
5
+ //
6
+ // Called from two places:
7
+ // 1. The Pi `tool_result` extension handler when the user picks "Connect now"
8
+ // in the just-in-time prompt (Task Group 10).
9
+ // 2. The `/connect` Pi command (Task Group 13).
10
+ //
11
+ // Validation (Task Group 8 final pass): before persisting, the pasted key is
12
+ // validated via `validateCredential`, which makes a single cheap request to
13
+ // the provider's canonical API and classifies the response. A hard
14
+ // auth failure (401/403 or a provider-specific error-in-200-body) is
15
+ // returned as `invalid_key` WITHOUT persisting the bad value; a transient
16
+ // failure (timeout, 5xx, network error) warns the user but still persists
17
+ // the key so they aren't blocked on a provider outage — the next real tool
18
+ // call will surface any lingering issue via the credential-required tag.
19
+ import { openInBrowser } from "../infra/open-url.js";
20
+ import { loadFileConfig, saveFileConfig, loadConfig, } from "../config.js";
21
+ import { getProvider, getCredentialSource, } from "./providers.js";
22
+ import { loadOnboardingState, markProviderCompleted, saveOnboardingState, } from "./state.js";
23
+ import { validateCredential } from "./validation.js";
24
+ function writeNested(obj, path, value) {
25
+ if (path.length === 0)
26
+ return obj;
27
+ const [head, ...rest] = path;
28
+ const next = { ...obj };
29
+ if (rest.length === 0) {
30
+ next[head] = value;
31
+ }
32
+ else {
33
+ const child = next[head] && typeof next[head] === "object"
34
+ ? next[head]
35
+ : {};
36
+ next[head] = writeNested(child, rest, value);
37
+ }
38
+ return next;
39
+ }
40
+ /**
41
+ * Run the connect flow for a single provider.
42
+ *
43
+ * Env-precedence short-circuit: if the provider's configured credential
44
+ * already comes from an environment variable, the file-config write would
45
+ * be invisible to the next tool call (env vars win in `resolveConfig`).
46
+ * Notify the user explicitly and return `blocked_by_env` — do not open
47
+ * the browser or collect a pasted value.
48
+ */
49
+ export async function runProviderConnect(ctx, providerId) {
50
+ const descriptor = getProvider(providerId);
51
+ // Env-precedence check.
52
+ if (getCredentialSource(providerId) === "env") {
53
+ ctx.ui.notify(`${descriptor.displayName} is currently set via the ${descriptor.envVar} environment variable. ` +
54
+ `To change it from here, unset that variable first and reopen /connect ${descriptor.aliases[0] ?? descriptor.id}. ` +
55
+ `Otherwise, update ${descriptor.envVar} directly in your shell profile.`, "warning");
56
+ return { status: "blocked_by_env" };
57
+ }
58
+ // Open the signup URL in the user's browser. We ignore errors here — if
59
+ // the browser can't be opened, the user can still paste a key they
60
+ // already have, so we continue rather than bailing.
61
+ await openInBrowser(descriptor.signupUrl).catch(() => { });
62
+ ctx.ui.notify(`Opening ${descriptor.displayName} signup in your browser...`, "info");
63
+ // Prompt for the key. Uses the provider's instructionsHint as the
64
+ // placeholder text to remind the user what they're pasting.
65
+ const pasted = await ctx.ui.input(`Paste your ${descriptor.displayName} API key`, descriptor.instructionsHint);
66
+ if (!pasted) {
67
+ return { status: "cancelled" };
68
+ }
69
+ const trimmed = pasted.trim();
70
+ if (trimmed.length === 0) {
71
+ return { status: "cancelled" };
72
+ }
73
+ // Validate the key with the provider BEFORE persisting. Hard auth failures
74
+ // short-circuit here without writing anything; transient failures warn
75
+ // but proceed to persist so users don't get stuck on a provider outage.
76
+ ctx.ui.notify(`Verifying your ${descriptor.displayName} key...`, "info");
77
+ const validation = await validateCredential(providerId, trimmed);
78
+ if (validation.status === "invalid") {
79
+ const statusHint = validation.httpStatus !== undefined ? ` (HTTP ${validation.httpStatus})` : "";
80
+ const messageHint = validation.message ? ` — ${validation.message}` : "";
81
+ ctx.ui.notify(`${descriptor.displayName} rejected the key${statusHint}${messageHint}. ` +
82
+ `Your existing configuration was not changed. Re-run /connect ${descriptor.aliases[0] ?? descriptor.id} to try a different key.`, "error");
83
+ return {
84
+ status: "invalid_key",
85
+ httpStatus: validation.httpStatus,
86
+ message: validation.message,
87
+ };
88
+ }
89
+ if (validation.status === "transient") {
90
+ ctx.ui.notify(`Couldn't reach ${descriptor.displayName} to verify the key (${validation.reason}). ` +
91
+ `Saving it anyway — the next request will surface any issue.`, "warning");
92
+ // Fall through to persist.
93
+ }
94
+ // Persist to file config. Merge into the existing structure, preserving
95
+ // any unrelated fields.
96
+ const existing = loadFileConfig();
97
+ const updated = writeNested(existing, descriptor.configPath, trimmed);
98
+ saveFileConfig(updated);
99
+ // Refresh the cached Config so the next tool call sees the new value.
100
+ loadConfig();
101
+ // Update onboarding state to completed.
102
+ const state = loadOnboardingState();
103
+ saveOnboardingState(markProviderCompleted(state, providerId));
104
+ ctx.ui.notify(`${descriptor.displayName} connected. Your key has been saved.`, "info");
105
+ return { status: "connected" };
106
+ }
107
+ //# sourceMappingURL=connect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/onboarding/connect.ts"],"names":[],"mappings":"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"}