@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.
- package/dist/src/bot.js +33 -30
- 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
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
logger.log(`[BOT] 🔄
|
|
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
|
-
|
|
259
|
-
|
|
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
|
-
|
|
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
|
|
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:
|
|
478
|
-
CommandBody:
|
|
480
|
+
RawBody: steerCommand,
|
|
481
|
+
CommandBody: steerCommand,
|
|
479
482
|
From: sessionId,
|
|
480
483
|
To: sessionId,
|
|
481
484
|
SessionKey: params.route.sessionKey,
|