ai-lls-lib 1.4.0rc3__py3-none-any.whl → 1.4.0rc4__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.
Files changed (34) hide show
  1. ai_lls_lib/__init__.py +1 -1
  2. ai_lls_lib/auth/__init__.py +4 -4
  3. ai_lls_lib/auth/context_parser.py +68 -68
  4. ai_lls_lib/cli/__init__.py +3 -3
  5. ai_lls_lib/cli/__main__.py +30 -30
  6. ai_lls_lib/cli/aws_client.py +115 -115
  7. ai_lls_lib/cli/commands/__init__.py +3 -3
  8. ai_lls_lib/cli/commands/admin.py +174 -174
  9. ai_lls_lib/cli/commands/cache.py +142 -142
  10. ai_lls_lib/cli/commands/stripe.py +377 -377
  11. ai_lls_lib/cli/commands/test_stack.py +216 -216
  12. ai_lls_lib/cli/commands/verify.py +111 -111
  13. ai_lls_lib/cli/env_loader.py +122 -122
  14. ai_lls_lib/core/__init__.py +3 -3
  15. ai_lls_lib/core/cache.py +106 -106
  16. ai_lls_lib/core/models.py +77 -77
  17. ai_lls_lib/core/processor.py +295 -295
  18. ai_lls_lib/core/verifier.py +84 -84
  19. ai_lls_lib/payment/__init__.py +13 -13
  20. ai_lls_lib/payment/credit_manager.py +186 -186
  21. ai_lls_lib/payment/models.py +102 -102
  22. ai_lls_lib/payment/stripe_manager.py +487 -487
  23. ai_lls_lib/payment/webhook_processor.py +215 -215
  24. ai_lls_lib/providers/__init__.py +7 -7
  25. ai_lls_lib/providers/base.py +28 -28
  26. ai_lls_lib/providers/external.py +87 -87
  27. ai_lls_lib/providers/stub.py +48 -48
  28. ai_lls_lib/testing/__init__.py +3 -3
  29. ai_lls_lib/testing/fixtures.py +104 -104
  30. {ai_lls_lib-1.4.0rc3.dist-info → ai_lls_lib-1.4.0rc4.dist-info}/METADATA +1 -1
  31. ai_lls_lib-1.4.0rc4.dist-info/RECORD +33 -0
  32. ai_lls_lib-1.4.0rc3.dist-info/RECORD +0 -33
  33. {ai_lls_lib-1.4.0rc3.dist-info → ai_lls_lib-1.4.0rc4.dist-info}/WHEEL +0 -0
  34. {ai_lls_lib-1.4.0rc3.dist-info → ai_lls_lib-1.4.0rc4.dist-info}/entry_points.txt +0 -0
@@ -1,102 +1,102 @@
1
- """Payment data models with legacy shape compatibility."""
2
-
3
- from dataclasses import dataclass
4
- from typing import Optional, Dict, Any
5
- from enum import Enum
6
-
7
-
8
- class PlanType(Enum):
9
- """Plan types matching legacy frontend expectations."""
10
- PREPAID = "prepaid"
11
- POSTPAID = "postpaid"
12
- INTRO = "intro"
13
-
14
-
15
- class SubscriptionStatus(Enum):
16
- """Subscription statuses."""
17
- ACTIVE = "active"
18
- PAUSED = "paused"
19
- CANCELLED = "cancelled"
20
- PAST_DUE = "past_due"
21
-
22
-
23
- @dataclass
24
- class Plan:
25
- """
26
- Plan model matching legacy frontend data structure.
27
- Maps from Stripe Price/Product to legacy fields.
28
- """
29
- plan_reference: str # Stripe price ID or legacy reference
30
- plan_type: str # prepaid, postpaid, intro
31
- plan_name: str # STANDARD, POWER, ELITE, UNLIMITED
32
- plan_subtitle: str
33
- plan_amount: float # Price in USD
34
- plan_credits: Optional[int] # Number of credits or None for unlimited
35
- plan_credits_text: str # Display text like "5,000 credits"
36
- percent_off: str # Discount percentage display text
37
-
38
- # Additional fields for internal use
39
- stripe_price_id: Optional[str] = None
40
- stripe_product_id: Optional[str] = None
41
-
42
- def to_dict(self) -> Dict[str, Any]:
43
- """Convert to dictionary for JSON serialization."""
44
- result = {
45
- "plan_reference": self.plan_reference,
46
- "plan_type": self.plan_type,
47
- "plan_name": self.plan_name,
48
- "plan_subtitle": self.plan_subtitle,
49
- "plan_amount": self.plan_amount,
50
- "plan_credits": self.plan_credits,
51
- "plan_credits_text": self.plan_credits_text,
52
- "percent_off": self.percent_off
53
- }
54
-
55
- # Add variable_amount flag for VARIABLE product
56
- if self.plan_name == "VARIABLE":
57
- result["variable_amount"] = True
58
-
59
- return result
60
-
61
- @classmethod
62
- def from_stripe_price(cls, price: Dict[str, Any], product: Dict[str, Any]) -> "Plan":
63
- """
64
- Create Plan from Stripe Price and Product objects.
65
- Maps Stripe metadata to legacy fields.
66
- """
67
- metadata = price.get("metadata", {})
68
-
69
- # Determine plan type
70
- if price.get("recurring"):
71
- plan_type = "postpaid"
72
- else:
73
- plan_type = metadata.get("plan_type", "prepaid")
74
-
75
- # Extract credits
76
- credits_str = metadata.get("credits", "")
77
- if credits_str.lower() == "unlimited":
78
- plan_credits = None
79
- plan_credits_text = "Unlimited"
80
- elif credits_str:
81
- try:
82
- plan_credits = int(credits_str)
83
- plan_credits_text = f"{plan_credits:,} credits"
84
- except ValueError:
85
- plan_credits = None
86
- plan_credits_text = credits_str
87
- else:
88
- plan_credits = None
89
- plan_credits_text = ""
90
-
91
- return cls(
92
- plan_reference=metadata.get("plan_reference", price["id"]),
93
- plan_type=plan_type,
94
- plan_name=metadata.get("tier", product.get("name", "")).upper(),
95
- plan_subtitle=metadata.get("plan_subtitle", product.get("description", "")),
96
- plan_amount=price["unit_amount"] / 100.0, # Convert cents to dollars
97
- plan_credits=plan_credits,
98
- plan_credits_text=metadata.get("plan_credits_text", plan_credits_text),
99
- percent_off=metadata.get("percent_off", ""),
100
- stripe_price_id=price["id"],
101
- stripe_product_id=product["id"]
102
- )
1
+ """Payment data models with legacy shape compatibility."""
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Optional, Dict, Any
5
+ from enum import Enum
6
+
7
+
8
+ class PlanType(Enum):
9
+ """Plan types matching legacy frontend expectations."""
10
+ PREPAID = "prepaid"
11
+ POSTPAID = "postpaid"
12
+ INTRO = "intro"
13
+
14
+
15
+ class SubscriptionStatus(Enum):
16
+ """Subscription statuses."""
17
+ ACTIVE = "active"
18
+ PAUSED = "paused"
19
+ CANCELLED = "cancelled"
20
+ PAST_DUE = "past_due"
21
+
22
+
23
+ @dataclass
24
+ class Plan:
25
+ """
26
+ Plan model matching legacy frontend data structure.
27
+ Maps from Stripe Price/Product to legacy fields.
28
+ """
29
+ plan_reference: str # Stripe price ID or legacy reference
30
+ plan_type: str # prepaid, postpaid, intro
31
+ plan_name: str # STANDARD, POWER, ELITE, UNLIMITED
32
+ plan_subtitle: str
33
+ plan_amount: float # Price in USD
34
+ plan_credits: Optional[int] # Number of credits or None for unlimited
35
+ plan_credits_text: str # Display text like "5,000 credits"
36
+ percent_off: str # Discount percentage display text
37
+
38
+ # Additional fields for internal use
39
+ stripe_price_id: Optional[str] = None
40
+ stripe_product_id: Optional[str] = None
41
+
42
+ def to_dict(self) -> Dict[str, Any]:
43
+ """Convert to dictionary for JSON serialization."""
44
+ result = {
45
+ "plan_reference": self.plan_reference,
46
+ "plan_type": self.plan_type,
47
+ "plan_name": self.plan_name,
48
+ "plan_subtitle": self.plan_subtitle,
49
+ "plan_amount": self.plan_amount,
50
+ "plan_credits": self.plan_credits,
51
+ "plan_credits_text": self.plan_credits_text,
52
+ "percent_off": self.percent_off
53
+ }
54
+
55
+ # Add variable_amount flag for VARIABLE product
56
+ if self.plan_name == "VARIABLE":
57
+ result["variable_amount"] = True
58
+
59
+ return result
60
+
61
+ @classmethod
62
+ def from_stripe_price(cls, price: Dict[str, Any], product: Dict[str, Any]) -> "Plan":
63
+ """
64
+ Create Plan from Stripe Price and Product objects.
65
+ Maps Stripe metadata to legacy fields.
66
+ """
67
+ metadata = price.get("metadata", {})
68
+
69
+ # Determine plan type
70
+ if price.get("recurring"):
71
+ plan_type = "postpaid"
72
+ else:
73
+ plan_type = metadata.get("plan_type", "prepaid")
74
+
75
+ # Extract credits
76
+ credits_str = metadata.get("credits", "")
77
+ if credits_str.lower() == "unlimited":
78
+ plan_credits = None
79
+ plan_credits_text = "Unlimited"
80
+ elif credits_str:
81
+ try:
82
+ plan_credits = int(credits_str)
83
+ plan_credits_text = f"{plan_credits:,} credits"
84
+ except ValueError:
85
+ plan_credits = None
86
+ plan_credits_text = credits_str
87
+ else:
88
+ plan_credits = None
89
+ plan_credits_text = ""
90
+
91
+ return cls(
92
+ plan_reference=metadata.get("plan_reference", price["id"]),
93
+ plan_type=plan_type,
94
+ plan_name=metadata.get("tier", product.get("name", "")).upper(),
95
+ plan_subtitle=metadata.get("plan_subtitle", product.get("description", "")),
96
+ plan_amount=price["unit_amount"] / 100.0, # Convert cents to dollars
97
+ plan_credits=plan_credits,
98
+ plan_credits_text=metadata.get("plan_credits_text", plan_credits_text),
99
+ percent_off=metadata.get("percent_off", ""),
100
+ stripe_price_id=price["id"],
101
+ stripe_product_id=product["id"]
102
+ )