feat(vscode): worktree 打开方式可选 VS Code/PyCharm,并修复 handleOpenWorktree 不展开 ~ 的打开报错

- worktree.ts: handleOpenWorktree/handleDeleteWorktree/dispatchImplTabPostCloseAsync 三处改用 resolveWorktreePath,修复带 ~ 的存量路径被拼成 <工作区>/~/... 导致打不开
- 新增全局设置 worktreeOpenWith('vscode' | 'pycharm',默认 vscode),贯穿 store/settings handler/messages/KanbanPanel 与 webview 的 messages/useIssues/App/SettingsModal「钩子」分组新增「工作树打开方式」下拉
- handleOpenWorktree 按设置分支:pycharm 走 JetBrains pycharm 启动器,ENOENT 时提示启用命令行启动器

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-24 05:20:22 +08:00
co-authored by Claude Opus 4.7
parent 5e7a3d20d9
commit cacc60eb0e
9 changed files with 78 additions and 4 deletions
+13
View File
@@ -94,6 +94,12 @@ export interface Settings {
* `~/Sources/worktree/$project_name/$feature_name`".
*/
worktreeDirectory: string
/**
* Which editor opens a worktree when the user clicks it in the detail
* panel. `'pycharm'` shells out to the JetBrains `pycharm` launcher;
* `'vscode'` (default) opens a new VS Code window.
*/
worktreeOpenWith: 'vscode' | 'pycharm'
/**
* Path to a user-provided shell script that runs *after* the extension
* creates a worktree via `git worktree add`. Empty string means use the
@@ -166,6 +172,7 @@ function defaults(ctx: ExtensionContext): Settings {
devBranch: 'main',
autoBuildBranch: '',
worktreeDirectory: '~/Sources/worktree/$project_name/$feature_name',
worktreeOpenWith: 'vscode',
worktreePostCreateScript: '',
worktreePreRemoveScript: '',
implTabPreCreateScript: '',
@@ -214,6 +221,11 @@ export function getSettings(ctx: ExtensionContext): Settings {
const worktreeDirectory = typeof stored.worktreeDirectory === 'string' && stored.worktreeDirectory.length > 0
? stored.worktreeDirectory
: base.worktreeDirectory
// worktreeOpenWith is an enum — only the two known values are valid; anything
// else (legacy installs, garbage) collapses to the default.
const worktreeOpenWith = stored.worktreeOpenWith === 'pycharm' || stored.worktreeOpenWith === 'vscode'
? stored.worktreeOpenWith
: base.worktreeOpenWith
// worktree hook script paths: '' is meaningful (= "use default
// .spx/worktree-*.sh"), so don't coerce. Non-string legacy values fall
// back to ''. The hook runner resolves '' to the default at execution
@@ -253,6 +265,7 @@ export function getSettings(ctx: ExtensionContext): Settings {
devBranch,
autoBuildBranch,
worktreeDirectory,
worktreeOpenWith,
worktreePostCreateScript,
worktreePreRemoveScript,
implTabPreCreateScript,