diff --git a/src/claude/claudeLocal.ts b/src/claude/claudeLocal.ts index a0b9d861..cb005e98 100644 --- a/src/claude/claudeLocal.ts +++ b/src/claude/claudeLocal.ts @@ -5,6 +5,7 @@ import { mkdirSync, existsSync } from "node:fs"; import { randomUUID } from "node:crypto"; import { logger } from "@/ui/logger"; import { claudeCheckSession } from "./utils/claudeCheckSession"; +import { claudeFindLastSession } from "./utils/claudeFindLastSession"; import { getProjectPath } from "./utils/path"; import { projectPath } from "@/projectPath"; import { systemPrompt } from "./utils/systemPrompt"; @@ -33,10 +34,19 @@ export async function claudeLocal(opts: { // - If resuming an existing session: use --resume (Claude keeps the same session ID) // - If starting fresh: generate UUID and pass via --session-id let startFrom = opts.sessionId; - if (opts.sessionId && !claudeCheckSession(opts.sessionId, opts.path)) { - startFrom = null; + + // Convert --continue to --resume: find last session and use existing resume logic + if (!startFrom && opts.claudeArgs?.includes('--continue')) { + const lastSession = claudeFindLastSession(opts.path); + if (lastSession) { + startFrom = lastSession; + logger.debug(`[ClaudeLocal] Converting --continue to --resume ${lastSession}`); + } + // Remove --continue from claudeArgs since we're handling it + opts.claudeArgs = opts.claudeArgs?.filter(arg => arg !== '--continue'); } + // Generate new session ID if not resuming const newSessionId = startFrom ? null : randomUUID(); const effectiveSessionId = startFrom || newSessionId!; diff --git a/src/claude/utils/claudeFindLastSession.ts b/src/claude/utils/claudeFindLastSession.ts new file mode 100644 index 00000000..ffc34d7d --- /dev/null +++ b/src/claude/utils/claudeFindLastSession.ts @@ -0,0 +1,35 @@ +import { readdirSync, statSync, readFileSync } from 'node:fs'; +import { join } from 'node:path'; +import { getProjectPath } from './path'; +import { claudeCheckSession } from './claudeCheckSession'; + +/** + * Finds the most recently modified VALID session in the project directory. + * A valid session must contain at least one message with a uuid field. + * Returns the session ID (filename without .jsonl extension) or null if no valid sessions found. + */ +export function claudeFindLastSession(workingDirectory: string): string | null { + try { + const projectDir = getProjectPath(workingDirectory); + const files = readdirSync(projectDir) + .filter(f => f.endsWith('.jsonl')) + .map(f => { + const sessionId = f.replace('.jsonl', ''); + // Check if this is a valid session + if (claudeCheckSession(sessionId, workingDirectory)) { + return { + name: f, + sessionId: sessionId, + mtime: statSync(join(projectDir, f)).mtime.getTime() + }; + } + return null; + }) + .filter(f => f !== null) + .sort((a, b) => b.mtime - a.mtime); // Most recent valid session first + + return files.length > 0 ? files[0].sessionId : null; + } catch { + return null; + } +} \ No newline at end of file