@ynhcj/xiaoyi 1.0.1 → 1.2.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 CHANGED
@@ -1,198 +1,202 @@
1
- # @openclaw/xiaoyi
1
+ # @ynhcj/xiaoyichannel
2
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.
3
+ XiaoYi channel plugin for OpenClaw with A2A protocol support.
8
4
 
9
5
  ## Features
10
6
 
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
7
+ - WebSocket-based connection to XiaoYi servers
8
+ - AK/SK authentication mechanism
9
+ - A2A (Agent-to-Agent) message protocol support
10
+ - Automatic reconnection with exponential backoff
11
+ - Heartbeat mechanism for connection health monitoring
12
+ - Full integration with OpenClaw's message routing and session management
17
13
 
18
14
  ## Installation
19
15
 
16
+ Install the plugin in your OpenClaw project:
17
+
20
18
  ```bash
21
- npm install @openclaw/xiaoyi
19
+ openclaw plugins install @ynhcj/xiaoyichannel@1.0.0
22
20
  ```
23
21
 
24
22
  ## Configuration
25
23
 
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"
24
+ After installation, add the XiaoYi channel configuration to your `openclaw.json` (or `.openclawd.json`):
25
+
26
+ ```json
27
+ {
28
+ "channels": {
29
+ "xiaoyi": {
30
+ "enabled": true,
31
+ "accounts": {
32
+ "default": {
33
+ "enabled": true,
34
+ "wsUrl": "wss://hag.com/ws/link",
35
+ "ak": "your-access-key",
36
+ "sk": "your-secret-key",
37
+ "agentId": "your-agent-id"
38
+ }
39
+ }
40
+ }
41
+ },
42
+ "agents": {
43
+ "bindings": [
44
+ {
45
+ "agentId": "main",
46
+ "match": {
47
+ "channel": "xiaoyi",
48
+ "accountId": "default"
49
+ }
50
+ }
51
+ ]
52
+ }
53
+ }
49
54
  ```
50
55
 
51
- ## Configuration via Environment Variables
56
+ ### Configuration Parameters
52
57
 
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"
58
+ - `wsUrl`: WebSocket server URL (e.g., `wss://hag.com/ws/link`)
59
+ - `ak`: Access Key for authentication
60
+ - `sk`: Secret Key for authentication
61
+ - `agentId`: Your agent identifier
62
+
63
+ ### Multiple Accounts
64
+
65
+ You can configure multiple XiaoYi accounts:
66
+
67
+ ```json
68
+ {
69
+ "channels": {
70
+ "xiaoyi": {
71
+ "enabled": true,
72
+ "accounts": {
73
+ "account1": {
74
+ "enabled": true,
75
+ "wsUrl": "wss://hag.com/ws/link",
76
+ "ak": "ak1",
77
+ "sk": "sk1",
78
+ "agentId": "agent1"
79
+ },
80
+ "account2": {
81
+ "enabled": true,
82
+ "wsUrl": "wss://hag.com/ws/link",
83
+ "ak": "ak2",
84
+ "sk": "sk2",
85
+ "agentId": "agent2"
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
57
91
  ```
58
92
 
59
- ## Message Protocol
93
+ ## A2A Protocol
94
+
95
+ This plugin implements the A2A (Agent-to-Agent) message protocol as specified in the [Huawei Message Stream documentation](https://developer.huawei.com/consumer/cn/doc/service/message-stream-0000002505761434).
60
96
 
61
- ### A2A Request Message (Incoming)
97
+ ### Message Structure
62
98
 
63
- ```typescript
99
+ **Incoming Request Message:**
100
+ ```json
64
101
  {
65
- "header": {
66
- "messageId": "msg_1234567890_abc123",
67
- "sessionId": "session_1234567890_def456",
68
- "timestamp": 1703145600000,
69
- "messageType": "request",
70
- "version": "1.0"
71
- },
102
+ "sessionId": "session-123",
103
+ "messageId": "msg-456",
104
+ "timestamp": 1234567890,
72
105
  "sender": {
73
- "id": "user123",
74
- "name": "John Doe",
106
+ "id": "user-id",
107
+ "name": "User Name",
75
108
  "type": "user"
76
109
  },
77
- "receiver": {
78
- "id": "openclaw",
79
- "type": "agent"
80
- },
81
110
  "content": {
82
- "contentType": "text",
83
- "text": "Hello, how can you help me?"
84
- },
85
- "context": {
86
- "chatType": "direct"
111
+ "type": "text",
112
+ "text": "Hello, agent!"
87
113
  }
88
114
  }
89
115
  ```
90
116
 
91
- ### A2A Response Message (Outgoing)
92
-
93
- ```typescript
117
+ **Outgoing Response Message:**
118
+ ```json
94
119
  {
95
- "header": {
96
- "messageId": "msg_1234567890_xyz789",
97
- "sessionId": "session_1234567890_def456",
98
- "timestamp": 1703145601000,
99
- "messageType": "response",
100
- "version": "1.0"
101
- },
120
+ "sessionId": "session-123",
121
+ "messageId": "msg-789",
122
+ "timestamp": 1234567891,
123
+ "agentId": "your-agent-id",
102
124
  "sender": {
103
- "id": "openclaw",
104
- "name": "Openclaw Agent",
125
+ "id": "your-agent-id",
126
+ "name": "OpenClaw Agent",
105
127
  "type": "agent"
106
128
  },
107
- "receiver": {
108
- "id": "user123",
109
- "type": "user"
110
- },
111
129
  "content": {
112
- "contentType": "text",
113
- "text": "I'm here to help! What do you need?"
114
- },
115
- "status": {
116
- "code": 200,
117
- "message": "OK"
130
+ "type": "text",
131
+ "text": "Hello! How can I help you?"
118
132
  },
119
- // Top-level fields for routing
120
- "agentId": "openclaw",
121
- "sessionId": "session_1234567890_def456"
133
+ "status": "success"
122
134
  }
123
135
  ```
124
136
 
125
137
  ## Authentication
126
138
 
127
- The plugin uses Huawei Cloud's AK/SK authentication mechanism:
139
+ The plugin uses AK/SK authentication as specified in the [Huawei Push Message documentation](https://developer.huawei.com/consumer/cn/doc/service/pushmessage-0000002505761436).
128
140
 
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
141
+ The authentication signature is generated using HMAC-SHA256:
133
142
 
134
- ## Reconnection Strategy
143
+ ```
144
+ signature = HMAC-SHA256(SK, "ak={AK}&timestamp={TIMESTAMP}")
145
+ ```
135
146
 
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
147
+ ## Connection Management
142
148
 
143
- ## API Reference
149
+ The plugin automatically manages WebSocket connections with the following features:
144
150
 
145
- ### `XiaoyiWebSocketClient`
151
+ - **Automatic Reconnection**: Reconnects automatically on connection loss with exponential backoff
152
+ - **Heartbeat Monitoring**: Sends ping messages every 30 seconds to keep the connection alive
153
+ - **Connection Health**: Monitors connection status and reports health via OpenClaw's status system
154
+ - **Max Retry Limit**: Stops reconnection attempts after 10 failed attempts
146
155
 
147
- Main WebSocket client class for Xiaoyi connection.
156
+ ## Session Management
148
157
 
149
- ```typescript
150
- import { createXiaoyiWebSocketClient } from '@openclaw/xiaoyi';
158
+ The plugin integrates with OpenClaw's session management system:
151
159
 
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
- });
160
+ - Sessions are scoped by `sessionId` from incoming A2A messages
161
+ - Each conversation maintains its own session context
162
+ - Session keys are automatically generated based on OpenClaw's configuration
164
163
 
165
- await client.connect();
166
- ```
164
+ ## Usage
167
165
 
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
- }
166
+ Once configured, the plugin will:
167
+
168
+ 1. Automatically connect to the XiaoYi WebSocket server on startup
169
+ 2. Authenticate using the provided AK/SK credentials
170
+ 3. Receive incoming messages via WebSocket
171
+ 4. Route messages to the appropriate OpenClaw agent
172
+ 5. Send agent responses back through the WebSocket connection
173
+
174
+ ## Troubleshooting
175
+
176
+ ### Connection Issues
177
+
178
+ Check the OpenClaw logs for connection status:
179
+
180
+ ```bash
181
+ openclaw logs
190
182
  ```
191
183
 
192
- ## References
184
+ ### Authentication Failures
185
+
186
+ Verify your AK/SK credentials are correct and have the necessary permissions.
187
+
188
+ ### Message Delivery
193
189
 
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)
190
+ Ensure your `agentId` is correctly configured and matches your XiaoYi account settings.
191
+
192
+ ## Development
193
+
194
+ To build the plugin from source:
195
+
196
+ ```bash
197
+ npm install
198
+ npm run build
199
+ ```
196
200
 
197
201
  ## License
198
202
 
@@ -200,6 +204,4 @@ MIT
200
204
 
201
205
  ## Support
202
206
 
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)
207
+ For issues and questions, please visit the [GitHub repository](https://github.com/ynhcj/xiaoyichannel).
package/dist/auth.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ import { AuthCredentials } from "./types";
2
+ /**
3
+ * Generate authentication signature using AK/SK mechanism
4
+ * Based on: https://developer.huawei.com/consumer/cn/doc/service/pushmessage-0000002505761436
5
+ */
6
+ export declare class XiaoYiAuth {
7
+ private ak;
8
+ private sk;
9
+ constructor(ak: string, sk: string);
10
+ /**
11
+ * Generate authentication credentials with signature
12
+ */
13
+ generateAuthCredentials(): AuthCredentials;
14
+ /**
15
+ * Generate HMAC-SHA256 signature
16
+ * Format: HMAC-SHA256(SK, "ak={AK}&timestamp={TIMESTAMP}")
17
+ */
18
+ private generateSignature;
19
+ /**
20
+ * Verify if credentials are valid
21
+ */
22
+ verifyCredentials(credentials: AuthCredentials): boolean;
23
+ /**
24
+ * Generate authentication message for WebSocket
25
+ */
26
+ generateAuthMessage(): any;
27
+ }
package/dist/auth.js ADDED
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.XiaoYiAuth = void 0;
37
+ const crypto = __importStar(require("crypto"));
38
+ /**
39
+ * Generate authentication signature using AK/SK mechanism
40
+ * Based on: https://developer.huawei.com/consumer/cn/doc/service/pushmessage-0000002505761436
41
+ */
42
+ class XiaoYiAuth {
43
+ constructor(ak, sk) {
44
+ this.ak = ak;
45
+ this.sk = sk;
46
+ }
47
+ /**
48
+ * Generate authentication credentials with signature
49
+ */
50
+ generateAuthCredentials() {
51
+ const timestamp = Date.now();
52
+ const signature = this.generateSignature(timestamp);
53
+ return {
54
+ ak: this.ak,
55
+ sk: this.sk,
56
+ timestamp,
57
+ signature,
58
+ };
59
+ }
60
+ /**
61
+ * Generate HMAC-SHA256 signature
62
+ * Format: HMAC-SHA256(SK, "ak={AK}&timestamp={TIMESTAMP}")
63
+ */
64
+ generateSignature(timestamp) {
65
+ const stringToSign = `ak=${this.ak}&timestamp=${timestamp}`;
66
+ const hmac = crypto.createHmac("sha256", this.sk);
67
+ hmac.update(stringToSign);
68
+ return hmac.digest("hex");
69
+ }
70
+ /**
71
+ * Verify if credentials are valid
72
+ */
73
+ verifyCredentials(credentials) {
74
+ const expectedSignature = this.generateSignature(credentials.timestamp);
75
+ return credentials.signature === expectedSignature;
76
+ }
77
+ /**
78
+ * Generate authentication message for WebSocket
79
+ */
80
+ generateAuthMessage() {
81
+ const credentials = this.generateAuthCredentials();
82
+ return {
83
+ type: "auth",
84
+ data: {
85
+ ak: credentials.ak,
86
+ timestamp: credentials.timestamp,
87
+ signature: credentials.signature,
88
+ },
89
+ };
90
+ }
91
+ }
92
+ exports.XiaoYiAuth = XiaoYiAuth;
@@ -0,0 +1,14 @@
1
+ import type { ChannelPlugin } from "openclaw";
2
+ import { XiaoYiAccountConfig } from "./types";
3
+ /**
4
+ * Resolved XiaoYi account configuration
5
+ */
6
+ export interface ResolvedXiaoYiAccount {
7
+ accountId: string;
8
+ config: XiaoYiAccountConfig;
9
+ }
10
+ /**
11
+ * XiaoYi Channel Plugin
12
+ * Implements OpenClaw ChannelPlugin interface for XiaoYi A2A protocol
13
+ */
14
+ export declare const xiaoyiPlugin: ChannelPlugin<ResolvedXiaoYiAccount>;