From 95b17ff8209161c7bf7cedd2296326b06c8abf12 Mon Sep 17 00:00:00 2001 From: waleed Date: Tue, 17 Mar 2026 15:58:55 -0700 Subject: [PATCH 1/3] fix(copilot): abort in-progress tools when stream ends Calls abortAllInProgressTools in the stream_end handler so tools stuck in generating/executing state are resolved when the stream closes, regardless of whether a done event was received. Co-Authored-By: Claude Sonnet 4.6 --- apps/sim/lib/copilot/client-sse/handlers.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/sim/lib/copilot/client-sse/handlers.ts b/apps/sim/lib/copilot/client-sse/handlers.ts index 0330853d69c..7705e1cf3dd 100644 --- a/apps/sim/lib/copilot/client-sse/handlers.ts +++ b/apps/sim/lib/copilot/client-sse/handlers.ts @@ -3,6 +3,7 @@ import { STREAM_STORAGE_KEY } from '@/lib/copilot/constants' import { asRecord } from '@/lib/copilot/orchestrator/sse/utils' import type { SSEEvent } from '@/lib/copilot/orchestrator/types' import { + abortAllInProgressTools, isBackgroundState, isRejectedState, isReviewState, @@ -956,7 +957,7 @@ export const sseHandlers: Record = { })) context.streamComplete = true }, - stream_end: (_data, context, _get, set) => { + stream_end: (_data, context, get, set) => { if (context.pendingContent) { if (context.isInThinkingBlock && context.currentThinkingBlock) { appendThinkingContent(context, context.pendingContent) @@ -967,6 +968,7 @@ export const sseHandlers: Record = { } finalizeThinkingBlock(context) updateStreamingMessage(set, context) + abortAllInProgressTools(set, get) }, default: () => {}, } From 84150c2557538165c854c3ab32b935d165f5f76d Mon Sep 17 00:00:00 2001 From: waleed Date: Tue, 17 Mar 2026 16:08:40 -0700 Subject: [PATCH 2/3] fix(workspace): prevent stale placeholder data from corrupting workflow registry on switch - Guard completeMetadataLoad to skip when isPlaceholderData is true, preventing the previous workspace's workflows from briefly populating the registry during switch - Trigger beginMetadataLoad when isPlaceholderData is true to ensure loading state is shown correctly on direct URL navigation (no switchToWorkspace call) - Narrow useCreateWorkspace invalidation from workspaceKeys.all to workspaceKeys.lists() to avoid unnecessary refetches of permissions, settings, and members --- apps/sim/hooks/queries/workflows.ts | 22 ++++++++++++++++++---- apps/sim/hooks/queries/workspace.ts | 10 ++-------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/apps/sim/hooks/queries/workflows.ts b/apps/sim/hooks/queries/workflows.ts index 97d3df0b2b5..cc9e7b0b696 100644 --- a/apps/sim/hooks/queries/workflows.ts +++ b/apps/sim/hooks/queries/workflows.ts @@ -113,10 +113,15 @@ export function useWorkflows( }) useEffect(() => { - if (syncRegistry && scope === 'active' && workspaceId && query.status === 'pending') { + if ( + syncRegistry && + scope === 'active' && + workspaceId && + (query.status === 'pending' || query.isPlaceholderData) + ) { beginMetadataLoad(workspaceId) } - }, [syncRegistry, scope, workspaceId, query.status, beginMetadataLoad]) + }, [syncRegistry, scope, workspaceId, query.status, query.isPlaceholderData, beginMetadataLoad]) useEffect(() => { if ( @@ -124,11 +129,20 @@ export function useWorkflows( scope === 'active' && workspaceId && query.status === 'success' && - query.data + query.data && + !query.isPlaceholderData ) { completeMetadataLoad(workspaceId, query.data) } - }, [syncRegistry, scope, workspaceId, query.status, query.data, completeMetadataLoad]) + }, [ + syncRegistry, + scope, + workspaceId, + query.status, + query.data, + query.isPlaceholderData, + completeMetadataLoad, + ]) useEffect(() => { if (syncRegistry && scope === 'active' && workspaceId && query.status === 'error') { diff --git a/apps/sim/hooks/queries/workspace.ts b/apps/sim/hooks/queries/workspace.ts index a3eb1bf5e6d..5a87b86d8df 100644 --- a/apps/sim/hooks/queries/workspace.ts +++ b/apps/sim/hooks/queries/workspace.ts @@ -86,14 +86,8 @@ export function useCreateWorkspace() { const data = await response.json() return data.workspace as Workspace }, - onSuccess: (data) => { - queryClient.invalidateQueries({ queryKey: workspaceKeys.all }) - if (data?.id) { - queryClient.removeQueries({ queryKey: workspaceKeys.detail(data.id) }) - queryClient.removeQueries({ queryKey: workspaceKeys.settings(data.id) }) - queryClient.removeQueries({ queryKey: workspaceKeys.permissions(data.id) }) - queryClient.removeQueries({ queryKey: workspaceKeys.members(data.id) }) - } + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: workspaceKeys.lists() }) }, }) } From 32f666081c58a95656c53e5f3e75ee0c3750419b Mon Sep 17 00:00:00 2001 From: waleed Date: Tue, 17 Mar 2026 16:13:54 -0700 Subject: [PATCH 3/3] fix(workspace): also invalidate admin workspace cache on creation --- apps/sim/hooks/queries/workspace.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/sim/hooks/queries/workspace.ts b/apps/sim/hooks/queries/workspace.ts index 5a87b86d8df..b4722aca3af 100644 --- a/apps/sim/hooks/queries/workspace.ts +++ b/apps/sim/hooks/queries/workspace.ts @@ -88,6 +88,7 @@ export function useCreateWorkspace() { }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: workspaceKeys.lists() }) + queryClient.invalidateQueries({ queryKey: workspaceKeys.adminLists() }) }, }) }