File size: 5,267 Bytes
9853396
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# Development Guide

---

## Architecture Design

AxonHub implements a bidirectional data transformation pipeline that ensures seamless communication between clients and AI providers.

<div align="center">
  <img src="../../transformation-flow.svg" alt="AxonHub Transformation Flow" width="900"/>
</div>

### Pipeline Components

| Component | Purpose | Key Features |
| --- | --- | --- |
| **Client** | Application layer | Web apps, mobile apps, API clients |
| **Inbound Transformer** | Request preprocessing | Parse, validate, normalize input |
| **Unified Request** | Core processing | Route selection, load balancing, failover |
| **Outbound Transformer** | Provider adaptation | Format conversion, protocol mapping |
| **Provider** | AI services | OpenAI, Anthropic, DeepSeek, etc. |

This architecture ensures:

-**Low Latency**: Optimized processing pipeline
- 🔄 **Auto Failover**: Seamless provider switching
- 📊 **Real-time Monitoring**: Complete request tracing
- 🛡️ **Security & Validation**: Input sanitization and output verification

## Technology Stack

### Backend Technology Stack

- **Go 1.24+**
- **Gin**
- **Ent ORM**
- **gqlgen**
- **JWT**

### Frontend Technology Stack

- **React 19**
- **TypeScript**
- **Tailwind CSS**
- **TanStack Router**
- **Zustand**

## Development Environment Setup

### Prerequisites

- Go 1.24 or higher
- Node.js 18+ and pnpm
- Git

### Clone the Project

```bash

git clone https://github.com/looplj/axonhub.git

cd axonhub

```

### Start Backend

```bash

# Option 1: Build and run directly

make build-backend

./axonhub



# Option 2: Use air for hot reload (recommended for development)

go install github.com/air-verse/air@latest

air

```

The backend server will start at `http://localhost:8090`.

### Start Frontend

In a new terminal window:

```bash

cd frontend

pnpm install

pnpm dev

```

The frontend development server will start at `http://localhost:5173`.

## Building the Project

### Build Complete Project

```bash

make build

```

This will build both backend and frontend, and embed frontend assets into the backend binary.

### Build Backend Only

```bash

make build-backend

```

### Build Frontend Only

```bash

cd frontend

pnpm build

```

## Code Generation

When changing Ent schema or GraphQL schema, regenerate generated code:

```bash

make generate

```

## Testing

### Run Backend Tests

```bash

go test ./...

```

### Run E2E Tests

```bash

bash ./scripts/e2e/e2e-test.sh

```

## Code Quality

### Run Go Linter

```bash

golangci-lint run -v

```

### Run Frontend Lint/Format

```bash

cd frontend

pnpm lint

pnpm format:check

```

## Transactions (Ent)

### When to use transactions

- Multiple writes must succeed or fail together.
- You need to ensure reads and writes are consistent within one logical operation.

### Recommended: use `AbstractService.RunInTransaction`

`RunInTransaction` will:
- Reuse the existing transaction if `ctx` already carries one.
- Otherwise start a new transaction, attach the tx-bound `*ent.Client` to `ctx`, and commit/rollback automatically.

```go

func (s *SomeService) doWork(ctx context.Context) error {

    return s.RunInTransaction(ctx, func(ctx context.Context) error {

        // ctx now carries:

        // - ent.TxFromContext(ctx) (the current tx)

        // - ent.FromContext(ctx)   (tx-bound *ent.Client)

        //

        // You can call other services and they will pick up the same tx via ctx.

        return nil

    })

}

```

### Notes

- A transaction client is not safe to share across goroutines.
- Prefer keeping the transaction scope as small as possible.

## Adding a Channel

When introducing a new provider channel, keep backend and frontend changes aligned:

1. **Extend the channel enum in the Ent schema**
   - Add the provider key to the `field.Enum("type")` list in [internal/ent/schema/channel.go](../../../internal/ent/schema/channel.go)
   - Run `make generate` to regenerate artifacts and migrations

2. **Wire the outbound transformer**
   - Update the switch in `ChannelService.buildChannel` to construct the correct outbound transformer for the new enum
   - Or add a new transformer under `internal/llm/transformer` if necessary

3. **Register provider metadata**
   - Add or extend an entry in [frontend/src/features/channels/data/config_providers.ts](../../../frontend/src/features/channels/data/config_providers.ts)
   - Keep the helper functions working by ensuring every channel type listed exists in `CHANNEL_CONFIGS`

4. **Sync the frontend schema and presentation**
   - Append the enum value to the Zod schema in [frontend/src/features/channels/data/schema.ts](../../../frontend/src/features/channels/data/schema.ts)
   - Add channel configuration to [frontend/src/features/channels/data/constants.ts](../../../frontend/src/features/channels/data/constants.ts)

5. **Add internationalization**
   - Add translation keys in both locale files:
     - [frontend/src/locales/en.json](../../../frontend/src/locales/en.json)
     - [frontend/src/locales/zh.json](../../../frontend/src/locales/zh.json)