This document covers FinchBot development environment setup, testing, code quality standards, and project structure.
FinchBot uses uv for dependency management and virtual environment isolation.
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh# Gitee (recommended for users in China)
git clone https://gitee.com/xt765/FinchBot.git
# or GitHub
git clone https://github.com/xt765/FinchBot.git
cd finchbotProduction (regular users):
uv syncDevelopment (contributors):
uv sync --extra devNote:
uv syncinstalls production dependencies--extra devadditionally installs dev tools: pytest, ruff, basedpyright- The embedding model (~95MB) will be automatically downloaded on first run to
.models/fastembed/, no manual intervention required.
flowchart LR
classDef step fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,rx:10,ry:10;
A["1. Install uv"]:::step --> B["2. Clone Repository"]:::step
B --> C["3. uv sync --extra dev"]:::step
C --> D["4. finchbot config"]:::step
D --> E["5. Start Development"]:::step
uv run pytestuv run pytest --cov=src --cov-report=htmlView htmlcov/index.html report.
# Test specific file
uv run pytest tests/test_memory.py
# Test specific function
uv run pytest tests/test_memory.py::test_remember
# Verbose output
uv run pytest -v tests/tests/
test_agent.py # Agent related tests
test_memory.py # Memory system tests
test_tools.py # Tool tests
test_config.py # Configuration tests
conftest.py # Test configuration and fixtures
uv run ruff format .uv run ruff check .uv run basedpyright srcflowchart TD
classDef startEnd fill:#ffebee,stroke:#c62828,stroke-width:2px,color:#b71c1c;
classDef process fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1;
classDef decision fill:#fff9c4,stroke:#fbc02d,stroke-width:2px,color:#f57f17;
A([Write Code]):::startEnd --> B[ruff format]:::process
B --> C{Format OK?}:::decision
C -->|No| B
C -->|Yes| D[ruff check]:::process
D --> E{Lint Pass?}:::decision
E -->|No| F[Fix Issues]:::process
F --> D
E -->|Yes| G[basedpyright]:::process
G --> H{Types OK?}:::decision
H -->|No| I[Fix Types]:::process
I --> G
H -->|Yes| J[pytest]:::process
J --> K{Tests Pass?}:::decision
K -->|No| L[Fix Tests]:::process
L --> J
K -->|Yes| M([Commit Code]):::startEnd
Create .pre-commit-config.yaml:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-formatfinchbot/
src/finchbot/ # Source code
agent/ # Agent logic
core.py # Agent creation and execution
factory.py # AgentFactory
context.py # ContextBuilder
skills.py # SkillsLoader
capabilities.py # CapabilitiesBuilder
tools/ # Agent tools
background.py # Background task tools
cron.py # Scheduled task tools
streaming.py # Progress streaming
memory/ # Memory system
manager.py # MemoryManager
types.py # Type definitions
services/ # Service layer
storage/ # Storage layer
tools/ # Tool collection
base.py # FinchTool base class
factory.py # ToolFactory
registry.py # ToolRegistry
*.py # Tool implementations
channels/ # Multi-platform messaging
base.py # BaseChannel
bus.py # MessageBus
manager.py # ChannelManager
webhook_server.py # Webhook Server (FastAPI)
cli/ # Command line interface
chat_session.py
config_manager.py
ui.py
config/ # Configuration management
loader.py
schema.py
constants.py # Unified constants definition
i18n/ # Internationalization
loader.py # Language loader
locales/
providers/ # LLM providers
factory.py
mcp/ # MCP protocol support
client.py # MCP client
loader.py # Tool loader
cron/ # Scheduled task service
service.py # CronService
selector.py # CronSelector (interactive UI)
heartbeat/ # Heartbeat service
service.py # HeartbeatService
sessions/ # Session management
utils/ # Utility functions
cache.py # Generic cache base class
logger.py
model_downloader.py
tests/ # Test directory
docs/ # Documentation
zh-CN/ # Chinese docs
en-US/ # English docs
.models/ # Local model cache (auto-generated)
pyproject.toml # Project configuration
uv.lock # Dependency lock
FinchBot uses Runtime Lazy Loading strategy for large file dependencies:
flowchart TD
classDef startEnd fill:#ffebee,stroke:#c62828,stroke-width:2px,color:#b71c1c;
classDef process fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1;
classDef decision fill:#fff9c4,stroke:#fbc02d,stroke-width:2px,color:#f57f17;
A([uv sync]):::startEnd --> B[Install Python deps only]:::process
B --> C([finchbot chat]):::startEnd
C --> D{Model exists?}:::decision
D -->|Yes| E([Start directly]):::startEnd
D -->|No| F[Detect network]:::process
F --> G{China network?}:::decision
G -->|Yes| H[Use hf-mirror.com]:::process
G -->|No| I[Use Hugging Face]:::process
H --> J[Download model]:::process
I --> J
J --> E
- Install Phase:
uv synconly installs Python dependencies, not the model. - Runtime Phase: When user runs
finchbot chat:- System checks
.models/fastembeddirectory. - If model doesn't exist, automatically selects best mirror (China/International) and downloads.
- After download, seamlessly enters the application.
- System checks
This design avoids build isolation issues and ensures good download experience for users in China.
Tool registration uses single-lock pattern for thread-safe lazy loading:
def _register_default_tools() -> None:
global _default_tools_registered
if _default_tools_registered:
return
with _tools_registration_lock:
if _default_tools_registered:
return
# Actual registration logic...
_default_tools_registered = TrueFinchBot uses asyncio + ThreadPoolExecutor for concurrent initialization:
| Task | Duration | Concurrent |
|---|---|---|
| LLM Model Init | ~2-5s | |
| SQLite Connection | ~0.1s | |
| Workspace Check | ~0.1s | |
| Tool Creation | ~0.5s |
# Enable DEBUG logging
finchbot -vv chat# tests/test_tools.py
from finchbot.tools.filesystem import ReadFileTool
def test_read_file():
tool = ReadFileTool()
result = tool._run(file_path="test.txt")
assert result is not None- Create
test_*.pyfile intests/directory - Write tests using
pytestframework - Run
uv run pytestto verify