cursorflow 1.2.0__py3-none-any.whl → 1.3.0__py3-none-any.whl

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.
@@ -20,6 +20,7 @@ from .auth_handler import AuthHandler
20
20
  from .css_iterator import CSSIterator
21
21
  from .cursor_integration import CursorIntegration
22
22
  from .persistent_session import PersistentSession, get_session_manager
23
+ from .mockup_comparator import MockupComparator
23
24
 
24
25
 
25
26
  class CursorFlow:
@@ -71,6 +72,7 @@ class CursorFlow:
71
72
  self.auth_handler = AuthHandler(auth_config) if auth_config else None
72
73
  self.css_iterator = CSSIterator()
73
74
  self.cursor_integration = CursorIntegration()
75
+ self.mockup_comparator = MockupComparator()
74
76
 
75
77
  # Session tracking
76
78
  self.session_id = None
@@ -502,6 +504,155 @@ class CursorFlow:
502
504
  await self.persistent_session.cleanup(save_state=save_state)
503
505
  self.persistent_session = None
504
506
 
507
+ async def compare_mockup_to_implementation(
508
+ self,
509
+ mockup_url: str,
510
+ mockup_actions: Optional[List[Dict]] = None,
511
+ implementation_actions: Optional[List[Dict]] = None,
512
+ comparison_config: Optional[Dict] = None
513
+ ) -> Dict[str, Any]:
514
+ """
515
+ Compare mockup design to current implementation
516
+
517
+ Args:
518
+ mockup_url: URL of the design mockup/reference
519
+ mockup_actions: Optional actions to perform on mockup (clicks, scrolls, etc.)
520
+ implementation_actions: Optional actions to perform on implementation
521
+ comparison_config: {
522
+ "viewports": [{"width": 1440, "height": 900, "name": "desktop"}],
523
+ "diff_threshold": 0.1,
524
+ "ignore_regions": [{"x": 0, "y": 0, "width": 100, "height": 50}]
525
+ }
526
+
527
+ Returns:
528
+ {
529
+ "comparison_id": "mockup_comparison_123456",
530
+ "mockup_url": "https://mockup.example.com",
531
+ "implementation_url": "http://localhost:3000",
532
+ "results": [
533
+ {
534
+ "viewport": {"width": 1440, "height": 900, "name": "desktop"},
535
+ "visual_diff": {
536
+ "similarity_score": 85.2,
537
+ "diff_image": "path/to/diff.png",
538
+ "major_differences": [...]
539
+ },
540
+ "layout_analysis": {...},
541
+ "element_analysis": {...}
542
+ }
543
+ ],
544
+ "summary": {
545
+ "average_similarity": 85.2,
546
+ "needs_improvement": false
547
+ },
548
+ "recommendations": [...]
549
+ }
550
+ """
551
+ try:
552
+ # Execute raw comparison
553
+ raw_results = await self.mockup_comparator.compare_mockup_to_implementation(
554
+ mockup_url=mockup_url,
555
+ implementation_url=self.base_url,
556
+ mockup_actions=mockup_actions,
557
+ implementation_actions=implementation_actions,
558
+ comparison_config=comparison_config
559
+ )
560
+
561
+ if "error" in raw_results:
562
+ return raw_results
563
+
564
+ # Format results for Cursor analysis
565
+ session_id = f"mockup_comparison_{int(time.time())}"
566
+ cursor_results = self.cursor_integration.format_mockup_comparison_results(
567
+ raw_results=raw_results,
568
+ session_id=session_id,
569
+ project_context={
570
+ "framework": "auto-detected",
571
+ "base_url": self.base_url,
572
+ "test_type": "mockup_comparison"
573
+ }
574
+ )
575
+
576
+ return cursor_results
577
+
578
+ except Exception as e:
579
+ self.logger.error(f"Mockup comparison failed: {e}")
580
+ return {"error": str(e)}
581
+
582
+ async def iterative_mockup_matching(
583
+ self,
584
+ mockup_url: str,
585
+ css_improvements: List[Dict],
586
+ base_actions: Optional[List[Dict]] = None,
587
+ comparison_config: Optional[Dict] = None
588
+ ) -> Dict[str, Any]:
589
+ """
590
+ Iteratively improve implementation to match mockup design
591
+
592
+ Args:
593
+ mockup_url: Reference mockup URL
594
+ css_improvements: [
595
+ {
596
+ "name": "fix-header-spacing",
597
+ "css": ".header { padding: 2rem 0; }",
598
+ "rationale": "Match mockup header spacing"
599
+ }
600
+ ]
601
+ base_actions: Actions to perform before each comparison
602
+ comparison_config: Configuration for comparison sensitivity
603
+
604
+ Returns:
605
+ {
606
+ "session_id": "ui_matching_123456",
607
+ "baseline_comparison": {...},
608
+ "iterations": [
609
+ {
610
+ "iteration_number": 1,
611
+ "css_change": {...},
612
+ "mockup_comparison": {...},
613
+ "improvement_metrics": {
614
+ "baseline_similarity": 75.0,
615
+ "improved_similarity": 82.5,
616
+ "improvement": 7.5,
617
+ "is_improvement": true
618
+ }
619
+ }
620
+ ],
621
+ "best_iteration": {...},
622
+ "final_recommendations": [...]
623
+ }
624
+ """
625
+ try:
626
+ # Execute raw iterative matching
627
+ raw_results = await self.mockup_comparator.iterative_ui_matching(
628
+ mockup_url=mockup_url,
629
+ implementation_url=self.base_url,
630
+ css_improvements=css_improvements,
631
+ base_actions=base_actions,
632
+ comparison_config=comparison_config
633
+ )
634
+
635
+ if "error" in raw_results:
636
+ return raw_results
637
+
638
+ # Format results for Cursor analysis
639
+ session_id = f"iterative_mockup_{int(time.time())}"
640
+ cursor_results = self.cursor_integration.format_iterative_mockup_results(
641
+ raw_results=raw_results,
642
+ session_id=session_id,
643
+ project_context={
644
+ "framework": "auto-detected",
645
+ "base_url": self.base_url,
646
+ "test_type": "iterative_mockup_matching"
647
+ }
648
+ )
649
+
650
+ return cursor_results
651
+
652
+ except Exception as e:
653
+ self.logger.error(f"Iterative mockup matching failed: {e}")
654
+ return {"error": str(e)}
655
+
505
656
  async def _initialize_session(self, session_options: Dict):
506
657
  """Initialize browser and authentication session"""
507
658
  self.session_id = f"session_{int(time.time())}"