fix: record debug runs for proposed chat titles (#24820)

This commit is contained in:
Thomas Kosiewski
2026-04-29 16:45:48 +02:00
committed by GitHub
parent 5907730dcf
commit ab75e46f1d
6 changed files with 245 additions and 52 deletions
+35
View File
@@ -30,6 +30,7 @@ import {
paginatedChatCostUsers,
pinChat,
promoteChatQueuedMessage,
proposeChatTitle,
regenerateChatTitle,
removeChildFromParentInCache,
reorderPinnedChat,
@@ -54,6 +55,7 @@ vi.mock("#/api/api", () => ({
editChatMessage: vi.fn(),
interruptChat: vi.fn(),
promoteChatQueuedMessage: vi.fn(),
proposeChatTitle: vi.fn(),
regenerateChatTitle: vi.fn(),
},
},
@@ -1293,6 +1295,39 @@ describe("mutation invalidation scope", () => {
}
});
for (const { label, error } of [
{ label: "success", error: undefined },
{ label: "failure", error: new Error("proposal failed") },
]) {
it(`proposeChatTitle invalidates debug runs on ${label} without touching unrelated queries`, async () => {
const queryClient = createTestQueryClient();
const chatId = "chat-1";
seedAllActiveQueries(queryClient, chatId);
const mutation = proposeChatTitle(queryClient);
await mutation.onSettled(undefined, error, chatId);
expect(
queryClient.getQueryState(chatDebugRunsKey(chatId))?.isInvalidated,
"chatDebugRunsKey should be invalidated",
).toBe(true);
for (const { label, key } of [
{ label: "flat chats", key: chatsKey },
{ label: "infinite chats", key: [...chatsKey, { archived: false }] },
{ label: "chat detail", key: chatKey(chatId) },
{ label: "messages", key: chatMessagesKey(chatId) },
...unrelatedKeys(chatId),
]) {
const state = queryClient.getQueryState(key);
expect(
state?.isInvalidated,
`${label} should NOT be invalidated by proposeChatTitle`,
).not.toBe(true);
}
});
}
it("createChat invalidates only sidebar queries on success", async () => {
const queryClient = createTestQueryClient();
const chatId = "chat-1";
+12
View File
@@ -1002,6 +1002,18 @@ export const regenerateChatTitle = (queryClient: QueryClient) => ({
},
});
export const proposeChatTitle = (queryClient: QueryClient) => ({
mutationFn: (chatId: string) => API.experimental.proposeChatTitle(chatId),
onSettled: (
_data: { title: string } | undefined,
_error: unknown,
chatId: string,
) => {
void invalidateChatDebugRuns(queryClient, chatId);
},
});
type UpdateChatTitleVariables = {
chatId: string;
title: string;
+3 -1
View File
@@ -23,6 +23,7 @@ import {
mergeWatchedChatIntoCaches,
pinChat,
prependToInfiniteChatsCache,
proposeChatTitle,
readInfiniteChatsCache,
regenerateChatTitle,
removeChildFromParentInCache,
@@ -247,6 +248,7 @@ const AgentsPage: FC = () => {
toast.error(getErrorMessage(error, "Failed to generate new title."));
},
});
const proposeTitleMutation = useMutation(proposeChatTitle(queryClient));
const renameTitleMutation = useMutation({
...updateChatTitle(queryClient),
onError: (error: unknown) => {
@@ -439,7 +441,7 @@ const AgentsPage: FC = () => {
return promise;
};
const requestProposeTitle = async (chatId: string): Promise<string> => {
const result = await API.experimental.proposeChatTitle(chatId);
const result = await proposeTitleMutation.mutateAsync(chatId);
return result.title;
};
const requestRenameTitle = async (chatId: string, title: string) => {