Skip to content

Commit 0e83894

Browse files
fix(copilot): targeted auto-layout for copilot edits + custom tool persistence (#1546)
* fix autolayout and custom tools persistence * fix * fix preserving positions within subflow * more fixes * fix resizing * consolidate constants
1 parent 7cc9a23 commit 0e83894

File tree

9 files changed

+996
-64
lines changed

9 files changed

+996
-64
lines changed

apps/sim/app/api/workflows/[id]/state/route.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { getSession } from '@/lib/auth'
77
import { createLogger } from '@/lib/logs/console/logger'
88
import { getUserEntityPermissions } from '@/lib/permissions/utils'
99
import { generateRequestId } from '@/lib/utils'
10+
import { extractAndPersistCustomTools } from '@/lib/workflows/custom-tools-persistence'
1011
import { saveWorkflowToNormalizedTables } from '@/lib/workflows/db-helpers'
1112
import { sanitizeAgentToolsInBlocks } from '@/lib/workflows/validation'
1213

@@ -207,6 +208,21 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{
207208
)
208209
}
209210

211+
// Extract and persist custom tools to database
212+
try {
213+
const { saved, errors } = await extractAndPersistCustomTools(workflowState, userId)
214+
215+
if (saved > 0) {
216+
logger.info(`[${requestId}] Persisted ${saved} custom tool(s) to database`, { workflowId })
217+
}
218+
219+
if (errors.length > 0) {
220+
logger.warn(`[${requestId}] Some custom tools failed to persist`, { errors, workflowId })
221+
}
222+
} catch (error) {
223+
logger.error(`[${requestId}] Failed to persist custom tools`, { error, workflowId })
224+
}
225+
210226
// Update workflow's lastSynced timestamp
211227
await db
212228
.update(workflow)

apps/sim/lib/copilot/tools/server/workflow/edit-workflow.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { eq } from 'drizzle-orm'
55
import type { BaseServerTool } from '@/lib/copilot/tools/server/base-tool'
66
import { createLogger } from '@/lib/logs/console/logger'
77
import { getBlockOutputs } from '@/lib/workflows/block-outputs'
8+
import { extractAndPersistCustomTools } from '@/lib/workflows/custom-tools-persistence'
89
import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/db-helpers'
910
import { validateWorkflowState } from '@/lib/workflows/validation'
1011
import { getAllBlocks } from '@/blocks/registry'
@@ -845,7 +846,7 @@ async function getCurrentWorkflowStateFromDb(
845846

846847
export const editWorkflowServerTool: BaseServerTool<EditWorkflowParams, any> = {
847848
name: 'edit_workflow',
848-
async execute(params: EditWorkflowParams): Promise<any> {
849+
async execute(params: EditWorkflowParams, context?: { userId: string }): Promise<any> {
849850
const logger = createLogger('EditWorkflowServerTool')
850851
const { operations, workflowId, currentUserWorkflow } = params
851852
if (!operations || operations.length === 0) throw new Error('operations are required')
@@ -891,6 +892,29 @@ export const editWorkflowServerTool: BaseServerTool<EditWorkflowParams, any> = {
891892
})
892893
}
893894

895+
// Extract and persist custom tools to database
896+
if (context?.userId) {
897+
try {
898+
const finalWorkflowState = validation.sanitizedState || modifiedWorkflowState
899+
const { saved, errors } = await extractAndPersistCustomTools(
900+
finalWorkflowState,
901+
context.userId
902+
)
903+
904+
if (saved > 0) {
905+
logger.info(`Persisted ${saved} custom tool(s) to database`, { workflowId })
906+
}
907+
908+
if (errors.length > 0) {
909+
logger.warn('Some custom tools failed to persist', { errors, workflowId })
910+
}
911+
} catch (error) {
912+
logger.error('Failed to persist custom tools', { error, workflowId })
913+
}
914+
} else {
915+
logger.warn('No userId in context - skipping custom tools persistence', { workflowId })
916+
}
917+
894918
logger.info('edit_workflow successfully applied operations', {
895919
operationCount: operations.length,
896920
blocksCount: Object.keys(modifiedWorkflowState.blocks).length,

apps/sim/lib/workflows/autolayout/containers.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import { assignLayers, groupByLayer } from './layering'
44
import { calculatePositions } from './positioning'
55
import type { Edge, LayoutOptions } from './types'
66
import {
7+
CONTAINER_PADDING,
8+
CONTAINER_PADDING_X,
9+
CONTAINER_PADDING_Y,
710
DEFAULT_CONTAINER_HEIGHT,
811
DEFAULT_CONTAINER_WIDTH,
912
getBlocksByParent,
@@ -12,10 +15,6 @@ import {
1215

1316
const logger = createLogger('AutoLayout:Containers')
1417

15-
const CONTAINER_PADDING = 150
16-
const CONTAINER_HORIZONTAL_PADDING = 180
17-
const CONTAINER_VERTICAL_PADDING = 100
18-
1918
export function layoutContainers(
2019
blocks: Record<string, BlockState>,
2120
edges: Edge[],
@@ -26,7 +25,7 @@ export function layoutContainers(
2625
const containerOptions: LayoutOptions = {
2726
horizontalSpacing: options.horizontalSpacing ? options.horizontalSpacing * 0.85 : 400,
2827
verticalSpacing: options.verticalSpacing ? options.verticalSpacing : 200,
29-
padding: { x: CONTAINER_HORIZONTAL_PADDING, y: CONTAINER_VERTICAL_PADDING },
28+
padding: { x: CONTAINER_PADDING_X, y: CONTAINER_PADDING_Y },
3029
alignment: options.alignment,
3130
}
3231

@@ -68,8 +67,8 @@ export function layoutContainers(
6867
}
6968

7069
// Adjust all child positions to start at proper padding from container edges
71-
const xOffset = CONTAINER_HORIZONTAL_PADDING - minX
72-
const yOffset = CONTAINER_VERTICAL_PADDING - minY
70+
const xOffset = CONTAINER_PADDING_X - minX
71+
const yOffset = CONTAINER_PADDING_Y - minY
7372

7473
for (const node of childNodes.values()) {
7574
childBlocks[node.id].position = {

apps/sim/lib/workflows/autolayout/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,6 @@ export function adjustForNewBlock(
100100
}
101101

102102
export type { LayoutOptions, LayoutResult, AdjustmentOptions, Edge, Loop, Parallel }
103+
export type { TargetedLayoutOptions } from './targeted'
104+
export { applyTargetedLayout, transferBlockHeights } from './targeted'
103105
export { getBlockMetrics, isContainerType } from './utils'

0 commit comments

Comments
 (0)