← Back to Plugins
Tools

Yeizi Openclaw

chungeplus By chungeplus 👁 2 views ▲ 0 votes

yeizi-openclaw-plugin

GitHub

Install

npm install
npm

Configuration Example

{
    "type": "message",
    "text": "็”จๆˆทๆถˆๆฏๅ†…ๅฎน",
    "from": "user_xxx",
    "to": "yeizi",
    "messageId": "1700000000000",
    "chatType": "dm"
}

README

# Yeizi Channel ๆ’ไปถๅผ€ๅ‘้œ€ๆฑ‚ๆ–‡ๆกฃ

## 1. ้กน็›ฎๆฆ‚่ฟฐ

### 1.1 ้กน็›ฎๅ็งฐ

Yeizi Channel ๆ’ไปถ

### 1.2 ้กน็›ฎ็›ฎๆ ‡

ๅผ€ๅ‘ไธ€ไธชๅŸบไบŽ Web ็š„ OpenClaw ๆ’ไปถ็ณป็ปŸ๏ผŒๅŒ…ๅซ๏ผš

- **Web ็ซฏ**๏ผšๆไพ›็”จๆˆทๅฏน่ฏ็•Œ้ขๅ’ŒๅŽ็ซฏๆœๅŠก๏ผˆ้‰ดๆƒใ€WebSocket ้€šไฟก๏ผ‰
- **OpenClaw ๆ’ไปถ**๏ผšไฝœไธบ OpenClaw ็š„ channel ๆ’ไปถ๏ผŒไธŽ Web ๅŽ็ซฏๅปบ็ซ‹่ฟžๆŽฅๅนถๅค„็†ๆถˆๆฏ

### 1.3 ้กน็›ฎ่Œƒๅ›ด

**ๅฝ“ๅ‰็‰ˆๆœฌ๏ผšๅ•ๆ™บ่ƒฝไฝ“ใ€ๅ•่ดฆๆˆทใ€ๅ•็”จๆˆท**

- **ๅ•ๆ™บ่ƒฝไฝ“**๏ผšๅชๆ”ฏๆŒไธ€ไธชๆ™บ่ƒฝไฝ“๏ผˆ้ป˜่ฎค `main`๏ผ‰
- **ๅ•่ดฆๆˆท**๏ผšๅชๆ”ฏๆŒไธ€ไธช่ดฆๆˆท๏ผˆ้ป˜่ฎค `default`๏ผ‰
- **ๅ•็”จๆˆท**๏ผš็”จๆˆทๆ— ้œ€็™ปๅฝ•๏ผŒๅ‰็ซฏ่‡ชๅŠจ็”Ÿๆˆ็”จๆˆทๆ ‡่ฏ†

### 1.4 ๆ ธๅฟƒๅŠŸ่ƒฝ

็”จๆˆท้€š่ฟ‡ Web ็•Œ้ข่พ“ๅ…ฅๆถˆๆฏ๏ผŒๆถˆๆฏ้€š่ฟ‡ WebSocket ไผ ้€’็ป™ OpenClaw ๆ’ไปถ๏ผŒๆ’ไปถๅ†ไธŽ OpenClaw ่ฟ›่กŒ้€šไฟก๏ผŒๆœ€็ปˆๅฐ† AI ๅ›žๅค่ฟ”ๅ›ž็ป™็”จๆˆทใ€‚

## 2. ็ณป็ปŸๆžถๆž„

### 2.1 ๆ•ดไฝ“ๆžถๆž„ๅ›พ

```
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                         ็”จๆˆทๆต่งˆๅ™จ                               โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚                    Web ๅ‰็ซฏ๏ผˆๅฏน่ฏ้กต้ข๏ผ‰                      โ”‚  โ”‚
โ”‚  โ”‚  โ€ข ็”จๆˆท่พ“ๅ…ฅๆถˆๆฏ                                             โ”‚  โ”‚
โ”‚  โ”‚  โ€ข ๆ˜พ็คบ AI ๅ›žๅค                                             โ”‚  โ”‚
โ”‚  โ”‚  โ€ข WebSocket ๅฎžๆ—ถ้€šไฟก                                        โ”‚  โ”‚
โ”‚  โ”‚  โ€ข ๆ’ไปถ้…็ฝฎๆ˜พ็คบ                                             โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
           โ–ฒ                                    โ”‚
           โ”‚                                    โ”‚ WebSocket
     AI ๅ›žๅค                                    โ”‚ ็”จๆˆทๆถˆๆฏ
           โ”‚                                    โ–ผ
           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ
                                 โ”‚
                                 โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                          Web ๅŽ็ซฏๆœๅŠก                            โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  โ€ข ้‰ดๆƒๆœๅŠก๏ผˆAppKey + AppSecret๏ผ‰                               โ”‚
โ”‚  โ€ข WebSocket ๆœๅŠก                                              โ”‚
โ”‚  โ€ข ๆถˆๆฏ่ทฏ็”ฑ                                                    โ”‚
โ”‚  โ€ข ้…็ฝฎๆŸฅ่ฏข API (/api/config)                                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
           โ–ฒ                                    โ”‚
           โ”‚                                    โ”‚ WebSocket
     AI ๅ›žๅค                                    โ”‚ ๆถˆๆฏ่ฝฌๅ‘
           โ”‚                                    โ–ผ
           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ
                                 โ”‚
                                 โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                        OpenClaw ๆ’ไปถ                            โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  โ€ข WebSocket ๅฎขๆˆท็ซฏ๏ผˆๆŽฅๆ”ถ/ๅ‘้€ๆถˆๆฏ๏ผ‰                             โ”‚
โ”‚  โ€ข dispatchReplyWithBufferedBlockDispatcher                     โ”‚
โ”‚  โ€ข ChannelDock ้…็ฝฎ                                            โ”‚
โ”‚  โ€ข YeiziDock ๅฎšไน‰ๆ’ไปถ่ƒฝๅŠ›                                       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                 โ”‚
                            AI ๅ›žๅค
                         (OpenClaw API)
```

### 2.2 ๆถˆๆฏๆต็จ‹

#### ๆถˆๆฏๅ‘้€ๆต็จ‹๏ผˆ็”จๆˆท โ†’ OpenClaw๏ผ‰

```
็”จๆˆท่พ“ๅ…ฅๆถˆๆฏ
    โ†“
ๅ‰็ซฏ้€š่ฟ‡ WebSocket ๅ‘้€ๆถˆๆฏๅˆฐๅŽ็ซฏ
    โ†“
ๅŽ็ซฏ่ฝฌๅ‘ๆถˆๆฏๅˆฐ OpenClaw ๆ’ไปถ
    โ†“
ๆ’ไปถๆž„ๅปบ ctxPayload
    โ†“
่ฐƒ็”จ finalizeInboundContext
    โ†“
่ฐƒ็”จ dispatchReplyWithBufferedBlockDispatcher ่งฆๅ‘ AI ๅค„็†
```

#### ๆถˆๆฏๅ›žๅคๆต็จ‹๏ผˆOpenClaw โ†’ ็”จๆˆท๏ผ‰

```
OpenClaw AI ๅค„็†ๅฎŒๆˆ
    โ†“
dispatchReplyWithBufferedBlockDispatcher ็š„ deliver ๅ›ž่ฐƒ่งฆๅ‘
    โ†“
ๆ’ไปถ้€š่ฟ‡ WebSocket ๅ‘้€ๅ›žๅคๅˆฐๅŽ็ซฏ
    โ†“
ๅŽ็ซฏ้€š่ฟ‡ WebSocket ๆŽจ้€ๅˆฐๅ‰็ซฏ
    โ†“
ๅ‰็ซฏๆ˜พ็คบ AI ๅ›žๅค
```

## 3. ๅฎ‰่ฃ…ไธŽ้…็ฝฎ

### 3.1 ็Žฏๅขƒ่ฆๆฑ‚

- **Node.js**๏ผš>= 18.0.0
- **OpenClaw**๏ผš>= 2026.3.12

### 3.2 ๅฎ‰่ฃ…ๆญฅ้ชค

#### ๆญฅ้ชค 1๏ผšๆž„ๅปบๆ’ไปถ

```bash
cd yeizi-plugin
npm install
npm run build
```

#### ๆญฅ้ชค 2๏ผšๅฎ‰่ฃ…ๆ’ไปถ

```bash
cd yeizi-plugin/scripts
node setup.mjs <app_key> <app_secret> [base_url] [websocket_url]
```

็คบไพ‹๏ผš

```bash
node setup.mjs yeizi-app-key-2026 yeizi-app-secret-2026 http://localhost:3000 ws://localhost:3000
```

#### ๆญฅ้ชค 3๏ผš้‡ๅฏ OpenClaw

ๅฎ‰่ฃ…ๅฎŒๆˆๅŽ้œ€่ฆ้‡ๅฏ OpenClaw Gateway ไฝฟ้…็ฝฎ็”Ÿๆ•ˆใ€‚

### 3.3 ๅŽ็ซฏ้…็ฝฎ

ๅŽ็ซฏไฝฟ็”จ็Žฏๅขƒๅ˜้‡้…็ฝฎ๏ผˆ.env ๆ–‡ไปถ๏ผ‰๏ผš

```bash
# ๅบ”็”จ้…็ฝฎ
APP_KEY=yeizi-app-key-2026
APP_SECRET=yeizi-app-secret-2026

# ๆœๅŠกๅœฐๅ€้…็ฝฎ
HOST=localhost
PORT=3000
PROTOCOL=http

# ๆœๅŠกๅœฐๅ€
BASE_URL=http://localhost:3000
WEBSOCKET_URL=ws://localhost:3000
```

## 4. ้กน็›ฎ็ป“ๆž„

```
yeizi/
โ”œโ”€โ”€ web-channel/                    # Web ็ซฏ้กน็›ฎ
โ”‚   โ”œโ”€โ”€ frontend/                   # ๅ‰็ซฏ้กน็›ฎ๏ผˆVue 3 + TypeScript๏ผ‰
โ”‚   โ”‚   โ”œโ”€โ”€ src/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ components/       # Vue ็ป„ไปถ
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ ChatInput.vue       # ๆถˆๆฏ่พ“ๅ…ฅ็ป„ไปถ
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ ChatMessage.vue     # ๆถˆๆฏๆ˜พ็คบ็ป„ไปถ
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ ChatWindow.vue     # ่Šๅคฉ็ช—ๅฃ็ป„ไปถ
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ ConnectionStatus.vue # ่ฟžๆŽฅ็Šถๆ€็ป„ไปถ
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ SettingsPanel.vue   # ๆ’ไปถ้…็ฝฎ้กต้ข
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ composables/
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ useWebSocket.ts     # WebSocket ้’ฉๅญ
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ stores/
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ chat.ts             # ่Šๅคฉ็Šถๆ€็ฎก็†
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ App.vue                 # ไธปๅบ”็”จ็ป„ไปถ
โ”‚   โ”‚   โ””โ”€โ”€ package.json
โ”‚   โ”œโ”€โ”€ backend/                   # ๅŽ็ซฏ้กน็›ฎ๏ผˆExpress.js๏ผ‰
โ”‚   โ”‚   โ”œโ”€โ”€ src/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ routes/
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ auth.ts            # ้‰ดๆƒ่ทฏ็”ฑ
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ config.ts          # ้…็ฝฎๆŸฅ่ฏข่ทฏ็”ฑ
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ services/
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ auth.ts            # ้‰ดๆƒๆœๅŠก
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ config.ts          # ้…็ฝฎๆœๅŠก
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ websocket.ts       # WebSocket ็ฎก็†
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ index.ts               # ๆœๅŠกๅ…ฅๅฃ
โ”‚   โ”‚   โ”œโ”€โ”€ .env                      # ็Žฏๅขƒๅ˜้‡้…็ฝฎ
โ”‚   โ”‚   โ””โ”€โ”€ package.json
โ”‚   โ””โ”€โ”€ package.json
โ”‚
โ””โ”€โ”€ yeizi-plugin/                  # OpenClaw ๆ’ไปถ้กน็›ฎ
    โ”œโ”€โ”€ src/
    โ”‚   โ”œโ”€โ”€ accounts.ts              # ่ดฆๆˆท็ฎก็†ๅทฅๅ…ท
    โ”‚   โ”œโ”€โ”€ channel.ts              # Channel Plugin ๅฎž็Žฐ
    โ”‚   โ”œโ”€โ”€ config-schema.ts        # ้…็ฝฎ Schema ๅฎšไน‰
    โ”‚   โ”œโ”€โ”€ runtime.ts              # ่ฟ่กŒๆ—ถๅญ˜ๅ‚จ็ฎก็†
    โ”‚   โ”œโ”€โ”€ types.ts                # ็ฑปๅž‹ๅฎšไน‰
    โ”‚   โ””โ”€โ”€ websocket-client.ts     # WebSocket ๅฎขๆˆท็ซฏๅฐ่ฃ…
    โ”œโ”€โ”€ scripts/
    โ”‚   โ”œโ”€โ”€ setup.mjs              # ๅฎ‰่ฃ…่„šๆœฌ
    โ”‚   โ””โ”€โ”€ README.md               # ๅฎ‰่ฃ…่ฏดๆ˜Ž
    โ”œโ”€โ”€ index.ts                   # ๆ’ไปถ่ฟ่กŒๆ—ถๅ…ฅๅฃ
    โ”œโ”€โ”€ openclaw.plugin.json       # ๆ’ไปถๅ…ƒๆ•ฐๆฎ
    โ”œโ”€โ”€ package.json
    โ””โ”€โ”€ tsconfig.json
```

## 5. ๆ’ไปถๆ ธๅฟƒๅฎž็Žฐ

### 5.1 ๆ’ไปถๅ…ฅๅฃ (index.ts)

```typescript
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
import { plugin, yeiziDock } from "./src/channel.js";
import { setRuntime } from "./src/runtime.js";

export { plugin, yeiziDock } from "./src/channel.js";

const yeizi: any = {
    id: "yeizi",
    name: "Yeizi",
    description: "Yeizi Channel ๆ’ไปถ",
    configSchema: emptyPluginConfigSchema(),
    register(api: OpenClawPluginApi) {
        setRuntime(api.runtime);
        api.registerChannel({ plugin, dock: yeiziDock });
    },
};

export function register(api: OpenClawPluginApi) {
    yeizi.register(api);
}

export function activate(api: OpenClawPluginApi) {
    register(api);
}

export default yeizi;
```

### 5.2 ChannelDock ๅฎšไน‰

```typescript
export const yeiziDock: ChannelDock = {
    id: "yeizi",
    capabilities: {
        chatTypes: ["direct"],
        blockStreaming: true,
    },
};
```

### 5.3 ๆถˆๆฏๅค„็†ๆต็จ‹

```typescript
// 1. ๅฏๅŠจ่ดฆๆˆทๆ—ถๅปบ็ซ‹ WebSocket ่ฟžๆŽฅ
startAccount: async (ctx) => {
    // HTTP ้‰ดๆƒ่Žทๅ– token
    const authResponse = await fetch(`${account.config.baseUrl}/api/auth/token`, {
        method: 'POST',
        body: JSON.stringify({
            appKey: account.config.appKey,
            appSecret: account.config.appSecret,
        }),
    });
    
    // ๅปบ็ซ‹ WebSocket ่ฟžๆŽฅ
    const wsClient = new WebSocketClient({
        url: `${account.config.websocketUrl}/ws/plugin`,
        token: authData.token,
        onMessage: handleMessage,
    });
    
    wsClient.connect();
    
    // ็ญ‰ๅพ… abort ไฟกๅท
    return new Promise((resolve) => {
        ctx.abortSignal?.addEventListener('abort', () => {
            wsClient.disconnect();
            resolve();
        });
    });
}

// 2. ๆ”ถๅˆฐๆถˆๆฏๆ—ถๅค„็†
onMessage: (message: WebSocketMessage) => {
    // ๆž„ๅปบ ctxPayload
    const ctxPayload = {
        Body: message.text,
        BodyForAgent: message.text,
        RawBody: JSON.stringify(message),
        From: message.from ?? 'unknown',
        To: message.to ?? 'yeizi',
        ChatType: 'dm',
        Provider: 'yeizi',
        Surface: 'yeizi',
        AgentId: agentId,
        Timestamp: Date.now(),
        AccountId: accountId,
        MessageSid: message.messageId ?? Date.now().toString(),
        OriginatingChannel: 'yeizi',
        OriginatingTo: message.to ?? 'yeizi',
    };
    
    const finalized = runtime.channel.reply.finalizeInboundContext(ctxPayload);
    
    // ๅˆ†ๅ‘ๆถˆๆฏๅˆฐ AI ๅค„็†
    await runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
        ctx: finalized,
        cfg,
        dispatcherOptions: {
            deliver: async (payload) => {
                const textOut = String(payload.text ?? payload.body ?? "");
                const target = message.from;
                
                if (!target || !textOut.trim()) {
                    return;
                }
                
                wsClient.send({
                    type: 'response',
                    payload: {
                        content: textOut,
                        messageId: message.messageId,
                        to: target,
                    },
                });
            },
        },
    });
}
```

### 5.4 ๅ‡บ็ซ™ๆถˆๆฏ้…็ฝฎ

```typescript
outbound: {
    deliveryMode: 'direct',
    chunker: (text: string, _limit: number) => [text],
    textChunkLimit: 4096,
    sendText: async ({ to, text, accountId }) => {
        const wsClient = accountConnections.get(accountId ?? 'default');
        const messageId = Date.now().toString();
        
        if (!wsClient || !wsClient.isConnected()) {
            return { channel: 'yeizi', ok: false, messageId };
        }

        const sent = wsClient.send({
            type: 'response',
            payload: { content: text, messageId, to },
        });

        return { channel: 'yeizi', ok: sent, messageId };
    },
},
```

## 6. WebSocket ๆถˆๆฏๆ ผๅผ

### 6.1 ๅ‰็ซฏ โ†’ ๆ’ไปถ๏ผˆ็”จๆˆทๆถˆๆฏ๏ผ‰

```json
{
    "type": "message",
    "text": "็”จๆˆทๆถˆๆฏๅ†…ๅฎน",
    "from": "user_xxx",
    "to": "yeizi",
    "messageId": "17000000

... (truncated)
tools

Comments

Sign in to leave a comment

Loading comments...