@ynhcj/xiaoyi-channel 0.0.87-next → 0.0.88-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.
|
@@ -19,6 +19,13 @@ if (!_g.__xyActiveSessions) {
|
|
|
19
19
|
_g.__xyActiveSessions = new Map();
|
|
20
20
|
}
|
|
21
21
|
const activeSessions = _g.__xyActiveSessions;
|
|
22
|
+
// Track the most recently registered sessionKey for reliable fallback
|
|
23
|
+
// when AsyncLocalStorage context is lost across openclaw's embedded runner boundary.
|
|
24
|
+
if (!_g.__xyLastRegisteredSessionKey) {
|
|
25
|
+
_g.__xyLastRegisteredSessionKey = "";
|
|
26
|
+
}
|
|
27
|
+
const getLastRegisteredKey = () => _g.__xyLastRegisteredSessionKey;
|
|
28
|
+
const setLastRegisteredKey = (key) => { _g.__xyLastRegisteredSessionKey = key; };
|
|
22
29
|
// AsyncLocalStorage for thread-safe session context isolation
|
|
23
30
|
const asyncLocalStorage = new AsyncLocalStorage();
|
|
24
31
|
/**
|
|
@@ -26,6 +33,8 @@ const asyncLocalStorage = new AsyncLocalStorage();
|
|
|
26
33
|
* Should be called when starting to process a message.
|
|
27
34
|
*/
|
|
28
35
|
export function registerSession(sessionKey, context) {
|
|
36
|
+
// Track last registered session for reliable ALS-miss fallback
|
|
37
|
+
setLastRegisteredKey(sessionKey);
|
|
29
38
|
const existing = activeSessions.get(sessionKey);
|
|
30
39
|
if (existing) {
|
|
31
40
|
// 更新上下文,增加引用计数,刷新存活时间
|
|
@@ -146,29 +155,32 @@ export function getCurrentSessionContext(sessionKey) {
|
|
|
146
155
|
}
|
|
147
156
|
return null;
|
|
148
157
|
}
|
|
149
|
-
// 2c. Multiple sessions —
|
|
150
|
-
//
|
|
151
|
-
//
|
|
152
|
-
|
|
158
|
+
// 2c. Multiple sessions — prefer the last registered session.
|
|
159
|
+
// This is the most reliable heuristic when ALS is lost across openclaw's
|
|
160
|
+
// embedded runner boundary: registerSession() is called just before
|
|
161
|
+
// runWithSessionContext(), and agentTools() is called during tool
|
|
162
|
+
// compilation shortly after. The last registered session is always the
|
|
163
|
+
// one currently being set up.
|
|
164
|
+
const lastKey = getLastRegisteredKey();
|
|
165
|
+
if (lastKey) {
|
|
166
|
+
const lastEntry = activeSessions.get(lastKey);
|
|
167
|
+
if (lastEntry) {
|
|
168
|
+
console.log(`[SESSION-MGR] 🎯 using lastRegistered session: ${lastKey}`);
|
|
169
|
+
const { refCount, createdAt, ...context } = lastEntry;
|
|
170
|
+
return enrichWithLatestTaskInfo(context);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// 2d. Fallback: find any non-stale session
|
|
153
174
|
const now = Date.now();
|
|
154
175
|
for (const [key, entry] of activeSessions) {
|
|
155
|
-
// Skip stale sessions
|
|
156
176
|
if (now - entry.createdAt > SESSION_TTL_MS) {
|
|
157
|
-
logger.log(`[SESSION-MGR] stale session detected, cleaning up: ${key}`);
|
|
158
177
|
configManager.clearSession(entry.sessionId);
|
|
159
178
|
toolCallNudgeManager.clearSession(key);
|
|
160
179
|
activeSessions.delete(key);
|
|
161
180
|
continue;
|
|
162
181
|
}
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
if (!bestMatch || recency > bestMatch.recency) {
|
|
166
|
-
const { refCount, createdAt, ...context } = entry;
|
|
167
|
-
bestMatch = { context, recency };
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
if (bestMatch) {
|
|
171
|
-
return enrichWithLatestTaskInfo(bestMatch.context);
|
|
182
|
+
const { refCount, createdAt, ...context } = entry;
|
|
183
|
+
return enrichWithLatestTaskInfo(context);
|
|
172
184
|
}
|
|
173
185
|
return null;
|
|
174
186
|
}
|