@ynhcj/xiaoyi 2.0.6 → 2.0.8
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 +24 -38
- package/dist/types.d.ts +19 -18
- package/dist/websocket.d.ts +1 -1
- package/dist/websocket.js +9 -5
- package/package.json +1 -1
package/dist/channel.js
CHANGED
|
@@ -211,39 +211,49 @@ exports.xiaoyiPlugin = {
|
|
|
211
211
|
const { getXiaoYiRuntime } = require("./runtime");
|
|
212
212
|
const runtime = getXiaoYiRuntime();
|
|
213
213
|
console.log(`XiaoYi: [Message Handler] Using runtime instance: ${runtime.getInstanceId()}`);
|
|
214
|
-
// Store sessionId -> taskId mapping in runtime
|
|
215
|
-
runtime.setTaskIdForSession(message.sessionId, message.id);
|
|
214
|
+
// Store sessionId -> taskId mapping in runtime (use params.id as taskId)
|
|
215
|
+
runtime.setTaskIdForSession(message.sessionId, message.params.id);
|
|
216
216
|
// Get PluginRuntime from our runtime wrapper
|
|
217
217
|
const pluginRuntime = runtime.getPluginRuntime();
|
|
218
218
|
if (!pluginRuntime) {
|
|
219
219
|
console.error("PluginRuntime not available");
|
|
220
220
|
return;
|
|
221
221
|
}
|
|
222
|
+
// Extract text content from parts array (ignore kind: "data" as per user request)
|
|
223
|
+
let bodyText = "";
|
|
224
|
+
for (const part of message.params.message.parts) {
|
|
225
|
+
if (part.kind === "text" && part.text) {
|
|
226
|
+
bodyText += part.text;
|
|
227
|
+
}
|
|
228
|
+
// TODO: Handle file parts if needed in the future
|
|
229
|
+
}
|
|
230
|
+
// Determine sender ID from role
|
|
231
|
+
const senderId = message.params.message.role === "user" ? "user" : message.agentId;
|
|
222
232
|
// Build MsgContext for OpenClaw's message pipeline
|
|
223
233
|
const msgContext = {
|
|
224
|
-
Body:
|
|
225
|
-
From:
|
|
234
|
+
Body: bodyText,
|
|
235
|
+
From: senderId,
|
|
226
236
|
To: message.sessionId,
|
|
227
237
|
SessionKey: `xiaoyi:${resolvedAccount.accountId}:${message.sessionId}`,
|
|
228
238
|
AccountId: resolvedAccount.accountId,
|
|
229
|
-
MessageSid: message.
|
|
230
|
-
Timestamp:
|
|
239
|
+
MessageSid: message.id, // Use top-level id as message sequence number
|
|
240
|
+
Timestamp: Date.now(), // Generate timestamp since new format doesn't include it
|
|
231
241
|
Provider: "xiaoyi",
|
|
232
242
|
Surface: "xiaoyi",
|
|
233
243
|
ChatType: "direct",
|
|
234
|
-
SenderName: message.sender
|
|
235
|
-
SenderId:
|
|
244
|
+
SenderName: message.params.message.role, // Use role as sender name
|
|
245
|
+
SenderId: senderId,
|
|
236
246
|
OriginatingChannel: "xiaoyi",
|
|
237
247
|
};
|
|
238
|
-
// Use the correct API to dispatch the message
|
|
248
|
+
// Use the correct API to dispatch the message (non-streaming mode)
|
|
239
249
|
try {
|
|
240
250
|
await pluginRuntime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
241
251
|
ctx: msgContext,
|
|
242
252
|
cfg: config,
|
|
243
253
|
dispatcherOptions: {
|
|
244
254
|
deliver: async (payload) => {
|
|
245
|
-
console.log("XiaoYi: Delivering final response:", payload);
|
|
246
|
-
// Send final response back through WebSocket
|
|
255
|
+
console.log("XiaoYi: Delivering final response:", payload.text?.substring(0, 100) + "...");
|
|
256
|
+
// Send final response back through WebSocket (non-streaming, complete message)
|
|
247
257
|
const taskId = runtime.getTaskIdForSession(message.sessionId) || `task_${Date.now()}`;
|
|
248
258
|
const response = {
|
|
249
259
|
sessionId: message.sessionId,
|
|
@@ -264,37 +274,13 @@ exports.xiaoyiPlugin = {
|
|
|
264
274
|
const conn = runtime.getConnection();
|
|
265
275
|
if (conn) {
|
|
266
276
|
await conn.sendResponse(response, taskId, message.sessionId);
|
|
267
|
-
console.log("XiaoYi: Final response sent successfully");
|
|
277
|
+
console.log("XiaoYi: Final response sent successfully (non-streaming mode)");
|
|
268
278
|
}
|
|
269
279
|
},
|
|
270
280
|
},
|
|
271
281
|
replyOptions: {
|
|
272
|
-
|
|
273
|
-
|
|
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);
|
|
296
|
-
}
|
|
297
|
-
},
|
|
282
|
+
// Disable streaming by removing onPartialReply callback
|
|
283
|
+
// This ensures all responses are buffered and delivered only once at the end
|
|
298
284
|
},
|
|
299
285
|
});
|
|
300
286
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
export interface A2ARequestMessage {
|
|
2
2
|
agentId: string;
|
|
3
3
|
sessionId: string;
|
|
4
|
+
jsonrpc: "2.0";
|
|
4
5
|
id: string;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
sender: {
|
|
6
|
+
method: "message/stream";
|
|
7
|
+
params: {
|
|
8
8
|
id: string;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
9
|
+
sessionId: string;
|
|
10
|
+
agentLoginSessionId?: string;
|
|
11
|
+
message: {
|
|
12
|
+
role: "user" | "agent";
|
|
13
|
+
parts: Array<{
|
|
14
|
+
kind: "text" | "file" | "data";
|
|
15
|
+
text?: string;
|
|
16
|
+
file?: {
|
|
17
|
+
name: string;
|
|
18
|
+
mimeType: string;
|
|
19
|
+
bytes?: string;
|
|
20
|
+
uri?: string;
|
|
21
|
+
};
|
|
22
|
+
data?: any;
|
|
23
|
+
}>;
|
|
24
|
+
};
|
|
24
25
|
};
|
|
25
26
|
}
|
|
26
27
|
export interface A2AResponseMessage {
|
package/dist/websocket.d.ts
CHANGED
|
@@ -76,7 +76,7 @@ export declare class XiaoYiWebSocketManager extends EventEmitter {
|
|
|
76
76
|
*/
|
|
77
77
|
sendCancelSuccessResponse(sessionId: string, taskId: string, requestId: string): Promise<void>;
|
|
78
78
|
/**
|
|
79
|
-
* Type guard for A2A request messages
|
|
79
|
+
* Type guard for A2A request messages (JSON-RPC 2.0 format)
|
|
80
80
|
*/
|
|
81
81
|
private isA2ARequestMessage;
|
|
82
82
|
/**
|
package/dist/websocket.js
CHANGED
|
@@ -355,17 +355,21 @@ class XiaoYiWebSocketManager extends events_1.EventEmitter {
|
|
|
355
355
|
this.activeTasks.delete(taskId);
|
|
356
356
|
}
|
|
357
357
|
/**
|
|
358
|
-
* Type guard for A2A request messages
|
|
358
|
+
* Type guard for A2A request messages (JSON-RPC 2.0 format)
|
|
359
359
|
*/
|
|
360
360
|
isA2ARequestMessage(data) {
|
|
361
361
|
return data &&
|
|
362
362
|
typeof data.agentId === "string" &&
|
|
363
363
|
typeof data.sessionId === "string" &&
|
|
364
|
+
data.jsonrpc === "2.0" &&
|
|
364
365
|
typeof data.id === "string" &&
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
data.
|
|
368
|
-
data.
|
|
366
|
+
data.method === "message/stream" &&
|
|
367
|
+
data.params &&
|
|
368
|
+
typeof data.params.id === "string" &&
|
|
369
|
+
typeof data.params.sessionId === "string" &&
|
|
370
|
+
data.params.message &&
|
|
371
|
+
typeof data.params.message.role === "string" &&
|
|
372
|
+
Array.isArray(data.params.message.parts);
|
|
369
373
|
}
|
|
370
374
|
/**
|
|
371
375
|
* Start protocol-level heartbeat (ping/pong)
|