diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..6283e807f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,364 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +ValueCell is a community-driven, multi-agent platform for financial applications. It provides a team of AI investment agents for stock selection, research, tracking, and trading. The project uses Python 3.12+ for backend/agents and React/TypeScript (React Router v7) for the frontend. + +## Common Commands + +### Running the Application + +```bash +# Start entire application (frontend + backend + agents) +bash start.sh + +# Windows +.\start.ps1 + +# Start only backend +bash start.sh --no-frontend + +# Start only frontend +bash start.sh --no-backend +``` + +The application will be available at http://localhost:1420 + +### Development Setup + +```bash +# First-time setup: prepare all environments (main + third-party) +cd python +bash scripts/prepare_envs.sh + +# Install main Python dependencies +cd python +uv sync --group dev + +# Install frontend dependencies +cd frontend +bun install +``` + +### Running Individual Agents + +```bash +# Launch specific agents via the launcher +cd python +uv run --env-file ../.env --with questionary scripts/launch.py + +# Or run agents directly +uv run --env-file ../.env -m valuecell.agents.research_agent +uv run --env-file ../.env -m valuecell.agents.auto_trading_agent +uv run --env-file ../.env -m valuecell.agents.news_agent +uv run --env-file ../.env -m valuecell.agents.strategy_agent +``` + +### Testing and Code Quality + +```bash +# Run tests +make test +# or +uv run pytest ./python + +# Format code +make format +# or +ruff format --config ./python/pyproject.toml ./python/ +uv run --directory ./python isort . + +# Lint code +make lint +# or +ruff check --config ./python/pyproject.toml ./python/ + +# Frontend linting and formatting +cd frontend +bun run lint +bun run format +bun run check # Run biome check +bun run check:fix # Auto-fix issues +``` + +### Database Management + +```bash +# Initialize database +cd python +uv run valuecell/server/db/init_db.py + +# If you encounter database compatibility issues, delete and restart: +rm -rf lancedb/ valuecell.db .knowledgebase/ +``` + +## Architecture Overview + +### High-Level Structure + +``` +valuecell/ +├── frontend/ # React Router v7 + TypeScript frontend +├── python/ +│ ├── valuecell/ # Main Python package +│ ├── configs/ # YAML configuration files +│ ├── scripts/ # Utility scripts (launch, prepare_envs) +│ └── third_party/ # Third-party agent integrations +├── docs/ # Documentation +└── start.sh # Application launcher +``` + +### Python Package Structure + +``` +python/valuecell/ +├── core/ # Core orchestration and coordination +│ ├── agent/ # Agent decorator, listener, client +│ ├── conversation/ # Conversation management & stores +│ ├── coordinate/ # Main orchestrator +│ ├── super_agent/ # Triage agent (ANSWER vs HANDOFF) +│ ├── plan/ # Planner with HITL support +│ ├── task/ # Task execution +│ └── event/ # Event response routing & buffering +├── agents/ # Concrete agent implementations +│ ├── research_agent/ +│ ├── auto_trading_agent/ +│ ├── news_agent/ +│ └── strategy_agent/ +├── server/ # FastAPI backend +│ ├── api/ # API routes +│ ├── db/ # Database models and stores +│ └── services/ # Business logic +├── adapters/ # External integrations +│ ├── models/ # LLM provider factory +│ ├── assets/ # Asset data providers +│ └── db/ # Database adapters +├── config/ # Configuration management +└── utils/ # Shared utilities +``` + +### Configuration System + +ValueCell uses a three-tier configuration system: + +1. **Environment Variables** (highest priority) - Set in `.env` file +2. **YAML Files** - In `python/configs/` directory + - `config.yaml` - Global defaults + - `providers/` - LLM provider configs (OpenRouter, SiliconFlow, Google, etc.) + - `agents/` - Agent-specific configurations + - `agent_cards/` - UI metadata for agents +3. **Code Defaults** (lowest priority) + +**Key configuration files:** +- `.env` - API keys and runtime settings (copy from `.env.example`) +- `python/configs/config.yaml` - Primary provider, model defaults +- `python/configs/agents/*.yaml` - Per-agent model and parameter settings +- `python/configs/providers/*.yaml` - Provider connection details + +See `docs/CONFIGURATION_GUIDE.md` for detailed configuration documentation. + +## Core Orchestration Flow + +The system follows an **async, re-entrant orchestrator pattern** with streaming responses: + +1. **User Input** → `AgentOrchestrator.process_user_input()` +2. **Super Agent Triage** - Quick analysis to decide: + - `ANSWER` - Respond directly for simple queries + - `HANDOFF_TO_PLANNER` - Complex requests needing planning +3. **Planning (with HITL)** - `PlanService` creates execution plan + - Can pause for human confirmation via `UserInputRequest` + - Resumes after user feedback +4. **Task Execution** - `TaskExecutor` runs plan steps + - Calls remote agents via A2A (Agent-to-Agent) protocol + - Streams task status events back +5. **Response Pipeline**: + - `ResponseRouter` - Maps A2A events to typed `BaseResponse` objects + - `ResponseBuffer` - Annotates with stable item IDs, aggregates partials + - Persists to `ConversationStore` (SQLite or in-memory) + - Streams to UI + +**Key insight:** The orchestrator decouples producers/consumers, allowing long-running tasks to continue even if the client disconnects. + +## Agent Development + +### Creating a New Agent + +1. Create agent directory: `python/valuecell/agents/my_agent/` +2. Add agent configuration: `python/configs/agents/my_agent.yaml` +3. Implement agent using the `agno` framework (see existing agents as examples) +4. Wrap with `@create_wrapped_agent` decorator for A2A integration +5. Register in `scripts/launch.py` for standalone execution +6. Add agent card metadata in `python/configs/agent_cards/my_agent.yaml` + +See `docs/CONTRIBUTE_AN_AGENT.md` for detailed guide. + +### Agent Framework + +Agents use the **Agno** framework (`agno` package), which provides: +- Multi-modal LLM integration +- Tool/function calling +- Knowledge base (RAG) with LanceDB +- Memory management +- Async streaming + +## Model Provider System + +ValueCell supports multiple LLM providers with automatic fallback: + +**Supported providers:** +- OpenRouter (recommended for multi-model access) +- SiliconFlow (cost-effective, Chinese models) +- Google (Gemini) +- Azure OpenAI +- OpenAI +- Custom OpenAI-compatible endpoints + +**Auto-detection priority:** +1. OpenRouter +2. SiliconFlow +3. Google +4. Others + +**Fallback mechanism:** If primary provider fails, automatically tries other configured providers with appropriate model mappings (defined in agent YAML `provider_models` field). + +**Factory pattern:** `valuecell/adapters/models/factory.py` handles model instantiation with provider-specific implementations. + +## Third-Party Agent Integration + +The project integrates third-party agents in isolated environments: + +- `python/third_party/ai-hedge-fund/` - AI Hedge Fund agents (various analyst personas) +- `python/third_party/TradingAgents/` - Trading strategy agents + +**Important:** Each third-party directory has its own `pyproject.toml` and virtual environment to prevent dependency conflicts. Use `scripts/prepare_envs.sh` to set up all environments. + +## Testing + +Tests use `pytest` with async support (`pytest-asyncio`): + +```bash +# Run all tests +uv run pytest ./python + +# Run specific test file +uv run pytest ./python/valuecell/core/plan/tests/test_planner.py + +# Run with coverage +uv run pytest --cov=valuecell --cov-report=html ./python +``` + +**Test structure mirrors source structure:** +- Tests live in `tests/` subdirectories alongside the code they test +- Example: `valuecell/core/plan/tests/test_planner.py` + +## Frontend Development + +```bash +cd frontend + +# Development server (with HMR) +bun run dev + +# Type checking +bun run typecheck + +# Build for production +bun run build + +# Preview production build +bun run start +``` + +**Tech stack:** +- React Router v7 (file-based routing) +- React 19 +- TypeScript +- Tailwind CSS v4 +- Radix UI components +- Zustand for state management +- TanStack Query for data fetching +- Biome for linting/formatting + +**Key directories:** +- `frontend/src/routes/` - File-based routing +- `frontend/src/components/` - Reusable components +- `frontend/src/api/` - API client +- `frontend/src/store/` - Zustand stores +- `frontend/src/hooks/` - Custom React hooks + +## API Development + +Backend uses **FastAPI** with: +- A2A (Agent-to-Agent) protocol via `a2a-sdk` +- SQLAlchemy with SQLite/async support +- Uvicorn ASGI server + +**Key files:** +- `python/valuecell/server/main.py` - Entry point +- `python/valuecell/server/api/app.py` - FastAPI app factory +- `python/valuecell/server/api/` - Route handlers +- `python/valuecell/server/services/` - Business logic + +**Default API settings:** +- Host: `localhost` +- Port: `8000` +- Debug mode: Controlled by `API_DEBUG` env var + +## OKX Trading Integration + +For live/paper crypto trading via OKX: + +**Environment variables:** +```bash +AUTO_TRADING_EXCHANGE=okx +OKX_NETWORK=paper # Use 'mainnet' for live trading +OKX_API_KEY=... +OKX_API_SECRET=... +OKX_API_PASSPHRASE=... +OKX_ALLOW_LIVE_TRADING=false # Must be true for mainnet +OKX_MARGIN_MODE=cash # or cross/isolated +``` + +**Safety:** Keep `OKX_ALLOW_LIVE_TRADING=false` until strategies are validated on paper. See `docs/OKX_SETUP.md` for details. + +## Logging + +Logs are written to `logs/{timestamp}/` directory: +- `{AgentName}.log` - Per-agent logs +- `backend.log` - Backend server logs + +The `launch.py` script automatically creates timestamped log directories and redirects output. + +## Important Notes + +- **Python 3.12+ required** - The project uses modern Python features +- **Use `uv` for Python** - Fast dependency management (auto-installed by `start.sh`) +- **Use `bun` for frontend** - Fast JavaScript runtime and package manager +- **Third-party isolation** - Third-party agents run in separate virtual environments +- **Configuration over code** - Prefer YAML configs for agent/model settings +- **Async-first** - Most core code is async; use `await` appropriately +- **A2A protocol** - Agents communicate via standardized Agent-to-Agent protocol +- **Streaming responses** - UI receives incremental updates during long-running tasks +- **HITL support** - Planner can pause for human input and resume + +## Common Troubleshooting + +**Database compatibility issues:** +```bash +rm -rf lancedb/ valuecell.db .knowledgebase/ +cd python && uv run valuecell/server/db/init_db.py +``` + +**Missing environment variables:** +- Ensure `.env` exists (copy from `.env.example`) +- Configure at least one LLM provider API key + +**Dependency conflicts:** +- Third-party agents use isolated environments +- Run `bash scripts/prepare_envs.sh` to reset all environments + +**Frontend build errors:** +- Ensure bun is installed: `brew install bun` (macOS) +- Clear cache: `rm -rf frontend/node_modules frontend/.react-router` diff --git a/python/configs/agent_cards/strategy_agent.json b/python/configs/agent_cards/strategy_agent.json index 2930117c3..b3fe27e63 100644 --- a/python/configs/agent_cards/strategy_agent.json +++ b/python/configs/agent_cards/strategy_agent.json @@ -1,7 +1,7 @@ { "name": "StrategyAgent", "display_name": "Strategy Agent", - "url": "http://localhost:10004/", + "url": "http://localhost:10006/", "description": "LLM-driven strategy composer that turns market features into normalized trade instructions. Includes a simple runtime for demo and testing.", "capabilities": { "streaming": true, diff --git a/python/pyproject.toml b/python/pyproject.toml index 0fc093590..bcdc4f525 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -29,6 +29,7 @@ dependencies = [ "aiofiles>=24.1.0", "crawl4ai>=0.7.4", "ccxt>=4.5.15", + "httpx[socks]>=0.28.1", ] [project.optional-dependencies] diff --git a/python/scripts/launch.py b/python/scripts/launch.py index 054a61805..76919895f 100644 --- a/python/scripts/launch.py +++ b/python/scripts/launch.py @@ -40,7 +40,7 @@ # ] AGENTS = [ RESEARCH_AGENT_NAME, - AUTO_TRADING_AGENT_NAME, + # AUTO_TRADING_AGENT_NAME, # Deprecated - agent card removed NEWS_AGENT_NAME, STRATEGY_AGENT_NAME, ] diff --git a/python/third_party/TradingAgents/pyproject.toml b/python/third_party/TradingAgents/pyproject.toml index 6a25df81d..e51a7943a 100644 --- a/python/third_party/TradingAgents/pyproject.toml +++ b/python/third_party/TradingAgents/pyproject.toml @@ -35,7 +35,8 @@ dependencies = [ "tushare>=1.4.21", "typing-extensions>=4.14.0", "yfinance>=0.2.63", - "valuecell" + "valuecell", + "httpx[socks]>=0.28.1", ] [tool.uv.sources] diff --git a/python/third_party/TradingAgents/uv.lock b/python/third_party/TradingAgents/uv.lock index 395fb7487..492cdb929 100644 --- a/python/third_party/TradingAgents/uv.lock +++ b/python/third_party/TradingAgents/uv.lock @@ -1719,6 +1719,9 @@ wheels = [ http2 = [ { name = "h2" }, ] +socks = [ + { name = "socksio" }, +] [[package]] name = "httpx-sse" @@ -4468,19 +4471,20 @@ wheels = [ [[package]] name = "pylance" -version = "0.38.2" +version = "0.38.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, { name = "pyarrow" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/83/2d/1564c2fdc4a05ae50395529e231e6bba8170de814598b6e623de0bf58dfe/pylance-0.38.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:4fe7416adac1acc503374a7f52999283ff714cfc0a5d6cc87b470721593548bf", size = 42215988, upload-time = "2025-10-08T18:20:31.506Z" }, - { url = "https://files.pythonhosted.org/packages/f2/f8/c3c2944573be5cf4b3c789d2474b7feffe2045ea788476ff285461c44f0e/pylance-0.38.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50fe486caeff35ce71084eb73539a04c20fc9bbecaa8476aeb8036aeaa4a2175", size = 44348573, upload-time = "2025-10-08T04:49:25.058Z" }, - { url = "https://files.pythonhosted.org/packages/75/a8/e6165c016d04cf31f7206cefc78da878ba9c05d877c4640164c4e7d7db01/pylance-0.38.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3ec9a946bb4de2a2179424ca6ff98f0200545844a6e562f13ca962647ef4117", size = 48214643, upload-time = "2025-10-08T04:54:02.152Z" }, - { url = "https://files.pythonhosted.org/packages/c2/ba/73851dc80dc690d2501dbbe582de7adca5a3fb08023af7aa931c4f153c0a/pylance-0.38.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:17c916d0cd0225766747733870f666ee61f9830a007be6c74b299999e2cba211", size = 44387342, upload-time = "2025-10-08T04:50:44.961Z" }, - { url = "https://files.pythonhosted.org/packages/fe/ec/2f059607ae28b1c363422a223ce08e2771e5c3c685390fd595e6e3b54b3d/pylance-0.38.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:bbd4cc7ac93cfea28c4366038c904474c3b36cbc6b6f05212d933a85f7ca0ff6", size = 48193224, upload-time = "2025-10-08T04:53:48.562Z" }, - { url = "https://files.pythonhosted.org/packages/67/83/68626c152fbcf6879c3203a2eea065c2b4eb0b923b81a7e50f6e8c80b88e/pylance-0.38.2-cp39-abi3-win_amd64.whl", hash = "sha256:a55023cdc34518acaf6dc8cc922e6627cc8d8757e45beafeb4da1ac25ca70908", size = 49559094, upload-time = "2025-10-08T18:27:17.688Z" }, + { url = "https://files.pythonhosted.org/packages/3d/fd/1584088917524acd974c86a1addaa679e7201b9073cfed3ef7e495315fd7/pylance-0.38.3-cp39-abi3-macosx_10_15_x86_64.whl", hash = "sha256:f6c42a8b1c3ffa3ab55cc608351775d537b96ab0fa283075a96495fdf47e1920", size = 46482483, upload-time = "2025-10-28T12:01:46.109Z" }, + { url = "https://files.pythonhosted.org/packages/f0/f9/5e5bcd547c7cc7a126fec2b32ebc42c22ecad3fcd73620793904bc8667bb/pylance-0.38.3-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:14329be831e3de21149f40a1437ad4bc6e5b7427e019586c0115fe05d2f016c1", size = 42459485, upload-time = "2025-10-28T11:38:51.793Z" }, + { url = "https://files.pythonhosted.org/packages/2c/69/8ccd88ca597bb5c1f0b8f8ec4491cafbe388ef867328c07b29fb467f1e34/pylance-0.38.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77a872b99c9c4b6a84ff6f4254fd9405ec7672413edd3b4ce3b4ed232fdf1ac3", size = 44575863, upload-time = "2025-10-28T11:34:54.118Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b4/78edb7e2c5a2e604b035a38d35857e5cdb242cec4171f386eed0920941c4/pylance-0.38.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88c87a0ada27856e9917dbf9eb59879891339a37d0cfb05b5df81caab2b11f31", size = 48011877, upload-time = "2025-10-28T11:38:20.902Z" }, + { url = "https://files.pythonhosted.org/packages/19/9b/45539c0724be34455655e70a4a6a3123ad338719687391dc037db0f7462d/pylance-0.38.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:b6a3c786f80d0bf8a2da379b89211d3ad9f3c723394bd9e78e5a234d65701b59", size = 44592430, upload-time = "2025-10-28T11:35:19.708Z" }, + { url = "https://files.pythonhosted.org/packages/6d/f3/8bed7707fc4b5bc6032ba1b7af8f2211af9d39f6fe925ae78961a14c85c7/pylance-0.38.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a169b2a254b8cb26399a0cc570784995280d2900d0ed8e50fbd3c38f21a3af76", size = 48024285, upload-time = "2025-10-28T11:38:53.192Z" }, + { url = "https://files.pythonhosted.org/packages/06/49/84966b5e28648740b157bd90e7a89ec99a835cb66a0a619e41c60ec71073/pylance-0.38.3-cp39-abi3-win_amd64.whl", hash = "sha256:ea106742c2032d3ed8aa9232923eed2054aabf683a769ddc564c285ce20b950d", size = 49747295, upload-time = "2025-10-28T11:56:25.262Z" }, ] [[package]] @@ -5266,6 +5270,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a", size = 93002, upload-time = "2021-11-16T18:38:34.792Z" }, ] +[[package]] +name = "socksio" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/5c/48a7d9495be3d1c651198fd99dbb6ce190e2274d0f28b9051307bdec6b85/socksio-1.0.0.tar.gz", hash = "sha256:f88beb3da5b5c38b9890469de67d0cb0f9d494b78b106ca1845f96c10b91c4ac", size = 19055, upload-time = "2020-04-17T15:50:34.664Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/37/c3/6eeb6034408dac0fa653d126c9204ade96b819c936e136c5e8a6897eee9c/socksio-1.0.0-py3-none-any.whl", hash = "sha256:95dc1f15f9b34e8d7b16f06d74b8ccf48f609af32ab33c608d08761c5dcbb1f3", size = 12763, upload-time = "2020-04-17T15:50:31.878Z" }, +] + [[package]] name = "soupsieve" version = "2.8" @@ -5592,6 +5605,7 @@ dependencies = [ { name = "eodhd" }, { name = "feedparser" }, { name = "finnhub-python" }, + { name = "httpx", extra = ["socks"] }, { name = "langchain-anthropic" }, { name = "langchain-community" }, { name = "langchain-core" }, @@ -5627,6 +5641,7 @@ requires-dist = [ { name = "eodhd", specifier = ">=1.0.32" }, { name = "feedparser", specifier = ">=6.0.11" }, { name = "finnhub-python", specifier = ">=2.4.23" }, + { name = "httpx", extras = ["socks"], specifier = ">=0.28.1" }, { name = "langchain-anthropic", specifier = ">=0.3.15" }, { name = "langchain-community", specifier = ">=0.3.25" }, { name = "langchain-core", specifier = ">=0.3.65" }, @@ -5896,6 +5911,7 @@ dependencies = [ { name = "crawl4ai" }, { name = "edgartools" }, { name = "fastapi" }, + { name = "httpx", extra = ["socks"] }, { name = "loguru" }, { name = "markdown" }, { name = "pydantic" }, @@ -5921,6 +5937,7 @@ requires-dist = [ { name = "diff-cover", marker = "extra == 'dev'", specifier = ">=9.0.0" }, { name = "edgartools", specifier = ">=4.12.2" }, { name = "fastapi", specifier = ">=0.104.0" }, + { name = "httpx", extras = ["socks"], specifier = ">=0.28.1" }, { name = "loguru", specifier = ">=0.7.3" }, { name = "markdown", specifier = ">=3.9" }, { name = "pydantic", specifier = ">=2.0.0" }, diff --git a/python/third_party/ai-hedge-fund/pyproject.toml b/python/third_party/ai-hedge-fund/pyproject.toml index 1a983579f..034e209a7 100644 --- a/python/third_party/ai-hedge-fund/pyproject.toml +++ b/python/third_party/ai-hedge-fund/pyproject.toml @@ -22,10 +22,10 @@ dependencies = [ "questionary>=2.1.0,<3", "rich>=13.9.4,<14", "langchain-google-genai>=2.0.11,<3", -# "fastapi[standard]>=0.104.0,<0.105", + # "fastapi[standard]>=0.104.0,<0.105", "fastapi-cli>=0.0.7,<0.0.8", "pydantic>=2.4.2,<3", - "httpx>=0.28.0,<0.29.0", + "httpx[socks]>=0.28.0,<0.29.0", "sqlalchemy>=2.0.22,<3", "alembic>=1.12.0,<2", "langchain-gigachat>=0.3.12,<0.4", diff --git a/python/third_party/ai-hedge-fund/uv.lock b/python/third_party/ai-hedge-fund/uv.lock index b87447c00..8315e9f1f 100644 --- a/python/third_party/ai-hedge-fund/uv.lock +++ b/python/third_party/ai-hedge-fund/uv.lock @@ -74,7 +74,7 @@ dependencies = [ { name = "alembic" }, { name = "colorama" }, { name = "fastapi-cli" }, - { name = "httpx" }, + { name = "httpx", extra = ["socks"] }, { name = "langchain" }, { name = "langchain-anthropic" }, { name = "langchain-deepseek" }, @@ -110,7 +110,7 @@ requires-dist = [ { name = "alembic", specifier = ">=1.12.0,<2" }, { name = "colorama", specifier = ">=0.4.6,<0.5" }, { name = "fastapi-cli", specifier = ">=0.0.7,<0.0.8" }, - { name = "httpx", specifier = ">=0.28.0,<0.29.0" }, + { name = "httpx", extras = ["socks"], specifier = ">=0.28.0,<0.29.0" }, { name = "langchain", specifier = ">=0.3.7,<0.4" }, { name = "langchain-anthropic", specifier = "==0.3.5" }, { name = "langchain-deepseek", specifier = ">=0.1.2,<0.2" }, @@ -1549,6 +1549,9 @@ wheels = [ http2 = [ { name = "h2" }, ] +socks = [ + { name = "socksio" }, +] [[package]] name = "httpx-sse" @@ -3272,19 +3275,20 @@ wheels = [ [[package]] name = "pylance" -version = "0.38.2" +version = "0.38.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, { name = "pyarrow" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/83/2d/1564c2fdc4a05ae50395529e231e6bba8170de814598b6e623de0bf58dfe/pylance-0.38.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:4fe7416adac1acc503374a7f52999283ff714cfc0a5d6cc87b470721593548bf", size = 42215988, upload-time = "2025-10-08T18:20:31.506Z" }, - { url = "https://files.pythonhosted.org/packages/f2/f8/c3c2944573be5cf4b3c789d2474b7feffe2045ea788476ff285461c44f0e/pylance-0.38.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50fe486caeff35ce71084eb73539a04c20fc9bbecaa8476aeb8036aeaa4a2175", size = 44348573, upload-time = "2025-10-08T04:49:25.058Z" }, - { url = "https://files.pythonhosted.org/packages/75/a8/e6165c016d04cf31f7206cefc78da878ba9c05d877c4640164c4e7d7db01/pylance-0.38.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3ec9a946bb4de2a2179424ca6ff98f0200545844a6e562f13ca962647ef4117", size = 48214643, upload-time = "2025-10-08T04:54:02.152Z" }, - { url = "https://files.pythonhosted.org/packages/c2/ba/73851dc80dc690d2501dbbe582de7adca5a3fb08023af7aa931c4f153c0a/pylance-0.38.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:17c916d0cd0225766747733870f666ee61f9830a007be6c74b299999e2cba211", size = 44387342, upload-time = "2025-10-08T04:50:44.961Z" }, - { url = "https://files.pythonhosted.org/packages/fe/ec/2f059607ae28b1c363422a223ce08e2771e5c3c685390fd595e6e3b54b3d/pylance-0.38.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:bbd4cc7ac93cfea28c4366038c904474c3b36cbc6b6f05212d933a85f7ca0ff6", size = 48193224, upload-time = "2025-10-08T04:53:48.562Z" }, - { url = "https://files.pythonhosted.org/packages/67/83/68626c152fbcf6879c3203a2eea065c2b4eb0b923b81a7e50f6e8c80b88e/pylance-0.38.2-cp39-abi3-win_amd64.whl", hash = "sha256:a55023cdc34518acaf6dc8cc922e6627cc8d8757e45beafeb4da1ac25ca70908", size = 49559094, upload-time = "2025-10-08T18:27:17.688Z" }, + { url = "https://files.pythonhosted.org/packages/3d/fd/1584088917524acd974c86a1addaa679e7201b9073cfed3ef7e495315fd7/pylance-0.38.3-cp39-abi3-macosx_10_15_x86_64.whl", hash = "sha256:f6c42a8b1c3ffa3ab55cc608351775d537b96ab0fa283075a96495fdf47e1920", size = 46482483, upload-time = "2025-10-28T12:01:46.109Z" }, + { url = "https://files.pythonhosted.org/packages/f0/f9/5e5bcd547c7cc7a126fec2b32ebc42c22ecad3fcd73620793904bc8667bb/pylance-0.38.3-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:14329be831e3de21149f40a1437ad4bc6e5b7427e019586c0115fe05d2f016c1", size = 42459485, upload-time = "2025-10-28T11:38:51.793Z" }, + { url = "https://files.pythonhosted.org/packages/2c/69/8ccd88ca597bb5c1f0b8f8ec4491cafbe388ef867328c07b29fb467f1e34/pylance-0.38.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77a872b99c9c4b6a84ff6f4254fd9405ec7672413edd3b4ce3b4ed232fdf1ac3", size = 44575863, upload-time = "2025-10-28T11:34:54.118Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b4/78edb7e2c5a2e604b035a38d35857e5cdb242cec4171f386eed0920941c4/pylance-0.38.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88c87a0ada27856e9917dbf9eb59879891339a37d0cfb05b5df81caab2b11f31", size = 48011877, upload-time = "2025-10-28T11:38:20.902Z" }, + { url = "https://files.pythonhosted.org/packages/19/9b/45539c0724be34455655e70a4a6a3123ad338719687391dc037db0f7462d/pylance-0.38.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:b6a3c786f80d0bf8a2da379b89211d3ad9f3c723394bd9e78e5a234d65701b59", size = 44592430, upload-time = "2025-10-28T11:35:19.708Z" }, + { url = "https://files.pythonhosted.org/packages/6d/f3/8bed7707fc4b5bc6032ba1b7af8f2211af9d39f6fe925ae78961a14c85c7/pylance-0.38.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a169b2a254b8cb26399a0cc570784995280d2900d0ed8e50fbd3c38f21a3af76", size = 48024285, upload-time = "2025-10-28T11:38:53.192Z" }, + { url = "https://files.pythonhosted.org/packages/06/49/84966b5e28648740b157bd90e7a89ec99a835cb66a0a619e41c60ec71073/pylance-0.38.3-cp39-abi3-win_amd64.whl", hash = "sha256:ea106742c2032d3ed8aa9232923eed2054aabf683a769ddc564c285ce20b950d", size = 49747295, upload-time = "2025-10-28T11:56:25.262Z" }, ] [[package]] @@ -3959,6 +3963,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a", size = 93002, upload-time = "2021-11-16T18:38:34.792Z" }, ] +[[package]] +name = "socksio" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/5c/48a7d9495be3d1c651198fd99dbb6ce190e2274d0f28b9051307bdec6b85/socksio-1.0.0.tar.gz", hash = "sha256:f88beb3da5b5c38b9890469de67d0cb0f9d494b78b106ca1845f96c10b91c4ac", size = 19055, upload-time = "2020-04-17T15:50:34.664Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/37/c3/6eeb6034408dac0fa653d126c9204ade96b819c936e136c5e8a6897eee9c/socksio-1.0.0-py3-none-any.whl", hash = "sha256:95dc1f15f9b34e8d7b16f06d74b8ccf48f609af32ab33c608d08761c5dcbb1f3", size = 12763, upload-time = "2020-04-17T15:50:31.878Z" }, +] + [[package]] name = "soupsieve" version = "2.8" @@ -4379,6 +4392,7 @@ dependencies = [ { name = "crawl4ai" }, { name = "edgartools" }, { name = "fastapi" }, + { name = "httpx", extra = ["socks"] }, { name = "loguru" }, { name = "markdown" }, { name = "pydantic" }, @@ -4404,6 +4418,7 @@ requires-dist = [ { name = "diff-cover", marker = "extra == 'dev'", specifier = ">=9.0.0" }, { name = "edgartools", specifier = ">=4.12.2" }, { name = "fastapi", specifier = ">=0.104.0" }, + { name = "httpx", extras = ["socks"], specifier = ">=0.28.1" }, { name = "loguru", specifier = ">=0.7.3" }, { name = "markdown", specifier = ">=3.9" }, { name = "pydantic", specifier = ">=2.0.0" }, diff --git a/python/uv.lock b/python/uv.lock index 0987c4ec1..68ec378d0 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -1201,6 +1201,9 @@ wheels = [ http2 = [ { name = "h2" }, ] +socks = [ + { name = "socksio" }, +] [[package]] name = "httpx-sse" @@ -2497,19 +2500,20 @@ wheels = [ [[package]] name = "pylance" -version = "0.38.2" +version = "0.38.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, { name = "pyarrow" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/83/2d/1564c2fdc4a05ae50395529e231e6bba8170de814598b6e623de0bf58dfe/pylance-0.38.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:4fe7416adac1acc503374a7f52999283ff714cfc0a5d6cc87b470721593548bf", size = 42215988, upload-time = "2025-10-08T18:20:31.506Z" }, - { url = "https://files.pythonhosted.org/packages/f2/f8/c3c2944573be5cf4b3c789d2474b7feffe2045ea788476ff285461c44f0e/pylance-0.38.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50fe486caeff35ce71084eb73539a04c20fc9bbecaa8476aeb8036aeaa4a2175", size = 44348573, upload-time = "2025-10-08T04:49:25.058Z" }, - { url = "https://files.pythonhosted.org/packages/75/a8/e6165c016d04cf31f7206cefc78da878ba9c05d877c4640164c4e7d7db01/pylance-0.38.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3ec9a946bb4de2a2179424ca6ff98f0200545844a6e562f13ca962647ef4117", size = 48214643, upload-time = "2025-10-08T04:54:02.152Z" }, - { url = "https://files.pythonhosted.org/packages/c2/ba/73851dc80dc690d2501dbbe582de7adca5a3fb08023af7aa931c4f153c0a/pylance-0.38.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:17c916d0cd0225766747733870f666ee61f9830a007be6c74b299999e2cba211", size = 44387342, upload-time = "2025-10-08T04:50:44.961Z" }, - { url = "https://files.pythonhosted.org/packages/fe/ec/2f059607ae28b1c363422a223ce08e2771e5c3c685390fd595e6e3b54b3d/pylance-0.38.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:bbd4cc7ac93cfea28c4366038c904474c3b36cbc6b6f05212d933a85f7ca0ff6", size = 48193224, upload-time = "2025-10-08T04:53:48.562Z" }, - { url = "https://files.pythonhosted.org/packages/67/83/68626c152fbcf6879c3203a2eea065c2b4eb0b923b81a7e50f6e8c80b88e/pylance-0.38.2-cp39-abi3-win_amd64.whl", hash = "sha256:a55023cdc34518acaf6dc8cc922e6627cc8d8757e45beafeb4da1ac25ca70908", size = 49559094, upload-time = "2025-10-08T18:27:17.688Z" }, + { url = "https://files.pythonhosted.org/packages/3d/fd/1584088917524acd974c86a1addaa679e7201b9073cfed3ef7e495315fd7/pylance-0.38.3-cp39-abi3-macosx_10_15_x86_64.whl", hash = "sha256:f6c42a8b1c3ffa3ab55cc608351775d537b96ab0fa283075a96495fdf47e1920", size = 46482483, upload-time = "2025-10-28T12:01:46.109Z" }, + { url = "https://files.pythonhosted.org/packages/f0/f9/5e5bcd547c7cc7a126fec2b32ebc42c22ecad3fcd73620793904bc8667bb/pylance-0.38.3-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:14329be831e3de21149f40a1437ad4bc6e5b7427e019586c0115fe05d2f016c1", size = 42459485, upload-time = "2025-10-28T11:38:51.793Z" }, + { url = "https://files.pythonhosted.org/packages/2c/69/8ccd88ca597bb5c1f0b8f8ec4491cafbe388ef867328c07b29fb467f1e34/pylance-0.38.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77a872b99c9c4b6a84ff6f4254fd9405ec7672413edd3b4ce3b4ed232fdf1ac3", size = 44575863, upload-time = "2025-10-28T11:34:54.118Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b4/78edb7e2c5a2e604b035a38d35857e5cdb242cec4171f386eed0920941c4/pylance-0.38.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88c87a0ada27856e9917dbf9eb59879891339a37d0cfb05b5df81caab2b11f31", size = 48011877, upload-time = "2025-10-28T11:38:20.902Z" }, + { url = "https://files.pythonhosted.org/packages/19/9b/45539c0724be34455655e70a4a6a3123ad338719687391dc037db0f7462d/pylance-0.38.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:b6a3c786f80d0bf8a2da379b89211d3ad9f3c723394bd9e78e5a234d65701b59", size = 44592430, upload-time = "2025-10-28T11:35:19.708Z" }, + { url = "https://files.pythonhosted.org/packages/6d/f3/8bed7707fc4b5bc6032ba1b7af8f2211af9d39f6fe925ae78961a14c85c7/pylance-0.38.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a169b2a254b8cb26399a0cc570784995280d2900d0ed8e50fbd3c38f21a3af76", size = 48024285, upload-time = "2025-10-28T11:38:53.192Z" }, + { url = "https://files.pythonhosted.org/packages/06/49/84966b5e28648740b157bd90e7a89ec99a835cb66a0a619e41c60ec71073/pylance-0.38.3-cp39-abi3-win_amd64.whl", hash = "sha256:ea106742c2032d3ed8aa9232923eed2054aabf683a769ddc564c285ce20b950d", size = 49747295, upload-time = "2025-10-28T11:56:25.262Z" }, ] [[package]] @@ -3230,6 +3234,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a", size = 93002, upload-time = "2021-11-16T18:38:34.792Z" }, ] +[[package]] +name = "socksio" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/5c/48a7d9495be3d1c651198fd99dbb6ce190e2274d0f28b9051307bdec6b85/socksio-1.0.0.tar.gz", hash = "sha256:f88beb3da5b5c38b9890469de67d0cb0f9d494b78b106ca1845f96c10b91c4ac", size = 19055, upload-time = "2020-04-17T15:50:34.664Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/37/c3/6eeb6034408dac0fa653d126c9204ade96b819c936e136c5e8a6897eee9c/socksio-1.0.0-py3-none-any.whl", hash = "sha256:95dc1f15f9b34e8d7b16f06d74b8ccf48f609af32ab33c608d08761c5dcbb1f3", size = 12763, upload-time = "2020-04-17T15:50:31.878Z" }, +] + [[package]] name = "soupsieve" version = "2.8" @@ -3630,6 +3643,7 @@ dependencies = [ { name = "crawl4ai" }, { name = "edgartools" }, { name = "fastapi" }, + { name = "httpx", extra = ["socks"] }, { name = "loguru" }, { name = "markdown" }, { name = "pydantic" }, @@ -3687,6 +3701,7 @@ requires-dist = [ { name = "diff-cover", marker = "extra == 'dev'", specifier = ">=9.0.0" }, { name = "edgartools", specifier = ">=4.12.2" }, { name = "fastapi", specifier = ">=0.104.0" }, + { name = "httpx", extras = ["socks"], specifier = ">=0.28.1" }, { name = "loguru", specifier = ">=0.7.3" }, { name = "markdown", specifier = ">=3.9" }, { name = "pydantic", specifier = ">=2.0.0" },