@ynhcj/xiaoyi-channel 0.0.133-next → 0.0.134-next

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.
Files changed (2) hide show
  1. package/dist/src/bot.js +33 -30
  2. package/package.json +1 -1
package/dist/src/bot.js CHANGED
@@ -197,11 +197,25 @@ export async function handleXYMessage(params) {
197
197
  logger.error(`[SELF_EVOLUTION] Failed to append inline keyword nudge: ${String(selfEvolutionError)}`);
198
198
  }
199
199
  }
200
- // 🔑 Steer消息加 /steer 前缀,触发core的 queueEmbeddedPiMessage
201
- if (isUpdate && textForAgent) {
202
- textForAgent = `/steer ${textForAgent}`;
203
- logger.log(`[BOT] 🔄 Prepended /steer for steer injection`);
200
+ // 🔑 Steer消息: 跳过旧路径直接进入 streaming-signal 队列
201
+ // /steer 前缀由 dispatchSteerWhenReady 内部添加
202
+ if (isUpdate) {
203
+ logger.log(`[BOT] 🔄 Steer message enqueuing to streaming-signal queue`);
204
+ await enqueueSteer({
205
+ sessionId: parsed.sessionId,
206
+ sessionKey: route.sessionKey,
207
+ steerText: textForAgent, // 原始文本,不带 /steer 前缀
208
+ cfg,
209
+ runtime,
210
+ parsed,
211
+ route,
212
+ deviceType,
213
+ });
214
+ logger.log(`[BOT] ✅ Steer queue completed for session: ${parsed.sessionId}`);
215
+ logger.log(`xy: dispatch complete (session=${parsed.sessionId})`);
216
+ return;
204
217
  }
218
+ // ── First message (non-steer) path below ──────────────────────
205
219
  // File download — only for real user messages, steer injections have no files
206
220
  let mediaPayload = {};
207
221
  if (!skipReg) {
@@ -250,14 +264,9 @@ export async function handleXYMessage(params) {
250
264
  ReplyToBody: undefined, // A2A protocol doesn't support reply/quote
251
265
  ...mediaPayload,
252
266
  });
253
- // 🔑 Dynamic steer state: when isUpdate (second message), start as steered=true
254
- // so the dispatcher skips all user-facing callbacks (deliver, onIdle, etc.)
255
- // and onSettled skips cleanup.
256
- const steerState = { steered: isUpdate };
257
267
  // 🔑 第一条消息创建 streaming 信号(provider.ts 的 wrapStreamFn 触发)
258
- if (!isUpdate) {
259
- createStreamingSignal(parsed.sessionId);
260
- }
268
+ createStreamingSignal(parsed.sessionId);
269
+ const steerState = { steered: false };
261
270
  // 🔑 创建dispatcher
262
271
  logger.log(`[BOT-DISPATCHER] 🎯 Creating reply dispatcher`);
263
272
  logger.log(`[BOT-DISPATCHER] - taskId: ${parsed.taskId}`);
@@ -335,19 +344,6 @@ export async function handleXYMessage(params) {
335
344
  return dispatchPromise;
336
345
  },
337
346
  });
338
- // 🔑 Steer 串行队列:等待 streaming 信号后 dispatch,多个 steer 按顺序处理
339
- if (isUpdate) {
340
- await enqueueSteer({
341
- sessionId: parsed.sessionId,
342
- sessionKey: route.sessionKey,
343
- steerText: textForAgent,
344
- cfg,
345
- runtime,
346
- parsed,
347
- route,
348
- deviceType,
349
- });
350
- }
351
347
  logger.log(`[BOT] ✅ Dispatcher completed for session: ${parsed.sessionId}`);
352
348
  logger.log(`xy: dispatch complete (session=${parsed.sessionId})`);
353
349
  }
@@ -403,7 +399,15 @@ function buildXYMediaPayload(mediaList) {
403
399
  MediaTypes: mediaTypes.length > 0 ? mediaTypes : undefined,
404
400
  };
405
401
  }
406
- const streamingSignals = new Map();
402
+ // Use globalThis to survive module deduplication — provider.ts may load a
403
+ // different copy of bot.ts, so a plain module-level Map would be two objects.
404
+ const _g = globalThis;
405
+ if (!_g.__xyStreamingSignals)
406
+ _g.__xyStreamingSignals = new Map();
407
+ if (!_g.__xySteerQueues)
408
+ _g.__xySteerQueues = new Map();
409
+ const streamingSignals = _g.__xyStreamingSignals;
410
+ const steerQueues = _g.__xySteerQueues;
407
411
  /**
408
412
  * 由 provider.ts 在 wrapStreamFn 调用时触发。
409
413
  * 这是模型 API 被调用的精确时刻,此时 isStreaming 一定为 true。
@@ -424,8 +428,6 @@ function createStreamingSignal(sessionId) {
424
428
  logger.log(`[STEER-QUEUE] 🟢 Streaming signal created for session ${sessionId}`);
425
429
  return signal;
426
430
  }
427
- /** Per-session 串行队列:保证同一 session 的 steer 消息按顺序处理 */
428
- const steerQueues = new Map();
429
431
  /**
430
432
  * 将 steer 消息放入 per-session 串行队列。
431
433
  * 等待第一条消息的 streaming 信号(deliver 首次触发),然后 dispatch。
@@ -463,7 +465,8 @@ async function dispatchSteerWhenReady(params) {
463
465
  // 3. 构建 dispatch 上下文并 dispatch /steer
464
466
  const core = getXYRuntime();
465
467
  const speaker = sessionId;
466
- const messageBody = `${speaker}: ${steerText}`;
468
+ const steerCommand = `/steer ${steerText}`;
469
+ const messageBody = `${speaker}: ${steerCommand}`;
467
470
  const envelopeOptions = core.channel.reply.resolveEnvelopeFormatOptions(params.cfg);
468
471
  const body = core.channel.reply.formatAgentEnvelope({
469
472
  channel: "xiaoyi-channel",
@@ -474,8 +477,8 @@ async function dispatchSteerWhenReady(params) {
474
477
  });
475
478
  const ctxPayload = core.channel.reply.finalizeInboundContext({
476
479
  Body: body,
477
- RawBody: steerText,
478
- CommandBody: steerText,
480
+ RawBody: steerCommand,
481
+ CommandBody: steerCommand,
479
482
  From: sessionId,
480
483
  To: sessionId,
481
484
  SessionKey: params.route.sessionKey,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ynhcj/xiaoyi-channel",
3
- "version": "0.0.133-next",
3
+ "version": "0.0.134-next",
4
4
  "description": "OpenClaw Xiaoyi Channel plugin - Xiaoyi A2A protocol integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",