From 89f05247eddec4fe53bd1616c6a5563e3ae2427a Mon Sep 17 00:00:00 2001 From: Haileyesus <118998054+blackmammoth@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:04:31 +0300 Subject: [PATCH] fix(shell): use correct session id --- server/index.js | 12 ++- .../services/shell-websocket.service.ts | 82 +++++++++++-------- 2 files changed, 61 insertions(+), 33 deletions(-) diff --git a/server/index.js b/server/index.js index d61c7a9b..4301733b 100755 --- a/server/index.js +++ b/server/index.js @@ -112,7 +112,17 @@ const wss = createWebSocketServer(server, { getPendingApprovalsForSession, }, shell: { - getSessionById: (sessionId) => sessionManager.getSession(sessionId), + resolveProviderSessionId: (sessionId, provider) => { + const dbSession = sessionsDb.getSessionById(sessionId); + const legacyGeminiSession = + provider === 'gemini' ? sessionManager.getSession(sessionId) : null; + + if (dbSession) { + return dbSession.provider_session_id ?? legacyGeminiSession?.cliSessionId ?? null; + } + + return legacyGeminiSession?.cliSessionId; + }, stripAnsiSequences, normalizeDetectedUrl, extractUrlsFromText, diff --git a/server/modules/websocket/services/shell-websocket.service.ts b/server/modules/websocket/services/shell-websocket.service.ts index a29959be..d41b781f 100644 --- a/server/modules/websocket/services/shell-websocket.service.ts +++ b/server/modules/websocket/services/shell-websocket.service.ts @@ -35,7 +35,10 @@ const PTY_SESSION_TIMEOUT = 30 * 60 * 1000; const SHELL_URL_PARSE_BUFFER_LIMIT = 32768; type ShellWebSocketDependencies = { - getSessionById: (sessionId: string) => { cliSessionId?: string } | null | undefined; + resolveProviderSessionId: ( + sessionId: string, + provider: string, + ) => string | null | undefined; stripAnsiSequences: (content: string) => string; normalizeDetectedUrl: (url: string) => string | null; extractUrlsFromText: (content: string) => string[]; @@ -76,6 +79,36 @@ function parseShellMessage(rawMessage: RawData): ShellIncomingMessage | null { return payload as ShellIncomingMessage; } +const SAFE_SESSION_ID_PATTERN = /^[a-zA-Z0-9_.\-:]+$/; + +function resolveResumeSessionId( + message: ShellIncomingMessage, + dependencies: ShellWebSocketDependencies +): string { + const hasSession = readBoolean(message.hasSession); + const sessionId = readString(message.sessionId); + const provider = readString(message.provider, 'claude'); + + if (!hasSession || !sessionId) { + return ''; + } + + let resumeSessionId: string | null | undefined; + try { + resumeSessionId = dependencies.resolveProviderSessionId(sessionId, provider); + } catch (error) { + console.error('Failed to resolve provider session ID:', error); + resumeSessionId = undefined; + } + + const resolvedSessionId = resumeSessionId === undefined ? sessionId : resumeSessionId; + if (!resolvedSessionId || !SAFE_SESSION_ID_PATTERN.test(resolvedSessionId)) { + return ''; + } + + return resolvedSessionId; +} + /** * Resolves provider command line for plain shell and agent-backed shell modes. */ @@ -84,10 +117,9 @@ function buildShellCommand( dependencies: ShellWebSocketDependencies ): string { const hasSession = readBoolean(message.hasSession); - const sessionId = readString(message.sessionId); const initialCommand = readString(message.initialCommand); const provider = readString(message.provider, 'claude'); - const safeSessionIdPattern = /^[a-zA-Z0-9_.\-:]+$/; + const resumeSessionId = resolveResumeSessionId(message, dependencies); const isPlainShell = readBoolean(message.isPlainShell) || (!!initialCommand && !hasSession) || @@ -98,58 +130,43 @@ function buildShellCommand( } if (provider === 'cursor') { - if (hasSession && sessionId) { - return `cursor-agent --resume="${sessionId}"`; + if (resumeSessionId) { + return `cursor-agent --resume="${resumeSessionId}"`; } return 'cursor-agent'; } if (provider === 'codex') { - if (hasSession && sessionId) { + if (resumeSessionId) { if (os.platform() === 'win32') { - return `codex resume "${sessionId}"; if ($LASTEXITCODE -ne 0) { codex }`; + return `codex resume "${resumeSessionId}"; if ($LASTEXITCODE -ne 0) { codex }`; } - return `codex resume "${sessionId}" || codex`; + return `codex resume "${resumeSessionId}" || codex`; } return 'codex'; } if (provider === 'gemini') { const command = initialCommand || 'gemini'; - let resumeId = sessionId; - if (hasSession && sessionId) { - try { - const existingSession = dependencies.getSessionById(sessionId); - if (existingSession && existingSession.cliSessionId) { - resumeId = existingSession.cliSessionId; - if (!safeSessionIdPattern.test(resumeId)) { - resumeId = ''; - } - } - } catch (error) { - console.error('Failed to get Gemini CLI session ID:', error); - } - } - - if (hasSession && resumeId) { - return `${command} --resume "${resumeId}"`; + if (resumeSessionId) { + return `${command} --resume "${resumeSessionId}"`; } return command; } if (provider === 'opencode') { - if (hasSession && sessionId) { - return `opencode --session "${sessionId}"`; + if (resumeSessionId) { + return `opencode --session "${resumeSessionId}"`; } return initialCommand || 'opencode'; } const command = initialCommand || 'claude'; - if (hasSession && sessionId) { + if (resumeSessionId) { if (os.platform() === 'win32') { - return `claude --resume "${sessionId}"; if ($LASTEXITCODE -ne 0) { claude }`; + return `claude --resume "${resumeSessionId}"; if ($LASTEXITCODE -ne 0) { claude }`; } - return `claude --resume "${sessionId}" || claude`; + return `claude --resume "${resumeSessionId}" || claude`; } return command; } @@ -261,6 +278,7 @@ export function handleShellConnection( } const shellCommand = buildShellCommand(data, dependencies); + const resumeSessionId = resolveResumeSessionId(data, dependencies); const shell = os.platform() === 'win32' ? 'powershell.exe' : 'bash'; const shellArgs = os.platform() === 'win32' ? ['-Command', shellCommand] : ['-c', shellCommand]; @@ -406,8 +424,8 @@ export function handleShellConnection( : provider === 'opencode' ? 'OpenCode' : 'Claude'; - welcomeMsg = hasSession - ? `\x1b[36mResuming ${providerName} session ${sessionId} in: ${projectPath}\x1b[0m\r\n` + welcomeMsg = hasSession && resumeSessionId + ? `\x1b[36mResuming ${providerName} session ${resumeSessionId} in: ${projectPath}\x1b[0m\r\n` : `\x1b[36mStarting new ${providerName} session in: ${projectPath}\x1b[0m\r\n`; }