mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-10 15:38:00 -05:00
Diff view
This commit is contained in:
committed by
Emir Karabeg
parent
8597786962
commit
0ba5ec65f7
@@ -206,54 +206,47 @@ export const DiffControls = memo(function DiffControls() {
|
||||
}
|
||||
}, [activeWorkflowId, currentChat, messages, baselineWorkflow])
|
||||
|
||||
const handleAccept = useCallback(async () => {
|
||||
const handleAccept = useCallback(() => {
|
||||
logger.info('Accepting proposed changes with backup protection')
|
||||
|
||||
// Resolve target toolCallId for build/edit and update to terminal success state in the copilot store
|
||||
// This happens synchronously first for instant UI feedback
|
||||
try {
|
||||
// Create a checkpoint before applying changes so it appears under the triggering user message
|
||||
await createCheckpoint().catch((error) => {
|
||||
logger.warn('Failed to create checkpoint before accept:', error)
|
||||
})
|
||||
|
||||
// Resolve target toolCallId for build/edit and update to terminal success state in the copilot store
|
||||
try {
|
||||
const { toolCallsById, messages } = useCopilotStore.getState()
|
||||
let id: string | undefined
|
||||
outer: for (let mi = messages.length - 1; mi >= 0; mi--) {
|
||||
const m = messages[mi]
|
||||
if (m.role !== 'assistant' || !m.contentBlocks) continue
|
||||
const blocks = m.contentBlocks as any[]
|
||||
for (let bi = blocks.length - 1; bi >= 0; bi--) {
|
||||
const b = blocks[bi]
|
||||
if (b?.type === 'tool_call') {
|
||||
const tn = b.toolCall?.name
|
||||
if (tn === 'edit_workflow') {
|
||||
id = b.toolCall?.id
|
||||
break outer
|
||||
}
|
||||
const { toolCallsById, messages } = useCopilotStore.getState()
|
||||
let id: string | undefined
|
||||
outer: for (let mi = messages.length - 1; mi >= 0; mi--) {
|
||||
const m = messages[mi]
|
||||
if (m.role !== 'assistant' || !m.contentBlocks) continue
|
||||
const blocks = m.contentBlocks as any[]
|
||||
for (let bi = blocks.length - 1; bi >= 0; bi--) {
|
||||
const b = blocks[bi]
|
||||
if (b?.type === 'tool_call') {
|
||||
const tn = b.toolCall?.name
|
||||
if (tn === 'edit_workflow') {
|
||||
id = b.toolCall?.id
|
||||
break outer
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!id) {
|
||||
const candidates = Object.values(toolCallsById).filter((t) => t.name === 'edit_workflow')
|
||||
id = candidates.length ? candidates[candidates.length - 1].id : undefined
|
||||
}
|
||||
if (id) updatePreviewToolCallState('accepted', id)
|
||||
} catch {}
|
||||
}
|
||||
if (!id) {
|
||||
const candidates = Object.values(toolCallsById).filter((t) => t.name === 'edit_workflow')
|
||||
id = candidates.length ? candidates[candidates.length - 1].id : undefined
|
||||
}
|
||||
if (id) updatePreviewToolCallState('accepted', id)
|
||||
} catch {}
|
||||
|
||||
// Accept changes without blocking the UI; errors will be logged by the store handler
|
||||
acceptChanges().catch((error) => {
|
||||
logger.error('Failed to accept changes (background):', error)
|
||||
})
|
||||
// Accept changes without blocking the UI; errors will be logged by the store handler
|
||||
acceptChanges().catch((error) => {
|
||||
logger.error('Failed to accept changes (background):', error)
|
||||
})
|
||||
|
||||
logger.info('Accept triggered; UI will update optimistically')
|
||||
} catch (error) {
|
||||
logger.error('Failed to accept changes:', error)
|
||||
// Create checkpoint in the background (fire-and-forget) so it doesn't block UI
|
||||
createCheckpoint().catch((error) => {
|
||||
logger.warn('Failed to create checkpoint after accept:', error)
|
||||
})
|
||||
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'
|
||||
logger.error('Workflow update failed:', errorMessage)
|
||||
alert(`Failed to save workflow changes: ${errorMessage}`)
|
||||
}
|
||||
logger.info('Accept triggered; UI will update optimistically')
|
||||
}, [createCheckpoint, updatePreviewToolCallState, acceptChanges])
|
||||
|
||||
const handleReject = useCallback(() => {
|
||||
|
||||
@@ -433,6 +433,7 @@ export const useWorkflowDiffStore = create<WorkflowDiffState & WorkflowDiffActio
|
||||
)
|
||||
}
|
||||
|
||||
// Background operations (fire-and-forget) - don't block
|
||||
if (triggerMessageId) {
|
||||
fetch('/api/copilot/stats', {
|
||||
method: 'POST',
|
||||
@@ -445,14 +446,13 @@ export const useWorkflowDiffStore = create<WorkflowDiffState & WorkflowDiffActio
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
const toolCallId = await findLatestEditWorkflowToolCallId()
|
||||
if (toolCallId) {
|
||||
try {
|
||||
await getClientTool(toolCallId)?.handleAccept?.()
|
||||
} catch (error) {
|
||||
logger.warn('Failed to notify tool accept state', { error })
|
||||
findLatestEditWorkflowToolCallId().then((toolCallId) => {
|
||||
if (toolCallId) {
|
||||
getClientTool(toolCallId)?.handleAccept?.()?.catch?.((error: Error) => {
|
||||
logger.warn('Failed to notify tool accept state', { error })
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
rejectChanges: async () => {
|
||||
@@ -487,27 +487,26 @@ export const useWorkflowDiffStore = create<WorkflowDiffState & WorkflowDiffActio
|
||||
})
|
||||
const afterReject = cloneWorkflowState(baselineWorkflow)
|
||||
|
||||
// Clear diff state FIRST for instant UI feedback
|
||||
set({
|
||||
hasActiveDiff: false,
|
||||
isShowingDiff: false,
|
||||
isDiffReady: false,
|
||||
baselineWorkflow: null,
|
||||
baselineWorkflowId: null,
|
||||
diffAnalysis: null,
|
||||
diffMetadata: null,
|
||||
diffError: null,
|
||||
_triggerMessageId: null,
|
||||
})
|
||||
|
||||
// Clear the diff engine
|
||||
diffEngine.clearDiff()
|
||||
|
||||
// Apply baseline state locally
|
||||
applyWorkflowStateToStores(baselineWorkflowId, baselineWorkflow)
|
||||
|
||||
// Broadcast to other users
|
||||
logger.info('Broadcasting reject to other users', {
|
||||
workflowId: activeWorkflowId,
|
||||
blockCount: Object.keys(baselineWorkflow.blocks).length,
|
||||
})
|
||||
|
||||
await enqueueReplaceWorkflowState({
|
||||
workflowId: activeWorkflowId,
|
||||
state: baselineWorkflow,
|
||||
})
|
||||
|
||||
// Persist to database
|
||||
const persisted = await persistWorkflowStateToServer(baselineWorkflowId, baselineWorkflow)
|
||||
if (!persisted) {
|
||||
throw new Error('Failed to restore baseline workflow state')
|
||||
}
|
||||
|
||||
// Emit event for undo/redo recording
|
||||
// Emit event for undo/redo recording synchronously
|
||||
if (!(window as any).__skipDiffRecording) {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('record-diff-operation', {
|
||||
@@ -522,6 +521,25 @@ export const useWorkflowDiffStore = create<WorkflowDiffState & WorkflowDiffActio
|
||||
)
|
||||
}
|
||||
|
||||
// Background operations (fire-and-forget) - don't block UI
|
||||
// Broadcast to other users
|
||||
logger.info('Broadcasting reject to other users', {
|
||||
workflowId: activeWorkflowId,
|
||||
blockCount: Object.keys(baselineWorkflow.blocks).length,
|
||||
})
|
||||
|
||||
enqueueReplaceWorkflowState({
|
||||
workflowId: activeWorkflowId,
|
||||
state: baselineWorkflow,
|
||||
}).catch((error) => {
|
||||
logger.error('Failed to broadcast reject to other users:', error)
|
||||
})
|
||||
|
||||
// Persist to database in background
|
||||
persistWorkflowStateToServer(baselineWorkflowId, baselineWorkflow).catch((error) => {
|
||||
logger.error('Failed to persist baseline workflow state:', error)
|
||||
})
|
||||
|
||||
if (_triggerMessageId) {
|
||||
fetch('/api/copilot/stats', {
|
||||
method: 'POST',
|
||||
@@ -534,16 +552,13 @@ export const useWorkflowDiffStore = create<WorkflowDiffState & WorkflowDiffActio
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
const toolCallId = await findLatestEditWorkflowToolCallId()
|
||||
if (toolCallId) {
|
||||
try {
|
||||
await getClientTool(toolCallId)?.handleReject?.()
|
||||
} catch (error) {
|
||||
logger.warn('Failed to notify tool reject state', { error })
|
||||
findLatestEditWorkflowToolCallId().then((toolCallId) => {
|
||||
if (toolCallId) {
|
||||
getClientTool(toolCallId)?.handleReject?.()?.catch?.((error: Error) => {
|
||||
logger.warn('Failed to notify tool reject state', { error })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
get().clearDiff({ restoreBaseline: false })
|
||||
})
|
||||
},
|
||||
|
||||
reapplyDiffMarkers: () => {
|
||||
|
||||
Reference in New Issue
Block a user