# 开发指南
---
## 架构设计
AxonHub 实现了一个双向数据转换管道,确保客户端与 AI 提供商之间的无缝通信。
### 管道组件
| 组件 | 用途 | 关键特性 |
| --- | --- | --- |
| **客户端** | 应用层 | Web 应用、移动应用、API 客户端 |
| **入站转换器** | 请求预处理 | 解析、验证、规范化输入 |
| **统一请求** | 核心处理 | 路由选择、负载均衡、故障转移 |
| **出站转换器** | 提供商适配 | 格式转换、协议映射 |
| **提供商** | AI 服务 | OpenAI、Anthropic、DeepSeek 等 |
该架构确保:
- ⚡ **低延迟**:优化的处理管道
- 🔄 **自动故障转移**:无缝提供商切换
- 📊 **实时监控**:完整的请求追踪
- 🛡️ **安全与验证**:输入清理与输出校验
## 技术栈
### 后端技术栈
- **Go 1.24+**
- **Gin**
- **Ent ORM**
- **gqlgen**
- **JWT**
### 前端技术栈
- **React 19**
- **TypeScript**
- **Tailwind CSS**
- **TanStack Router**
- **Zustand**
## 开发环境搭建
### 前置要求
- Go 1.24 或更高版本
- Node.js 18+ 与 pnpm
- Git
### 克隆项目
```bash
git clone https://github.com/looplj/axonhub.git
cd axonhub
```
### 启动后端
```bash
# 方式 1:直接构建并运行
make build-backend
./axonhub
# 方式 2:使用 air 热重载(推荐)
go install github.com/air-verse/air@latest
air
```
后端服务默认启动在 `http://localhost:8090`。
### 启动前端
在新的终端窗口中:
```bash
cd frontend
pnpm install
pnpm dev
```
前端开发服务器默认启动在 `http://localhost:5173`。
## 项目构建
### 构建完整项目
```bash
make build
```
该命令会构建后端与前端,并将前端产物嵌入到后端二进制文件中。
### 仅构建后端
```bash
make build-backend
```
### 仅构建前端
```bash
cd frontend
pnpm build
```
## 代码生成
当修改 Ent schema 或 GraphQL schema 后,需要重新生成代码:
```bash
make generate
```
## 测试
### 运行后端测试
```bash
go test ./...
```
### 运行 E2E 测试
```bash
bash ./scripts/e2e/e2e-test.sh
```
## 代码质量
### 运行 Go Linter
```bash
golangci-lint run -v
```
### 运行前端 Lint/格式化检查
```bash
cd frontend
pnpm lint
pnpm format:check
```
## 事务处理(Ent)
### 何时使用事务
- 多次写入需要保证“要么全部成功,要么全部失败”。
- 需要在同一个逻辑操作中保证读写一致性。
### 推荐:使用 `AbstractService.RunInTransaction`
`RunInTransaction` 会:
- 如果 `ctx` 已经携带事务,则复用当前事务。
- 否则开启新事务,将 tx 绑定的 `*ent.Client` 放入 `ctx`,并自动 commit/rollback。
```go
func (s *SomeService) doWork(ctx context.Context) error {
return s.RunInTransaction(ctx, func(ctx context.Context) error {
// ctx 现在同时携带:
// - ent.TxFromContext(ctx)(当前 tx)
// - ent.FromContext(ctx)(绑定到 tx 的 *ent.Client)
//
// 可以继续调用其它 service,它们会通过 ctx 复用同一个事务。
return nil
})
}
```
### 注意事项
- 事务 client 不适合在多个 goroutine 间共享。
- 事务作用域尽量保持小,并避免在事务内执行耗时 I/O。
## 添加新的 Channel
新增渠道时需要同时关注后端与前端的改动:
1. **在 Ent Schema 中扩展枚举**
- 在 [internal/ent/schema/channel.go](../../../internal/ent/schema/channel.go) 的 `field.Enum("type")` 列表里添加新的渠道标识
- 执行 `make generate` 以生成代码与迁移
2. **在业务层构造 Transformer**
- 在 `ChannelService.buildChannel` 的 switch 中为新枚举返回合适的 outbound transformer
- 必要时在 `internal/llm/transformer` 下实现新的 transformer
3. **注册 Provider 元数据**
- 在 [frontend/src/features/channels/data/config_providers.ts](../../../frontend/src/features/channels/data/config_providers.ts) 添加或扩展 Provider 配置
- 确保 `channelTypes` 中引用的渠道都已经在 `CHANNEL_CONFIGS` 中存在
4. **同步前端的 schema 与展示**
- 将枚举值加入 [frontend/src/features/channels/data/schema.ts](../../../frontend/src/features/channels/data/schema.ts) 的 Zod schema
- 在 [frontend/src/features/channels/data/constants.ts](../../../frontend/src/features/channels/data/constants.ts) 中添加渠道配置
5. **添加国际化**
- 在两个 locale 文件中补充翻译:
- [frontend/src/locales/en.json](../../../frontend/src/locales/en.json)
- [frontend/src/locales/zh.json](../../../frontend/src/locales/zh.json)