Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 3.8k
improvement(mothership): workflow edits via sockets#3927
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Uh oh!
There was an error while loading. Please reload this page.
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
6255838
improvement(mothership): workflow edits via sockets
icecrasher321 79476dd
make embedded view join room
icecrasher321 b9dd576
Merge branch 'staging' into improvement/mothership-workflow-edit
icecrasher321 93197f1
fix cursor positioning bug
icecrasher321 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
17 changes: 11 additions & 6 deletions
17 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -122,6 +122,7 @@ export function useCollaborativeWorkflow() { | ||
| onVariableUpdate, | ||
| onWorkflowDeleted, | ||
| onWorkflowReverted, | ||
| onWorkflowUpdated, | ||
| onOperationConfirmed, | ||
| onOperationFailed, | ||
| } = useSocket() | ||
| @@ -536,81 +537,99 @@ export function useCollaborativeWorkflow() { | ||
| } | ||
| } | ||
| const reloadWorkflowFromApi = async (workflowId: string, reason: string): Promise<boolean> => { | ||
| const response = await fetch(`/api/workflows/${workflowId}`) | ||
| if (!response.ok) { | ||
| logger.error(`Failed to fetch workflow data after ${reason}: ${response.statusText}`) | ||
| return false | ||
| } | ||
| const responseData = await response.json() | ||
| const workflowData = responseData.data | ||
| if (!workflowData?.state) { | ||
| logger.error(`No state found in workflow data after ${reason}`, { workflowData }) | ||
| return false | ||
| } | ||
| isApplyingRemoteChange.current = true | ||
| try { | ||
| useWorkflowStore.getState().replaceWorkflowState({ | ||
| blocks: workflowData.state.blocks || {}, | ||
| edges: workflowData.state.edges || [], | ||
| loops: workflowData.state.loops || {}, | ||
| parallels: workflowData.state.parallels || {}, | ||
| lastSaved: workflowData.state.lastSaved || Date.now(), | ||
| }) | ||
| const subblockValues: Record<string, Record<string, any>> = {} | ||
| Object.entries(workflowData.state.blocks || {}).forEach(([blockId, block]) => { | ||
| const blockState = block as any | ||
| subblockValues[blockId] = {} | ||
| Object.entries(blockState.subBlocks || {}).forEach(([subblockId, subblock]) => { | ||
| subblockValues[blockId][subblockId] = (subblock as any).value | ||
| }) | ||
| }) | ||
| useSubBlockStore.setState((state: any) => ({ | ||
| workflowValues: { | ||
| ...state.workflowValues, | ||
| [workflowId]: subblockValues, | ||
| }, | ||
| })) | ||
| const graph = { | ||
| blocksById: workflowData.state.blocks || {}, | ||
| edgesById: Object.fromEntries( | ||
| (workflowData.state.edges || []).map((e: any) => [e.id, e]) | ||
| ), | ||
| } | ||
| const undoRedoStore = useUndoRedoStore.getState() | ||
| const stackKeys = Object.keys(undoRedoStore.stacks) | ||
| stackKeys.forEach((key) => { | ||
| const [wfId, userId] = key.split(':') | ||
| if (wfId === workflowId) { | ||
| undoRedoStore.pruneInvalidEntries(wfId, userId, graph) | ||
| } | ||
| }) | ||
| logger.info(`Successfully reloaded workflow state after ${reason}`, { workflowId }) | ||
| return true | ||
| } finally { | ||
| isApplyingRemoteChange.current = false | ||
| } | ||
| } | ||
| const handleWorkflowReverted = async (data: any) => { | ||
| const { workflowId } = data | ||
| logger.info(`Workflow ${workflowId} has been reverted to deployed state`) | ||
| // If the reverted workflow is the currently active one, reload the workflow state | ||
| if (activeWorkflowId === workflowId) { | ||
| logger.info(`Currently active workflow ${workflowId} was reverted, reloading state`) | ||
| try { | ||
| // Fetch the updated workflow state from the server (which loads from normalized tables) | ||
| const response = await fetch(`/api/workflows/${workflowId}`) | ||
| if (response.ok) { | ||
| const responseData = await response.json() | ||
| const workflowData = responseData.data | ||
| if (workflowData?.state) { | ||
| // Update the workflow store with the reverted state | ||
| isApplyingRemoteChange.current = true | ||
| try { | ||
| // Update the main workflow state using the API response | ||
| useWorkflowStore.getState().replaceWorkflowState({ | ||
| blocks: workflowData.state.blocks || {}, | ||
| edges: workflowData.state.edges || [], | ||
| loops: workflowData.state.loops || {}, | ||
| parallels: workflowData.state.parallels || {}, | ||
| lastSaved: workflowData.state.lastSaved || Date.now(), | ||
| }) | ||
| if (activeWorkflowId !== workflowId) return | ||
| // Update subblock store with reverted values | ||
| const subblockValues: Record<string, Record<string, any>> = {} | ||
| Object.entries(workflowData.state.blocks || {}).forEach(([blockId, block]) => { | ||
| const blockState = block as any | ||
| subblockValues[blockId] = {} | ||
| Object.entries(blockState.subBlocks || {}).forEach(([subblockId, subblock]) => { | ||
| subblockValues[blockId][subblockId] = (subblock as any).value | ||
| }) | ||
| }) | ||
| try { | ||
| await reloadWorkflowFromApi(workflowId, 'revert') | ||
| } catch (error) { | ||
| logger.error('Error reloading workflow state after revert:', error) | ||
| } | ||
| } | ||
| // Update subblock store for this workflow | ||
| useSubBlockStore.setState((state: any) => ({ | ||
| workflowValues: { | ||
| ...state.workflowValues, | ||
| [workflowId]: subblockValues, | ||
| }, | ||
| })) | ||
| const handleWorkflowUpdated = async (data: any) => { | ||
| const { workflowId } = data | ||
| logger.info(`Workflow ${workflowId} has been updated externally`) | ||
| logger.info(`Successfully loaded reverted workflow state for ${workflowId}`) | ||
| if (activeWorkflowId !== workflowId) return | ||
| const graph = { | ||
| blocksById: workflowData.state.blocks || {}, | ||
| edgesById: Object.fromEntries( | ||
| (workflowData.state.edges || []).map((e: any) => [e.id, e]) | ||
| ), | ||
| } | ||
| const { hasActiveDiff } = useWorkflowDiffStore.getState() | ||
| if (hasActiveDiff) { | ||
| logger.info('Skipping workflow-updated: active diff in progress', { workflowId }) | ||
| return | ||
| } | ||
| const undoRedoStore = useUndoRedoStore.getState() | ||
| const stackKeys = Object.keys(undoRedoStore.stacks) | ||
| stackKeys.forEach((key) => { | ||
| const [wfId, userId] = key.split(':') | ||
| if (wfId === workflowId) { | ||
| undoRedoStore.pruneInvalidEntries(wfId, userId, graph) | ||
| } | ||
| }) | ||
| } finally { | ||
| isApplyingRemoteChange.current = false | ||
| } | ||
| } else { | ||
| logger.error('No state found in workflow data after revert', { workflowData }) | ||
| } | ||
| } else { | ||
| logger.error(`Failed to fetch workflow data after revert: ${response.statusText}`) | ||
| } | ||
| } catch (error) { | ||
| logger.error('Error reloading workflow state after revert:', error) | ||
| } | ||
| try { | ||
| await reloadWorkflowFromApi(workflowId, 'external update') | ||
| } catch (error) { | ||
| logger.error('Error reloading workflow state after external update:', error) | ||
| } | ||
| } | ||
icecrasher321 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| @@ -632,6 +651,7 @@ export function useCollaborativeWorkflow() { | ||
| onVariableUpdate(handleVariableUpdate) | ||
| onWorkflowDeleted(handleWorkflowDeleted) | ||
| onWorkflowReverted(handleWorkflowReverted) | ||
| onWorkflowUpdated(handleWorkflowUpdated) | ||
| onOperationConfirmed(handleOperationConfirmed) | ||
| onOperationFailed(handleOperationFailed) | ||
| }, [ | ||
| @@ -640,6 +660,7 @@ export function useCollaborativeWorkflow() { | ||
| onVariableUpdate, | ||
| onWorkflowDeleted, | ||
| onWorkflowReverted, | ||
| onWorkflowUpdated, | ||
| onOperationConfirmed, | ||
| onOperationFailed, | ||
| activeWorkflowId, | ||
13 changes: 13 additions & 0 deletions
13 apps/sim/lib/copilot/tools/server/workflow/edit-workflow/index.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.