adp-openclaw 0.0.5 → 0.0.7
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/package.json +1 -1
- package/src/channel.ts +5 -0
- package/src/monitor.ts +81 -19
package/package.json
CHANGED
package/src/channel.ts
CHANGED
|
@@ -92,6 +92,11 @@ export const adpOpenclawPlugin: ChannelPlugin<ResolvedAdpOpenclawAccount> = {
|
|
|
92
92
|
reactions: false,
|
|
93
93
|
threads: false,
|
|
94
94
|
media: false,
|
|
95
|
+
/**
|
|
96
|
+
* blockStreaming: true 启用 SDK 的块流式功能
|
|
97
|
+
* SDK 会通过 deliver 回调的 info.kind="block" 传递流式块
|
|
98
|
+
*/
|
|
99
|
+
blockStreaming: true,
|
|
95
100
|
},
|
|
96
101
|
reload: { configPrefixes: ["channels.adp-openclaw"] },
|
|
97
102
|
configSchema: {
|
package/src/monitor.ts
CHANGED
|
@@ -22,6 +22,8 @@ const MsgType = {
|
|
|
22
22
|
Pong: "pong",
|
|
23
23
|
Inbound: "inbound",
|
|
24
24
|
Outbound: "outbound",
|
|
25
|
+
OutboundChunk: "outbound_chunk",
|
|
26
|
+
OutboundEnd: "outbound_end",
|
|
25
27
|
Ack: "ack",
|
|
26
28
|
Error: "error",
|
|
27
29
|
ConvHistory: "conv_history",
|
|
@@ -260,29 +262,89 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
260
262
|
...userMetadata,
|
|
261
263
|
});
|
|
262
264
|
|
|
265
|
+
// Generate unique stream ID for this response
|
|
266
|
+
const streamId = `stream-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
267
|
+
let chunkIndex = 0;
|
|
268
|
+
const displayName = inMsg.user?.username || inMsg.from;
|
|
269
|
+
|
|
263
270
|
await runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
264
271
|
ctx,
|
|
265
272
|
cfg: cfg ?? {},
|
|
266
273
|
dispatcherOptions: {
|
|
267
|
-
deliver
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
274
|
+
// Unified deliver callback - handles both streaming blocks and final reply
|
|
275
|
+
// SDK calls this with info.kind = "block" for streaming chunks, "final" for complete response
|
|
276
|
+
deliver: async (payload: { text?: string }, info?: { kind?: string }) => {
|
|
277
|
+
const text = payload.text || "";
|
|
278
|
+
const kind = info?.kind || "final";
|
|
279
|
+
|
|
280
|
+
// Handle streaming block - send chunk via WebSocket
|
|
281
|
+
if (kind === "block" && text) {
|
|
282
|
+
log?.debug?.(`[adp-openclaw] Streaming block[${chunkIndex}] to ${displayName}: ${text.slice(0, 30)}...`);
|
|
283
|
+
|
|
284
|
+
const chunkMsg: WSMessage = {
|
|
285
|
+
type: MsgType.OutboundChunk,
|
|
286
|
+
requestId: generateRequestId(),
|
|
287
|
+
payload: {
|
|
288
|
+
to: inMsg.from,
|
|
289
|
+
chunk: text,
|
|
290
|
+
conversationId: inMsg.conversationId,
|
|
291
|
+
streamId: streamId,
|
|
292
|
+
index: chunkIndex,
|
|
293
|
+
user: inMsg.user,
|
|
294
|
+
},
|
|
295
|
+
timestamp: Date.now(),
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
ws.send(JSON.stringify(chunkMsg));
|
|
299
|
+
chunkIndex++;
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Handle tool result - log but don't send separately
|
|
304
|
+
if (kind === "tool") {
|
|
305
|
+
log?.debug?.(`[adp-openclaw] Tool result received for ${displayName}`);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Handle final reply
|
|
310
|
+
if (kind === "final") {
|
|
311
|
+
log?.info(`[adp-openclaw] Sending final reply to ${displayName}: ${text.slice(0, 50)}...`);
|
|
312
|
+
|
|
313
|
+
// If we have streaming chunks, send stream end message
|
|
314
|
+
if (chunkIndex > 0) {
|
|
315
|
+
const endMsg: WSMessage = {
|
|
316
|
+
type: MsgType.OutboundEnd,
|
|
317
|
+
requestId: generateRequestId(),
|
|
318
|
+
payload: {
|
|
319
|
+
to: inMsg.from,
|
|
320
|
+
text: text,
|
|
321
|
+
conversationId: inMsg.conversationId,
|
|
322
|
+
streamId: streamId,
|
|
323
|
+
totalChunks: chunkIndex,
|
|
324
|
+
user: inMsg.user,
|
|
325
|
+
},
|
|
326
|
+
timestamp: Date.now(),
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
ws.send(JSON.stringify(endMsg));
|
|
330
|
+
} else {
|
|
331
|
+
// No streaming chunks were sent, send as regular outbound message
|
|
332
|
+
const outMsg: WSMessage = {
|
|
333
|
+
type: MsgType.Outbound,
|
|
334
|
+
requestId: generateRequestId(),
|
|
335
|
+
payload: {
|
|
336
|
+
to: inMsg.from,
|
|
337
|
+
text: text,
|
|
338
|
+
conversationId: inMsg.conversationId,
|
|
339
|
+
// Include user info in response for tracing
|
|
340
|
+
user: inMsg.user,
|
|
341
|
+
},
|
|
342
|
+
timestamp: Date.now(),
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
ws.send(JSON.stringify(outMsg));
|
|
346
|
+
}
|
|
347
|
+
}
|
|
286
348
|
},
|
|
287
349
|
onError: (err: Error) => {
|
|
288
350
|
log?.error(`[adp-openclaw] Reply error: ${err.message}`);
|