From 0517eb7d394864a8333eef0b23b1ad304f33e1a9 Mon Sep 17 00:00:00 2001 From: waleed Date: Wed, 29 Apr 2026 20:12:47 -0700 Subject: [PATCH 1/2] feat(fork): optimistic sidebar entry + rename to 'Fork | Chat Name' Adds the forked task to the sidebar immediately by writing an optimistic entry into the task list cache in onSuccess, before the background refetch arrives. Without this, the sidebar showed no new task until the invalidation refetch completed after navigation. Also moves the Fork prefix to the front of the name ('Fork | Chat Name') so it is immediately scannable in the sidebar. --- .../mothership/chats/[chatId]/fork/route.ts | 4 ++-- apps/sim/hooks/queries/tasks.ts | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/apps/sim/app/api/mothership/chats/[chatId]/fork/route.ts b/apps/sim/app/api/mothership/chats/[chatId]/fork/route.ts index 7a33f2326b6..e1e4a70c98a 100644 --- a/apps/sim/app/api/mothership/chats/[chatId]/fork/route.ts +++ b/apps/sim/app/api/mothership/chats/[chatId]/fork/route.ts @@ -74,8 +74,8 @@ export const POST = withRouteHandler( : [] const newId = generateId() - const baseTitle = (parent.title ?? 'New task').replace(/ \| Fork$/, '') - const title = `${baseTitle} | Fork` + const baseTitle = (parent.title ?? 'New task').replace(/^Fork \| /, '') + const title = `Fork | ${baseTitle}` const now = new Date() const [newChat] = await db diff --git a/apps/sim/hooks/queries/tasks.ts b/apps/sim/hooks/queries/tasks.ts index 100f891c36e..cc3dd4a5c45 100644 --- a/apps/sim/hooks/queries/tasks.ts +++ b/apps/sim/hooks/queries/tasks.ts @@ -609,6 +609,24 @@ export function useForkTask(workspaceId?: string) { const queryClient = useQueryClient() return useMutation({ mutationFn: forkChat, + onSuccess: (data, variables) => { + const existing = queryClient.getQueryData(taskKeys.list(workspaceId)) + if (existing) { + const sourceTask = existing.find((t) => t.id === variables.chatId) + const baseName = (sourceTask?.name ?? 'New task').replace(/^Fork \| /, '') + const optimisticTask: TaskMetadata = { + id: data.id, + name: `Fork | ${baseName}`, + updatedAt: new Date(), + isActive: false, + isUnread: false, + } + queryClient.setQueryData(taskKeys.list(workspaceId), [ + optimisticTask, + ...existing, + ]) + } + }, onSettled: () => { queryClient.invalidateQueries({ queryKey: taskKeys.list(workspaceId) }) }, From b4de0303e7d6a11eb75929e7179b4695cd13ff2d Mon Sep 17 00:00:00 2001 From: waleed Date: Wed, 29 Apr 2026 20:32:16 -0700 Subject: [PATCH 2/2] fix(fork): cancel in-flight queries before optimistic sidebar write --- apps/sim/hooks/queries/tasks.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/sim/hooks/queries/tasks.ts b/apps/sim/hooks/queries/tasks.ts index cc3dd4a5c45..e336f6e85d7 100644 --- a/apps/sim/hooks/queries/tasks.ts +++ b/apps/sim/hooks/queries/tasks.ts @@ -609,7 +609,8 @@ export function useForkTask(workspaceId?: string) { const queryClient = useQueryClient() return useMutation({ mutationFn: forkChat, - onSuccess: (data, variables) => { + onSuccess: async (data, variables) => { + await queryClient.cancelQueries({ queryKey: taskKeys.list(workspaceId) }) const existing = queryClient.getQueryData(taskKeys.list(workspaceId)) if (existing) { const sourceTask = existing.find((t) => t.id === variables.chatId)