diff --git a/apps/sim/app/api/copilot/chat/route.ts b/apps/sim/app/api/copilot/chat/route.ts index b14feb495d..0f96688647 100644 --- a/apps/sim/app/api/copilot/chat/route.ts +++ b/apps/sim/app/api/copilot/chat/route.ts @@ -171,6 +171,27 @@ export async function POST(req: NextRequest) { } } + // Detect migration requests and add specialized system prompt + const isMigrationRequest = message.toLowerCase().includes('convert this n8n workflow') + if (isMigrationRequest) { + try { + const { getMigrationSystemPrompt } = await import('@/lib/migration') + const migrationPrompt = getMigrationSystemPrompt() + + // Add migration instructions as a high-priority context + agentContexts.unshift({ + type: 'migration_instructions', + content: migrationPrompt, + }) + + logger.info(`[${tracker.requestId}] Migration request detected - added specialized prompt`, { + promptLength: migrationPrompt.length, + }) + } catch (e) { + logger.error(`[${tracker.requestId}] Failed to add migration prompt`, e) + } + } + // Handle chat context let currentChat: any = null let conversationHistory: any[] = [] diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/index.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/index.ts index 28de03e6cb..32cd081c34 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/index.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/index.ts @@ -1,4 +1,5 @@ export * from './copilot-message/copilot-message' +export * from './migration-dialog' export * from './plan-mode-section/plan-mode-section' export * from './todo-list/todo-list' export * from './tool-call/tool-call' diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/migration-dialog.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/migration-dialog.tsx new file mode 100644 index 0000000000..f7390dfa27 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/migration-dialog.tsx @@ -0,0 +1,181 @@ +'use client' + +import { useState } from 'react' +import { AlertCircle, FileUp, Upload } from 'lucide-react' +import { Button, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader } from '@/components/emcn' + +interface MigrationDialogProps { + open: boolean + onOpenChange: (open: boolean) => void + onSubmitToChat: (jsonContent: string) => void +} + +export function MigrationDialog({ open, onOpenChange, onSubmitToChat }: MigrationDialogProps) { + const [workflowJson, setWorkflowJson] = useState('') + const [validationError, setValidationError] = useState('') + + const handleFileUpload = (e: React.ChangeEvent) => { + const file = e.target.files?.[0] + if (!file) return + + const reader = new FileReader() + reader.onload = (event) => { + const content = event.target?.result as string + setWorkflowJson(content) + setValidationError('') + + // Validate it's valid JSON + try { + JSON.parse(content) + } catch (error) { + setValidationError('Invalid JSON format') + } + } + reader.onerror = () => { + setValidationError('Failed to read file. Please try again.') + } + reader.readAsText(file) + } + + const handleSubmit = async () => { + if (!workflowJson.trim()) { + setValidationError('Please upload or paste a workflow JSON') + return + } + + // Validate JSON + try { + const parsed = JSON.parse(workflowJson) + + // Basic n8n workflow validation + if (!parsed.nodes || !Array.isArray(parsed.nodes)) { + setValidationError('Invalid n8n workflow: missing "nodes" array') + return + } + + if (parsed.nodes.length === 0) { + setValidationError('Invalid n8n workflow: must contain at least one node') + return + } + + // Use the simplified formatter + const { formatMigrationRequest } = await import('@/lib/migration') + const message = await formatMigrationRequest(workflowJson) + + onSubmitToChat(message) + + // Reset and close + setWorkflowJson('') + setValidationError('') + onOpenChange(false) + } catch (error) { + setValidationError(error instanceof Error ? error.message : 'Invalid JSON format') + } + } + + const handleClose = () => { + setWorkflowJson('') + setValidationError('') + onOpenChange(false) + } + + return ( + + + +
+ Migrate from n8n + + BETA + +
+
+ + +
+ {/* Info Banner */} +
+
+ +
+

Upload n8n Workflow

+

+ Upload or paste your n8n workflow JSON. The workflow will be submitted to Copilot for intelligent conversion to Sim blocks. +

+
+
+
+ + {/* Upload Section */} +
+ +
+ +
+
+ + {/* JSON Input */} +
+ +