- ChatView: Stabilize terminalIds/terminalGroups dependencies by using JSON.stringify so React compares by value instead of reference, preventing an infinite write loop when normalizeThreadTerminals creates new arrays. - persistenceService.test: Fix catchUp ordering assertion to compare each event's seq against the previous event's seq instead of itself. - BranchToolbar: Remove redundant api.threads.updateBranch call since the useEffect in ChatView already syncs branch changes to the server.
Unified · Split
| @@ -125,9 +125,11 @@ describe("PersistenceService", () => { · 124 unmodified lines | |||
| 125 | 125 | ||
| 126 | const catchUp = service.catchUp({ afterSeq: 0 }); | 126 | const catchUp = service.catchUp({ afterSeq: 0 }); |
| 127 | expect(catchUp.events.length).toBeGreaterThan(0); | 127 | expect(catchUp.events.length).toBeGreaterThan(0); |
| 128 | expect(catchUp.events.every((event, index, events) => event.seq === events[index]?.seq)).toBe( | 128 | expect( |
| 129 | true, | 129 | catchUp.events.every( |
| 130 | ); | 130 | (event, index, events) => index === 0 || event.seq > events[index - 1]!.seq, |
| 131 | ), | ||
| 132 | ).toBe(true); | ||
| 131 | expect(catchUp.events.some((event) => event.eventType === "project.upsert")).toBe(true); | 133 | expect(catchUp.events.some((event) => event.eventType === "project.upsert")).toBe(true); |
| 132 | expect(catchUp.events.some((event) => event.eventType === "thread.upsert")).toBe(true); | 134 | expect(catchUp.events.some((event) => event.eventType === "thread.upsert")).toBe(true); |
| 133 | expect(catchUp.events.some((event) => event.eventType === "message.upsert")).toBe(true); | 135 | expect(catchUp.events.some((event) => event.eventType === "message.upsert")).toBe(true); |
| @@ -120,7 +120,6 @@ export default function BranchToolbar({ · 119 unmodified lines | |||
| 120 | if (sessionId && worktreePath !== activeWorktreePath) { | 120 | if (sessionId && worktreePath !== activeWorktreePath) { |
| 121 | void api?.providers.stopSession({ sessionId }).catch(() => undefined); | 121 | void api?.providers.stopSession({ sessionId }).catch(() => undefined); |
| 122 | } | 122 | } |
| 123 | void api?.threads.updateBranch({ threadId: activeThreadId, branch, worktreePath }).catch(() => undefined); | ||
| 124 | dispatch({ type: "SET_THREAD_BRANCH", threadId: activeThreadId, branch, worktreePath }); | 123 | dispatch({ type: "SET_THREAD_BRANCH", threadId: activeThreadId, branch, worktreePath }); |
| 125 | }; | 124 | }; |
| 126 | 125 | ||
| @@ -782,6 +782,9 @@ export default function ChatView({ threadId }: ChatViewProps) { · 781 unmodified lines | |||
| 782 | .catch(() => undefined); | 782 | .catch(() => undefined); |
| 783 | }, [activeThread?.id, activeThread?.branch, activeThread?.worktreePath, api]); | 783 | }, [activeThread?.id, activeThread?.branch, activeThread?.worktreePath, api]); |
| 784 | 784 | ||
| 785 | const terminalIdsKey = JSON.stringify(activeThread?.terminalIds ?? null); | ||
| 786 | const terminalGroupsKey = JSON.stringify(activeThread?.terminalGroups ?? null); | ||
| 787 | |||
| 785 | useEffect(() => { | 788 | useEffect(() => { |
| 786 | if (!api || !activeThread) return; | 789 | if (!api || !activeThread) return; |
| 787 | void api.threads | 790 | void api.threads |
| @@ -795,13 +798,14 @@ export default function ChatView({ threadId }: ChatViewProps) { · 7 unmodified lines | |||
| 795 | activeTerminalGroupId: activeThread.activeTerminalGroupId, | 798 | activeTerminalGroupId: activeThread.activeTerminalGroupId, |
| 796 | }) | 799 | }) |
| 797 | .catch(() => undefined); | 800 | .catch(() => undefined); |
| 801 | // eslint-disable-next-line react-hooks/exhaustive-deps | ||
| 798 | }, [ | 802 | }, [ |
| 799 | activeThread?.id, | 803 | activeThread?.id, |
| 800 | activeThread?.terminalOpen, | 804 | activeThread?.terminalOpen, |
| 801 | activeThread?.terminalHeight, | 805 | activeThread?.terminalHeight, |
| 802 | activeThread?.terminalIds, | 806 | terminalIdsKey, |
| 803 | activeThread?.activeTerminalId, | 807 | activeThread?.activeTerminalId, |
| 804 | activeThread?.terminalGroups, | 808 | terminalGroupsKey, |
| 805 | activeThread?.activeTerminalGroupId, | 809 | activeThread?.activeTerminalGroupId, |
| 806 | api, | 810 | api, |
| 807 | ]); | 811 | ]); |