feat: add certificate verification functionality
This commit is contained in:
parent
eb0121b787
commit
cea3411911
99
.env.example
99
.env.example
|
|
@ -1,17 +1,100 @@
|
|||
# Trading Agents Environment Variables
|
||||
# TradingAgents Environment Configuration
|
||||
# Copy this file to .env and fill in your values
|
||||
|
||||
# Finnhub API Key (required for market data)
|
||||
# =============================================================================
|
||||
# API Keys (Required)
|
||||
# =============================================================================
|
||||
OPENAI_API_KEY=your_openai_api_key_here
|
||||
FINNHUB_API_KEY=your_finnhub_api_key_here
|
||||
|
||||
# OpenAI API Key (required for AI processing)
|
||||
OPENAI_API_KEY=your_openai_api_key_here
|
||||
# Optional API Keys
|
||||
OPENROUTER_API_KEY=your_openrouter_api_key_here
|
||||
GOOGLE_API_KEY=your_google_api_key_here
|
||||
ANTHROPIC_API_KEY=your_anthropic_api_key_here
|
||||
|
||||
# Reddit API Credentials (required for social media analysis)
|
||||
REDDIT_CLIENT_ID=your_reddit_client_id_here
|
||||
REDDIT_CLIENT_SECRET=your_reddit_client_secret_here
|
||||
# Reddit API (Optional - for social media analysis)
|
||||
REDDIT_CLIENT_ID=your_reddit_client_id
|
||||
REDDIT_CLIENT_SECRET=your_reddit_client_secret
|
||||
REDDIT_USER_AGENT=TradingAgents/1.0
|
||||
|
||||
# =============================================================================
|
||||
# SSL/TLS Certificate Configuration (OPTIONAL)
|
||||
# =============================================================================
|
||||
|
||||
# Certificate Bundle Path (ONLY set if you need a custom certificate bundle)
|
||||
# If not set, system default SSL behavior is used
|
||||
# Common locations:
|
||||
# - macOS: /etc/ssl/cert.pem
|
||||
# - Ubuntu/Debian: /etc/ssl/certs/ca-certificates.crt
|
||||
# - CentOS/RHEL: /etc/pki/tls/certs/ca-bundle.crt
|
||||
# - Custom: /path/to/your/custom-ca-bundle.crt
|
||||
# REQUESTS_CA_BUNDLE=/etc/ssl/cert.pem
|
||||
# CURL_CA_BUNDLE=/etc/ssl/cert.pem
|
||||
|
||||
# SSL Verification (ONLY set to false if needed for development/testing)
|
||||
# If not set, SSL verification is enabled by default (recommended)
|
||||
# SSL_VERIFY=false
|
||||
|
||||
# HTTP Timeout (ONLY set if default timeout is insufficient)
|
||||
# If not set, uses reasonable defaults
|
||||
# HTTP_TIMEOUT=60
|
||||
|
||||
# =============================================================================
|
||||
# Proxy Configuration (ONLY if behind corporate firewall)
|
||||
# =============================================================================
|
||||
|
||||
# HTTP/HTTPS Proxy Settings (ONLY set if required by your network)
|
||||
# If not set, direct connections are used
|
||||
# HTTP_PROXY=http://proxy.company.com:8080
|
||||
# HTTPS_PROXY=https://proxy.company.com:8080
|
||||
|
||||
# Proxy with authentication
|
||||
# HTTP_PROXY=http://username:password@proxy.company.com:8080
|
||||
# HTTPS_PROXY=https://username:password@proxy.company.com:8080
|
||||
|
||||
# =============================================================================
|
||||
# Application Settings
|
||||
# =============================================================================
|
||||
|
||||
# Results Directory
|
||||
TRADINGAGENTS_RESULTS_DIR=./results
|
||||
|
||||
# Ollama Configuration (if using local Ollama)
|
||||
OLLAMA_HOST=localhost
|
||||
|
||||
# Optional Configuration
|
||||
# DEBUG=True
|
||||
# LOG_LEVEL=INFO
|
||||
# LOG_LEVEL=INFO
|
||||
|
||||
# =============================================================================
|
||||
# SSL Certificate Examples for Common Enterprise Environments
|
||||
# =============================================================================
|
||||
|
||||
# Example 1: Using system certificate store (macOS)
|
||||
# REQUESTS_CA_BUNDLE=/System/Library/OpenSSL/certs/cert.pem
|
||||
|
||||
# Example 2: Using system certificate store (Ubuntu/Debian)
|
||||
# REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
|
||||
|
||||
# Example 3: Using custom corporate certificate bundle
|
||||
# REQUESTS_CA_BUNDLE=/usr/local/share/ca-certificates/corporate-ca-bundle.crt
|
||||
|
||||
# Example 4: Disabling SSL verification (development only)
|
||||
# SSL_VERIFY=false
|
||||
|
||||
# =============================================================================
|
||||
# Troubleshooting SSL Issues
|
||||
# =============================================================================
|
||||
|
||||
# If you encounter SSL certificate errors:
|
||||
# 1. Run the diagnostic tool: python diagnose_ssl.py
|
||||
# 2. Check if your organization uses a custom CA
|
||||
# 3. Ask your IT department for the corporate certificate bundle
|
||||
# 4. Try using certifi's bundle: pip install certifi
|
||||
# 5. Set REQUESTS_CA_BUNDLE to certifi's location (usually shown by diagnose_ssl.py)
|
||||
|
||||
# Common SSL Error Solutions:
|
||||
# - "certificate verify failed": Set REQUESTS_CA_BUNDLE to correct cert bundle
|
||||
# - "SSL: WRONG_VERSION_NUMBER": Check if you're behind a proxy
|
||||
# - "Connection timeout": Increase HTTP_TIMEOUT or check proxy settings
|
||||
# - "Name or service not known": Check DNS settings and proxy configuration
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
# SSL Certificate Bundle Configuration for TradingAgents
|
||||
|
||||
## Overview
|
||||
|
||||
This implementation provides flexible SSL/TLS certificate configuration for TradingAgents while maintaining backward compatibility. The system only applies custom SSL settings when explicitly configured via environment variables.
|
||||
|
||||
## Key Features
|
||||
|
||||
### 1. Environment Variable Based Configuration
|
||||
- `REQUESTS_CA_BUNDLE` or `CURL_CA_BUNDLE`: Path to custom certificate bundle
|
||||
- `SSL_VERIFY`: Enable/disable SSL verification (true/false)
|
||||
- `HTTP_TIMEOUT`: Custom timeout for HTTP requests (seconds)
|
||||
- `HTTP_PROXY`: HTTP proxy server
|
||||
- `HTTPS_PROXY`: HTTPS proxy server
|
||||
|
||||
### 2. Default Behavior Preservation
|
||||
- **If no environment variables are set**: Uses system default SSL behavior
|
||||
- **Only applies custom settings when explicitly configured**
|
||||
- **Empty or undefined variables are ignored**
|
||||
|
||||
### 3. Comprehensive Coverage
|
||||
- **LangChain LLM clients**: Custom SSL configuration for OpenAI, OpenRouter, etc.
|
||||
- **HTTP requests**: Custom configuration for Google News, Reddit APIs
|
||||
- **Global SSL setup**: Sets environment variables for libraries that respect them
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Basic Usage (No Custom SSL)
|
||||
```bash
|
||||
# No SSL environment variables set
|
||||
# Uses system default SSL behavior
|
||||
python webapp/main.py
|
||||
```
|
||||
|
||||
### Custom Certificate Bundle
|
||||
```bash
|
||||
# Use custom corporate certificate bundle
|
||||
export REQUESTS_CA_BUNDLE=/path/to/corporate-ca-bundle.crt
|
||||
python webapp/main.py
|
||||
```
|
||||
|
||||
### Development/Testing (Disable SSL Verification)
|
||||
```bash
|
||||
# Disable SSL verification (NOT recommended for production)
|
||||
export SSL_VERIFY=false
|
||||
python webapp/main.py
|
||||
```
|
||||
|
||||
### Behind Corporate Proxy
|
||||
```bash
|
||||
# Configure proxy settings
|
||||
export HTTP_PROXY=http://proxy.company.com:8080
|
||||
export HTTPS_PROXY=https://proxy.company.com:8080
|
||||
export REQUESTS_CA_BUNDLE=/etc/ssl/corporate-ca-bundle.crt
|
||||
python webapp/main.py
|
||||
```
|
||||
|
||||
## Files Modified
|
||||
|
||||
### Core Configuration
|
||||
- `tradingagents/default_config.py`: Added SSL configuration parameters
|
||||
- `tradingagents/dataflows/ssl_utils.py`: SSL utility functions (NEW)
|
||||
|
||||
### Integration Points
|
||||
- `tradingagents/graph/trading_graph.py`: LLM client SSL configuration
|
||||
- `tradingagents/dataflows/googlenews_utils.py`: HTTP requests SSL configuration
|
||||
- `tradingagents/dataflows/interface.py`: Integration with SSL configuration
|
||||
|
||||
### Documentation and Tools
|
||||
- `.env.example`: Updated with SSL configuration examples
|
||||
- `diagnose_ssl.py`: SSL diagnostic tool (NEW)
|
||||
- `test_ssl_config.py`: SSL configuration test suite (NEW)
|
||||
|
||||
## Testing
|
||||
|
||||
Run the diagnostic tool to check your SSL configuration:
|
||||
```bash
|
||||
python diagnose_ssl.py
|
||||
```
|
||||
|
||||
Run the test suite to verify SSL configuration behavior:
|
||||
```bash
|
||||
python test_ssl_config.py
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common SSL Errors and Solutions
|
||||
|
||||
1. **Certificate verification failed**
|
||||
- Set `REQUESTS_CA_BUNDLE` to correct certificate bundle path
|
||||
- Check if your organization uses custom CA certificates
|
||||
|
||||
2. **SSL: WRONG_VERSION_NUMBER**
|
||||
- Usually indicates proxy configuration issues
|
||||
- Set appropriate `HTTP_PROXY` and `HTTPS_PROXY` variables
|
||||
|
||||
3. **Connection timeout**
|
||||
- Increase `HTTP_TIMEOUT` value
|
||||
- Check network connectivity and proxy settings
|
||||
|
||||
4. **Name or service not known**
|
||||
- Check DNS settings
|
||||
- Verify proxy configuration
|
||||
|
||||
### Getting Help
|
||||
|
||||
1. Run `python diagnose_ssl.py` for comprehensive SSL diagnostics
|
||||
2. Check your organization's IT documentation for certificate bundles
|
||||
3. Contact your IT department for corporate proxy and certificate information
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- **Never disable SSL verification in production**
|
||||
- **Use custom certificate bundles for corporate environments**
|
||||
- **Keep certificate bundles updated**
|
||||
- **Secure proxy credentials if using authenticated proxies**
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Certificate Bundle Combiner for TradingAgents
|
||||
|
||||
This script combines your corporate certificate bundle (Netskope) with
|
||||
the certifi certificate bundle to ensure all certificates are available.
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
def combine_certificate_bundles():
|
||||
"""Combine corporate and certifi certificate bundles"""
|
||||
|
||||
print("🔗 Certificate Bundle Combiner")
|
||||
print("=" * 40)
|
||||
|
||||
# Paths
|
||||
corporate_bundle = "/Users/kevin.bruton/netskope-certificates/netskope-cert-bundle.pem"
|
||||
|
||||
try:
|
||||
import certifi
|
||||
certifi_bundle = certifi.where()
|
||||
except ImportError:
|
||||
print("❌ certifi package not found. Please install it: pip install certifi")
|
||||
return False
|
||||
|
||||
combined_bundle = "/Users/kevin.bruton/netskope-certificates/combined-cert-bundle.pem"
|
||||
|
||||
print(f"📋 Corporate bundle: {corporate_bundle}")
|
||||
print(f"📋 Certifi bundle: {certifi_bundle}")
|
||||
print(f"📋 Combined bundle: {combined_bundle}")
|
||||
|
||||
# Check if corporate bundle exists
|
||||
if not os.path.exists(corporate_bundle):
|
||||
print(f"❌ Corporate certificate bundle not found: {corporate_bundle}")
|
||||
return False
|
||||
|
||||
# Create combined bundle
|
||||
try:
|
||||
with open(combined_bundle, 'w') as combined_file:
|
||||
# Write corporate certificates first
|
||||
print("📝 Adding corporate certificates...")
|
||||
with open(corporate_bundle, 'r') as corp_file:
|
||||
combined_file.write(corp_file.read())
|
||||
|
||||
# Add separator
|
||||
combined_file.write("\n# Certifi certificates below\n")
|
||||
|
||||
# Write certifi certificates
|
||||
print("📝 Adding certifi certificates...")
|
||||
with open(certifi_bundle, 'r') as certifi_file:
|
||||
certifi_content = certifi_file.read()
|
||||
combined_file.write(certifi_content)
|
||||
|
||||
print(f"✅ Combined certificate bundle created: {combined_bundle}")
|
||||
|
||||
# Set permissions
|
||||
os.chmod(combined_bundle, 0o644)
|
||||
|
||||
# Show usage instructions
|
||||
print("\n💡 Usage Instructions:")
|
||||
print(f" Add this to your .env file:")
|
||||
print(f" REQUESTS_CA_BUNDLE={combined_bundle}")
|
||||
print(f" CURL_CA_BUNDLE={combined_bundle}")
|
||||
|
||||
print("\n Or export in your shell:")
|
||||
print(f" export REQUESTS_CA_BUNDLE={combined_bundle}")
|
||||
print(f" export CURL_CA_BUNDLE={combined_bundle}")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error creating combined bundle: {e}")
|
||||
return False
|
||||
|
||||
def test_combined_bundle():
|
||||
"""Test the combined certificate bundle"""
|
||||
combined_bundle = "/Users/kevin.bruton/netskope-certificates/combined-cert-bundle.pem"
|
||||
|
||||
if not os.path.exists(combined_bundle):
|
||||
print("❌ Combined bundle not found. Run combine_certificate_bundles() first.")
|
||||
return False
|
||||
|
||||
print(f"\n🧪 Testing combined certificate bundle: {combined_bundle}")
|
||||
|
||||
import requests
|
||||
test_urls = [
|
||||
"https://www.google.com",
|
||||
"https://api.openai.com/v1/models",
|
||||
"https://openrouter.ai/api/v1/models"
|
||||
]
|
||||
|
||||
for url in test_urls:
|
||||
try:
|
||||
response = requests.get(url, verify=combined_bundle, timeout=10)
|
||||
print(f"✅ {url} - Status: {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f"❌ {url} - Error: {e}")
|
||||
|
||||
return True
|
||||
|
||||
if __name__ == "__main__":
|
||||
if combine_certificate_bundles():
|
||||
test_combined_bundle()
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Debug script to test the TradingAgentsGraph streaming behavior
|
||||
"""
|
||||
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from tradingagents.graph.trading_graph import TradingAgentsGraph
|
||||
from tradingagents.default_config import DEFAULT_CONFIG
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
def debug_callback(state):
|
||||
"""Debug callback to see what state is being passed"""
|
||||
print(f"\n🔍 CALLBACK RECEIVED:")
|
||||
print(f" State type: {type(state)}")
|
||||
print(f" State keys: {list(state.keys()) if isinstance(state, dict) else 'Not a dict'}")
|
||||
|
||||
if isinstance(state, dict):
|
||||
for key, value in state.items():
|
||||
if key in ["__end__", "messages"]:
|
||||
continue
|
||||
print(f" {key}: {type(value)} - {str(value)[:100]}...")
|
||||
print("-" * 50)
|
||||
|
||||
def test_streaming():
|
||||
"""Test the streaming functionality"""
|
||||
print("🚀 Testing TradingAgentsGraph streaming...")
|
||||
|
||||
# Create a minimal config for testing
|
||||
config = DEFAULT_CONFIG.copy()
|
||||
config["llm_provider"] = "openai"
|
||||
config["quick_think_llm"] = "gpt-3.5-turbo"
|
||||
config["deep_think_llm"] = "gpt-4"
|
||||
|
||||
try:
|
||||
# Initialize the graph
|
||||
print("📊 Initializing TradingAgentsGraph...")
|
||||
graph = TradingAgentsGraph(config=config)
|
||||
|
||||
# Test propagation with callback
|
||||
print("🔄 Starting propagation with callback...")
|
||||
final_state, signal = graph.propagate(
|
||||
company_name="AAPL",
|
||||
trade_date="2024-01-01",
|
||||
on_step_callback=debug_callback
|
||||
)
|
||||
|
||||
print(f"✅ Propagation completed!")
|
||||
print(f"📈 Final signal: {signal}")
|
||||
print(f"🎯 Final state keys: {list(final_state.keys())}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error during streaming test: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_streaming()
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
SSL Certificate Diagnostic Tool for TradingAgents
|
||||
|
||||
This script helps diagnose SSL/TLS certificate issues and provides guidance
|
||||
on how to configure certificate bundles properly.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import ssl
|
||||
import socket
|
||||
import requests
|
||||
from urllib.parse import urlparse
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
from tradingagents.dataflows.ssl_utils import get_certificate_info, get_ssl_config
|
||||
from tradingagents.default_config import DEFAULT_CONFIG
|
||||
|
||||
|
||||
def test_ssl_connection(hostname, port=443):
|
||||
"""Test SSL connection to a specific hostname."""
|
||||
print(f"\n🔒 Testing SSL connection to {hostname}:{port}")
|
||||
|
||||
try:
|
||||
# Create SSL context
|
||||
context = ssl.create_default_context()
|
||||
|
||||
# Connect and get certificate info
|
||||
with socket.create_connection((hostname, port), timeout=10) as sock:
|
||||
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
|
||||
cert = ssock.getpeercert()
|
||||
print(f"✅ SSL connection successful")
|
||||
print(f" Subject: {cert.get('subject', 'Unknown')}")
|
||||
print(f" Issuer: {cert.get('issuer', 'Unknown')}")
|
||||
print(f" Version: {cert.get('version', 'Unknown')}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ SSL connection failed: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def test_requests_connection(url):
|
||||
"""Test HTTP request with requests library."""
|
||||
print(f"\n🌐 Testing HTTP request to {url}")
|
||||
|
||||
try:
|
||||
response = requests.get(url, timeout=10)
|
||||
print(f"✅ HTTP request successful")
|
||||
print(f" Status: {response.status_code}")
|
||||
print(f" SSL Cert: {response.raw.connection.sock.getpeercert().get('subject', 'Unknown') if hasattr(response.raw.connection, 'sock') else 'Unknown'}")
|
||||
return True
|
||||
|
||||
except requests.exceptions.SSLError as e:
|
||||
print(f"❌ SSL Error: {e}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"❌ Request failed: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def test_with_custom_cert_bundle(url, cert_bundle_path):
|
||||
"""Test HTTP request with custom certificate bundle."""
|
||||
print(f"\n🔐 Testing with custom cert bundle: {cert_bundle_path}")
|
||||
|
||||
if not os.path.exists(cert_bundle_path):
|
||||
print(f"❌ Certificate bundle not found: {cert_bundle_path}")
|
||||
return False
|
||||
|
||||
try:
|
||||
response = requests.get(url, verify=cert_bundle_path, timeout=10)
|
||||
print(f"✅ Request with custom cert bundle successful")
|
||||
print(f" Status: {response.status_code}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Request with custom cert bundle failed: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
"""Main diagnostic function."""
|
||||
print("🔍 TradingAgents SSL Certificate Diagnostic Tool")
|
||||
print("=" * 50)
|
||||
|
||||
# Get certificate information
|
||||
print("\n📋 Certificate Bundle Information:")
|
||||
cert_info = get_certificate_info()
|
||||
for key, value in cert_info.items():
|
||||
if isinstance(value, list):
|
||||
print(f" {key}: {', '.join(value) if value else 'None found'}")
|
||||
else:
|
||||
print(f" {key}: {value}")
|
||||
|
||||
# Test SSL configuration
|
||||
print(f"\n⚙️ Current SSL Configuration:")
|
||||
ssl_config = get_ssl_config(DEFAULT_CONFIG)
|
||||
for key, value in ssl_config.items():
|
||||
print(f" {key}: {value}")
|
||||
|
||||
# Test common endpoints
|
||||
test_endpoints = [
|
||||
("api.openai.com", 443),
|
||||
("openrouter.ai", 443),
|
||||
("generativelanguage.googleapis.com", 443),
|
||||
("www.google.com", 443)
|
||||
]
|
||||
|
||||
print(f"\n🎯 Testing SSL connections:")
|
||||
for hostname, port in test_endpoints:
|
||||
test_ssl_connection(hostname, port)
|
||||
|
||||
# Test HTTP requests
|
||||
test_urls = [
|
||||
"https://api.openai.com/v1/models",
|
||||
"https://www.google.com/search?q=test",
|
||||
"https://openrouter.ai/api/v1/models"
|
||||
]
|
||||
|
||||
print(f"\n🌍 Testing HTTP requests:")
|
||||
for url in test_urls:
|
||||
test_requests_connection(url)
|
||||
|
||||
# Test with different certificate bundles
|
||||
if cert_info.get("certifi_bundle") and cert_info["certifi_bundle"] != "Not available (certifi not installed)":
|
||||
print(f"\n🧪 Testing with certifi bundle:")
|
||||
test_with_custom_cert_bundle("https://www.google.com", cert_info["certifi_bundle"])
|
||||
|
||||
# Provide recommendations
|
||||
print(f"\n💡 Recommendations:")
|
||||
print(" 📋 Certificate Bundle Configuration:")
|
||||
print(" • Only set if you need a custom certificate bundle")
|
||||
print(" • If not set, system default SSL behavior is used")
|
||||
print(" export REQUESTS_CA_BUNDLE=/path/to/your/ca-bundle.crt")
|
||||
print(" export CURL_CA_BUNDLE=/path/to/your/ca-bundle.crt")
|
||||
|
||||
print("\n ⚠️ SSL Verification (use with caution):")
|
||||
print(" • Only disable for development/testing")
|
||||
print(" • If not set, SSL verification is enabled by default")
|
||||
print(" export SSL_VERIFY=false")
|
||||
|
||||
print("\n ⏱️ Timeout Configuration:")
|
||||
print(" • Only set if default timeout is insufficient")
|
||||
print(" export HTTP_TIMEOUT=60")
|
||||
|
||||
print("\n 🌐 Proxy Configuration:")
|
||||
print(" • Only required if behind corporate firewall")
|
||||
print(" export HTTP_PROXY=http://proxy.company.com:8080")
|
||||
print(" export HTTPS_PROXY=https://proxy.company.com:8080")
|
||||
|
||||
print("\n 📝 Configuration:")
|
||||
print(" • Add these to your .env file or export in shell")
|
||||
print(" • Leave unset to use system defaults")
|
||||
print(" • Only configure what you actually need")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test SSL configuration behavior
|
||||
"""
|
||||
|
||||
import os
|
||||
from tradingagents.default_config import DEFAULT_CONFIG
|
||||
from tradingagents.dataflows.ssl_utils import get_ssl_config, setup_global_ssl_config
|
||||
|
||||
def test_ssl_config():
|
||||
"""Test SSL configuration with different environment variable settings"""
|
||||
|
||||
print("🧪 Testing SSL Configuration Behavior")
|
||||
print("=" * 50)
|
||||
|
||||
# Test 1: No environment variables set
|
||||
print("\n1️⃣ Test: No SSL environment variables set")
|
||||
os.environ.pop("REQUESTS_CA_BUNDLE", None)
|
||||
os.environ.pop("CURL_CA_BUNDLE", None)
|
||||
os.environ.pop("SSL_VERIFY", None)
|
||||
os.environ.pop("HTTP_TIMEOUT", None)
|
||||
|
||||
from tradingagents.default_config import DEFAULT_CONFIG
|
||||
config = DEFAULT_CONFIG.copy()
|
||||
ssl_config = get_ssl_config(config)
|
||||
print(f" SSL Config: {ssl_config}")
|
||||
print(f" Expected: Empty or minimal config (default behavior)")
|
||||
|
||||
# Test 2: Custom certificate bundle set
|
||||
print("\n2️⃣ Test: Custom certificate bundle set")
|
||||
os.environ["REQUESTS_CA_BUNDLE"] = "/custom/path/ca-bundle.crt"
|
||||
|
||||
# Re-import to get updated config
|
||||
from importlib import reload
|
||||
import tradingagents.default_config
|
||||
reload(tradingagents.default_config)
|
||||
from tradingagents.default_config import DEFAULT_CONFIG
|
||||
|
||||
config = DEFAULT_CONFIG.copy()
|
||||
ssl_config = get_ssl_config(config)
|
||||
print(f" Config ssl_cert_bundle: {config.get('ssl_cert_bundle')}")
|
||||
print(f" SSL Config: {ssl_config}")
|
||||
print(f" Expected: cert_bundle and verify set to custom path")
|
||||
|
||||
# Test 3: SSL verification disabled
|
||||
print("\n3️⃣ Test: SSL verification disabled")
|
||||
os.environ.pop("REQUESTS_CA_BUNDLE", None)
|
||||
os.environ["SSL_VERIFY"] = "false"
|
||||
|
||||
reload(tradingagents.default_config)
|
||||
from tradingagents.default_config import DEFAULT_CONFIG
|
||||
|
||||
config = DEFAULT_CONFIG.copy()
|
||||
ssl_config = get_ssl_config(config)
|
||||
print(f" Config ssl_verify: {config.get('ssl_verify')}")
|
||||
print(f" SSL Config: {ssl_config}")
|
||||
print(f" Expected: verify set to False")
|
||||
|
||||
# Test 4: Timeout and proxy settings
|
||||
print("\n4️⃣ Test: Timeout and proxy settings")
|
||||
os.environ["HTTP_TIMEOUT"] = "60"
|
||||
os.environ["HTTP_PROXY"] = "http://proxy.example.com:8080"
|
||||
os.environ["HTTPS_PROXY"] = "https://proxy.example.com:8080"
|
||||
|
||||
reload(tradingagents.default_config)
|
||||
from tradingagents.default_config import DEFAULT_CONFIG
|
||||
|
||||
config = DEFAULT_CONFIG.copy()
|
||||
ssl_config = get_ssl_config(config)
|
||||
print(f" Config timeout: {config.get('http_timeout')}")
|
||||
print(f" Config proxies: HTTP={config.get('http_proxy')}, HTTPS={config.get('https_proxy')}")
|
||||
print(f" SSL Config: {ssl_config}")
|
||||
print(f" Expected: timeout and proxies in ssl_config")
|
||||
|
||||
# Test 5: Empty environment variables (should not be used)
|
||||
print("\n5️⃣ Test: Empty environment variables")
|
||||
os.environ["REQUESTS_CA_BUNDLE"] = ""
|
||||
os.environ["HTTP_TIMEOUT"] = ""
|
||||
|
||||
reload(tradingagents.default_config)
|
||||
from tradingagents.default_config import DEFAULT_CONFIG
|
||||
|
||||
config = DEFAULT_CONFIG.copy()
|
||||
ssl_config = get_ssl_config(config)
|
||||
print(f" Config ssl_cert_bundle: '{config.get('ssl_cert_bundle')}'")
|
||||
print(f" Config http_timeout: {config.get('http_timeout')}")
|
||||
print(f" SSL Config: {ssl_config}")
|
||||
print(f" Expected: Empty values should not be used")
|
||||
|
||||
# Clean up
|
||||
for var in ["REQUESTS_CA_BUNDLE", "CURL_CA_BUNDLE", "SSL_VERIFY", "HTTP_TIMEOUT", "HTTP_PROXY", "HTTPS_PROXY"]:
|
||||
os.environ.pop(var, None)
|
||||
|
||||
print("\n✅ SSL configuration tests completed")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_ssl_config()
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test SSL connectivity for TradingAgents components
|
||||
"""
|
||||
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
def test_api_connections():
|
||||
"""Test API connections that TradingAgents will use"""
|
||||
|
||||
print("🔍 Testing TradingAgents API Connections")
|
||||
print("=" * 50)
|
||||
|
||||
# Test 1: Basic HTTP requests with proper SSL
|
||||
print("\n1️⃣ Testing HTTP requests with SSL configuration:")
|
||||
|
||||
import requests
|
||||
|
||||
test_endpoints = [
|
||||
("OpenAI API", "https://api.openai.com/v1/models"),
|
||||
("Google Search", "https://www.google.com/search?q=AAPL"),
|
||||
("OpenRouter API", "https://openrouter.ai/api/v1/models"),
|
||||
]
|
||||
|
||||
for name, url in test_endpoints:
|
||||
try:
|
||||
response = requests.get(url, timeout=10)
|
||||
print(f" ✅ {name}: Status {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f" ❌ {name}: {e}")
|
||||
|
||||
# Test 2: LangChain LLM initialization
|
||||
print("\n2️⃣ Testing LangChain LLM initialization:")
|
||||
|
||||
try:
|
||||
from langchain_openai import ChatOpenAI
|
||||
|
||||
# Test with the SSL configuration
|
||||
llm = ChatOpenAI(
|
||||
model="gpt-3.5-turbo",
|
||||
api_key=os.getenv("OPENAI_API_KEY", "test-key")
|
||||
)
|
||||
print(" ✅ ChatOpenAI initialization successful")
|
||||
|
||||
# Test a simple API call (this might fail due to API key, but SSL should work)
|
||||
try:
|
||||
# This will test SSL connectivity
|
||||
response = llm.invoke("Hello")
|
||||
print(" ✅ ChatOpenAI API call successful")
|
||||
except Exception as e:
|
||||
if "401" in str(e) or "Unauthorized" in str(e):
|
||||
print(" ✅ ChatOpenAI SSL working (401 = API key issue, not SSL)")
|
||||
else:
|
||||
print(f" ⚠️ ChatOpenAI API call error: {e}")
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ ChatOpenAI initialization failed: {e}")
|
||||
|
||||
# Test 3: TradingAgents configuration
|
||||
print("\n3️⃣ Testing TradingAgents SSL configuration:")
|
||||
|
||||
try:
|
||||
from tradingagents.default_config import DEFAULT_CONFIG
|
||||
from tradingagents.dataflows.ssl_utils import get_ssl_config, setup_global_ssl_config
|
||||
|
||||
print(f" 📋 SSL cert bundle: {DEFAULT_CONFIG.get('ssl_cert_bundle')}")
|
||||
print(f" 📋 SSL verify: {DEFAULT_CONFIG.get('ssl_verify')}")
|
||||
|
||||
ssl_config = get_ssl_config(DEFAULT_CONFIG)
|
||||
print(f" 📋 SSL config: {ssl_config}")
|
||||
|
||||
# Set up global SSL configuration
|
||||
setup_global_ssl_config(DEFAULT_CONFIG)
|
||||
print(" ✅ Global SSL configuration applied")
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ TradingAgents SSL configuration failed: {e}")
|
||||
|
||||
# Test 4: Google News functionality
|
||||
print("\n4️⃣ Testing Google News data retrieval:")
|
||||
|
||||
try:
|
||||
from tradingagents.dataflows.googlenews_utils import getNewsData
|
||||
from tradingagents.dataflows.ssl_utils import get_ssl_config
|
||||
from tradingagents.default_config import DEFAULT_CONFIG
|
||||
|
||||
ssl_config = get_ssl_config(DEFAULT_CONFIG)
|
||||
|
||||
# Test news retrieval with SSL config
|
||||
news_results = getNewsData("AAPL", "2024-01-01", "2024-01-02", ssl_config)
|
||||
print(f" ✅ Google News retrieval successful, got {len(news_results)} results")
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Google News retrieval failed: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_api_connections()
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test TradingAgents SSL connections specifically
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to path
|
||||
project_root = Path(__file__).parent.absolute()
|
||||
if str(project_root) not in sys.path:
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
|
||||
from tradingagents.default_config import DEFAULT_CONFIG
|
||||
from tradingagents.dataflows.ssl_utils import get_ssl_config, setup_global_ssl_config, get_certificate_info
|
||||
from tradingagents.graph.trading_graph import TradingAgentsGraph
|
||||
import requests
|
||||
|
||||
def test_certificate_issues():
|
||||
"""Test SSL certificate issues that might occur in TradingAgents"""
|
||||
|
||||
print("🔍 Testing TradingAgents SSL Certificate Issues")
|
||||
print("=" * 55)
|
||||
|
||||
# Show environment variables
|
||||
print("\n📋 Environment Variables:")
|
||||
ssl_vars = ["REQUESTS_CA_BUNDLE", "CURL_CA_BUNDLE", "SSL_VERIFY", "HTTP_TIMEOUT",
|
||||
"HTTP_PROXY", "HTTPS_PROXY", "OPENAI_API_KEY", "FINNHUB_API_KEY"]
|
||||
for var in ssl_vars:
|
||||
value = os.getenv(var)
|
||||
if value:
|
||||
if "API_KEY" in var:
|
||||
print(f" {var}: {'*' * min(8, len(value))}...")
|
||||
else:
|
||||
print(f" {var}: {value}")
|
||||
else:
|
||||
print(f" {var}: Not set")
|
||||
|
||||
# Show certificate info
|
||||
print("\n📋 Certificate Bundle Information:")
|
||||
cert_info = get_certificate_info()
|
||||
for key, value in cert_info.items():
|
||||
if isinstance(value, list):
|
||||
print(f" {key}: {', '.join(value) if value else 'None found'}")
|
||||
else:
|
||||
print(f" {key}: {value}")
|
||||
|
||||
# Test SSL config
|
||||
print("\n⚙️ Current SSL Configuration:")
|
||||
config = DEFAULT_CONFIG.copy()
|
||||
ssl_config = get_ssl_config(config)
|
||||
print(f" SSL Config: {ssl_config}")
|
||||
|
||||
# Set up global SSL config
|
||||
print("\n🔧 Setting up global SSL configuration...")
|
||||
setup_global_ssl_config(config)
|
||||
|
||||
# Test basic HTTPS connections
|
||||
test_urls = [
|
||||
"https://api.openai.com/",
|
||||
"https://www.google.com/",
|
||||
"https://openrouter.ai/",
|
||||
"https://finnhub.io/"
|
||||
]
|
||||
|
||||
print(f"\n🌐 Testing HTTPS connections:")
|
||||
for url in test_urls:
|
||||
try:
|
||||
print(f" Testing {url}...")
|
||||
response = requests.get(url, timeout=10)
|
||||
print(f" ✅ {url}: Status {response.status_code}")
|
||||
except requests.exceptions.SSLError as e:
|
||||
print(f" ❌ SSL Error for {url}: {e}")
|
||||
except Exception as e:
|
||||
print(f" ❌ Connection error for {url}: {e}")
|
||||
|
||||
# Test TradingAgentsGraph initialization
|
||||
print(f"\n🤖 Testing TradingAgentsGraph initialization:")
|
||||
try:
|
||||
# Create minimal config
|
||||
test_config = DEFAULT_CONFIG.copy()
|
||||
test_config["llm_provider"] = "openai"
|
||||
test_config["quick_think_llm"] = "gpt-3.5-turbo"
|
||||
test_config["deep_think_llm"] = "gpt-4"
|
||||
|
||||
print(" Creating TradingAgentsGraph...")
|
||||
graph = TradingAgentsGraph(config=test_config)
|
||||
print(" ✅ TradingAgentsGraph created successfully")
|
||||
|
||||
# Test if we can make a simple LLM call
|
||||
print(" Testing LLM connection...")
|
||||
try:
|
||||
# This won't actually make an API call but will test the LLM initialization
|
||||
llm = graph.quick_thinking_llm
|
||||
print(f" ✅ LLM initialized: {llm}")
|
||||
except Exception as e:
|
||||
print(f" ❌ LLM initialization error: {e}")
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ TradingAgentsGraph initialization error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
# Recommendations based on findings
|
||||
print(f"\n💡 Troubleshooting Recommendations:")
|
||||
|
||||
# Check if we're on macOS and suggest system certificates
|
||||
if sys.platform == "darwin":
|
||||
macos_cert = "/etc/ssl/cert.pem"
|
||||
if os.path.exists(macos_cert):
|
||||
print(f" 📱 macOS detected - try: export REQUESTS_CA_BUNDLE={macos_cert}")
|
||||
else:
|
||||
print(f" 📱 macOS detected but {macos_cert} not found")
|
||||
|
||||
# Check for certifi
|
||||
try:
|
||||
import certifi
|
||||
print(f" 🔐 Certifi available - try: export REQUESTS_CA_BUNDLE={certifi.where()}")
|
||||
except ImportError:
|
||||
print(f" ❌ Certifi not installed - try: pip install certifi")
|
||||
|
||||
# Corporate environment suggestions
|
||||
print(f" 🏢 If behind corporate firewall:")
|
||||
print(f" • Contact IT for corporate certificate bundle")
|
||||
print(f" • Check if HTTP_PROXY/HTTPS_PROXY needed")
|
||||
print(f" • Ask about custom CA certificates")
|
||||
|
||||
# Temporary workaround (not recommended for production)
|
||||
print(f" 🚨 Temporary workaround (development only):")
|
||||
print(f" export SSL_VERIFY=false")
|
||||
print(f" ⚠️ This disables SSL verification - use with caution!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_certificate_issues()
|
||||
|
|
@ -23,20 +23,36 @@ def is_rate_limited(response):
|
|||
wait=wait_exponential(multiplier=1, min=4, max=60),
|
||||
stop=stop_after_attempt(5),
|
||||
)
|
||||
def make_request(url, headers):
|
||||
def make_request(url, headers, ssl_config=None):
|
||||
"""Make a request with retry logic for rate limiting"""
|
||||
# Random delay before each request to avoid detection
|
||||
time.sleep(random.uniform(2, 6))
|
||||
response = requests.get(url, headers=headers)
|
||||
|
||||
# Prepare SSL configuration - only use if explicitly configured
|
||||
kwargs = {}
|
||||
if ssl_config:
|
||||
if ssl_config.get("cert_bundle"):
|
||||
kwargs["verify"] = ssl_config["cert_bundle"]
|
||||
elif "verify" in ssl_config:
|
||||
kwargs["verify"] = ssl_config["verify"]
|
||||
|
||||
if ssl_config.get("timeout"):
|
||||
kwargs["timeout"] = ssl_config["timeout"]
|
||||
|
||||
if ssl_config.get("proxies"):
|
||||
kwargs["proxies"] = ssl_config["proxies"]
|
||||
|
||||
response = requests.get(url, headers=headers, **kwargs)
|
||||
return response
|
||||
|
||||
|
||||
def getNewsData(query, start_date, end_date):
|
||||
def getNewsData(query, start_date, end_date, ssl_config=None):
|
||||
"""
|
||||
Scrape Google News search results for a given query and date range.
|
||||
query: str - search query
|
||||
start_date: str - start date in the format yyyy-mm-dd or mm/dd/yyyy
|
||||
end_date: str - end date in the format yyyy-mm-dd or mm/dd/yyyy
|
||||
ssl_config: dict - SSL configuration including cert_bundle, verify, timeout, proxies
|
||||
"""
|
||||
if "-" in start_date:
|
||||
start_date = datetime.strptime(start_date, "%Y-%m-%d")
|
||||
|
|
@ -64,7 +80,7 @@ def getNewsData(query, start_date, end_date):
|
|||
)
|
||||
|
||||
try:
|
||||
response = make_request(url, headers)
|
||||
response = make_request(url, headers, ssl_config)
|
||||
soup = BeautifulSoup(response.content, "html.parser")
|
||||
results_on_page = soup.select("div.SoaBEf")
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ from .yfin_utils import *
|
|||
from .stockstats_utils import *
|
||||
from .googlenews_utils import *
|
||||
from .finnhub_utils import get_data_in_range
|
||||
from .ssl_utils import get_ssl_config, setup_global_ssl_config
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from datetime import datetime
|
||||
|
|
@ -294,7 +295,13 @@ def get_google_news(
|
|||
before = start_date - relativedelta(days=look_back_days)
|
||||
before = before.strftime("%Y-%m-%d")
|
||||
|
||||
news_results = getNewsData(query, before, curr_date)
|
||||
config = get_config()
|
||||
ssl_config = get_ssl_config(config)
|
||||
# Only pass ssl_config if it has actual configuration
|
||||
if ssl_config:
|
||||
news_results = getNewsData(query, before, curr_date, ssl_config)
|
||||
else:
|
||||
news_results = getNewsData(query, before, curr_date)
|
||||
|
||||
news_str = ""
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,149 @@
|
|||
"""
|
||||
SSL/TLS configuration utilities for TradingAgents
|
||||
"""
|
||||
|
||||
import os
|
||||
import ssl
|
||||
import certifi
|
||||
from typing import Dict, Any, Optional
|
||||
|
||||
|
||||
def get_ssl_config(config: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""
|
||||
Create SSL configuration dictionary from the main config.
|
||||
|
||||
Args:
|
||||
config: Main configuration dictionary
|
||||
|
||||
Returns:
|
||||
SSL configuration dictionary with cert_bundle, verify, timeout, proxies
|
||||
"""
|
||||
ssl_config = {}
|
||||
|
||||
# Certificate bundle configuration - only use if explicitly specified
|
||||
cert_bundle = config.get("ssl_cert_bundle")
|
||||
if cert_bundle and cert_bundle.strip():
|
||||
# Use explicitly specified certificate bundle
|
||||
ssl_config["cert_bundle"] = cert_bundle
|
||||
ssl_config["verify"] = cert_bundle
|
||||
elif not config.get("ssl_verify", True):
|
||||
# Only disable SSL verification if explicitly set to false
|
||||
ssl_config["verify"] = False
|
||||
|
||||
# If no explicit cert bundle and ssl_verify is true (default),
|
||||
# don't set anything - use default behavior
|
||||
|
||||
# Timeout configuration
|
||||
if config.get("http_timeout"):
|
||||
ssl_config["timeout"] = config["http_timeout"]
|
||||
|
||||
# Proxy configuration
|
||||
proxies = {}
|
||||
if config.get("http_proxy"):
|
||||
proxies["http"] = config["http_proxy"]
|
||||
if config.get("https_proxy"):
|
||||
proxies["https"] = config["https_proxy"]
|
||||
if proxies:
|
||||
ssl_config["proxies"] = proxies
|
||||
|
||||
return ssl_config
|
||||
|
||||
|
||||
def setup_global_ssl_config(config: Dict[str, Any]) -> None:
|
||||
"""
|
||||
Set up global SSL configuration for the application.
|
||||
This affects all SSL connections made by requests and other libraries.
|
||||
Only sets configuration if explicitly specified in environment variables.
|
||||
|
||||
Args:
|
||||
config: Main configuration dictionary
|
||||
"""
|
||||
# Set environment variables for requests library only if explicitly configured
|
||||
cert_bundle = config.get("ssl_cert_bundle")
|
||||
if cert_bundle and cert_bundle.strip():
|
||||
os.environ["REQUESTS_CA_BUNDLE"] = cert_bundle
|
||||
os.environ["CURL_CA_BUNDLE"] = cert_bundle
|
||||
print(f"🔒 Using custom SSL certificate bundle: {cert_bundle}")
|
||||
|
||||
# Set SSL verification for requests only if explicitly disabled
|
||||
if not config.get("ssl_verify", True):
|
||||
# Disable SSL warnings when verification is disabled
|
||||
import urllib3
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
print("⚠️ SSL certificate verification disabled")
|
||||
|
||||
# Set proxy environment variables if specified
|
||||
if config.get("http_proxy"):
|
||||
os.environ["HTTP_PROXY"] = config["http_proxy"]
|
||||
print(f"🌐 Using HTTP proxy: {config['http_proxy']}")
|
||||
if config.get("https_proxy"):
|
||||
os.environ["HTTPS_PROXY"] = config["https_proxy"]
|
||||
print(f"🌐 Using HTTPS proxy: {config['https_proxy']}")
|
||||
|
||||
# Set timeout if specified
|
||||
if config.get("http_timeout"):
|
||||
print(f"⏱️ HTTP timeout set to: {config['http_timeout']} seconds")
|
||||
|
||||
|
||||
def create_ssl_context(cert_bundle: Optional[str] = None, verify_ssl: bool = True) -> ssl.SSLContext:
|
||||
"""
|
||||
Create a custom SSL context with specified certificate bundle.
|
||||
|
||||
Args:
|
||||
cert_bundle: Path to certificate bundle file
|
||||
verify_ssl: Whether to verify SSL certificates
|
||||
|
||||
Returns:
|
||||
Configured SSL context
|
||||
"""
|
||||
if not verify_ssl:
|
||||
# Create unverified context (not recommended for production)
|
||||
context = ssl._create_unverified_context()
|
||||
else:
|
||||
# Create default context
|
||||
context = ssl.create_default_context()
|
||||
|
||||
if cert_bundle:
|
||||
# Load custom certificate bundle
|
||||
context.load_verify_locations(cafile=cert_bundle)
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_certificate_info() -> Dict[str, str]:
|
||||
"""
|
||||
Get information about available certificate bundles.
|
||||
|
||||
Returns:
|
||||
Dictionary with certificate bundle information
|
||||
"""
|
||||
info = {}
|
||||
|
||||
# Check certifi bundle
|
||||
try:
|
||||
import certifi
|
||||
info["certifi_bundle"] = certifi.where()
|
||||
except ImportError:
|
||||
info["certifi_bundle"] = "Not available (certifi not installed)"
|
||||
|
||||
# Check environment variables
|
||||
info["env_ca_bundle"] = os.getenv("REQUESTS_CA_BUNDLE", "Not set")
|
||||
info["env_curl_bundle"] = os.getenv("CURL_CA_BUNDLE", "Not set")
|
||||
|
||||
# Check system certificate stores
|
||||
common_cert_paths = [
|
||||
"/etc/ssl/certs/ca-certificates.crt", # Debian/Ubuntu
|
||||
"/etc/pki/tls/certs/ca-bundle.crt", # RedHat/CentOS
|
||||
"/usr/local/share/certs/ca-root-nss.crt", # FreeBSD
|
||||
"/etc/ssl/cert.pem", # OpenBSD
|
||||
"/System/Library/OpenSSL/certs/cert.pem", # macOS
|
||||
]
|
||||
|
||||
available_system_certs = []
|
||||
for path in common_cert_paths:
|
||||
if os.path.exists(path):
|
||||
available_system_certs.append(path)
|
||||
|
||||
info["system_cert_bundles"] = available_system_certs
|
||||
|
||||
return info
|
||||
|
|
@ -26,4 +26,11 @@ DEFAULT_CONFIG = {
|
|||
"online_tools": True,
|
||||
"user_position": "none",
|
||||
"cost_per_trade": 0.0,
|
||||
# SSL/TLS Certificate settings - only use if explicitly set
|
||||
"ssl_cert_bundle": os.getenv("REQUESTS_CA_BUNDLE") or os.getenv("CURL_CA_BUNDLE"),
|
||||
"ssl_verify": os.getenv("SSL_VERIFY", "true").lower() in ("true", "1", "yes"),
|
||||
"http_timeout": int(os.getenv("HTTP_TIMEOUT")) if os.getenv("HTTP_TIMEOUT") else None,
|
||||
# Proxy settings (if needed)
|
||||
"http_proxy": os.getenv("HTTP_PROXY"),
|
||||
"https_proxy": os.getenv("HTTPS_PROXY"),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ from tradingagents.agents.utils.agent_states import (
|
|||
RiskDebateState,
|
||||
)
|
||||
from tradingagents.dataflows.interface import set_config
|
||||
from tradingagents.dataflows.ssl_utils import setup_global_ssl_config
|
||||
|
||||
from .conditional_logic import ConditionalLogic
|
||||
from .setup import GraphSetup
|
||||
|
|
@ -50,6 +51,9 @@ class TradingAgentsGraph:
|
|||
|
||||
# Update the interface's config
|
||||
set_config(self.config)
|
||||
|
||||
# Set up global SSL configuration
|
||||
setup_global_ssl_config(self.config)
|
||||
|
||||
# Create necessary directories
|
||||
os.makedirs(
|
||||
|
|
@ -79,15 +83,48 @@ class TradingAgentsGraph:
|
|||
"export OPENAI_API_KEY=your_openai_key_here"
|
||||
)
|
||||
|
||||
# Prepare SSL configuration for HTTP client - only if explicitly configured
|
||||
http_client_kwargs = {}
|
||||
cert_bundle = self.config.get("ssl_cert_bundle")
|
||||
|
||||
if cert_bundle and cert_bundle.strip():
|
||||
import httpx
|
||||
http_client_kwargs["verify"] = cert_bundle
|
||||
elif not self.config.get("ssl_verify", True):
|
||||
import httpx
|
||||
http_client_kwargs["verify"] = False
|
||||
|
||||
if self.config.get("http_timeout"):
|
||||
import httpx
|
||||
http_client_kwargs["timeout"] = self.config["http_timeout"]
|
||||
|
||||
# Add proxy configuration if specified
|
||||
if self.config.get("http_proxy") or self.config.get("https_proxy"):
|
||||
import httpx
|
||||
proxies = {}
|
||||
if self.config.get("http_proxy"):
|
||||
proxies["http://"] = self.config["http_proxy"]
|
||||
if self.config.get("https_proxy"):
|
||||
proxies["https://"] = self.config["https_proxy"]
|
||||
http_client_kwargs["proxies"] = proxies
|
||||
|
||||
# Create HTTP client only if we have custom settings
|
||||
http_client = None
|
||||
if http_client_kwargs:
|
||||
import httpx
|
||||
http_client = httpx.Client(**http_client_kwargs)
|
||||
|
||||
self.deep_thinking_llm = ChatOpenAI(
|
||||
model=self.config["deep_think_llm"],
|
||||
base_url=self.config["backend_url"],
|
||||
api_key=api_key
|
||||
api_key=api_key,
|
||||
http_client=http_client
|
||||
)
|
||||
self.quick_thinking_llm = ChatOpenAI(
|
||||
model=self.config["quick_think_llm"],
|
||||
base_url=self.config["backend_url"],
|
||||
api_key=api_key
|
||||
api_key=api_key,
|
||||
http_client=http_client
|
||||
)
|
||||
elif self.config["llm_provider"].lower() == "anthropic":
|
||||
self.deep_thinking_llm = ChatAnthropic(model=self.config["deep_think_llm"], base_url=self.config["backend_url"])
|
||||
|
|
|
|||
Loading…
Reference in New Issue