| author | |
| committer | |
| log | 5b7af7b9f641b8e8f1bdffabcdd423d3f09e9d80 |
| tree | b97b3f84878aac084e8d9d40a518e5f3ffd59b16 |
| parent | 8324949b54c9aadc5d5db1b6cebbd10325a0ea79 |
When selecting a branch that lives in a different worktree, the store
updated the thread's worktreePath but the running session kept its
original cwd. The agent continued operating in the old directory.
- SET_THREAD_BRANCH now clears the session when worktreePath changes
- BranchToolbar stops the server-side session before dispatching the
branch change, so the next message creates a fresh session with the
correct cwd
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>2 files changed, 20 insertions(+), 6 deletions(-)
apps/web/src/components/BranchToolbar.tsx+6| ... | @@ -108,6 +108,12 @@ export default function BranchToolbar({ envMode, onEnvModeChange, envLocked }: B | ... | @@ -108,6 +108,12 @@ export default function BranchToolbar({ envMode, onEnvModeChange, envLocked }: B |
| 108 | 108 | ||
| 109 | const setThreadBranch = (branch: string | null, worktreePath: string | null) => { | 109 | const setThreadBranch = (branch: string | null, worktreePath: string | null) => { |
| 110 | if (!activeThreadId) return; | 110 | if (!activeThreadId) return; |
| 111 | // If the effective cwd is about to change, stop the running session so the | ||
| 112 | // next message creates a new one with the correct cwd. | ||
| 113 | const sessionId = activeThread?.session?.sessionId; | ||
| 114 | if (sessionId && worktreePath !== activeWorktreePath) { | ||
| 115 | void api?.providers.stopSession({ sessionId }).catch(() => undefined); | ||
| 116 | } | ||
| 111 | dispatch({ type: "SET_THREAD_BRANCH", threadId: activeThreadId, branch, worktreePath }); | 117 | dispatch({ type: "SET_THREAD_BRANCH", threadId: activeThreadId, branch, worktreePath }); |
| 112 | }; | 118 | }; |
| 113 | 119 |
apps/web/src/store.ts+14-6| ... | @@ -376,15 +376,23 @@ export function reducer(state: AppState, action: Action): AppState { | ... | @@ -376,15 +376,23 @@ export function reducer(state: AppState, action: Action): AppState { |
| 376 | })), | 376 | })), |
| 377 | }; | 377 | }; |
| 378 | 378 | ||
| 379 | case "SET_THREAD_BRANCH": | 379 | case "SET_THREAD_BRANCH": { |
| 380 | return { | 380 | return { |
| 381 | ...state, | 381 | ...state, |
| 382 | threads: updateThread(state.threads, action.threadId, (t) => ({ | 382 | threads: updateThread(state.threads, action.threadId, (t) => { |
| 383 | ...t, | 383 | // When the effective cwd changes (worktreePath differs), the old |
| 384 | branch: action.branch, | 384 | // session is no longer valid — clear it so ensureSession creates a |
| 385 | worktreePath: action.worktreePath, | 385 | // new one with the correct cwd on the next message. |
| 386 | })), | 386 | const cwdChanged = t.worktreePath !== action.worktreePath; |
| 387 | return { | ||
| 388 | ...t, | ||
| 389 | branch: action.branch, | ||
| 390 | worktreePath: action.worktreePath, | ||
| 391 | ...(cwdChanged ? { session: null } : {}), | ||
| 392 | }; | ||
| 393 | }), | ||
| 387 | }; | 394 | }; |
| 395 | } | ||
| 388 | 396 | ||
| 389 | case "SET_RUNTIME_MODE": | 397 | case "SET_RUNTIME_MODE": |
| 390 | return { | 398 | return { |