@friggframework/devtools 2.0.0--canary.398.7664c46.0 → 2.0.0--canary.400.bed3308.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/frigg-cli/.eslintrc.js +141 -0
  2. package/frigg-cli/__tests__/jest.config.js +102 -0
  3. package/frigg-cli/__tests__/unit/commands/build.test.js +483 -0
  4. package/frigg-cli/__tests__/unit/commands/install.test.js +418 -0
  5. package/frigg-cli/__tests__/unit/commands/ui.test.js +592 -0
  6. package/frigg-cli/__tests__/utils/command-tester.js +170 -0
  7. package/frigg-cli/__tests__/utils/mock-factory.js +270 -0
  8. package/frigg-cli/__tests__/utils/test-fixtures.js +463 -0
  9. package/frigg-cli/__tests__/utils/test-setup.js +286 -0
  10. package/frigg-cli/build-command/index.js +15 -2
  11. package/frigg-cli/deploy-command/index.js +15 -2
  12. package/frigg-cli/generate-command/__tests__/generate-command.test.js +312 -0
  13. package/frigg-cli/generate-command/azure-generator.js +43 -0
  14. package/frigg-cli/generate-command/gcp-generator.js +47 -0
  15. package/frigg-cli/generate-command/index.js +350 -0
  16. package/frigg-cli/generate-command/terraform-generator.js +555 -0
  17. package/frigg-cli/index.js +66 -4
  18. package/frigg-cli/install-command/index.js +15 -2
  19. package/frigg-cli/package.json +75 -0
  20. package/frigg-cli/start-command/index.js +17 -2
  21. package/frigg-cli/ui-command/index.js +167 -0
  22. package/frigg-cli/utils/app-resolver.js +319 -0
  23. package/frigg-cli/utils/backend-path.js +38 -0
  24. package/frigg-cli/utils/process-manager.js +199 -0
  25. package/frigg-cli/utils/repo-detection.js +405 -0
  26. package/infrastructure/AWS-IAM-CREDENTIAL-NEEDS.md +43 -19
  27. package/infrastructure/IAM-POLICY-TEMPLATES.md +1 -1
  28. package/infrastructure/frigg-deployment-iam-stack.yaml +16 -2
  29. package/infrastructure/iam-generator.js +129 -6
  30. package/infrastructure/iam-policy-basic.json +29 -5
  31. package/infrastructure/iam-policy-full.json +28 -5
  32. package/infrastructure/serverless-template.js +209 -3
  33. package/infrastructure/serverless-template.test.js +12 -0
  34. package/management-ui/.eslintrc.js +22 -0
  35. package/management-ui/README.md +203 -0
  36. package/management-ui/components.json +21 -0
  37. package/management-ui/{dist/index.html → index.html} +1 -2
  38. package/management-ui/merge-conflict-cleaner.py +371 -0
  39. package/management-ui/package-lock.json +10997 -0
  40. package/management-ui/package.json +76 -0
  41. package/management-ui/postcss.config.js +6 -0
  42. package/management-ui/server/api/backend.js +256 -0
  43. package/management-ui/server/api/cli.js +315 -0
  44. package/management-ui/server/api/codegen.js +663 -0
  45. package/management-ui/server/api/connections.js +857 -0
  46. package/management-ui/server/api/discovery.js +185 -0
  47. package/management-ui/server/api/environment/index.js +1 -0
  48. package/management-ui/server/api/environment/router.js +378 -0
  49. package/management-ui/server/api/environment.js +328 -0
  50. package/management-ui/server/api/integrations.js +479 -0
  51. package/management-ui/server/api/logs.js +248 -0
  52. package/management-ui/server/api/monitoring.js +282 -0
  53. package/management-ui/server/api/open-ide.js +31 -0
  54. package/management-ui/server/api/project.js +553 -0
  55. package/management-ui/server/api/users/sessions.js +371 -0
  56. package/management-ui/server/api/users/simulation.js +254 -0
  57. package/management-ui/server/api/users.js +362 -0
  58. package/management-ui/server/api-contract.md +275 -0
  59. package/management-ui/server/index.js +428 -0
  60. package/management-ui/server/middleware/errorHandler.js +70 -0
  61. package/management-ui/server/middleware/security.js +32 -0
  62. package/management-ui/server/processManager.js +296 -0
  63. package/management-ui/server/server.js +188 -0
  64. package/management-ui/server/services/aws-monitor.js +413 -0
  65. package/management-ui/server/services/npm-registry.js +347 -0
  66. package/management-ui/server/services/template-engine.js +538 -0
  67. package/management-ui/server/utils/cliIntegration.js +220 -0
  68. package/management-ui/server/utils/environment/auditLogger.js +471 -0
  69. package/management-ui/server/utils/environment/awsParameterStore.js +264 -0
  70. package/management-ui/server/utils/environment/encryption.js +278 -0
  71. package/management-ui/server/utils/environment/envFileManager.js +286 -0
  72. package/management-ui/server/utils/import-commonjs.js +28 -0
  73. package/management-ui/server/utils/response.js +83 -0
  74. package/management-ui/server/websocket/handler.js +325 -0
  75. package/management-ui/src/App.jsx +51 -0
  76. package/management-ui/src/components/AppRouter.jsx +65 -0
  77. package/management-ui/src/components/Button.jsx +2 -0
  78. package/management-ui/src/components/Card.jsx +9 -0
  79. package/management-ui/src/components/EnvironmentCompare.jsx +400 -0
  80. package/management-ui/src/components/EnvironmentEditor.jsx +372 -0
  81. package/management-ui/src/components/EnvironmentImportExport.jsx +469 -0
  82. package/management-ui/src/components/EnvironmentSchema.jsx +491 -0
  83. package/management-ui/src/components/EnvironmentSecurity.jsx +463 -0
  84. package/management-ui/src/components/ErrorBoundary.jsx +73 -0
  85. package/management-ui/src/components/IntegrationCard.jsx +199 -0
  86. package/management-ui/src/components/IntegrationCardEnhanced.jsx +490 -0
  87. package/management-ui/src/components/IntegrationExplorer.jsx +379 -0
  88. package/management-ui/src/components/IntegrationStatus.jsx +235 -0
  89. package/management-ui/src/components/Layout.jsx +250 -0
  90. package/management-ui/src/components/LoadingSpinner.jsx +45 -0
  91. package/management-ui/src/components/RepositoryPicker.jsx +248 -0
  92. package/management-ui/src/components/SessionMonitor.jsx +255 -0
  93. package/management-ui/src/components/StatusBadge.jsx +70 -0
  94. package/management-ui/src/components/UserContextSwitcher.jsx +154 -0
  95. package/management-ui/src/components/UserSimulation.jsx +299 -0
  96. package/management-ui/src/components/Welcome.jsx +434 -0
  97. package/management-ui/src/components/codegen/APIEndpointGenerator.jsx +637 -0
  98. package/management-ui/src/components/codegen/APIModuleSelector.jsx +227 -0
  99. package/management-ui/src/components/codegen/CodeGenerationWizard.jsx +247 -0
  100. package/management-ui/src/components/codegen/CodePreviewEditor.jsx +316 -0
  101. package/management-ui/src/components/codegen/DynamicModuleForm.jsx +271 -0
  102. package/management-ui/src/components/codegen/FormBuilder.jsx +737 -0
  103. package/management-ui/src/components/codegen/IntegrationGenerator.jsx +855 -0
  104. package/management-ui/src/components/codegen/ProjectScaffoldWizard.jsx +797 -0
  105. package/management-ui/src/components/codegen/SchemaBuilder.jsx +303 -0
  106. package/management-ui/src/components/codegen/TemplateSelector.jsx +586 -0
  107. package/management-ui/src/components/codegen/index.js +10 -0
  108. package/management-ui/src/components/connections/ConnectionConfigForm.jsx +362 -0
  109. package/management-ui/src/components/connections/ConnectionHealthMonitor.jsx +182 -0
  110. package/management-ui/src/components/connections/ConnectionTester.jsx +200 -0
  111. package/management-ui/src/components/connections/EntityRelationshipMapper.jsx +292 -0
  112. package/management-ui/src/components/connections/OAuthFlow.jsx +204 -0
  113. package/management-ui/src/components/connections/index.js +5 -0
  114. package/management-ui/src/components/index.js +21 -0
  115. package/management-ui/src/components/monitoring/APIGatewayMetrics.jsx +222 -0
  116. package/management-ui/src/components/monitoring/LambdaMetrics.jsx +169 -0
  117. package/management-ui/src/components/monitoring/MetricsChart.jsx +197 -0
  118. package/management-ui/src/components/monitoring/MonitoringDashboard.jsx +393 -0
  119. package/management-ui/src/components/monitoring/SQSMetrics.jsx +246 -0
  120. package/management-ui/src/components/monitoring/index.js +6 -0
  121. package/management-ui/src/components/monitoring/monitoring.css +218 -0
  122. package/management-ui/src/components/theme-provider.jsx +52 -0
  123. package/management-ui/src/components/theme-toggle.jsx +39 -0
  124. package/management-ui/src/components/ui/badge.tsx +36 -0
  125. package/management-ui/src/components/ui/button.test.jsx +56 -0
  126. package/management-ui/src/components/ui/button.tsx +57 -0
  127. package/management-ui/src/components/ui/card.tsx +76 -0
  128. package/management-ui/src/components/ui/dropdown-menu.tsx +199 -0
  129. package/management-ui/src/components/ui/select.tsx +157 -0
  130. package/management-ui/src/components/ui/skeleton.jsx +15 -0
  131. package/management-ui/src/hooks/useFrigg.jsx +387 -0
  132. package/management-ui/src/hooks/useSocket.jsx +58 -0
  133. package/management-ui/src/index.css +194 -0
  134. package/management-ui/src/lib/utils.ts +6 -0
  135. package/management-ui/src/main.jsx +10 -0
  136. package/management-ui/src/pages/CodeGeneration.jsx +14 -0
  137. package/management-ui/src/pages/Connections.jsx +252 -0
  138. package/management-ui/src/pages/ConnectionsEnhanced.jsx +427 -0
  139. package/management-ui/src/pages/Dashboard.jsx +311 -0
  140. package/management-ui/src/pages/Environment.jsx +314 -0
  141. package/management-ui/src/pages/IntegrationConfigure.jsx +544 -0
  142. package/management-ui/src/pages/IntegrationDiscovery.jsx +479 -0
  143. package/management-ui/src/pages/IntegrationTest.jsx +494 -0
  144. package/management-ui/src/pages/Integrations.jsx +254 -0
  145. package/management-ui/src/pages/Monitoring.jsx +17 -0
  146. package/management-ui/src/pages/Simulation.jsx +155 -0
  147. package/management-ui/src/pages/Users.jsx +492 -0
  148. package/management-ui/src/services/api.js +41 -0
  149. package/management-ui/src/services/apiModuleService.js +193 -0
  150. package/management-ui/src/services/websocket-handlers.js +120 -0
  151. package/management-ui/src/test/api/project.test.js +273 -0
  152. package/management-ui/src/test/components/Welcome.test.jsx +378 -0
  153. package/management-ui/src/test/mocks/server.js +178 -0
  154. package/management-ui/src/test/setup.js +61 -0
  155. package/management-ui/src/test/utils/test-utils.jsx +134 -0
  156. package/management-ui/src/utils/repository.js +98 -0
  157. package/management-ui/src/utils/repository.test.js +118 -0
  158. package/management-ui/src/workflows/phase2-integration-workflows.js +884 -0
  159. package/management-ui/tailwind.config.js +63 -0
  160. package/management-ui/tsconfig.json +37 -0
  161. package/management-ui/tsconfig.node.json +10 -0
  162. package/management-ui/vite.config.js +26 -0
  163. package/management-ui/vitest.config.js +38 -0
  164. package/package.json +5 -5
  165. package/management-ui/dist/assets/index-CbM64Oba.js +0 -1221
  166. package/management-ui/dist/assets/index-CkvseXTC.css +0 -1
  167. /package/management-ui/{dist/assets/FriggLogo-B7Xx8ZW1.svg → src/assets/FriggLogo.svg} +0 -0
@@ -0,0 +1,371 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Merge Conflict Cleaner Script
4
+
5
+ This script automatically cleans up merge conflicts by:
6
+ 1. Removing duplicate imports
7
+ 2. Keeping the most complete version of duplicated code blocks
8
+ 3. Ensuring proper syntax after cleanup
9
+ 4. Preserving functionality while removing conflicts
10
+
11
+ Focus on these key patterns:
12
+ - Import dedupe and consolidation
13
+ - Taking the most complete version of components
14
+ - Preserving industrial design system elements
15
+ - Keeping proper React patterns
16
+ """
17
+
18
+ import os
19
+ import re
20
+ import sys
21
+ from pathlib import Path
22
+ from typing import List, Dict, Set, Tuple
23
+ import logging
24
+
25
+ # Configure logging
26
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
27
+ logger = logging.getLogger(__name__)
28
+
29
+ class MergeConflictCleaner:
30
+ def __init__(self, base_path: str):
31
+ self.base_path = Path(base_path)
32
+ self.files_processed = 0
33
+ self.conflicts_resolved = 0
34
+ self.errors = []
35
+
36
+ def find_conflict_files(self) -> List[Path]:
37
+ """Find all files with merge conflict markers"""
38
+ conflict_files = []
39
+
40
+ for file_path in self.base_path.rglob('*.jsx'):
41
+ if self._has_conflicts(file_path):
42
+ conflict_files.append(file_path)
43
+
44
+ for file_path in self.base_path.rglob('*.js'):
45
+ if self._has_conflicts(file_path):
46
+ conflict_files.append(file_path)
47
+
48
+ for file_path in self.base_path.rglob('*.css'):
49
+ if self._has_conflicts(file_path):
50
+ conflict_files.append(file_path)
51
+
52
+ return conflict_files
53
+
54
+ def _has_conflicts(self, file_path: Path) -> bool:
55
+ """Check if file has merge conflict markers"""
56
+ try:
57
+ with open(file_path, 'r', encoding='utf-8') as f:
58
+ content = f.read()
59
+ return any(marker in content for marker in ['<<<<<<<', '=======', '>>>>>>>'])
60
+ except Exception as e:
61
+ logger.error(f"Error reading {file_path}: {e}")
62
+ return False
63
+
64
+ def clean_file(self, file_path: Path) -> bool:
65
+ """Clean merge conflicts in a single file"""
66
+ try:
67
+ with open(file_path, 'r', encoding='utf-8') as f:
68
+ content = f.read()
69
+
70
+ logger.info(f"Processing {file_path}")
71
+
72
+ # Parse and resolve conflicts
73
+ cleaned_content = self._resolve_conflicts(content, file_path)
74
+
75
+ # Write cleaned content back
76
+ with open(file_path, 'w', encoding='utf-8') as f:
77
+ f.write(cleaned_content)
78
+
79
+ self.files_processed += 1
80
+ return True
81
+
82
+ except Exception as e:
83
+ error_msg = f"Error processing {file_path}: {e}"
84
+ logger.error(error_msg)
85
+ self.errors.append(error_msg)
86
+ return False
87
+
88
+ def _resolve_conflicts(self, content: str, file_path: Path) -> str:
89
+ """Resolve merge conflicts in content"""
90
+ lines = content.split('\n')
91
+ cleaned_lines = []
92
+ i = 0
93
+
94
+ while i < len(lines):
95
+ line = lines[i]
96
+
97
+ # Check for conflict start
98
+ if line.startswith('<<<<<<<'):
99
+ conflict_resolved = self._resolve_conflict_block(lines, i, file_path)
100
+ if conflict_resolved:
101
+ resolved_lines, skip_count = conflict_resolved
102
+ cleaned_lines.extend(resolved_lines)
103
+ i += skip_count
104
+ self.conflicts_resolved += 1
105
+ else:
106
+ # If we can't resolve, keep the line as is
107
+ cleaned_lines.append(line)
108
+ i += 1
109
+ else:
110
+ cleaned_lines.append(line)
111
+ i += 1
112
+
113
+ return '\n'.join(cleaned_lines)
114
+
115
+ def _resolve_conflict_block(self, lines: List[str], start_idx: int, file_path: Path) -> Tuple[List[str], int]:
116
+ """Resolve a single conflict block"""
117
+ # Find the boundaries of the conflict
118
+ head_start = start_idx
119
+ separator_idx = -1
120
+ end_idx = -1
121
+
122
+ for i in range(start_idx + 1, len(lines)):
123
+ if lines[i].startswith('======='):
124
+ separator_idx = i
125
+ elif lines[i].startswith('>>>>>>>'):
126
+ end_idx = i
127
+ break
128
+
129
+ if separator_idx == -1 or end_idx == -1:
130
+ logger.warning(f"Malformed conflict block at line {start_idx + 1} in {file_path}")
131
+ return None
132
+
133
+ # Extract the two versions
134
+ head_version = lines[head_start + 1:separator_idx]
135
+ incoming_version = lines[separator_idx + 1:end_idx]
136
+
137
+ # Resolve based on file-specific logic
138
+ resolved_lines = self._choose_best_version(head_version, incoming_version, file_path)
139
+
140
+ # Return resolved lines and number of lines to skip
141
+ return resolved_lines, end_idx - start_idx + 1
142
+
143
+ def _choose_best_version(self, head_version: List[str], incoming_version: List[str], file_path: Path) -> List[str]:
144
+ """Choose the best version based on content analysis"""
145
+
146
+ # Handle imports specially
147
+ if self._is_import_block(head_version) or self._is_import_block(incoming_version):
148
+ return self._merge_imports(head_version, incoming_version)
149
+
150
+ # Handle export statements
151
+ if self._is_export_block(head_version) or self._is_export_block(incoming_version):
152
+ return self._merge_exports(head_version, incoming_version)
153
+
154
+ # For Layout.jsx and similar component files, prefer the more complete version
155
+ if 'Layout.jsx' in str(file_path):
156
+ return self._resolve_layout_conflicts(head_version, incoming_version)
157
+
158
+ # For Button.jsx, prefer the shadcn re-export version
159
+ if 'Button.jsx' in str(file_path):
160
+ return self._resolve_button_conflicts(head_version, incoming_version)
161
+
162
+ # General heuristic: prefer the version with more content
163
+ if len(''.join(head_version).strip()) > len(''.join(incoming_version).strip()):
164
+ return head_version
165
+ else:
166
+ return incoming_version
167
+
168
+ def _is_import_block(self, lines: List[str]) -> bool:
169
+ """Check if this is an import block"""
170
+ content = ''.join(lines).strip()
171
+ return content.startswith('import') or 'import' in content
172
+
173
+ def _is_export_block(self, lines: List[str]) -> bool:
174
+ """Check if this is an export block"""
175
+ content = ''.join(lines).strip()
176
+ return content.startswith('export') or 'export' in content
177
+
178
+ def _merge_imports(self, head_version: List[str], incoming_version: List[str]) -> List[str]:
179
+ """Merge and deduplicate imports"""
180
+ all_imports = set()
181
+ import_lines = []
182
+
183
+ # Process both versions
184
+ for version in [head_version, incoming_version]:
185
+ for line in version:
186
+ line = line.strip()
187
+ if line and not line.startswith('//'):
188
+ # Extract import statements
189
+ if line.startswith('import'):
190
+ if line not in all_imports:
191
+ all_imports.add(line)
192
+ import_lines.append(line)
193
+ elif 'import' in line and '{' in line:
194
+ # Handle multi-line imports
195
+ if line not in all_imports:
196
+ all_imports.add(line)
197
+ import_lines.append(line)
198
+
199
+ # Sort imports for consistency
200
+ import_lines.sort()
201
+ return import_lines
202
+
203
+ def _merge_exports(self, head_version: List[str], incoming_version: List[str]) -> List[str]:
204
+ """Merge exports, preferring named exports"""
205
+ for version in [head_version, incoming_version]:
206
+ for line in version:
207
+ if 'export {' in line:
208
+ return version
209
+
210
+ # If no named exports, prefer the version with more content
211
+ if len(''.join(head_version).strip()) > len(''.join(incoming_version).strip()):
212
+ return head_version
213
+ else:
214
+ return incoming_version
215
+
216
+ def _resolve_layout_conflicts(self, head_version: List[str], incoming_version: List[str]) -> List[str]:
217
+ """Resolve Layout.jsx specific conflicts"""
218
+ # Look for industrial design elements
219
+ head_content = ''.join(head_version)
220
+ incoming_content = ''.join(incoming_version)
221
+
222
+ # Prefer version with industrial design elements
223
+ industrial_keywords = ['industrial', 'FriggLogo', 'ThemeToggle', 'RepositoryPicker']
224
+
225
+ head_score = sum(1 for keyword in industrial_keywords if keyword in head_content)
226
+ incoming_score = sum(1 for keyword in industrial_keywords if keyword in incoming_content)
227
+
228
+ if head_score > incoming_score:
229
+ return head_version
230
+ elif incoming_score > head_score:
231
+ return incoming_version
232
+ else:
233
+ # If equal, prefer the longer version
234
+ return head_version if len(head_content) > len(incoming_content) else incoming_version
235
+
236
+ def _resolve_button_conflicts(self, head_version: List[str], incoming_version: List[str]) -> List[str]:
237
+ """Resolve Button.jsx conflicts - prefer shadcn re-export"""
238
+ head_content = ''.join(head_version)
239
+ incoming_content = ''.join(incoming_version)
240
+
241
+ # Prefer the shadcn re-export version
242
+ if 'ui/button' in head_content:
243
+ return head_version
244
+ elif 'ui/button' in incoming_content:
245
+ return incoming_version
246
+ else:
247
+ # If neither has shadcn, prefer the more complete implementation
248
+ return head_version if len(head_content) > len(incoming_content) else incoming_version
249
+
250
+ def verify_syntax(self, file_path: Path) -> bool:
251
+ """Basic syntax verification for JS/JSX files"""
252
+ try:
253
+ with open(file_path, 'r', encoding='utf-8') as f:
254
+ content = f.read()
255
+
256
+ # Basic checks
257
+ if file_path.suffix in ['.jsx', '.js']:
258
+ # Check for unbalanced braces
259
+ open_braces = content.count('{')
260
+ close_braces = content.count('}')
261
+ if open_braces != close_braces:
262
+ logger.warning(f"Unbalanced braces in {file_path}")
263
+ return False
264
+
265
+ # Check for unbalanced parentheses
266
+ open_parens = content.count('(')
267
+ close_parens = content.count(')')
268
+ if open_parens != close_parens:
269
+ logger.warning(f"Unbalanced parentheses in {file_path}")
270
+ return False
271
+
272
+ # Check for remaining conflict markers
273
+ if any(marker in content for marker in ['<<<<<<<', '=======', '>>>>>>>']):
274
+ logger.warning(f"Remaining conflict markers in {file_path}")
275
+ return False
276
+
277
+ return True
278
+
279
+ except Exception as e:
280
+ logger.error(f"Error verifying syntax for {file_path}: {e}")
281
+ return False
282
+
283
+ def run(self) -> Dict[str, any]:
284
+ """Run the merge conflict cleaner"""
285
+ logger.info(f"Starting merge conflict cleanup in {self.base_path}")
286
+
287
+ # Find all files with conflicts
288
+ conflict_files = self.find_conflict_files()
289
+
290
+ if not conflict_files:
291
+ logger.info("No merge conflicts found!")
292
+ return {
293
+ 'files_processed': 0,
294
+ 'conflicts_resolved': 0,
295
+ 'errors': [],
296
+ 'success': True
297
+ }
298
+
299
+ logger.info(f"Found {len(conflict_files)} files with merge conflicts")
300
+
301
+ # Process each file
302
+ successful_files = []
303
+ failed_files = []
304
+
305
+ for file_path in conflict_files:
306
+ if self.clean_file(file_path):
307
+ if self.verify_syntax(file_path):
308
+ successful_files.append(file_path)
309
+ logger.info(f"✓ Successfully cleaned {file_path}")
310
+ else:
311
+ failed_files.append(file_path)
312
+ logger.error(f"✗ Syntax issues after cleaning {file_path}")
313
+ else:
314
+ failed_files.append(file_path)
315
+ logger.error(f"✗ Failed to clean {file_path}")
316
+
317
+ # Summary
318
+ logger.info(f"Cleanup complete!")
319
+ logger.info(f"Files processed: {self.files_processed}")
320
+ logger.info(f"Conflicts resolved: {self.conflicts_resolved}")
321
+ logger.info(f"Successful: {len(successful_files)}")
322
+ logger.info(f"Failed: {len(failed_files)}")
323
+
324
+ if failed_files:
325
+ logger.error("Failed files:")
326
+ for file_path in failed_files:
327
+ logger.error(f" - {file_path}")
328
+
329
+ if self.errors:
330
+ logger.error("Errors encountered:")
331
+ for error in self.errors:
332
+ logger.error(f" - {error}")
333
+
334
+ return {
335
+ 'files_processed': self.files_processed,
336
+ 'conflicts_resolved': self.conflicts_resolved,
337
+ 'successful_files': successful_files,
338
+ 'failed_files': failed_files,
339
+ 'errors': self.errors,
340
+ 'success': len(failed_files) == 0
341
+ }
342
+
343
+ def main():
344
+ """Main entry point"""
345
+ if len(sys.argv) != 2:
346
+ print("Usage: python merge-conflict-cleaner.py <path-to-src-directory>")
347
+ sys.exit(1)
348
+
349
+ src_path = sys.argv[1]
350
+
351
+ if not os.path.exists(src_path):
352
+ print(f"Error: Path {src_path} does not exist")
353
+ sys.exit(1)
354
+
355
+ cleaner = MergeConflictCleaner(src_path)
356
+ result = cleaner.run()
357
+
358
+ if result['success']:
359
+ print(f"\n✓ All merge conflicts resolved successfully!")
360
+ print(f" Files processed: {result['files_processed']}")
361
+ print(f" Conflicts resolved: {result['conflicts_resolved']}")
362
+ sys.exit(0)
363
+ else:
364
+ print(f"\n✗ Some issues occurred during cleanup")
365
+ print(f" Files processed: {result['files_processed']}")
366
+ print(f" Conflicts resolved: {result['conflicts_resolved']}")
367
+ print(f" Errors: {len(result['errors'])}")
368
+ sys.exit(1)
369
+
370
+ if __name__ == "__main__":
371
+ main()