openclaw-xiaoyou 1.3.9 → 1.4.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-xiaoyou",
3
- "version": "1.3.9",
3
+ "version": "1.4.1",
4
4
  "type": "module",
5
5
  "description": "Xiaoyou channel plugin for OpenClaw — connects enterprise services via persistent outbound WebSocket",
6
6
  "openclaw": {
package/src/channel.ts CHANGED
@@ -11,6 +11,8 @@ import { createEnterpriseClient, type EnterpriseClient } from "./enterprise-clie
11
11
  // ─── 运行时状态 ──────────────────────────────────────
12
12
 
13
13
  let _client: EnterpriseClient | null = null;
14
+ /** 记录最后一个活跃的 conversationId,用于 cron delivery 兜底 */
15
+ let _lastConversationId: string | null = null;
14
16
 
15
17
  let _runtime: any = null;
16
18
  export function setRuntime(rt: any) { _runtime = rt; }
@@ -138,6 +140,9 @@ export const xiayouPlugin = {
138
140
  const conversationId = msg.conversationId;
139
141
  const inboundMessageId = msg.messageId;
140
142
  const text = msg.text ?? "";
143
+
144
+ // 记录最后活跃的 conversationId,供 cron delivery 兜底使用
145
+ _lastConversationId = conversationId;
141
146
  const accountId = account?.accountId || "default";
142
147
 
143
148
  // 1. 路由
@@ -155,7 +160,7 @@ export const xiayouPlugin = {
155
160
  channel: "Xiaoyou",
156
161
  from: fromLabel,
157
162
  timestamp: Date.now(),
158
- body: text,
163
+ body: `[系统信息] 当前 conversationId: ${conversationId} | 当前 senderId: ${senderId}\n\n${text}`,
159
164
  chatType: "direct",
160
165
  sender: { name: senderName, id: senderId },
161
166
  envelope: envelopeOptions,
@@ -207,6 +212,7 @@ export const xiayouPlugin = {
207
212
  conversationId,
208
213
  messageId: replyMessageId,
209
214
  replyToMessageId: inboundMessageId,
215
+ senderId,
210
216
  text: textToSend,
211
217
  streamStatus: "chunk",
212
218
  seq: chunkSeq++,
@@ -223,6 +229,7 @@ export const xiayouPlugin = {
223
229
  conversationId,
224
230
  messageId: replyMessageId,
225
231
  replyToMessageId: inboundMessageId,
232
+ senderId,
226
233
  text: fullText,
227
234
  streamStatus: "end",
228
235
  timestamp: Date.now(),
@@ -240,6 +247,7 @@ export const xiayouPlugin = {
240
247
  conversationId,
241
248
  messageId: replyMessageId,
242
249
  replyToMessageId: inboundMessageId,
250
+ senderId,
243
251
  text: fullText,
244
252
  streamStatus: "end",
245
253
  timestamp: Date.now(),
@@ -273,6 +281,22 @@ export const xiayouPlugin = {
273
281
  },
274
282
  },
275
283
 
284
+ // ── Target 解析(让 Gateway delivery 系统识别 xiaoyou target)──
285
+ normalizeTarget: (target: string) => {
286
+ // 去掉可能的 xiaoyou: 前缀
287
+ const normalized = target.replace(/^xiaoyou:/i, "");
288
+ return { ok: true, to: normalized };
289
+ },
290
+
291
+ targetResolver: {
292
+ looksLikeId: (id: string): boolean => {
293
+ // 支持 conv-xxx 格式和任意非空字符串
294
+ const normalized = id.replace(/^xiaoyou:/i, "");
295
+ return normalized.length > 0;
296
+ },
297
+ hint: "conversationId (e.g. conv-125)",
298
+ },
299
+
276
300
  // ── Outbound 出站(符合 ChannelPluginOutbound 接口)──────
277
301
  outbound: {
278
302
  deliveryMode: "direct" as const,
@@ -283,17 +307,22 @@ export const xiayouPlugin = {
283
307
  return { channel: "xiaoyou", error: new Error("xiaoyou: not connected") };
284
308
  }
285
309
 
310
+ // 如果 to 为空,使用最后活跃的 conversationId 兜底
311
+ const targetTo = to || _lastConversationId || "cron-delivery";
312
+
286
313
  const reply = {
287
314
  type: "reply" as const,
288
- conversationId: to || "cron-delivery",
315
+ conversationId: targetTo,
289
316
  messageId: `xiaoyou-${Date.now()}`,
290
317
  replyToMessageId: replyToId,
318
+ senderId: to,
319
+ source: "scheduled_task" as const,
291
320
  text: text,
292
321
  timestamp: Date.now(),
293
322
  };
294
323
 
295
324
  _client.sendReply(reply);
296
- console.log(`[xiaoyou][outbound] sendText to=${to}, text=${text?.substring(0, 50)}`);
325
+ console.log(`[xiaoyou][outbound] sendText to=${targetTo}, text=${text?.substring(0, 50)}`);
297
326
  return { channel: "xiaoyou", messageId: reply.messageId };
298
327
  },
299
328
 
@@ -302,18 +331,22 @@ export const xiayouPlugin = {
302
331
  return { channel: "xiaoyou", error: new Error("xiaoyou: not connected") };
303
332
  }
304
333
 
334
+ const targetTo = to || _lastConversationId || "cron-delivery";
335
+
305
336
  const reply = {
306
337
  type: "reply" as const,
307
- conversationId: to || "cron-delivery",
338
+ conversationId: targetTo,
308
339
  messageId: `xiaoyou-${Date.now()}`,
309
340
  replyToMessageId: replyToId,
341
+ senderId: to,
342
+ source: "scheduled_task" as const,
310
343
  text: text ?? "",
311
344
  mediaUrls: mediaUrl ? [mediaUrl] : [],
312
345
  timestamp: Date.now(),
313
346
  };
314
347
 
315
348
  _client.sendReply(reply);
316
- console.log(`[xiaoyou][outbound] sendMedia to=${to}`);
349
+ console.log(`[xiaoyou][outbound] sendMedia to=${targetTo}`);
317
350
  return { channel: "xiaoyou", messageId: reply.messageId };
318
351
  },
319
352
  },
package/src/types.ts CHANGED
@@ -60,10 +60,13 @@ export type OutboundReply = {
60
60
  conversationId: string;
61
61
  messageId: string;
62
62
  replyToMessageId?: string;
63
+ senderId?: string;
63
64
  text: string;
64
65
  mediaUrls?: string[];
65
66
  agentId?: string;
66
67
  timestamp: number;
68
+ /** 消息来源标识:scheduled_task=定时任务推送,不传=正常对话回复 */
69
+ source?: "scheduled_task";
67
70
  /** 流式标记:chunk=增量片段, end=流结束, 不传=一次性完整回复 */
68
71
  streamStatus?: StreamStatus;
69
72
  /** 流式片段序号(仅 streamStatus="chunk" 时有值,从 0 开始) */