# Feishu WebSocket Integration - Design Document

**Date**: 2026-03-17
**Author**: Sisyphus AI Agent
**Status**: Draft for Review

## Executive Summary

Add WebSocket long-connection support for Feishu bot integration, enabling internal network deployment without requiring public domain or internet-facing endpoints. The system will support both existing webhook mode and new WebSocket mode, allowing users to choose their preferred connection method.

---

## 1. Architecture Overview

### Current Architecture (Webhook Mode)

```
Feishu Cloud → Public Domain → NAT/Firewall → Internal Server
                                    └→ POST /api/feishu/webhook/:appId
```

**Limitations:**
- Requires public domain with SSL certificate
- Requires NAT/firewall port forwarding or reverse proxy
- Not suitable for pure internal network deployment

### New Architecture (WebSocket Mode)

```
Feishu Cloud ←──────── WebSocket (wss://open.feishu.cn) ──────── Internal Server
                                         ↑
Feishu Cloud → Webhook (optional backup) → Internal Server
```

**Advantages:**
- No public domain required
- No NAT/firewall configuration needed
- Direct connection from internal network to Feishu cloud
- Real-time message delivery (milliseconds vs minutes)
- Connection复用，资源效率更高

### Architecture Diagram

```
┌─────────────────────────────────────────────────────────────┐
│                     Feishu Open Platform                    │
│                  (WebSocket Event Subscription)             │
└───────────────────────┬─────────────────────────────────────┘
                        │
          ┌─────────────┴─────────────┐
          │                           │
    ┌─────▼──────┐            ┌──────▼─────┐
    │   Bot A    │            │   Bot B    │
    │ ws://.../A │            │ ws://.../B │
    └─────┬──────┘            └──────┬─────┘
          │                          │
    ┌─────▼──────────────────────────▼──────┐
    │            AuraK Server                │
    │  ┌──────────────────────────────────┐  │
    │  │      FeishuModule               │  │
    │  │  ┌────────────────────────────┐ │  │
    │  │  │  FeishuWsManager           │ │  │
    │  │  │  - per-bot connections     │ │  │
    │  │  │  - auto-reconnect         │ │  │
    │  │  │  - message routing        │ │  │
    │  │  └────────────────────────────┘ │  │
    │  │  ┌────────────────────────────┐ │  │
    │  │  │  FeishuService            │ │  │
    │  │  │  - existing logic        │ │  │
    │  │  │  - new ws connect/disconnect│ │  │
    │  │  └────────────────────────────┘ │  │
    │  │  ┌────────────────────────────┐ │  │
    │  │  │  FeishuController         │ │  │
    │  │  │  - webhook endpoints     │ │  │
    │  │  │  - ws management APIs    │ │  │
    │  │  └────────────────────────────┘ │  │
    │  └──────────────────────────────────┘  │
    └──────────────────────────────────────────┘
```

---

## 2. Implementation Plan

### 2.1 New Components

#### 2.1.1 FeishuWsManager

**Purpose**: Manage WebSocket connections for each bot

**Responsibilities:**
- Establish and maintain WebSocket connections
- Handle connection lifecycle (connect, disconnect, reconnect)
- Route incoming messages to appropriate bot handlers
- Manage connection state per bot

**Location**: `server/src/feishu/feishu-ws.manager.ts`

**Key Methods:**
```typescript
class FeishuWsManager {
  // Start WebSocket connection for a bot
  async connect(bot: FeishuBot): Promise<void>
  
  // Stop WebSocket connection for a bot
  async disconnect(botId: string): Promise<void>
  
  // Get connection status
  getStatus(botId: string): ConnectionStatus
  
  // Get all active connections
  getAllConnections(): Map<string, ConnectionStatus>
}
```

#### 2.1.2 ConnectionStatus Type

```typescript
enum ConnectionState {
  DISCONNECTED = 'disconnected',
  CONNECTING = 'connecting',
  CONNECTED = 'connected',
  ERROR = 'error'
}

interface ConnectionStatus {
  botId: string
  state: ConnectionState
  connectedAt?: Date
  lastHeartbeat?: Date
  error?: string
}
```

### 2.2 Modified Components

#### 2.2.1 FeishuService

**New Methods:**
```typescript
class FeishuService {
  // Start WebSocket connection for a bot
  async startWsConnection(botId: string): Promise<void>
  
  // Stop WebSocket connection for a bot
  async stopWsConnection(botId: string): Promise<void>
  
  // Get connection status
  async getWsStatus(botId: string): Promise<ConnectionStatus>
  
  // List all connection statuses
  async getAllWsStatuses(): Promise<ConnectionStatus[]>
}
```

#### 2.2.2 FeishuController

**New Endpoints:**
```typescript
// POST /feishu/bots/:id/ws/connect - Start WebSocket connection
// POST /feishu/bots/:id/ws/disconnect - Stop WebSocket connection  
// GET  /feishu/bots/:id/ws/status - Get connection status
// GET  /feishu/ws/status - Get all connection statuses
```

**Modified Endpoints:**
- Keep existing webhook endpoints unchanged
- Add WebSocket status indicator in bot list response

#### 2.2.3 FeishuBot Entity

**New Fields:**
```typescript
@Entity('feishu_bots')
export class FeishuBot {
  // ... existing fields ...
  
  @Column({ default: false })
  useWebSocket: boolean
  
  @Column({ nullable: true })
  wsConnectionState: string
}
```

### 2.3 Feishu SDK Integration

**Package**: `@larksuiteoapi/node-sdk`

**Installation:**
```bash
cd server && yarn add @larksuiteoapi/node-sdk
```

**Configuration:**
```typescript
import { EventDispatcher, Conf } from '@larksuiteoapi/node-sdk'

const client = new EventDispatcher({
  appId: bot.appId,
  appSecret: bot.appSecret,
  verificationToken: bot.verificationToken,
}, {
  logger: console
})
```

### 2.4 Event Handling

**Flow for WebSocket Mode:**
```
Feishu Cloud ──WebSocket──> FeishuWsManager.on('message')
                                    │
                                    ▼
                            Parse event type
                                    │
                    ┌───────────────┼───────────────┐
                    │               │               │
              im.message.   im.message.      other
              receive_v1    p2p_msg_received
                    │               │
                    ▼               ▼
            FeishuService.processChatMessage()
                                    │
                                    ▼
                            Send response via
                            FeishuService.sendTextMessage()
```

### 2.5 Configuration Changes

**Feishu Open Platform:**

Users need to configure in Feishu developer console:
1. Go to "Event Subscription" (事件与回调)
2. Select "Use long connection to receive events" (使用长连接接收事件)
3. Add event: `im.message.receive_v1`
4. **Important**: Must start local WebSocket client first before saving

---

## 3. Data Flow

### WebSocket Message Flow

```
1. User triggers connect API
       │
       ▼
2. FeishuController.connect(botId)
       │
       ▼
3. FeishuService.startWsConnection(botId)
       │
       ▼
4. FeishuWsManager.connect(bot)
       │
       ▼
5. SDK establishes WebSocket to open.feishu.cn
       │
       ▼
6. Connection established, events flow:
       │
       ├─> on('message') ──> _processEvent() ──> _handleMessage()
       │                                              │
       │                                              ▼
       │                                    FeishuService.processChatMessage()
       │                                              │
       │                                              ▼
       │                                    FeishuService.sendTextMessage() (via SDK)
       │
       ├─> on('error') ──> log error ──> trigger reconnect
       │
       └─> on('close') ──> trigger auto-reconnect
```

---

## 4. Error Handling

### Connection Errors

| Error Type | Handling |
|------------|----------|
| Network timeout | Retry with exponential backoff (max 5 attempts) |
| Invalid credentials | Mark bot as error state, notify user |
| Token expired | Refresh token, reconnect |
| Feishu server error | Wait 30s, retry |

### Auto-Reconnect Strategy

```
Initial delay: 1 second
Max delay: 60 seconds
Backoff multiplier: 2x
Max attempts: 5
Reset on successful connection
```

---

## 5. API Design

### 5.1 Connect WebSocket

```
POST /api/feishu/bots/:id/ws/connect

Response 200:
{
  "success": true,
  "botId": "bot_xxx",
  "status": "connecting"
}

Response 400:
{
  "success": false,
  "error": "Bot not found or disabled"
}
```

### 5.2 Disconnect WebSocket

```
POST /api/feishu/bots/:id/ws/disconnect

Response 200:
{
  "success": true,
  "botId": "bot_xxx",
  "status": "disconnected"
}
```

### 5.3 Get Connection Status

```
GET /api/feishu/bots/:id/ws/status

Response 200:
{
  "botId": "bot_xxx",
  "state": "connected",
  "connectedAt": "2026-03-17T10:00:00Z",
  "lastHeartbeat": "2026-03-17T10:05:00Z"
}
```

### 5.4 Get All Statuses

```
GET /api/feishu/ws/status

Response 200:
{
  "connections": [
    {
      "botId": "bot_xxx",
      "state": "connected",
      "connectedAt": "2026-03-17T10:00:00Z"
    },
    {
      "botId": "bot_yyy",
      "state": "disconnected"
    }
  ]
}
```

---

## 6. Security Considerations

1. **Credential Storage**: App ID and App Secret stored encrypted in database
2. **Connection Validation**: Verify bot belongs to authenticated user before connect
3. **Rate Limiting**: Implement per-bot message rate limiting
4. **Connection Limits**: Max 10 concurrent WebSocket connections per server instance

---

## 7. Testing Strategy

### Unit Tests
- FeishuWsManager connection lifecycle
- Message routing logic
- Error handling and reconnection

### Integration Tests
- Full WebSocket connection flow
- Message send/receive cycle
- Reconnection after network failure

### Manual Testing
- Local development without ngrok
- Verify webhook still works alongside WebSocket

---

## 8. Backward Compatibility

- **Existing webhook endpoints**: Unchanged, continue to work
- **Bot configuration**: Existing bots keep webhook mode by default
- **Migration path**: Users can switch to WebSocket anytime via API
- **Dual mode**: Both modes can run simultaneously for different bots

---

## 9. Migration Guide

### For Existing Users

1. Update AuraK to new version (with WebSocket support)
2. Install Feishu SDK: `yarn add @larksuiteoapi/node-sdk`
3. In Feishu Developer Console:
   - Start local WebSocket server
   - Change event subscription to "Use long connection"
4. Call `POST /api/feishu/bots/:id/ws/connect` to activate

---

## 10. Limitations

1. **Outbound Network Required**: Server must be able to reach `open.feishu.cn` via WebSocket
2. **Single Connection Per Bot**: Each bot needs its own WebSocket connection
3. **Feishu SDK Required**: Must install official SDK, cannot use raw WebSocket
4. **Private Feishu**: Does not support Feishu private deployment (自建飞书)

---

## 11. File Changes Summary

### New Files
- `server/src/feishu/feishu-ws.manager.ts` - WebSocket connection manager
- `server/src/feishu/dto/ws-status.dto.ts` - WebSocket status DTOs

### Modified Files
- `server/src/feishu/feishu.service.ts` - Add WS methods
- `server/src/feishu/feishu.controller.ts` - Add WS endpoints
- `server/src/feishu/entities/feishu-bot.entity.ts` - Add WS fields
- `server/src/feishu/feishu.module.ts` - Register new manager

### Dependencies
- Add: `@larksuiteoapi/node-sdk`

---

## 12. Success Criteria

- [ ] Server can establish WebSocket connection to Feishu
- [ ] Messages received via WebSocket are processed correctly
- [ ] Responses sent back to Feishu via SDK
- [ ] Auto-reconnect works after network interruption
- [ ] Webhook mode continues to work unchanged
- [ ] Both modes can coexist for different bots
- [ ] Internal network deployment works without public domain
