From b45257a38d62c7ff60971c32d59ee37cef01c8f6 Mon Sep 17 00:00:00 2001 From: cruldra Date: Thu, 16 Jul 2026 01:51:08 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(vscode):=20resume=20?= =?UTF-8?q?=E4=BC=9A=E8=AF=9D=E7=94=A8=20resolveWorktreePath=20=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E8=AF=AF=E5=88=A4=20worktree=20=E5=B7=B2=E6=B8=85?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vscode/src/git/worktree.test.ts | 22 +++++++++++++++++++++- vscode/src/panel/handlers/sessions.ts | 7 ++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/vscode/src/git/worktree.test.ts b/vscode/src/git/worktree.test.ts index b9ef57d..b1bfa1e 100644 --- a/vscode/src/git/worktree.test.ts +++ b/vscode/src/git/worktree.test.ts @@ -3,7 +3,27 @@ import { existsSync, mkdtempSync, rmSync } from 'node:fs' import * as os from 'node:os' import * as path from 'node:path' import { describe, expect, it } from 'vitest' -import { findProcessesUsingWorktree } from './worktree' +import { findProcessesUsingWorktree, resolveWorktreePath } from './worktree' + +describe('resolveWorktreePath', () => { + const workspaceRoot = '/workspace/project' + + it('绝对路径原样返回', () => { + const abs = '/home/user/Sources/worktree/repo/session-foo' + expect(resolveWorktreePath(abs, workspaceRoot)).toBe(abs) + }) + + it('~/... 展开为 home 下路径', () => { + const home = os.homedir() + expect(resolveWorktreePath('~/Sources/worktree/repo/session-foo', workspaceRoot)) + .toBe(path.join(home, 'Sources/worktree/repo/session-foo')) + }) + + it('相对路径拼到 workspaceRoot 下', () => { + expect(resolveWorktreePath('.claude/worktrees/abc123', workspaceRoot)) + .toBe(path.join(workspaceRoot, '.claude/worktrees/abc123')) + }) +}) // 检测靠扫 /proc,只有 Linux 有;别的平台整组跳过(函数本身也会返回空)。 describe.runIf(existsSync('/proc'))('findProcessesUsingWorktree', () => { diff --git a/vscode/src/panel/handlers/sessions.ts b/vscode/src/panel/handlers/sessions.ts index 92956b5..559840d 100644 --- a/vscode/src/panel/handlers/sessions.ts +++ b/vscode/src/panel/handlers/sessions.ts @@ -84,15 +84,16 @@ export async function handleResumeSession(panel: KanbanWebviewPanel, sessionId: return } const workspaceRoot = workspace.workspaceFolders?.[0]?.uri.fsPath - // Implementation sessions live in a worktree; the caller can pass a - // workspace-relative `relCwd` so `--resume` runs from the right place. + // Implementation sessions live in a worktree; `relCwd` may be absolute / + // `~/...` / workspace-relative — must go through resolveWorktreePath + // (path.join(workspaceRoot, abs) would mangle absolute paths). // If the worktree has since been cleaned up (typical: drop card to // "完成" → auto `git worktree remove`), fall back to the workspace // root instead of pointing the terminal at a missing directory. let effectiveCwd: string | undefined = workspaceRoot let cwdFallback = false if (relCwd && workspaceRoot) { - const resolved = path.join(workspaceRoot, relCwd) + const resolved = resolveWorktreePath(relCwd, workspaceRoot) if (fs.existsSync(resolved)) { effectiveCwd = resolved }