user-scoped channel sessions, whatsapp disconnect cleanup, browser relay token fix
Channel session IDs now include userId (channel-{provider}-{userId}-{contextId})
to prevent cross-user contamination in multi-user setups. WhatsApp disconnect
properly logs out and clears cached auth. Browser relay uses server-derived token
directly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,10 @@ const sessionCallbacks = new Map<string, EventCallback>();
|
||||
// Channel model overrides — survive session eviction/recreation
|
||||
const channelModelOverrides = new Map<string, string>();
|
||||
|
||||
function buildSessionId(context: string, userId: number, contextId: string): string {
|
||||
return `channel-${context}-${userId}-${contextId}`;
|
||||
}
|
||||
|
||||
async function getUserDefaultModel(userId: number): Promise<string | null> {
|
||||
try {
|
||||
const settings = await getUserSettings(userId);
|
||||
@@ -49,14 +53,14 @@ async function getUserDefaultModel(userId: number): Promise<string | null> {
|
||||
}
|
||||
}
|
||||
|
||||
export function getSessionModel(context: string, contextId: string): string | null {
|
||||
const sessionId = `channel-${context}-${contextId}`;
|
||||
export function getSessionModel(context: string, userId: number, contextId: string): string | null {
|
||||
const sessionId = buildSessionId(context, userId, contextId);
|
||||
const session = sessionManager.getSession(sessionId);
|
||||
return session?.model ?? channelModelOverrides.get(sessionId) ?? null;
|
||||
}
|
||||
|
||||
export function setSessionModel(context: string, contextId: string, model: string): void {
|
||||
const sessionId = `channel-${context}-${contextId}`;
|
||||
export function setSessionModel(context: string, userId: number, contextId: string, model: string): void {
|
||||
const sessionId = buildSessionId(context, userId, contextId);
|
||||
// Store override independently of session — survives idle eviction
|
||||
channelModelOverrides.set(sessionId, model);
|
||||
|
||||
@@ -76,8 +80,8 @@ export function setSessionModel(context: string, contextId: string, model: strin
|
||||
}
|
||||
|
||||
export async function sendAndAwait(params: SendAndAwaitParams): Promise<SendAndAwaitResult> {
|
||||
const { context, contextId } = params;
|
||||
const sessionId = `channel-${context}-${contextId}`;
|
||||
const { userId, context, contextId } = params;
|
||||
const sessionId = buildSessionId(context, userId, contextId);
|
||||
|
||||
// Serialize per session — if two messages arrive at once, second waits for first
|
||||
const existing = sessionLocks.get(sessionId) ?? Promise.resolve();
|
||||
@@ -112,19 +116,20 @@ async function doSend(sessionId: string, params: SendAndAwaitParams): Promise<Se
|
||||
const homeDir = getHomeDir(email);
|
||||
const cwd = homeDir;
|
||||
|
||||
// Resolve model: explicit param > channel override > existing session model > user default > system default
|
||||
// Resolve model: explicit param > !model override > user default > existing session > system default
|
||||
const existingSession = sessionManager.getSession(sessionId);
|
||||
let model = params.model ?? channelModelOverrides.get(sessionId) ?? existingSession?.model;
|
||||
const override = channelModelOverrides.get(sessionId);
|
||||
let model = params.model ?? override;
|
||||
if (!model) {
|
||||
const userDefault = await getUserDefaultModel(userId);
|
||||
model = userDefault ?? DEFAULT_MODEL;
|
||||
model = userDefault ?? existingSession?.model ?? DEFAULT_MODEL;
|
||||
}
|
||||
|
||||
const session = sessionManager.getOrCreate(sessionId, email, cwd, model, null, context, contextId);
|
||||
session.model = model;
|
||||
session.meta.model = model;
|
||||
session.userId = userId;
|
||||
logger.info('Channel doSend', { sessionId, model, hasProcess: !!session.piProcess });
|
||||
logger.info('Channel doSend', { sessionId, model, hasProcess: !!session.piProcess, userId, email });
|
||||
|
||||
return new Promise<SendAndAwaitResult>((resolve, reject) => {
|
||||
let resultText = '';
|
||||
@@ -296,7 +301,7 @@ async function doSend(sessionId: string, params: SendAndAwaitParams): Promise<Se
|
||||
}
|
||||
});
|
||||
|
||||
logger.info('Spawned Pi for channel session', { sessionId, model, context });
|
||||
logger.info('Spawned Pi for channel session', { sessionId, model, context, userId, email });
|
||||
}
|
||||
|
||||
// Add user message
|
||||
|
||||
Reference in New Issue
Block a user