fix(copilot): targeted auto-layout for copilot edits + custom tool persistence#1546
fix(copilot): targeted auto-layout for copilot edits + custom tool persistence#1546icecrasher321 merged 6 commits intostagingfrom
Conversation
There was a problem hiding this comment.
Greptile Overview
Summary
This PR implements two critical fixes for the copilot feature: targeted auto-layout and custom tool persistence. The changes address user experience issues where copilot edits would disrupt entire workflow layouts and lose custom tools between sessions.The targeted auto-layout system introduces a more surgical approach to block positioning. Instead of repositioning all blocks during copilot edits, the new system only moves blocks that have actually been modified (changedBlockIds) while preserving the positions of unchanged blocks. This is implemented through a sophisticated anchor-based positioning strategy that uses unchanged blocks as reference points to maintain spatial relationships. The system includes logic to detect incremental edits vs complete workflow rebuilds, using targeted layout for the former and full autolayout only when copilot builds 100% of blocks from scratch.
The custom tool persistence feature ensures that tools generated during copilot sessions are properly saved to the database. The implementation extracts custom tools from workflow agent blocks through complex nested object traversal, handles deduplication by toolId/title, and persists them using database transactions with proper user ownership verification. This functionality is integrated into both the workflow state API endpoint and the copilot's workflow editing process, ensuring custom tools are saved whenever workflows are modified.
Both systems include comprehensive error handling, logging, and maintain backward compatibility. The targeted layout system integrates seamlessly with the existing autolayout infrastructure, while the persistence system handles edge cases like JSON parsing fallbacks and ID normalization. These changes transform the copilot from a disruptive workflow rebuilder into a collaborative editing partner that preserves user intent and tool continuity.
Changed Files
| Filename | Score | Overview |
|---|---|---|
| apps/sim/app/api/workflows/[id]/state/route.ts | 5/5 | Added custom tools persistence to workflow state save endpoint |
| apps/sim/lib/workflows/autolayout/index.ts | 5/5 | Exported targeted layout functions from new targeted module |
| apps/sim/lib/workflows/custom-tools-persistence.ts | 4/5 | New module implementing custom tool extraction and database persistence |
| apps/sim/lib/workflows/diff/diff-engine.ts | 4/5 | Implemented targeted auto-layout strategy for copilot edits |
| apps/sim/lib/copilot/tools/server/workflow/edit-workflow.ts | 4/5 | Added custom tool persistence to copilot workflow editing process |
| apps/sim/lib/workflows/autolayout/targeted.ts | 4/5 | New targeted auto-layout implementation with anchor-based positioning |
Confidence score: 4/5
- This PR addresses real UX issues with surgical precision and includes comprehensive error handling throughout
- Score reflects the complexity of the targeted layout logic and extensive use of
anytypes in the persistence system - Pay close attention to apps/sim/lib/workflows/custom-tools-persistence.ts for potential type safety and ID collision issues
Sequence Diagram
sequenceDiagram
participant User
participant Copilot
participant EditWorkflowTool
participant WorkflowDiffEngine
participant TargetedLayout
participant WorkflowStateAPI
participant CustomToolsPersistence
participant Database
User->>Copilot: "Request workflow edits"
Copilot->>EditWorkflowTool: "execute(operations, workflowId)"
EditWorkflowTool->>EditWorkflowTool: "getCurrentWorkflowStateFromDb()"
EditWorkflowTool->>Database: "Load workflow state"
Database-->>EditWorkflowTool: "Current workflow state"
EditWorkflowTool->>EditWorkflowTool: "applyOperationsToWorkflowState()"
Note over EditWorkflowTool: Process add/edit/delete operations
Note over EditWorkflowTool: Normalize custom tools in agent blocks
EditWorkflowTool->>CustomToolsPersistence: "extractAndPersistCustomTools()"
CustomToolsPersistence->>Database: "Save custom tools"
Database-->>CustomToolsPersistence: "Confirmation"
EditWorkflowTool->>WorkflowDiffEngine: "createDiffFromWorkflowState()"
WorkflowDiffEngine->>WorkflowDiffEngine: "Compute diff analysis"
WorkflowDiffEngine->>TargetedLayout: "applyTargetedLayout(changedBlockIds)"
Note over TargetedLayout: Apply targeted autolayout only to changed blocks
TargetedLayout-->>WorkflowDiffEngine: "Updated block positions"
WorkflowDiffEngine-->>EditWorkflowTool: "Diff with layout applied"
EditWorkflowTool-->>Copilot: "Modified workflow state"
Copilot-->>User: "Show diff preview"
User->>User: "Accept changes"
User->>WorkflowStateAPI: "PUT /api/workflows/[id]/state"
WorkflowStateAPI->>WorkflowStateAPI: "Validate permissions"
WorkflowStateAPI->>WorkflowStateAPI: "sanitizeAgentToolsInBlocks()"
WorkflowStateAPI->>WorkflowStateAPI: "saveWorkflowToNormalizedTables()"
WorkflowStateAPI->>Database: "Save workflow state"
WorkflowStateAPI->>CustomToolsPersistence: "extractAndPersistCustomTools()"
CustomToolsPersistence->>Database: "Persist custom tools"
Database-->>CustomToolsPersistence: "Success"
WorkflowStateAPI->>Database: "Update lastSynced timestamp"
Database-->>WorkflowStateAPI: "Confirmation"
WorkflowStateAPI-->>User: "Success response"
Context used:
Context from dashboard - Avoid using type assertions to 'any' in TypeScript. Instead, ensure proper type definitions are used... (source)
6 files reviewed, 4 comments
| : tool.toolId | ||
| } else { | ||
| // Use title as the base identifier (agent handler will add 'custom_' prefix) | ||
| baseId = tool.title |
There was a problem hiding this comment.
logic: Using title as baseId could cause conflicts if multiple tools have the same title but different functionality
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/lib/workflows/custom-tools-persistence.ts
Line: 121:121
Comment:
**logic:** Using title as baseId could cause conflicts if multiple tools have the same title but different functionality
How can I resolve this? If you propose a fix, please make it concise.
Summary
Type of Change
Testing
Tested Manually
Checklist