@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 — find the most recently active one by task-manager activity
150
- // Prefer sessions whose taskId matches the current active task (from task-manager),
151
- // with recency as tiebreaker.
152
- let bestMatch = null;
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 latestTaskId = getCurrentTaskId(entry.sessionId);
164
- const recency = latestTaskId ? 2 : 1; // sessions with active task get higher priority
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ynhcj/xiaoyi-channel",
3
- "version": "0.0.87-next",
3
+ "version": "0.0.88-next",
4
4
  "description": "OpenClaw Xiaoyi Channel plugin - Xiaoyi A2A protocol integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",