Metadata-Version: 2.5
Name: bolt-boot
Version: 0.1.4
Summary: AI原生 FastAPI 框架，支持 Agent、可观测性、微服务
Project-URL: Homepage, https://gitee.com/wk_bo/bolt
Project-URL: Repository, https://gitee.com/wk_bo/bolt
Author-email: 程波 <17593064+wk_bo@user.noreply.gitee.com>
License: MIT
License-File: LICENSE
Keywords: agent,fastapi,llm,microservice,observability
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.11
Requires-Dist: alembic>=1.14.0
Requires-Dist: asyncpg>=0.30.0
Requires-Dist: fastapi>=0.115.0
Requires-Dist: httpx>=0.28.0
Requires-Dist: numpy>=1.26.0
Requires-Dist: prometheus-client>=0.21.0
Requires-Dist: pydantic-settings>=2.6.0
Requires-Dist: pydantic>=2.10.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: pyyaml>=6.0.0
Requires-Dist: rich>=13.9.0
Requires-Dist: sqlalchemy[asyncio]>=2.0.0
Requires-Dist: structlog>=24.4.0
Requires-Dist: tenacity>=9.0.0
Requires-Dist: typer>=0.15.0
Requires-Dist: uvicorn[standard]>=0.32.0
Provides-Extra: admin
Requires-Dist: sqladmin>=0.20.0; extra == 'admin'
Provides-Extra: agent
Requires-Dist: openai>=1.60.0; extra == 'agent'
Provides-Extra: cache
Requires-Dist: redis>=5.2.0; extra == 'cache'
Provides-Extra: dev
Requires-Dist: aiosqlite>=0.20.0; extra == 'dev'
Requires-Dist: mypy>=1.14.0; extra == 'dev'
Requires-Dist: pre-commit>=4.0.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
Requires-Dist: pytest-cov>=6.0.0; extra == 'dev'
Requires-Dist: pytest>=8.3.0; extra == 'dev'
Requires-Dist: ruff>=0.8.0; extra == 'dev'
Provides-Extra: full
Requires-Dist: aio-pika>=9.5.0; extra == 'full'
Requires-Dist: aiokafka>=0.12.0; extra == 'full'
Requires-Dist: apscheduler>=3.11.0; extra == 'full'
Requires-Dist: consulate>=1.2.0; extra == 'full'
Requires-Dist: grpcio-tools>=1.68.0; extra == 'full'
Requires-Dist: grpcio>=1.68.0; extra == 'full'
Requires-Dist: mcp<2,>=1.8; extra == 'full'
Requires-Dist: nacos-sdk-python>=0.1.12; extra == 'full'
Requires-Dist: openai>=1.60.0; extra == 'full'
Requires-Dist: opentelemetry-api>=1.28.0; extra == 'full'
Requires-Dist: opentelemetry-exporter-otlp>=1.28.0; extra == 'full'
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.50b0; extra == 'full'
Requires-Dist: opentelemetry-instrumentation-httpx>=0.50b0; extra == 'full'
Requires-Dist: opentelemetry-instrumentation-sqlalchemy>=0.50b0; extra == 'full'
Requires-Dist: opentelemetry-sdk>=1.28.0; extra == 'full'
Requires-Dist: oxygent==1.1.3; extra == 'full'
Requires-Dist: prometheus-client>=0.21.0; extra == 'full'
Requires-Dist: python-dotenv>=1.0.0; extra == 'full'
Requires-Dist: redis>=5.2.0; extra == 'full'
Requires-Dist: rocketmq-client-python>=5.0.0; extra == 'full'
Requires-Dist: sqladmin>=0.20.0; extra == 'full'
Provides-Extra: microservice
Requires-Dist: consulate>=1.2.0; extra == 'microservice'
Requires-Dist: grpcio-tools>=1.68.0; extra == 'microservice'
Requires-Dist: grpcio>=1.68.0; extra == 'microservice'
Requires-Dist: nacos-sdk-python>=0.1.12; extra == 'microservice'
Provides-Extra: mq
Requires-Dist: aio-pika>=9.5.0; extra == 'mq'
Requires-Dist: aiokafka>=0.12.0; extra == 'mq'
Requires-Dist: rocketmq-client-python>=5.0.0; extra == 'mq'
Provides-Extra: observability
Requires-Dist: opentelemetry-api>=1.28.0; extra == 'observability'
Requires-Dist: opentelemetry-exporter-otlp>=1.28.0; extra == 'observability'
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.50b0; extra == 'observability'
Requires-Dist: opentelemetry-instrumentation-httpx>=0.50b0; extra == 'observability'
Requires-Dist: opentelemetry-instrumentation-sqlalchemy>=0.50b0; extra == 'observability'
Requires-Dist: opentelemetry-sdk>=1.28.0; extra == 'observability'
Requires-Dist: prometheus-client>=0.21.0; extra == 'observability'
Provides-Extra: oxy
Requires-Dist: mcp<2,>=1.8; extra == 'oxy'
Requires-Dist: oxygent==1.1.3; extra == 'oxy'
Requires-Dist: python-dotenv>=1.0.0; extra == 'oxy'
Provides-Extra: rag
Requires-Dist: chromadb>=0.5.0; extra == 'rag'
Requires-Dist: networkx>=3.0; extra == 'rag'
Requires-Dist: pypdf>=5.0.0; extra == 'rag'
Provides-Extra: scheduler
Requires-Dist: apscheduler>=3.11.0; extra == 'scheduler'
Description-Content-Type: text/markdown

# Bolt Boot

<div align="center">

[![Python](https://img.shields.io/badge/Python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![FastAPI](https://img.shields.io/badge/FastAPI-0.115+-green.svg)](https://fastapi.tiangolo.com/)
[![License](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

**AI 原生 FastAPI 框架** - Agent、可观测性、微服务

[快速开始](#快速开始) · [功能特性](#功能特性) · [示例代码](#示例代码)

</div>

---

## 特性

| 特性 | 说明 |
|------|------|
| 🤖 **AI 原生** | Agent 框架（OxyGent 引擎驱动，ReAct 工具循环 + 多 Agent 编排） |
| 📚 **RAG 支持** | 多向量库 + 云存储加载 + 检索增强生成 |
| 📊 **可观测性** | OpenTelemetry + Prometheus + 结构化日志 |
| 🏗️ **微服务** | gRPC + 消息队列(Kafka/RabbitMQ/RocketMQ) + 服务发现 |
| 🔐 **企业级** | JWT/API Key 认证 + RBAC 权限 + 多租户 |
| ⚡ **高性能** | 异步优先，连接池，批量操作 |
| 🛠️ **开发友好** | 完善的 CLI 工具链 + 代码生成 |
| ✅ **测试友好** | pytest + 异步测试 + Mock 工具 |

---

## 快速开始

### 安装

```bash
# 完整安装（推荐）
pip install "bolt-boot[full]"

# 最小安装
pip install bolt-boot

# 按需安装
pip install "bolt-boot[agent,rag,observability]"
```

### 创建应用

```python
from bolt import App, create_app
from fastapi import APIRouter

# 方式 1：使用 App 类（推荐）
app_builder = App(
    title="My AI App",
    cors_origins=["http://localhost:3000"],
)

router = APIRouter()

@router.get("/health")
async def health():
    return {"status": "ok"}

app_builder.include_router(router)
app = app_builder.create()

# 方式 2：快速创建
app = create_app(title="Quick Start")
```

> **路由前缀**：通过 `include_router` 注册的路由默认挂在 **`/api/v1`** 前缀下
> （上例实际路径为 `/api/v1/health`）。如需去掉前缀：
> `App(title="...", api_prefix="")`。

### 运行

```bash
# 使用 uvicorn
uvicorn main:app --reload

# 使用 bolt CLI
bolt server
```

---

## 功能特性

### 🤖 AI Agent（OxyGent 引擎）

底层由 [OxyGent](https://github.com/jd-opensource/OxyGent) MAS 驱动：工具调用走完整的 ReAct 循环，多 Agent 协作开箱即用。

> **接入 DeepSeek 等国产模型**：`provider="deepseek"`（自动读
> `DEEPSEEK_API_KEY`，默认端点 `https://api.deepseek.com`）；
> 也支持 `qwen/dashscope`、`azure`、`local`（Ollama）、`custom`。

```python
from bolt.agent import BoltAgent, AgentResult, tool

class MyAgent(BoltAgent):
    def __init__(self):
        super().__init__(
            name="my_agent",
            model="gpt-4o",
            system_prompt="你是一个专业的助手",
        )

    @tool(description="搜索知识库")
    async def search_kb(self, query: str) -> str:
        return await self.kb.search(query)

    async def run(self, question: str) -> AgentResult:
        # invoke 内部由 OxyGent ReAct 循环驱动：模型自动调用工具并汇总结果
        response = await self.invoke(question)
        return AgentResult(output=response)

# 使用
agent = MyAgent()
result = await agent.run("今天天气如何？")

# 会话记忆（多轮对话）
answer = await agent.invoke("能详细说说吗？", session_id="user-1")

# 流式输出：有工具 Agent 为缓冲策略（整轮结束后输出完整答案），
# 无工具 Agent 逐段透传
async for chunk in agent.stream("讲个故事"):
    print(chunk, end="", flush=True)
```

多 Agent 编排：

```python
from bolt.agent import AgentSpec, MultiAgentSystem

mas = MultiAgentSystem(name="support")
mas.add_agent(AgentSpec(name="master", is_master=True,
                        system_prompt="你是主管，把任务委派给专员",
                        sub_agents=["order_agent"]))
mas.add_agent(AgentSpec(name="order_agent",
                        system_prompt="你是订单专员",
                        tools=[query_order]))   # 裸 async 函数即工具

result = await mas.run("查一下订单 A1001 的状态")
await mas.aclose()
```

> 📖 完整上手文档（含部署配置矩阵、A2A 跨服务协作、常见坑速查）见 [docs/OXYGENT_GUIDE.md](docs/OXYGENT_GUIDE.md)

跨进程协作（A2A）：另一台机器上的 bolt 应用只需开启 `BOLT_OXY_A2A_SERVER_ENABLED=true`，本地即可把它的 agent 当远程专员委派：

```python
mas.add_remote_agent(
    name="order_svc",
    server_url="https://order-svc.example.com/a2a",
    desc="订单域服务",
    headers={"X-A2A-Token": "共享密钥"},
)
mas.add_agent(AgentSpec(name="master", is_master=True, sub_agents=["order_svc"]))
```

### 📚 RAG 检索增强生成

```python
from bolt.rag import BoltRetriever, CloudStorageLoader

# 创建检索器
retriever = BoltRetriever(
    documents_path="./docs",
    embedding_provider="openai",
    vectorstore_backend="chroma",
)

# 索引文档
await retriever.index_documents()

# 问答
answer = await retriever.query("Bolt 支持哪些数据库？")

# 云存储支持（COS/OSS/S3/MinIO）
loader = CloudStorageLoader(
    backend="cos",
    bucket="my-bucket",
    region="ap-guangzhou",
    secret_id=os.getenv("COS_SECRET_ID"),
    secret_key=os.getenv("COS_SECRET_KEY"),
)
docs = await loader.load_directory("docs/", pattern="**/*.md")
```

### 🔐 安全认证

```python
from bolt.security import (
    JWTAuth,
    get_current_user,
    require_permission,
    TokenPayload,
)
from fastapi import Depends

# JWT 认证
auth = JWTAuth(secret_key="your-secret")
token = auth.create_access_token(
    user_id="user_123",
    roles=["admin"],
    permissions=["read", "write"],
)

# 保护端点
@app.get("/me")
async def me(user: TokenPayload = Depends(get_current_user)):
    return {"user_id": user.sub}

# 权限控制
@app.get("/admin/users")
@require_permission("admin:read")
async def list_users():
    return {"users": []}
```

### 🗄️ 数据访问

```python
from bolt.domain import BaseRepository, BaseModel

class User(BaseModel):
    __tablename__ = "users"
    username: str
    email: str

class UserRepository(BaseRepository[User]):
    pass

# 使用
async with AsyncSession(engine) as session:
    repo = UserRepository(session, User)

    # CRUD
    user = await repo.create({"username": "alice", "email": "alice@example.com"})
    users = await repo.get_all(limit=10)

    # 过滤
    users = await repo.get_by_filter(status="active")

    # 批量操作
    await repo.bulk_create([...])
```

### 📦 缓存

```python
from bolt.infrastructure import CacheService, RedisCacheBackend

cache = CacheService(backend=RedisCacheBackend("redis://localhost:6379"))

await cache.set("user:123", {"name": "Alice"}, ttl=300)
user = await cache.get("user:123")
```

---

## CLI 命令

```bash
# 创建新项目
bolt init myproject

# 运行开发服务器
bolt server --reload

# 生成代码
bolt generate crud User
bolt generate agent comment_agent --model gpt-4o

# 数据库迁移
bolt migrate up

# 运行 Agent
bolt agent run comment_agent --input "..."
```

---

## 项目结构

```
bolt/
├── core/              # 核心模块
│   ├── app.py         # 应用工厂
│   ├── config.py      # 配置管理
│   └── exceptions.py  # 异常体系
├── domain/            # 领域层
│   ├── model.py       # 领域模型
│   ├── repository.py  # 数据仓库
│   └── service.py     # 领域服务
├── infrastructure/    # 基础设施
│   ├── cache.py       # 缓存服务
│   ├── database.py    # 数据库
│   └── observability/ # 可观测性
├── api/               # API 层
│   ├── deps.py        # 依赖注入
│   └── health.py      # 健康检查
├── agent/             # AI Agent
│   ├── base.py        # Agent 基类
│   ├── memory.py      # 对话记忆
│   └── providers/     # LLM 提供者
├── rag/               # RAG 模块
│   ├── retriever.py   # 检索器
│   ├── loaders.py     # 文档加载
│   └── vectorstore.py # 向量存储
├── security/          # 安全模块
│   ├── jwt.py         # JWT 认证
│   ├── api_key.py     # API Key
│   └── permissions.py # 权限控制
└── cli/               # CLI 工具
```

---

## 配置

### 环境变量

```bash
# 应用配置
BOLT_APP_NAME=my-app
BOLT_DEBUG=false
BOLT_ENVIRONMENT=production

# 数据库
BOLT_DATABASE_URL=postgresql+asyncpg://user:pass@localhost/db

# Redis
BOLT_REDIS_URL=redis://localhost:6379/0

# LLM（OxyGent 引擎，OpenAI 兼容端点）
# provider 可选：openai / deepseek / qwen(dashscope) / azure / local(Ollama) / custom
# provider 决定读取哪个 API Key 环境变量（如 deepseek → DEEPSEEK_API_KEY）
BOLT_LLM_DEFAULT_PROVIDER=openai
BOLT_LLM_DEFAULT_MODEL=gpt-4o
BOLT_LLM_API_KEY=your-api-key

# 独立指标端口（Prometheus 抓取 /metrics，无认证，限内网）
BOLT_METRICS_SERVER_ENABLED=false
BOLT_METRICS_PORT=9090
BOLT_OXY_ES_HOSTS=

# 可观测性
BOLT_TELEMETRY_ENABLED=true
BOLT_TELEMETRY_ENDPOINT=http://localhost:4317
```

---

## 开发

```bash
# 安装开发依赖
pip install -e ".[dev]"

# 运行测试
pytest --cov=bolt

# 代码检查
ruff check bolt/
mypy bolt/
```

---

## License

[MIT](LICENSE)

---

<div align="center">

**[⬆ 回到顶部](#bolt-boot)**

</div>

## Known Issues（已知限制）

- **SSRF 防护不含重定向逐跳校验**：URL 校验覆盖私网/回环/链路本地全家族，但 302 跳转不复检，加载不可信 URL 的场景请自行限制 `follow_redirects=False`（逐跳校验在路线图中）
- **OxyGent 引擎锁定 1.1.3**：Agent 能力依赖 `oxygent==1.1.3`（Apache-2.0），其 ES 客户端钉死 `elasticsearch==7.17.12`（兼容 ES 8.x 服务端）；升级引擎需回归 Agent 测试
- **生产验证范围**：当前在单一生产项目全链路验证；欢迎反馈更多场景

## License

MIT，依赖项含 Apache-2.0 组件（oxygent / prometheus-client / grpcio / openai），致谢各上游项目
