@ynhcj/xiaoyi-channel 0.0.128-next → 0.0.129-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/monitor.js
CHANGED
|
@@ -29,6 +29,27 @@ function createSessionQueue() {
|
|
|
29
29
|
return next;
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Per-session serial queue for steer messages only.
|
|
34
|
+
* Steer messages must run concurrently with the main query (which may block for
|
|
35
|
+
* minutes inside the Pi agent loop), but must be serialized among themselves to
|
|
36
|
+
* prevent concurrent dispatchReplyFromConfig calls that can drop mid-stream
|
|
37
|
+
* steer messages under race conditions.
|
|
38
|
+
*/
|
|
39
|
+
function createSteerQueue() {
|
|
40
|
+
const queues = new Map();
|
|
41
|
+
return (sessionId, task) => {
|
|
42
|
+
const prev = queues.get(sessionId) ?? Promise.resolve();
|
|
43
|
+
const next = prev.then(task, task);
|
|
44
|
+
queues.set(sessionId, next);
|
|
45
|
+
void next.finally(() => {
|
|
46
|
+
if (queues.get(sessionId) === next) {
|
|
47
|
+
queues.delete(sessionId);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return next;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
32
53
|
/**
|
|
33
54
|
* Monitor XY channel WebSocket connections.
|
|
34
55
|
* Keeps the connection alive until abortSignal is triggered.
|
|
@@ -65,6 +86,9 @@ export async function monitorXYProvider(opts = {}) {
|
|
|
65
86
|
const activeMessages = new Set();
|
|
66
87
|
// Create session queue for ordered message processing
|
|
67
88
|
const enqueue = createSessionQueue();
|
|
89
|
+
// Steer-only serial queue: keeps steer messages concurrent with the main
|
|
90
|
+
// query but serialized among themselves to avoid race conditions.
|
|
91
|
+
const enqueueSteer = createSteerQueue();
|
|
68
92
|
// Global gate that serializes dispatch initialization across sessions.
|
|
69
93
|
// When a new session starts dispatching, it acquires this gate and holds it
|
|
70
94
|
// until agent setup (agentTools + wrapStreamFn) is complete, then releases it.
|
|
@@ -118,11 +142,12 @@ export async function monitorXYProvider(opts = {}) {
|
|
|
118
142
|
const steerMode = cfg.messages?.queue?.mode === "steer";
|
|
119
143
|
const hasActiveRun = hasActiveTask(parsed.sessionId);
|
|
120
144
|
if (steerMode && hasActiveRun) {
|
|
121
|
-
// Steer
|
|
122
|
-
|
|
145
|
+
// Steer模式且有活跃任务:通过 steer 专用队列串行执行,与主消息并发但
|
|
146
|
+
// 避免多个 steer 同时进入 dispatchReplyFromConfig 导致中间消息丢失
|
|
147
|
+
logger.log(`[MONITOR-HANDLER] 🔄 STEER MODE: Enqueuing steer for messageKey=${messageKey}`);
|
|
123
148
|
logger.log(`[MONITOR-HANDLER] - sessionId: ${parsed.sessionId}`);
|
|
124
|
-
void task
|
|
125
|
-
logger.error(`XY gateway:
|
|
149
|
+
void enqueueSteer(parsed.sessionId, task).catch((err) => {
|
|
150
|
+
logger.error(`XY gateway: steer queue processing failed for ${messageKey}: ${String(err)}`);
|
|
126
151
|
activeMessages.delete(messageKey);
|
|
127
152
|
});
|
|
128
153
|
}
|
|
@@ -8,7 +8,7 @@ import { getCurrentTaskId, getCurrentMessageId } from "../task-manager.js";
|
|
|
8
8
|
* 仅用于全局 Map 回退路径的清理,不影响 ALS 路径。
|
|
9
9
|
* 工具已改为闭包捕获 ctx,此 TTL 仅作为防止 session 泄漏的最后防线。
|
|
10
10
|
* 正常对话中 registerSession 会刷新 createdAt,所以长对话不受影响。 */
|
|
11
|
-
const SESSION_TTL_MS = 60 * 60 * 1000; //
|
|
11
|
+
const SESSION_TTL_MS = 6 * 60 * 60 * 1000; // 6 hours
|
|
12
12
|
// Use globalThis to ensure a single Map instance across all module copies.
|
|
13
13
|
// The xy_channel plugin may be loaded by openclaw from different module resolution
|
|
14
14
|
// paths (plugin entry vs tool registration), causing session-manager.ts to be
|