mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-04 06:30:53 +00:00
fix(channels): isolate sessions per chat and serialize prompts per session
Two bugs caused cross-talk between DM and group conversations: 1. Session routing key only used senderId, so the same user in DM and group shared one ACP session (and conversation context). Now includes chatId: `channelName:senderId:chatId`. 2. Concurrent messages on the same session caused textChunk listener pollution in AcpBridge.prompt(), leaking response text across chats. Added per-session promise queue in ChannelBase to serialize prompts.
This commit is contained in:
parent
33901fb9cd
commit
f3a03d0bdc
2 changed files with 63 additions and 15 deletions
|
|
@ -48,7 +48,7 @@ export class SessionRouter {
|
|||
return `${channelName}:__single__`;
|
||||
case 'user':
|
||||
default:
|
||||
return `${channelName}:${senderId}`;
|
||||
return `${channelName}:${senderId}:${chatId}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -78,18 +78,46 @@ export class SessionRouter {
|
|||
return this.toTarget.get(sessionId);
|
||||
}
|
||||
|
||||
hasSession(channelName: string, senderId: string): boolean {
|
||||
return this.toSession.has(`${channelName}:${senderId}`);
|
||||
hasSession(channelName: string, senderId: string, chatId?: string): boolean {
|
||||
const key = chatId
|
||||
? this.routingKey(channelName, senderId, chatId)
|
||||
: `${channelName}:${senderId}`;
|
||||
// If chatId is provided, do exact lookup; otherwise prefix-scan for any match
|
||||
if (chatId) return this.toSession.has(key);
|
||||
for (const k of this.toSession.keys()) {
|
||||
if (k.startsWith(`${channelName}:${senderId}`)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
removeSession(channelName: string, senderId: string): boolean {
|
||||
const key = `${channelName}:${senderId}`;
|
||||
removeSession(
|
||||
channelName: string,
|
||||
senderId: string,
|
||||
chatId?: string,
|
||||
): boolean {
|
||||
if (chatId) {
|
||||
const key = this.routingKey(channelName, senderId, chatId);
|
||||
return this.deleteByKey(key);
|
||||
}
|
||||
// No chatId: remove all sessions for this sender on this channel
|
||||
let removed = false;
|
||||
const prefix = `${channelName}:${senderId}`;
|
||||
for (const k of [...this.toSession.keys()]) {
|
||||
if (k.startsWith(prefix)) {
|
||||
this.deleteByKey(k);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
if (removed) this.persist();
|
||||
return removed;
|
||||
}
|
||||
|
||||
private deleteByKey(key: string): boolean {
|
||||
const sessionId = this.toSession.get(key);
|
||||
if (!sessionId) return false;
|
||||
this.toSession.delete(key);
|
||||
this.toTarget.delete(sessionId);
|
||||
this.toCwd.delete(sessionId);
|
||||
this.persist();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue