(input)
| 225 | renderToolUseMessage, |
| 226 | renderToolResultMessage, |
| 227 | async call(input) { |
| 228 | const session = getCurrentWorktreeSession() |
| 229 | if (!session) { |
| 230 | // validateInput guards this, but the session is module-level mutable |
| 231 | // state — defend against a race between validation and execution. |
| 232 | throw new Error('Not in a worktree session') |
| 233 | } |
| 234 | |
| 235 | // Capture before keepWorktree/cleanupWorktree null out currentWorktreeSession. |
| 236 | const { |
| 237 | originalCwd, |
| 238 | worktreePath, |
| 239 | worktreeBranch, |
| 240 | tmuxSessionName, |
| 241 | originalHeadCommit, |
| 242 | } = session |
| 243 | |
| 244 | // --worktree startup calls setOriginalCwd(getCwd()) and |
| 245 | // setProjectRoot(getCwd()) back-to-back right after setCwd(worktreePath) |
| 246 | // (setup.ts:235/239), so both hold the same realpath'd value and BashTool |
| 247 | // cd never touches either. Mid-session EnterWorktreeTool sets originalCwd |
| 248 | // but NOT projectRoot. (Can't use getCwd() — BashTool mutates it on every |
| 249 | // cd. Can't use session.worktreePath — it's join()'d, not realpath'd.) |
| 250 | const projectRootIsWorktree = getProjectRoot() === getOriginalCwd() |
| 251 | |
| 252 | // Re-count at execution time for accurate analytics and output — the |
| 253 | // worktree state at validateInput time may not match now. Null (git |
| 254 | // failure) falls back to 0/0; safety gating already happened in |
| 255 | // validateInput, so this only affects analytics + messaging. |
| 256 | const { changedFiles, commits } = (await countWorktreeChanges( |
| 257 | worktreePath, |
| 258 | originalHeadCommit, |
| 259 | )) ?? { changedFiles: 0, commits: 0 } |
| 260 | |
| 261 | if (input.action === 'keep') { |
| 262 | await keepWorktree() |
| 263 | restoreSessionToOriginalCwd(originalCwd, projectRootIsWorktree) |
| 264 | |
| 265 | logEvent('tengu_worktree_kept', { |
| 266 | mid_session: true, |
| 267 | commits, |
| 268 | changed_files: changedFiles, |
| 269 | }) |
| 270 | |
| 271 | const tmuxNote = tmuxSessionName |
| 272 | ? ` Tmux session ${tmuxSessionName} is still running; reattach with: tmux attach -t ${tmuxSessionName}` |
| 273 | : '' |
| 274 | return { |
| 275 | data: { |
| 276 | action: 'keep' as const, |
| 277 | originalCwd, |
| 278 | worktreePath, |
| 279 | worktreeBranch, |
| 280 | tmuxSessionName, |
| 281 | message: `Exited worktree. Your work is preserved at ${worktreePath}${worktreeBranch ? ` on branch ${worktreeBranch}` : ''}. Session is now back in ${originalCwd}.${tmuxNote}`, |
| 282 | }, |
| 283 | } |
| 284 | } |
nothing calls this directly
no test coverage detected