@ynhcj/xiaoyi 2.0.4 → 2.0.6
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/dist/channel.js +31 -3
- package/dist/types.d.ts +55 -0
- package/dist/websocket.d.ts +16 -1
- package/dist/websocket.js +114 -38
- package/package.json +1 -1
package/dist/channel.js
CHANGED
|
@@ -242,8 +242,8 @@ exports.xiaoyiPlugin = {
|
|
|
242
242
|
cfg: config,
|
|
243
243
|
dispatcherOptions: {
|
|
244
244
|
deliver: async (payload) => {
|
|
245
|
-
console.log("XiaoYi: Delivering response:", payload);
|
|
246
|
-
// Send response back through WebSocket
|
|
245
|
+
console.log("XiaoYi: Delivering final response:", payload);
|
|
246
|
+
// Send final response back through WebSocket
|
|
247
247
|
const taskId = runtime.getTaskIdForSession(message.sessionId) || `task_${Date.now()}`;
|
|
248
248
|
const response = {
|
|
249
249
|
sessionId: message.sessionId,
|
|
@@ -264,7 +264,35 @@ exports.xiaoyiPlugin = {
|
|
|
264
264
|
const conn = runtime.getConnection();
|
|
265
265
|
if (conn) {
|
|
266
266
|
await conn.sendResponse(response, taskId, message.sessionId);
|
|
267
|
-
console.log("XiaoYi:
|
|
267
|
+
console.log("XiaoYi: Final response sent successfully");
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
replyOptions: {
|
|
272
|
+
// Enable streaming responses through onPartialReply callback
|
|
273
|
+
onPartialReply: async (payload) => {
|
|
274
|
+
console.log("XiaoYi: Streaming partial response:", payload.text?.substring(0, 50));
|
|
275
|
+
// Send partial response back through WebSocket
|
|
276
|
+
const taskId = runtime.getTaskIdForSession(message.sessionId) || `task_${Date.now()}`;
|
|
277
|
+
const partialResponse = {
|
|
278
|
+
sessionId: message.sessionId,
|
|
279
|
+
messageId: `partial_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
280
|
+
timestamp: Date.now(),
|
|
281
|
+
agentId: resolvedAccount.config.agentId,
|
|
282
|
+
sender: {
|
|
283
|
+
id: resolvedAccount.config.agentId,
|
|
284
|
+
name: "OpenClaw Agent",
|
|
285
|
+
type: "agent",
|
|
286
|
+
},
|
|
287
|
+
content: {
|
|
288
|
+
type: "text",
|
|
289
|
+
text: payload.text || "",
|
|
290
|
+
},
|
|
291
|
+
status: "processing",
|
|
292
|
+
};
|
|
293
|
+
const conn = runtime.getConnection();
|
|
294
|
+
if (conn) {
|
|
295
|
+
await conn.sendResponse(partialResponse, taskId, message.sessionId);
|
|
268
296
|
}
|
|
269
297
|
},
|
|
270
298
|
},
|
package/dist/types.d.ts
CHANGED
|
@@ -52,6 +52,61 @@ export interface A2AResponseMessage {
|
|
|
52
52
|
message: string;
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
|
+
export interface A2AJsonRpcResponse {
|
|
56
|
+
jsonrpc: "2.0";
|
|
57
|
+
id: string;
|
|
58
|
+
result?: A2ATaskArtifactUpdateEvent | A2ATaskStatusUpdateEvent | A2AClearContextResult | A2ATasksCancelResult;
|
|
59
|
+
error?: {
|
|
60
|
+
code: number | string;
|
|
61
|
+
message: string;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export interface A2ATaskArtifactUpdateEvent {
|
|
65
|
+
taskId: string;
|
|
66
|
+
kind: "artifact-update";
|
|
67
|
+
append?: boolean;
|
|
68
|
+
lastChunk?: boolean;
|
|
69
|
+
final: boolean;
|
|
70
|
+
artifact: {
|
|
71
|
+
artifactId: string;
|
|
72
|
+
parts: Array<{
|
|
73
|
+
kind: "text" | "file" | "data";
|
|
74
|
+
text?: string;
|
|
75
|
+
file?: {
|
|
76
|
+
name: string;
|
|
77
|
+
mimeType: string;
|
|
78
|
+
bytes?: string;
|
|
79
|
+
uri?: string;
|
|
80
|
+
};
|
|
81
|
+
data?: any;
|
|
82
|
+
}>;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
export interface A2ATaskStatusUpdateEvent {
|
|
86
|
+
taskId: string;
|
|
87
|
+
kind: "status-update";
|
|
88
|
+
final: boolean;
|
|
89
|
+
status: {
|
|
90
|
+
message: {
|
|
91
|
+
role: "agent";
|
|
92
|
+
parts: Array<{
|
|
93
|
+
kind: "text";
|
|
94
|
+
text: string;
|
|
95
|
+
}>;
|
|
96
|
+
};
|
|
97
|
+
state: "submitted" | "working" | "input-required" | "completed" | "canceled" | "failed" | "unknown";
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
export interface A2AClearContextResult {
|
|
101
|
+
status: {
|
|
102
|
+
state: "cleared" | "failed" | "unknown";
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export interface A2ATasksCancelResult {
|
|
106
|
+
status: {
|
|
107
|
+
state: "canceled" | "failed" | "unknown";
|
|
108
|
+
};
|
|
109
|
+
}
|
|
55
110
|
export interface A2AWebSocketMessage {
|
|
56
111
|
type: "message" | "heartbeat" | "auth" | "error";
|
|
57
112
|
data: A2ARequestMessage | A2AResponseMessage | any;
|
package/dist/websocket.d.ts
CHANGED
|
@@ -23,9 +23,24 @@ export declare class XiaoYiWebSocketManager extends EventEmitter {
|
|
|
23
23
|
*/
|
|
24
24
|
private sendInitMessage;
|
|
25
25
|
/**
|
|
26
|
-
* Send A2A response message
|
|
26
|
+
* Send A2A response message (converts to JSON-RPC 2.0 format)
|
|
27
|
+
* This method is for regular agent responses only
|
|
27
28
|
*/
|
|
28
29
|
sendResponse(response: A2AResponseMessage, taskId: string, sessionId: string): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Send A2A clear context response (uses specific clear context format)
|
|
32
|
+
* Reference: https://developer.huawei.com/consumer/cn/doc/service/clear-context-0000002537681163
|
|
33
|
+
*/
|
|
34
|
+
sendClearContextResponse(requestId: string, sessionId: string, success?: boolean): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Send A2A tasks cancel response (uses specific cancel format)
|
|
37
|
+
* Reference: https://developer.huawei.com/consumer/cn/doc/service/tasks-cancel-0000002537561193
|
|
38
|
+
*/
|
|
39
|
+
sendTasksCancelResponse(requestId: string, sessionId: string, success?: boolean): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Convert A2AResponseMessage to A2A JSON-RPC 2.0 format
|
|
42
|
+
*/
|
|
43
|
+
private convertToJsonRpcFormat;
|
|
29
44
|
/**
|
|
30
45
|
* Send generic outbound message
|
|
31
46
|
*/
|
package/dist/websocket.js
CHANGED
|
@@ -95,21 +95,129 @@ class XiaoYiWebSocketManager extends events_1.EventEmitter {
|
|
|
95
95
|
console.log("Sent clawd_bot_init message");
|
|
96
96
|
}
|
|
97
97
|
/**
|
|
98
|
-
* Send A2A response message
|
|
98
|
+
* Send A2A response message (converts to JSON-RPC 2.0 format)
|
|
99
|
+
* This method is for regular agent responses only
|
|
99
100
|
*/
|
|
100
101
|
async sendResponse(response, taskId, sessionId) {
|
|
101
102
|
if (!this.isReady()) {
|
|
102
103
|
throw new Error("WebSocket not ready");
|
|
103
104
|
}
|
|
105
|
+
// Convert A2AResponseMessage to A2A JSON-RPC 2.0 format
|
|
106
|
+
const jsonRpcResponse = this.convertToJsonRpcFormat(response, taskId);
|
|
104
107
|
const message = {
|
|
105
108
|
msgType: "agent_response",
|
|
106
109
|
agentId: this.config.agentId,
|
|
107
110
|
sessionId: sessionId,
|
|
108
111
|
taskId: taskId,
|
|
109
|
-
msgDetail: JSON.stringify(
|
|
112
|
+
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
110
113
|
};
|
|
111
114
|
this.sendMessage(message);
|
|
112
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Send A2A clear context response (uses specific clear context format)
|
|
118
|
+
* Reference: https://developer.huawei.com/consumer/cn/doc/service/clear-context-0000002537681163
|
|
119
|
+
*/
|
|
120
|
+
async sendClearContextResponse(requestId, sessionId, success = true) {
|
|
121
|
+
if (!this.isReady()) {
|
|
122
|
+
throw new Error("WebSocket not ready");
|
|
123
|
+
}
|
|
124
|
+
const jsonRpcResponse = {
|
|
125
|
+
jsonrpc: "2.0",
|
|
126
|
+
id: requestId,
|
|
127
|
+
result: {
|
|
128
|
+
status: {
|
|
129
|
+
state: success ? "cleared" : "failed"
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
const message = {
|
|
134
|
+
msgType: "agent_response",
|
|
135
|
+
agentId: this.config.agentId,
|
|
136
|
+
sessionId: sessionId,
|
|
137
|
+
taskId: requestId,
|
|
138
|
+
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
139
|
+
};
|
|
140
|
+
this.sendMessage(message);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Send A2A tasks cancel response (uses specific cancel format)
|
|
144
|
+
* Reference: https://developer.huawei.com/consumer/cn/doc/service/tasks-cancel-0000002537561193
|
|
145
|
+
*/
|
|
146
|
+
async sendTasksCancelResponse(requestId, sessionId, success = true) {
|
|
147
|
+
if (!this.isReady()) {
|
|
148
|
+
throw new Error("WebSocket not ready");
|
|
149
|
+
}
|
|
150
|
+
const jsonRpcResponse = {
|
|
151
|
+
jsonrpc: "2.0",
|
|
152
|
+
id: requestId,
|
|
153
|
+
result: {
|
|
154
|
+
status: {
|
|
155
|
+
state: success ? "canceled" : "failed"
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
const message = {
|
|
160
|
+
msgType: "agent_response",
|
|
161
|
+
agentId: this.config.agentId,
|
|
162
|
+
sessionId: sessionId,
|
|
163
|
+
taskId: requestId,
|
|
164
|
+
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
165
|
+
};
|
|
166
|
+
this.sendMessage(message);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Convert A2AResponseMessage to A2A JSON-RPC 2.0 format
|
|
170
|
+
*/
|
|
171
|
+
convertToJsonRpcFormat(response, taskId) {
|
|
172
|
+
// Generate artifact ID
|
|
173
|
+
const artifactId = `artifact_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
174
|
+
// Check if there's an error
|
|
175
|
+
if (response.status === "error" && response.error) {
|
|
176
|
+
return {
|
|
177
|
+
jsonrpc: "2.0",
|
|
178
|
+
id: response.messageId,
|
|
179
|
+
error: {
|
|
180
|
+
code: response.error.code,
|
|
181
|
+
message: response.error.message,
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
// Convert content to artifact parts
|
|
186
|
+
const parts = [];
|
|
187
|
+
if (response.content.type === "text" && response.content.text) {
|
|
188
|
+
parts.push({
|
|
189
|
+
kind: "text",
|
|
190
|
+
text: response.content.text,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
else if (response.content.type === "file") {
|
|
194
|
+
parts.push({
|
|
195
|
+
kind: "file",
|
|
196
|
+
file: {
|
|
197
|
+
name: response.content.fileName || "file",
|
|
198
|
+
mimeType: response.content.mimeType || "application/octet-stream",
|
|
199
|
+
uri: response.content.mediaUrl,
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
// Create TaskArtifactUpdateEvent
|
|
204
|
+
const artifactEvent = {
|
|
205
|
+
taskId: taskId,
|
|
206
|
+
kind: "artifact-update",
|
|
207
|
+
append: false,
|
|
208
|
+
lastChunk: true,
|
|
209
|
+
final: true, // Mark as final since this is the complete response
|
|
210
|
+
artifact: {
|
|
211
|
+
artifactId: artifactId,
|
|
212
|
+
parts: parts,
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
return {
|
|
216
|
+
jsonrpc: "2.0",
|
|
217
|
+
id: response.messageId,
|
|
218
|
+
result: artifactEvent,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
113
221
|
/**
|
|
114
222
|
* Send generic outbound message
|
|
115
223
|
*/
|
|
@@ -212,25 +320,8 @@ class XiaoYiWebSocketManager extends events_1.EventEmitter {
|
|
|
212
320
|
*/
|
|
213
321
|
handleClearMessage(message) {
|
|
214
322
|
console.log(`Received clear message for session: ${message.sessionId}`);
|
|
215
|
-
// Send success response according to A2A spec
|
|
216
|
-
|
|
217
|
-
sessionId: message.sessionId,
|
|
218
|
-
messageId: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
219
|
-
timestamp: Date.now(),
|
|
220
|
-
agentId: this.config.agentId,
|
|
221
|
-
sender: {
|
|
222
|
-
id: this.config.agentId,
|
|
223
|
-
name: "OpenClaw Agent",
|
|
224
|
-
type: "agent",
|
|
225
|
-
},
|
|
226
|
-
content: {
|
|
227
|
-
type: "text",
|
|
228
|
-
text: "Context cleared successfully",
|
|
229
|
-
},
|
|
230
|
-
status: "success",
|
|
231
|
-
};
|
|
232
|
-
// Send response
|
|
233
|
-
this.sendResponse(response, message.id, message.sessionId).catch(error => {
|
|
323
|
+
// Send success response according to A2A spec using the correct format
|
|
324
|
+
this.sendClearContextResponse(message.id, message.sessionId, true).catch(error => {
|
|
234
325
|
console.error("Failed to send clear response:", error);
|
|
235
326
|
});
|
|
236
327
|
// Emit clear event for application to handle
|
|
@@ -258,23 +349,8 @@ class XiaoYiWebSocketManager extends events_1.EventEmitter {
|
|
|
258
349
|
* Send tasks/cancel success response
|
|
259
350
|
*/
|
|
260
351
|
async sendCancelSuccessResponse(sessionId, taskId, requestId) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
messageId: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
264
|
-
timestamp: Date.now(),
|
|
265
|
-
agentId: this.config.agentId,
|
|
266
|
-
sender: {
|
|
267
|
-
id: this.config.agentId,
|
|
268
|
-
name: "OpenClaw Agent",
|
|
269
|
-
type: "agent",
|
|
270
|
-
},
|
|
271
|
-
content: {
|
|
272
|
-
type: "text",
|
|
273
|
-
text: "Task cancelled successfully",
|
|
274
|
-
},
|
|
275
|
-
status: "success",
|
|
276
|
-
};
|
|
277
|
-
await this.sendResponse(response, requestId, sessionId);
|
|
352
|
+
// Use the dedicated tasks cancel response method with correct format
|
|
353
|
+
await this.sendTasksCancelResponse(requestId, sessionId, true);
|
|
278
354
|
// Remove from active tasks
|
|
279
355
|
this.activeTasks.delete(taskId);
|
|
280
356
|
}
|