Skip to content

Commit 0ba5ec6

Browse files
Sg312emir-karabeg
authored andcommitted
Diff view
1 parent 8597786 commit 0ba5ec6

File tree

2 files changed

+80
-72
lines changed

2 files changed

+80
-72
lines changed

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/diff-controls/diff-controls.tsx

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -206,54 +206,47 @@ export const DiffControls = memo(function DiffControls() {
206206
}
207207
}, [activeWorkflowId, currentChat, messages, baselineWorkflow])
208208

209-
const handleAccept = useCallback(async () => {
209+
const handleAccept = useCallback(() => {
210210
logger.info('Accepting proposed changes with backup protection')
211211

212+
// Resolve target toolCallId for build/edit and update to terminal success state in the copilot store
213+
// This happens synchronously first for instant UI feedback
212214
try {
213-
// Create a checkpoint before applying changes so it appears under the triggering user message
214-
await createCheckpoint().catch((error) => {
215-
logger.warn('Failed to create checkpoint before accept:', error)
216-
})
217-
218-
// Resolve target toolCallId for build/edit and update to terminal success state in the copilot store
219-
try {
220-
const { toolCallsById, messages } = useCopilotStore.getState()
221-
let id: string | undefined
222-
outer: for (let mi = messages.length - 1; mi >= 0; mi--) {
223-
const m = messages[mi]
224-
if (m.role !== 'assistant' || !m.contentBlocks) continue
225-
const blocks = m.contentBlocks as any[]
226-
for (let bi = blocks.length - 1; bi >= 0; bi--) {
227-
const b = blocks[bi]
228-
if (b?.type === 'tool_call') {
229-
const tn = b.toolCall?.name
230-
if (tn === 'edit_workflow') {
231-
id = b.toolCall?.id
232-
break outer
233-
}
215+
const { toolCallsById, messages } = useCopilotStore.getState()
216+
let id: string | undefined
217+
outer: for (let mi = messages.length - 1; mi >= 0; mi--) {
218+
const m = messages[mi]
219+
if (m.role !== 'assistant' || !m.contentBlocks) continue
220+
const blocks = m.contentBlocks as any[]
221+
for (let bi = blocks.length - 1; bi >= 0; bi--) {
222+
const b = blocks[bi]
223+
if (b?.type === 'tool_call') {
224+
const tn = b.toolCall?.name
225+
if (tn === 'edit_workflow') {
226+
id = b.toolCall?.id
227+
break outer
234228
}
235229
}
236230
}
237-
if (!id) {
238-
const candidates = Object.values(toolCallsById).filter((t) => t.name === 'edit_workflow')
239-
id = candidates.length ? candidates[candidates.length - 1].id : undefined
240-
}
241-
if (id) updatePreviewToolCallState('accepted', id)
242-
} catch {}
231+
}
232+
if (!id) {
233+
const candidates = Object.values(toolCallsById).filter((t) => t.name === 'edit_workflow')
234+
id = candidates.length ? candidates[candidates.length - 1].id : undefined
235+
}
236+
if (id) updatePreviewToolCallState('accepted', id)
237+
} catch {}
243238

244-
// Accept changes without blocking the UI; errors will be logged by the store handler
245-
acceptChanges().catch((error) => {
246-
logger.error('Failed to accept changes (background):', error)
247-
})
239+
// Accept changes without blocking the UI; errors will be logged by the store handler
240+
acceptChanges().catch((error) => {
241+
logger.error('Failed to accept changes (background):', error)
242+
})
248243

249-
logger.info('Accept triggered; UI will update optimistically')
250-
} catch (error) {
251-
logger.error('Failed to accept changes:', error)
244+
// Create checkpoint in the background (fire-and-forget) so it doesn't block UI
245+
createCheckpoint().catch((error) => {
246+
logger.warn('Failed to create checkpoint after accept:', error)
247+
})
252248

253-
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'
254-
logger.error('Workflow update failed:', errorMessage)
255-
alert(`Failed to save workflow changes: ${errorMessage}`)
256-
}
249+
logger.info('Accept triggered; UI will update optimistically')
257250
}, [createCheckpoint, updatePreviewToolCallState, acceptChanges])
258251

259252
const handleReject = useCallback(() => {

apps/sim/stores/workflow-diff/store.ts

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ export const useWorkflowDiffStore = create<WorkflowDiffState & WorkflowDiffActio
433433
)
434434
}
435435

436+
// Background operations (fire-and-forget) - don't block
436437
if (triggerMessageId) {
437438
fetch('/api/copilot/stats', {
438439
method: 'POST',
@@ -445,14 +446,13 @@ export const useWorkflowDiffStore = create<WorkflowDiffState & WorkflowDiffActio
445446
}).catch(() => {})
446447
}
447448

448-
const toolCallId = await findLatestEditWorkflowToolCallId()
449-
if (toolCallId) {
450-
try {
451-
await getClientTool(toolCallId)?.handleAccept?.()
452-
} catch (error) {
453-
logger.warn('Failed to notify tool accept state', { error })
449+
findLatestEditWorkflowToolCallId().then((toolCallId) => {
450+
if (toolCallId) {
451+
getClientTool(toolCallId)?.handleAccept?.()?.catch?.((error: Error) => {
452+
logger.warn('Failed to notify tool accept state', { error })
453+
})
454454
}
455-
}
455+
})
456456
},
457457

458458
rejectChanges: async () => {
@@ -487,27 +487,26 @@ export const useWorkflowDiffStore = create<WorkflowDiffState & WorkflowDiffActio
487487
})
488488
const afterReject = cloneWorkflowState(baselineWorkflow)
489489

490-
// Apply baseline state locally
491-
applyWorkflowStateToStores(baselineWorkflowId, baselineWorkflow)
492-
493-
// Broadcast to other users
494-
logger.info('Broadcasting reject to other users', {
495-
workflowId: activeWorkflowId,
496-
blockCount: Object.keys(baselineWorkflow.blocks).length,
490+
// Clear diff state FIRST for instant UI feedback
491+
set({
492+
hasActiveDiff: false,
493+
isShowingDiff: false,
494+
isDiffReady: false,
495+
baselineWorkflow: null,
496+
baselineWorkflowId: null,
497+
diffAnalysis: null,
498+
diffMetadata: null,
499+
diffError: null,
500+
_triggerMessageId: null,
497501
})
498502

499-
await enqueueReplaceWorkflowState({
500-
workflowId: activeWorkflowId,
501-
state: baselineWorkflow,
502-
})
503+
// Clear the diff engine
504+
diffEngine.clearDiff()
503505

504-
// Persist to database
505-
const persisted = await persistWorkflowStateToServer(baselineWorkflowId, baselineWorkflow)
506-
if (!persisted) {
507-
throw new Error('Failed to restore baseline workflow state')
508-
}
506+
// Apply baseline state locally
507+
applyWorkflowStateToStores(baselineWorkflowId, baselineWorkflow)
509508

510-
// Emit event for undo/redo recording
509+
// Emit event for undo/redo recording synchronously
511510
if (!(window as any).__skipDiffRecording) {
512511
window.dispatchEvent(
513512
new CustomEvent('record-diff-operation', {
@@ -522,6 +521,25 @@ export const useWorkflowDiffStore = create<WorkflowDiffState & WorkflowDiffActio
522521
)
523522
}
524523

524+
// Background operations (fire-and-forget) - don't block UI
525+
// Broadcast to other users
526+
logger.info('Broadcasting reject to other users', {
527+
workflowId: activeWorkflowId,
528+
blockCount: Object.keys(baselineWorkflow.blocks).length,
529+
})
530+
531+
enqueueReplaceWorkflowState({
532+
workflowId: activeWorkflowId,
533+
state: baselineWorkflow,
534+
}).catch((error) => {
535+
logger.error('Failed to broadcast reject to other users:', error)
536+
})
537+
538+
// Persist to database in background
539+
persistWorkflowStateToServer(baselineWorkflowId, baselineWorkflow).catch((error) => {
540+
logger.error('Failed to persist baseline workflow state:', error)
541+
})
542+
525543
if (_triggerMessageId) {
526544
fetch('/api/copilot/stats', {
527545
method: 'POST',
@@ -534,16 +552,13 @@ export const useWorkflowDiffStore = create<WorkflowDiffState & WorkflowDiffActio
534552
}).catch(() => {})
535553
}
536554

537-
const toolCallId = await findLatestEditWorkflowToolCallId()
538-
if (toolCallId) {
539-
try {
540-
await getClientTool(toolCallId)?.handleReject?.()
541-
} catch (error) {
542-
logger.warn('Failed to notify tool reject state', { error })
555+
findLatestEditWorkflowToolCallId().then((toolCallId) => {
556+
if (toolCallId) {
557+
getClientTool(toolCallId)?.handleReject?.()?.catch?.((error: Error) => {
558+
logger.warn('Failed to notify tool reject state', { error })
559+
})
543560
}
544-
}
545-
546-
get().clearDiff({ restoreBaseline: false })
561+
})
547562
},
548563

549564
reapplyDiffMarkers: () => {

0 commit comments

Comments
 (0)