@ynhcj/xiaoyi 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +205 -0
- package/index.ts +40 -0
- package/openclaw.plugin.json +14 -0
- package/package.json +59 -0
- package/scripts/dev-link.sh +29 -0
- package/tsconfig.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# @openclaw/xiaoyi
|
|
2
|
+
|
|
3
|
+
Openclaw Xiaoyi channel plugin - Huawei A2A (Agent-to-Agent) protocol integration via WebSocket.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This plugin enables Openclaw to communicate with Huawei's A2A Gateway service, allowing AI agents to send and receive messages through Huawei's messaging infrastructure.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **WebSocket Connection**: Persistent WebSocket connection to `wss://xiaoyi.com/ws/link`
|
|
12
|
+
- **Auto-Reconnection**: Automatic reconnection with exponential backoff
|
|
13
|
+
- **AK/SK Authentication**: Huawei Cloud Access Key/Secret Key authentication
|
|
14
|
+
- **A2A Protocol**: Full support for Huawei's A2A message protocol
|
|
15
|
+
- **Session Management**: Automatic session tracking and continuity
|
|
16
|
+
- **Media Support**: Text and media message handling
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @openclaw/xiaoyi
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Configuration
|
|
25
|
+
|
|
26
|
+
Add the following to your Openclaw configuration file:
|
|
27
|
+
|
|
28
|
+
```yaml
|
|
29
|
+
channels:
|
|
30
|
+
xiaoyi:
|
|
31
|
+
enabled: true
|
|
32
|
+
# Huawei Cloud credentials
|
|
33
|
+
accessKeyId: "your-access-key-id"
|
|
34
|
+
secretAccessKey: "your-secret-access-key"
|
|
35
|
+
projectId: "your-project-id"
|
|
36
|
+
# Optional settings
|
|
37
|
+
serverUrl: "wss://xiaoyi.com/ws/link" # Default: wss://xiaoyi.com/ws/link
|
|
38
|
+
agentId: "openclaw" # Default: openclaw
|
|
39
|
+
proxy: "" # Optional proxy URL
|
|
40
|
+
|
|
41
|
+
# Multiple accounts support
|
|
42
|
+
accounts:
|
|
43
|
+
account1:
|
|
44
|
+
enabled: true
|
|
45
|
+
accessKeyId: "account1-key-id"
|
|
46
|
+
secretAccessKey: "account1-secret"
|
|
47
|
+
projectId: "account1-project"
|
|
48
|
+
agentId: "openclaw-account1"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Configuration via Environment Variables
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
export XIAOYI_ACCESS_KEY_ID="your-access-key-id"
|
|
55
|
+
export XIAOYI_SECRET_ACCESS_KEY="your-secret-access-key"
|
|
56
|
+
export XIAOYI_PROJECT_ID="your-project-id"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Message Protocol
|
|
60
|
+
|
|
61
|
+
### A2A Request Message (Incoming)
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
{
|
|
65
|
+
"header": {
|
|
66
|
+
"messageId": "msg_1234567890_abc123",
|
|
67
|
+
"sessionId": "session_1234567890_def456",
|
|
68
|
+
"timestamp": 1703145600000,
|
|
69
|
+
"messageType": "request",
|
|
70
|
+
"version": "1.0"
|
|
71
|
+
},
|
|
72
|
+
"sender": {
|
|
73
|
+
"id": "user123",
|
|
74
|
+
"name": "John Doe",
|
|
75
|
+
"type": "user"
|
|
76
|
+
},
|
|
77
|
+
"receiver": {
|
|
78
|
+
"id": "openclaw",
|
|
79
|
+
"type": "agent"
|
|
80
|
+
},
|
|
81
|
+
"content": {
|
|
82
|
+
"contentType": "text",
|
|
83
|
+
"text": "Hello, how can you help me?"
|
|
84
|
+
},
|
|
85
|
+
"context": {
|
|
86
|
+
"chatType": "direct"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### A2A Response Message (Outgoing)
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
{
|
|
95
|
+
"header": {
|
|
96
|
+
"messageId": "msg_1234567890_xyz789",
|
|
97
|
+
"sessionId": "session_1234567890_def456",
|
|
98
|
+
"timestamp": 1703145601000,
|
|
99
|
+
"messageType": "response",
|
|
100
|
+
"version": "1.0"
|
|
101
|
+
},
|
|
102
|
+
"sender": {
|
|
103
|
+
"id": "openclaw",
|
|
104
|
+
"name": "Openclaw Agent",
|
|
105
|
+
"type": "agent"
|
|
106
|
+
},
|
|
107
|
+
"receiver": {
|
|
108
|
+
"id": "user123",
|
|
109
|
+
"type": "user"
|
|
110
|
+
},
|
|
111
|
+
"content": {
|
|
112
|
+
"contentType": "text",
|
|
113
|
+
"text": "I'm here to help! What do you need?"
|
|
114
|
+
},
|
|
115
|
+
"status": {
|
|
116
|
+
"code": 200,
|
|
117
|
+
"message": "OK"
|
|
118
|
+
},
|
|
119
|
+
// Top-level fields for routing
|
|
120
|
+
"agentId": "openclaw",
|
|
121
|
+
"sessionId": "session_1234567890_def456"
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Authentication
|
|
126
|
+
|
|
127
|
+
The plugin uses Huawei Cloud's AK/SK authentication mechanism:
|
|
128
|
+
|
|
129
|
+
1. Generates a JWT-like token signed with the secret access key
|
|
130
|
+
2. Sends an authentication message on WebSocket connection
|
|
131
|
+
3. Automatically refreshes tokens before expiration
|
|
132
|
+
4. Handles authentication failures with reconnection
|
|
133
|
+
|
|
134
|
+
## Reconnection Strategy
|
|
135
|
+
|
|
136
|
+
- Initial delay: 1 second
|
|
137
|
+
- Backoff multiplier: 1.5x
|
|
138
|
+
- Maximum delay: 30 seconds
|
|
139
|
+
- Maximum attempts: Unlimited (configurable)
|
|
140
|
+
- Ping interval: 30 seconds
|
|
141
|
+
- Pong timeout: 10 seconds
|
|
142
|
+
|
|
143
|
+
## API Reference
|
|
144
|
+
|
|
145
|
+
### `XiaoyiWebSocketClient`
|
|
146
|
+
|
|
147
|
+
Main WebSocket client class for Xiaoyi connection.
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
import { createXiaoyiWebSocketClient } from '@openclaw/xiaoyi';
|
|
151
|
+
|
|
152
|
+
const client = createXiaoyiWebSocketClient({
|
|
153
|
+
serverUrl: 'wss://xiaoyi.com/ws/link',
|
|
154
|
+
credentials: {
|
|
155
|
+
accessKeyId: 'your-key',
|
|
156
|
+
secretAccessKey: 'your-secret',
|
|
157
|
+
projectId: 'your-project',
|
|
158
|
+
agentId: 'openclaw',
|
|
159
|
+
},
|
|
160
|
+
reconnect: true,
|
|
161
|
+
onMessage: (message) => console.log('Received:', message),
|
|
162
|
+
onStateChange: (status) => console.log('Status:', status.state),
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
await client.connect();
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Message Handlers
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import {
|
|
172
|
+
createOutgoingMessage,
|
|
173
|
+
a2aToOpenclaw,
|
|
174
|
+
openclawToA2A,
|
|
175
|
+
validateA2ARequest,
|
|
176
|
+
} from '@openclaw/xiaoyi';
|
|
177
|
+
|
|
178
|
+
// Create outgoing message
|
|
179
|
+
const outgoing = createOutgoingMessage({
|
|
180
|
+
to: 'user123',
|
|
181
|
+
text: 'Hello!',
|
|
182
|
+
sessionId: 'session_123',
|
|
183
|
+
agentId: 'openclaw',
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Validate incoming message
|
|
187
|
+
if (validateA2ARequest(incoming)) {
|
|
188
|
+
const openclawMsg = a2aToOpenclaw(incoming, 'default', 'openclaw');
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## References
|
|
193
|
+
|
|
194
|
+
- [Huawei Push Message Service](https://developer.huawei.com/consumer/cn/doc/service/pushmessage-0000002505761436)
|
|
195
|
+
- [Huawei Message Stream (A2A Protocol)](https://developer.huawei.com/consumer/cn/doc/service/message-stream-0000002505761434)
|
|
196
|
+
|
|
197
|
+
## License
|
|
198
|
+
|
|
199
|
+
MIT
|
|
200
|
+
|
|
201
|
+
## Support
|
|
202
|
+
|
|
203
|
+
For issues and questions:
|
|
204
|
+
- GitHub Issues: [openclaw/xiaoyi-channel](https://github.com/openclaw/xiaoyi-channel/issues)
|
|
205
|
+
- Openclaw Discord: [Join our server](https://discord.gg/openclaw)
|
package/index.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Xiaoyi Channel Plugin for Openclaw
|
|
3
|
+
* Huawei A2A Gateway integration via WebSocket
|
|
4
|
+
*
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
9
|
+
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
|
|
10
|
+
|
|
11
|
+
import { xiaoyiPlugin } from "./src/channel.js";
|
|
12
|
+
import { setXiaoyiRuntime } from "./src/runtime.js";
|
|
13
|
+
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// Plugin Definition
|
|
16
|
+
// ============================================================================
|
|
17
|
+
|
|
18
|
+
const plugin = {
|
|
19
|
+
id: "xiaoyi",
|
|
20
|
+
name: "Xiaoyi (Huawei A2A Gateway)",
|
|
21
|
+
description: "Openclaw Xiaoyi channel plugin - Huawei A2A protocol integration via WebSocket",
|
|
22
|
+
version: "1.0.0",
|
|
23
|
+
configSchema: emptyPluginConfigSchema(),
|
|
24
|
+
register(api: OpenClawPluginApi) {
|
|
25
|
+
// Set runtime reference
|
|
26
|
+
setXiaoyiRuntime(api.runtime);
|
|
27
|
+
|
|
28
|
+
// Register the channel plugin
|
|
29
|
+
api.registerChannel({ plugin: xiaoyiPlugin });
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default plugin;
|
|
34
|
+
|
|
35
|
+
// ============================================================================
|
|
36
|
+
// Re-exports
|
|
37
|
+
// ============================================================================
|
|
38
|
+
|
|
39
|
+
export { xiaoyiPlugin } from "./src/channel.js";
|
|
40
|
+
export * from "./src/types.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "xiaoyi",
|
|
3
|
+
"name": "Xiaoyi",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Openclaw Xiaoyi channel plugin - Huawei A2A protocol integration via WebSocket",
|
|
6
|
+
"channels": ["xiaoyi"],
|
|
7
|
+
"author": "",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"configSchema": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"additionalProperties": false,
|
|
12
|
+
"properties": {}
|
|
13
|
+
}
|
|
14
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ynhcj/xiaoyi",
|
|
3
|
+
"publishConfig": {
|
|
4
|
+
"access": "public"
|
|
5
|
+
},
|
|
6
|
+
"version": "1.0.0",
|
|
7
|
+
"description": "OpenClaw Xiaoyi channel plugin - Huawei A2A Gateway integration",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"openclaw",
|
|
10
|
+
"channel",
|
|
11
|
+
"xiaoyi",
|
|
12
|
+
"huawei",
|
|
13
|
+
"a2a",
|
|
14
|
+
"websocket"
|
|
15
|
+
],
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"author": "",
|
|
18
|
+
"type": "module",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": "./index.ts",
|
|
21
|
+
"./types": "./src/types.ts"
|
|
22
|
+
},
|
|
23
|
+
"main": "index.ts",
|
|
24
|
+
"scripts": {
|
|
25
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"ws": "^8.18.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^20.0.0",
|
|
32
|
+
"@types/ws": "^8.5.0"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"openclaw": ">=2026.2.1"
|
|
36
|
+
},
|
|
37
|
+
"openclaw": {
|
|
38
|
+
"extensions": [
|
|
39
|
+
"./index.ts"
|
|
40
|
+
],
|
|
41
|
+
"channel": {
|
|
42
|
+
"id": "xiaoyi",
|
|
43
|
+
"label": "Xiaoyi (Huawei A2A Gateway)",
|
|
44
|
+
"selectionLabel": "Xiaoyi",
|
|
45
|
+
"docsPath": "/channels/xiaoyi",
|
|
46
|
+
"docsLabel": "xiaoyi",
|
|
47
|
+
"blurb": "Huawei A2A Gateway integration for AI agent messaging via WebSocket",
|
|
48
|
+
"aliases": [
|
|
49
|
+
"xy",
|
|
50
|
+
"huawei"
|
|
51
|
+
],
|
|
52
|
+
"order": 100,
|
|
53
|
+
"quickstartAllowFrom": true
|
|
54
|
+
},
|
|
55
|
+
"install": {
|
|
56
|
+
"npmSpec": "@openclaw/xiaoyi"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Development setup script for moltbot-hag-channel
|
|
3
|
+
|
|
4
|
+
EXT_DIR="$HOME/.openclaw/extensions/xiaoyi"
|
|
5
|
+
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
6
|
+
|
|
7
|
+
echo "Project directory: $PROJECT_DIR"
|
|
8
|
+
echo "Extension directory: $EXT_DIR"
|
|
9
|
+
|
|
10
|
+
# Remove existing installation
|
|
11
|
+
if [ -L "$EXT_DIR" ]; then
|
|
12
|
+
echo "Removing existing symlink..."
|
|
13
|
+
rm "$EXT_DIR"
|
|
14
|
+
elif [ -d "$EXT_DIR" ]; then
|
|
15
|
+
echo "Backing up existing installation..."
|
|
16
|
+
mv "$EXT_DIR" "${EXT_DIR}.backup.$(date +%s)"
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
# Create symlink
|
|
20
|
+
echo "Creating development symlink..."
|
|
21
|
+
ln -s "$PROJECT_DIR" "$EXT_DIR"
|
|
22
|
+
|
|
23
|
+
# Install dependencies
|
|
24
|
+
echo "Installing dependencies..."
|
|
25
|
+
cd "$PROJECT_DIR"
|
|
26
|
+
npm install --omit=dev
|
|
27
|
+
|
|
28
|
+
echo "Development setup complete!"
|
|
29
|
+
echo "The plugin will use your source code directly."
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ES2022",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"lib": ["ES2022"],
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"declarationMap": true,
|
|
9
|
+
"sourceMap": true,
|
|
10
|
+
"outDir": "./dist",
|
|
11
|
+
"rootDir": "./",
|
|
12
|
+
"strict": true,
|
|
13
|
+
"esModuleInterop": true,
|
|
14
|
+
"skipLibCheck": true,
|
|
15
|
+
"forceConsistentCasingInFileNames": true,
|
|
16
|
+
"resolveJsonModule": true,
|
|
17
|
+
"allowSyntheticDefaultImports": true,
|
|
18
|
+
"types": ["node"]
|
|
19
|
+
},
|
|
20
|
+
"include": [
|
|
21
|
+
"src/**/*.ts",
|
|
22
|
+
"index.ts"
|
|
23
|
+
],
|
|
24
|
+
"exclude": [
|
|
25
|
+
"node_modules",
|
|
26
|
+
"dist"
|
|
27
|
+
]
|
|
28
|
+
}
|