History

Fix terminal state infinite loop, test ordering assertion, and redundant updateBranch call

- 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.

Cursor Agent committed 8 months ago

Commit ab955dd1 parent 384878a3 files · +11 −6Browse files

Unified · Split

3 files
  1. apps/server/src/persistenceService.test.ts +5 −3
  2. apps/web/src/components/BranchToolbar.tsx +0 −1
  3. apps/web/src/components/ChatView.tsx +6 −2
apps/server/src/persistenceService.test.ts+5−3
@@ -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);
apps/web/src/components/BranchToolbar.tsx+0−1
@@ -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
apps/web/src/components/ChatView.tsx+6−2
@@ -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.threads790 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 ]);