levelfour 0.1.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.
Files changed (208) hide show
  1. levelfour/__init__.py +495 -0
  2. levelfour/api_keys/__init__.py +34 -0
  3. levelfour/api_keys/client.py +337 -0
  4. levelfour/api_keys/raw_client.py +621 -0
  5. levelfour/api_keys/types/__init__.py +34 -0
  6. levelfour/api_keys/types/create_api_key_request_scope.py +5 -0
  7. levelfour/async_levelfour_client.py +39 -0
  8. levelfour/base_client.py +346 -0
  9. levelfour/client.py +54 -0
  10. levelfour/core/__init__.py +127 -0
  11. levelfour/core/api_error.py +23 -0
  12. levelfour/core/client_wrapper.py +105 -0
  13. levelfour/core/datetime_utils.py +70 -0
  14. levelfour/core/file.py +67 -0
  15. levelfour/core/force_multipart.py +18 -0
  16. levelfour/core/http_client.py +776 -0
  17. levelfour/core/http_response.py +59 -0
  18. levelfour/core/http_sse/__init__.py +42 -0
  19. levelfour/core/http_sse/_api.py +112 -0
  20. levelfour/core/http_sse/_decoders.py +61 -0
  21. levelfour/core/http_sse/_exceptions.py +7 -0
  22. levelfour/core/http_sse/_models.py +17 -0
  23. levelfour/core/jsonable_encoder.py +108 -0
  24. levelfour/core/logging.py +107 -0
  25. levelfour/core/pagination.py +82 -0
  26. levelfour/core/pydantic_utilities.py +577 -0
  27. levelfour/core/query_encoder.py +58 -0
  28. levelfour/core/remove_none_from_dict.py +11 -0
  29. levelfour/core/request_options.py +35 -0
  30. levelfour/core/serialization.py +276 -0
  31. levelfour/errors/__init__.py +40 -0
  32. levelfour/errors/forbidden_error.py +11 -0
  33. levelfour/errors/unauthorized_error.py +11 -0
  34. levelfour/errors/unprocessable_entity_error.py +11 -0
  35. levelfour/evaluation/__init__.py +4 -0
  36. levelfour/evaluation/client.py +102 -0
  37. levelfour/evaluation/raw_client.py +141 -0
  38. levelfour/exceptions.py +63 -0
  39. levelfour/health/__init__.py +4 -0
  40. levelfour/health/client.py +163 -0
  41. levelfour/health/raw_client.py +164 -0
  42. levelfour/integrations/__init__.py +0 -0
  43. levelfour/integrations/django.py +26 -0
  44. levelfour/integrations/fastapi.py +39 -0
  45. levelfour/integrations/telemetry.py +66 -0
  46. levelfour/levelfour_client.py +47 -0
  47. levelfour/pagination.py +84 -0
  48. levelfour/pr_analysis/__init__.py +4 -0
  49. levelfour/pr_analysis/client.py +408 -0
  50. levelfour/pr_analysis/raw_client.py +620 -0
  51. levelfour/pr_analysis_actions/__init__.py +4 -0
  52. levelfour/pr_analysis_actions/client.py +588 -0
  53. levelfour/pr_analysis_actions/raw_client.py +939 -0
  54. levelfour/pr_analysis_installations/__init__.py +4 -0
  55. levelfour/pr_analysis_installations/client.py +470 -0
  56. levelfour/pr_analysis_installations/raw_client.py +868 -0
  57. levelfour/providers/__init__.py +34 -0
  58. levelfour/providers/client.py +1504 -0
  59. levelfour/providers/raw_client.py +2398 -0
  60. levelfour/providers/types/__init__.py +36 -0
  61. levelfour/providers/types/list_spending_breakdown_providers_response.py +11 -0
  62. levelfour/py.typed +0 -0
  63. levelfour/recommendations/__init__.py +4 -0
  64. levelfour/recommendations/client.py +1018 -0
  65. levelfour/recommendations/raw_client.py +1810 -0
  66. levelfour/savings/__init__.py +4 -0
  67. levelfour/savings/client.py +401 -0
  68. levelfour/savings/raw_client.py +624 -0
  69. levelfour/spending/__init__.py +34 -0
  70. levelfour/spending/client.py +437 -0
  71. levelfour/spending/raw_client.py +684 -0
  72. levelfour/spending/types/__init__.py +34 -0
  73. levelfour/spending/types/list_breakdown_spending_response.py +12 -0
  74. levelfour/types/__init__.py +413 -0
  75. levelfour/types/accept_terms_data.py +25 -0
  76. levelfour/types/accept_terms_response.py +27 -0
  77. levelfour/types/action_request.py +42 -0
  78. levelfour/types/api_key_created_data.py +28 -0
  79. levelfour/types/api_key_data.py +27 -0
  80. levelfour/types/authentication_error.py +5 -0
  81. levelfour/types/authorization_error.py +5 -0
  82. levelfour/types/bad_request_error.py +5 -0
  83. levelfour/types/comparison_item.py +32 -0
  84. levelfour/types/complete_wizard_data.py +27 -0
  85. levelfour/types/complete_wizard_response.py +27 -0
  86. levelfour/types/conflict_error.py +5 -0
  87. levelfour/types/cost_breakdown_data.py +35 -0
  88. levelfour/types/cost_breakdown_item.py +71 -0
  89. levelfour/types/cost_breakdown_raw_data.py +37 -0
  90. levelfour/types/cost_breakdown_raw_response.py +27 -0
  91. levelfour/types/cost_breakdown_response.py +27 -0
  92. levelfour/types/costs_breakdown_chart_data.py +48 -0
  93. levelfour/types/costs_breakdown_chart_response.py +27 -0
  94. levelfour/types/costs_breakdown_data_point.py +46 -0
  95. levelfour/types/costs_breakdown_grouped_chart_data.py +52 -0
  96. levelfour/types/costs_breakdown_grouped_chart_response.py +27 -0
  97. levelfour/types/costs_breakdown_grouped_data_point.py +36 -0
  98. levelfour/types/costs_breakdown_totals.py +41 -0
  99. levelfour/types/create_api_key_response.py +23 -0
  100. levelfour/types/daily_spending_breakdown_data.py +42 -0
  101. levelfour/types/daily_spending_breakdown_response.py +27 -0
  102. levelfour/types/daily_spending_data_point.py +31 -0
  103. levelfour/types/dashboard_summary_data.py +72 -0
  104. levelfour/types/dashboard_summary_response.py +27 -0
  105. levelfour/types/delete_endpoint_data.py +20 -0
  106. levelfour/types/delete_endpoint_response.py +23 -0
  107. levelfour/types/endpoint_data.py +23 -0
  108. levelfour/types/error_response.py +23 -0
  109. levelfour/types/error_response_error.py +21 -0
  110. levelfour/types/evaluation_status_data.py +71 -0
  111. levelfour/types/evaluation_status_response.py +27 -0
  112. levelfour/types/execution_log_command.py +21 -0
  113. levelfour/types/execution_log_entry.py +23 -0
  114. levelfour/types/execution_step_schema.py +23 -0
  115. levelfour/types/http_validation_error.py +20 -0
  116. levelfour/types/implementation_method_data.py +25 -0
  117. levelfour/types/implementation_method_response.py +27 -0
  118. levelfour/types/implementation_step.py +27 -0
  119. levelfour/types/internal_server_error.py +5 -0
  120. levelfour/types/list_api_keys_data.py +21 -0
  121. levelfour/types/list_api_keys_response.py +23 -0
  122. levelfour/types/list_endpoints_response.py +23 -0
  123. levelfour/types/metric_data_point.py +27 -0
  124. levelfour/types/metric_series.py +40 -0
  125. levelfour/types/metric_series_entry.py +25 -0
  126. levelfour/types/monthly_spending_data.py +27 -0
  127. levelfour/types/monthly_spending_data_point.py +31 -0
  128. levelfour/types/monthly_spending_response.py +27 -0
  129. levelfour/types/not_found_error.py +5 -0
  130. levelfour/types/pagination_meta.py +51 -0
  131. levelfour/types/processing_recommendation_item.py +61 -0
  132. levelfour/types/processing_recommendations_data.py +28 -0
  133. levelfour/types/processing_recommendations_response.py +27 -0
  134. levelfour/types/provider.py +46 -0
  135. levelfour/types/provider_breakdown_data.py +31 -0
  136. levelfour/types/provider_breakdown_item.py +77 -0
  137. levelfour/types/provider_breakdown_response.py +27 -0
  138. levelfour/types/provider_filter_options_data.py +51 -0
  139. levelfour/types/provider_filter_options_response.py +27 -0
  140. levelfour/types/provider_potential_savings_summary_data.py +46 -0
  141. levelfour/types/provider_potential_savings_summary_response.py +27 -0
  142. levelfour/types/provider_recommendations_summary_data.py +37 -0
  143. levelfour/types/provider_recommendations_summary_response.py +27 -0
  144. levelfour/types/provider_saved_summary_data.py +56 -0
  145. levelfour/types/provider_saved_summary_response.py +27 -0
  146. levelfour/types/provider_service_breakdown_data.py +65 -0
  147. levelfour/types/provider_service_breakdown_item.py +72 -0
  148. levelfour/types/provider_service_breakdown_raw_data.py +62 -0
  149. levelfour/types/provider_service_breakdown_raw_response.py +27 -0
  150. levelfour/types/provider_service_breakdown_response.py +27 -0
  151. levelfour/types/provider_service_costs_breakdown_data.py +62 -0
  152. levelfour/types/provider_service_costs_breakdown_response.py +27 -0
  153. levelfour/types/provider_service_costs_data_point.py +36 -0
  154. levelfour/types/provider_spending.py +61 -0
  155. levelfour/types/provider_spending_summary_data.py +67 -0
  156. levelfour/types/provider_spending_summary_response.py +27 -0
  157. levelfour/types/provider_timeline_data.py +57 -0
  158. levelfour/types/provider_timeline_response.py +27 -0
  159. levelfour/types/provider_top_service.py +36 -0
  160. levelfour/types/providers_summary_data.py +24 -0
  161. levelfour/types/providers_summary_response.py +27 -0
  162. levelfour/types/rate_limit_error.py +5 -0
  163. levelfour/types/recommendation_actions.py +60 -0
  164. levelfour/types/recommendation_detail.py +42 -0
  165. levelfour/types/recommendation_detail_response.py +27 -0
  166. levelfour/types/recommendation_filter_options_data.py +41 -0
  167. levelfour/types/recommendation_filter_options_response.py +27 -0
  168. levelfour/types/recommendation_item.py +36 -0
  169. levelfour/types/recommendation_wizard_data.py +173 -0
  170. levelfour/types/recommendation_wizard_data_metrics.py +7 -0
  171. levelfour/types/recommendation_wizard_response.py +27 -0
  172. levelfour/types/recommendations_breakdown_data.py +26 -0
  173. levelfour/types/recommendations_breakdown_response.py +27 -0
  174. levelfour/types/recommendations_overview_data.py +51 -0
  175. levelfour/types/recommendations_overview_response.py +27 -0
  176. levelfour/types/register_endpoint_response.py +23 -0
  177. levelfour/types/resource_change.py +42 -0
  178. levelfour/types/resource_snapshot.py +21 -0
  179. levelfour/types/revoke_api_key_data.py +20 -0
  180. levelfour/types/revoke_api_key_response.py +23 -0
  181. levelfour/types/risk_assessment.py +29 -0
  182. levelfour/types/risk_factor.py +27 -0
  183. levelfour/types/saved_breakdown_data.py +31 -0
  184. levelfour/types/saved_breakdown_response.py +27 -0
  185. levelfour/types/saved_by_provider_breakdown_data.py +31 -0
  186. levelfour/types/saved_by_provider_breakdown_response.py +27 -0
  187. levelfour/types/saved_by_provider_item.py +76 -0
  188. levelfour/types/saved_item.py +35 -0
  189. levelfour/types/saved_provider_summary.py +36 -0
  190. levelfour/types/saved_summary_data.py +57 -0
  191. levelfour/types/saved_summary_response.py +27 -0
  192. levelfour/types/savings_decision_data.py +28 -0
  193. levelfour/types/savings_decision_response.py +27 -0
  194. levelfour/types/spending_by_date_item.py +36 -0
  195. levelfour/types/top_recommendation.py +56 -0
  196. levelfour/types/trigger_info.py +22 -0
  197. levelfour/types/update_tag_data.py +20 -0
  198. levelfour/types/update_tag_response.py +23 -0
  199. levelfour/types/validation_error.py +24 -0
  200. levelfour/types/validation_error_loc_item.py +5 -0
  201. levelfour/webhooks/__init__.py +4 -0
  202. levelfour/webhooks/client.py +273 -0
  203. levelfour/webhooks/raw_client.py +483 -0
  204. levelfour/webhooks/verifier.py +61 -0
  205. levelfour-0.1.0.dist-info/METADATA +12 -0
  206. levelfour-0.1.0.dist-info/RECORD +208 -0
  207. levelfour-0.1.0.dist-info/WHEEL +5 -0
  208. levelfour-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,27 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import datetime as dt
4
+ import typing
5
+
6
+ import pydantic
7
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
8
+ from .provider_timeline_data import ProviderTimelineData
9
+
10
+
11
+ class ProviderTimelineResponse(UniversalBaseModel):
12
+ """
13
+ Response for provider spending timeline
14
+ """
15
+
16
+ success: typing.Optional[bool] = None
17
+ timestamp: typing.Optional[dt.datetime] = None
18
+ data: ProviderTimelineData
19
+
20
+ if IS_PYDANTIC_V2:
21
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
22
+ else:
23
+
24
+ class Config:
25
+ frozen = True
26
+ smart_union = True
27
+ extra = pydantic.Extra.allow
@@ -0,0 +1,36 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ import pydantic
6
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
7
+
8
+
9
+ class ProviderTopService(UniversalBaseModel):
10
+ """
11
+ Top service for provider summary
12
+ """
13
+
14
+ service: str = pydantic.Field()
15
+ """
16
+ Service name
17
+ """
18
+
19
+ cost: float = pydantic.Field()
20
+ """
21
+ Current period cost
22
+ """
23
+
24
+ change_percentage: typing.Optional[float] = pydantic.Field(default=None)
25
+ """
26
+ Change from previous period
27
+ """
28
+
29
+ if IS_PYDANTIC_V2:
30
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
31
+ else:
32
+
33
+ class Config:
34
+ frozen = True
35
+ smart_union = True
36
+ extra = pydantic.Extra.allow
@@ -0,0 +1,24 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ import pydantic
6
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
7
+ from .provider import Provider
8
+
9
+
10
+ class ProvidersSummaryData(UniversalBaseModel):
11
+ """
12
+ Summary data for all providers
13
+ """
14
+
15
+ providers: typing.List[Provider]
16
+
17
+ if IS_PYDANTIC_V2:
18
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
19
+ else:
20
+
21
+ class Config:
22
+ frozen = True
23
+ smart_union = True
24
+ extra = pydantic.Extra.allow
@@ -0,0 +1,27 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import datetime as dt
4
+ import typing
5
+
6
+ import pydantic
7
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
8
+ from .providers_summary_data import ProvidersSummaryData
9
+
10
+
11
+ class ProvidersSummaryResponse(UniversalBaseModel):
12
+ """
13
+ Response for providers summary (carousel view)
14
+ """
15
+
16
+ success: typing.Optional[bool] = None
17
+ timestamp: typing.Optional[dt.datetime] = None
18
+ data: ProvidersSummaryData
19
+
20
+ if IS_PYDANTIC_V2:
21
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
22
+ else:
23
+
24
+ class Config:
25
+ frozen = True
26
+ smart_union = True
27
+ extra = pydantic.Extra.allow
@@ -0,0 +1,5 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from .error_response import ErrorResponse
4
+
5
+ RateLimitError = ErrorResponse
@@ -0,0 +1,60 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ import pydantic
6
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
7
+
8
+
9
+ class RecommendationActions(UniversalBaseModel):
10
+ """
11
+ Action structure with simple text fields.
12
+
13
+ All fields support markdown formatting for rich text display.
14
+ Frontend can use a markdown renderer (e.g., react-markdown) to display.
15
+
16
+ Example markdown formatting:
17
+ - **Bold text** for emphasis
18
+ - `code snippets` for commands
19
+ - Numbered/bulleted lists for steps
20
+ - Code blocks with ```language syntax
21
+ """
22
+
23
+ description: typing.Optional[str] = pydantic.Field(default=None)
24
+ """
25
+ Brief summary of the recommendation
26
+ """
27
+
28
+ overview: typing.Optional[str] = pydantic.Field(default=None)
29
+ """
30
+ Detailed overview explaining the recommendation (supports markdown)
31
+ """
32
+
33
+ implementation_process: typing.Optional[str] = pydantic.Field(default=None)
34
+ """
35
+ How to implement this recommendation (supports markdown)
36
+ """
37
+
38
+ execution_method: typing.Optional[str] = pydantic.Field(default=None)
39
+ """
40
+ Technical execution details (supports markdown)
41
+ """
42
+
43
+ key_takeaway: typing.Optional[str] = pydantic.Field(default=None)
44
+ """
45
+ Important notes, risks, and safety information (supports markdown)
46
+ """
47
+
48
+ operational_impact: typing.Optional[str] = pydantic.Field(default=None)
49
+ """
50
+ Impact on operations and any downtime requirements (supports markdown)
51
+ """
52
+
53
+ if IS_PYDANTIC_V2:
54
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
55
+ else:
56
+
57
+ class Config:
58
+ frozen = True
59
+ smart_union = True
60
+ extra = pydantic.Extra.allow
@@ -0,0 +1,42 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ import pydantic
6
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
7
+ from .recommendation_actions import RecommendationActions
8
+
9
+
10
+ class RecommendationDetail(UniversalBaseModel):
11
+ """
12
+ Full details for a single recommendation (detail view)
13
+ """
14
+
15
+ recommendation_id: str = pydantic.Field()
16
+ """
17
+ Unique business identifier for the recommendation
18
+ """
19
+
20
+ service: str
21
+ environment: typing.Optional[str] = None
22
+ analysis_period: typing.Optional[str] = None
23
+ monthly_savings: float
24
+ annual_savings: float
25
+ current_spending: float
26
+ savings_percentage: float
27
+ actions: typing.Optional[RecommendationActions] = None
28
+ status: str = pydantic.Field()
29
+ """
30
+ Status: pending, implemented, rejected
31
+ """
32
+
33
+ created_at: typing.Optional[str] = None
34
+
35
+ if IS_PYDANTIC_V2:
36
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
37
+ else:
38
+
39
+ class Config:
40
+ frozen = True
41
+ smart_union = True
42
+ extra = pydantic.Extra.allow
@@ -0,0 +1,27 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import datetime as dt
4
+ import typing
5
+
6
+ import pydantic
7
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
8
+ from .recommendation_detail import RecommendationDetail
9
+
10
+
11
+ class RecommendationDetailResponse(UniversalBaseModel):
12
+ """
13
+ Response for recommendation detail
14
+ """
15
+
16
+ success: typing.Optional[bool] = None
17
+ timestamp: typing.Optional[dt.datetime] = None
18
+ data: RecommendationDetail
19
+
20
+ if IS_PYDANTIC_V2:
21
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
22
+ else:
23
+
24
+ class Config:
25
+ frozen = True
26
+ smart_union = True
27
+ extra = pydantic.Extra.allow
@@ -0,0 +1,41 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ import pydantic
6
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
7
+
8
+
9
+ class RecommendationFilterOptionsData(UniversalBaseModel):
10
+ """
11
+ Filter options for provider recommendation breakdown
12
+ """
13
+
14
+ environments: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
15
+ """
16
+ Distinct environment values
17
+ """
18
+
19
+ accounts: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
20
+ """
21
+ Distinct account values
22
+ """
23
+
24
+ tags: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
25
+ """
26
+ Distinct tag values
27
+ """
28
+
29
+ services: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
30
+ """
31
+ Distinct service values
32
+ """
33
+
34
+ if IS_PYDANTIC_V2:
35
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
36
+ else:
37
+
38
+ class Config:
39
+ frozen = True
40
+ smart_union = True
41
+ extra = pydantic.Extra.allow
@@ -0,0 +1,27 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import datetime as dt
4
+ import typing
5
+
6
+ import pydantic
7
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
8
+ from .recommendation_filter_options_data import RecommendationFilterOptionsData
9
+
10
+
11
+ class RecommendationFilterOptionsResponse(UniversalBaseModel):
12
+ """
13
+ Response for recommendation filter options
14
+ """
15
+
16
+ success: typing.Optional[bool] = None
17
+ timestamp: typing.Optional[dt.datetime] = None
18
+ data: RecommendationFilterOptionsData
19
+
20
+ if IS_PYDANTIC_V2:
21
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
22
+ else:
23
+
24
+ class Config:
25
+ frozen = True
26
+ smart_union = True
27
+ extra = pydantic.Extra.allow
@@ -0,0 +1,36 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ import pydantic
6
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
7
+ from .recommendation_actions import RecommendationActions
8
+
9
+
10
+ class RecommendationItem(UniversalBaseModel):
11
+ """
12
+ Detailed recommendation item (for list view)
13
+ """
14
+
15
+ recommendation_id: str = pydantic.Field()
16
+ """
17
+ Unique business identifier for the recommendation
18
+ """
19
+
20
+ service: str
21
+ environment: typing.Optional[str] = None
22
+ analysis_period: typing.Optional[str] = None
23
+ monthly_savings: float
24
+ annual_savings: float
25
+ current_spending: float
26
+ savings_percentage: float
27
+ actions: typing.Optional[RecommendationActions] = None
28
+
29
+ if IS_PYDANTIC_V2:
30
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
31
+ else:
32
+
33
+ class Config:
34
+ frozen = True
35
+ smart_union = True
36
+ extra = pydantic.Extra.allow
@@ -0,0 +1,173 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ import pydantic
6
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
7
+ from .comparison_item import ComparisonItem
8
+ from .execution_log_entry import ExecutionLogEntry
9
+ from .execution_step_schema import ExecutionStepSchema
10
+ from .implementation_step import ImplementationStep
11
+ from .recommendation_wizard_data_metrics import RecommendationWizardDataMetrics
12
+ from .risk_assessment import RiskAssessment
13
+ from .trigger_info import TriggerInfo
14
+
15
+
16
+ class RecommendationWizardData(UniversalBaseModel):
17
+ """
18
+ Full recommendation data for wizard flow
19
+ """
20
+
21
+ recommendation_id: str = pydantic.Field()
22
+ """
23
+ Unique business identifier
24
+ """
25
+
26
+ service: str
27
+ account: typing.Optional[str] = None
28
+ region: typing.Optional[str] = None
29
+ monthly_spending: float = pydantic.Field()
30
+ """
31
+ Current monthly spending
32
+ """
33
+
34
+ monthly_savings: float = pydantic.Field()
35
+ """
36
+ Potential monthly savings
37
+ """
38
+
39
+ annual_savings: float = pydantic.Field()
40
+ """
41
+ Annual savings amount
42
+ """
43
+
44
+ monthly_spending_percentage: typing.Optional[float] = pydantic.Field(default=None)
45
+ """
46
+ Spending as percentage
47
+ """
48
+
49
+ monthly_savings_percentage: typing.Optional[float] = pydantic.Field(default=None)
50
+ """
51
+ Savings as percentage
52
+ """
53
+
54
+ implementation_tags: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
55
+ """
56
+ Available implementation methods: Automated Savings, IaC, Manual Setup
57
+ """
58
+
59
+ terms_accepted_by: typing.Optional[str] = None
60
+ terms_accepted_at: typing.Optional[str] = None
61
+ saving_acceptance: typing.Optional[str] = pydantic.Field(default=None)
62
+ """
63
+ pending, accepted, rejected
64
+ """
65
+
66
+ saving_accepted_by: typing.Optional[str] = None
67
+ saving_accepted_at: typing.Optional[str] = None
68
+ rejection_reason: typing.Optional[str] = pydantic.Field(default=None)
69
+ """
70
+ operational, strategy, not_applicable, other
71
+ """
72
+
73
+ rejection_explanation: typing.Optional[str] = None
74
+ implementation_method: typing.Optional[str] = pydantic.Field(default=None)
75
+ """
76
+ one-click, iac, one-click-plus-iac
77
+ """
78
+
79
+ status: typing.Optional[str] = None
80
+ overview: typing.Optional[str] = pydantic.Field(default=None)
81
+ """
82
+ Markdown overview of the recommendation
83
+ """
84
+
85
+ key_takeaway: typing.Optional[str] = None
86
+ operational_impact: typing.Optional[str] = pydantic.Field(default=None)
87
+ """
88
+ Markdown description of operational impact
89
+ """
90
+
91
+ iam_role_arn: typing.Optional[str] = None
92
+ iam_policy: typing.Optional[typing.Dict[str, typing.Any]] = None
93
+ vcs_username: typing.Optional[str] = None
94
+ vcs_email: typing.Optional[str] = None
95
+ manual_instructions: typing.Optional[str] = pydantic.Field(default=None)
96
+ """
97
+ Markdown instructions for manual implementation
98
+ """
99
+
100
+ completed_at: typing.Optional[str] = None
101
+ environment: typing.Optional[str] = pydantic.Field(default=None)
102
+ """
103
+ Environment (e.g., Production, Staging)
104
+ """
105
+
106
+ tag: typing.Optional[str] = pydantic.Field(default=None)
107
+ """
108
+ Resource tag value
109
+ """
110
+
111
+ tags: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
112
+ """
113
+ All resource tags
114
+ """
115
+
116
+ resource_console_url: typing.Optional[str] = pydantic.Field(default=None)
117
+ """
118
+ Direct link to resource in cloud console
119
+ """
120
+
121
+ description: typing.Optional[str] = pydantic.Field(default=None)
122
+ """
123
+ Brief summary of the recommendation
124
+ """
125
+
126
+ comparison_data: typing.Optional[typing.List[ComparisonItem]] = pydantic.Field(default=None)
127
+ """
128
+ Before/after comparison rows
129
+ """
130
+
131
+ metrics: typing.Optional[RecommendationWizardDataMetrics] = pydantic.Field(default=None)
132
+ """
133
+ Historical metric series for the resource
134
+ """
135
+
136
+ risk_assessment: typing.Optional[RiskAssessment] = pydantic.Field(default=None)
137
+ """
138
+ Risk level and factors
139
+ """
140
+
141
+ implementation_steps: typing.Optional[typing.List[ImplementationStep]] = pydantic.Field(default=None)
142
+ """
143
+ Ordered implementation steps
144
+ """
145
+
146
+ execution_steps: typing.Optional[typing.List[ExecutionStepSchema]] = pydantic.Field(default=None)
147
+ """
148
+ Execution pipeline steps for status flow
149
+ """
150
+
151
+ execution_logs: typing.Optional[typing.List[ExecutionLogEntry]] = pydantic.Field(default=None)
152
+ """
153
+ Execution log entries with commands
154
+ """
155
+
156
+ trigger_info: typing.Optional[TriggerInfo] = pydantic.Field(default=None)
157
+ """
158
+ Who triggered the execution and when
159
+ """
160
+
161
+ implementation_status: typing.Optional[str] = pydantic.Field(default=None)
162
+ """
163
+ Overall implementation status label
164
+ """
165
+
166
+ if IS_PYDANTIC_V2:
167
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
168
+ else:
169
+
170
+ class Config:
171
+ frozen = True
172
+ smart_union = True
173
+ extra = pydantic.Extra.allow
@@ -0,0 +1,7 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ from .metric_series import MetricSeries
6
+
7
+ RecommendationWizardDataMetrics = typing.Union[typing.List[MetricSeries], typing.Dict[str, typing.Any]]
@@ -0,0 +1,27 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import datetime as dt
4
+ import typing
5
+
6
+ import pydantic
7
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
8
+ from .recommendation_wizard_data import RecommendationWizardData
9
+
10
+
11
+ class RecommendationWizardResponse(UniversalBaseModel):
12
+ """
13
+ Response for wizard recommendation detail
14
+ """
15
+
16
+ success: typing.Optional[bool] = None
17
+ timestamp: typing.Optional[dt.datetime] = None
18
+ data: RecommendationWizardData
19
+
20
+ if IS_PYDANTIC_V2:
21
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
22
+ else:
23
+
24
+ class Config:
25
+ frozen = True
26
+ smart_union = True
27
+ extra = pydantic.Extra.allow
@@ -0,0 +1,26 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ import pydantic
6
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
7
+ from .pagination_meta import PaginationMeta
8
+ from .recommendation_item import RecommendationItem
9
+
10
+
11
+ class RecommendationsBreakdownData(UniversalBaseModel):
12
+ """
13
+ Recommendations breakdown data with pagination
14
+ """
15
+
16
+ items: typing.List[RecommendationItem]
17
+ pagination: PaginationMeta
18
+
19
+ if IS_PYDANTIC_V2:
20
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
21
+ else:
22
+
23
+ class Config:
24
+ frozen = True
25
+ smart_union = True
26
+ extra = pydantic.Extra.allow
@@ -0,0 +1,27 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import datetime as dt
4
+ import typing
5
+
6
+ import pydantic
7
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
8
+ from .recommendations_breakdown_data import RecommendationsBreakdownData
9
+
10
+
11
+ class RecommendationsBreakdownResponse(UniversalBaseModel):
12
+ """
13
+ Response for recommendations breakdown
14
+ """
15
+
16
+ success: typing.Optional[bool] = None
17
+ timestamp: typing.Optional[dt.datetime] = None
18
+ data: RecommendationsBreakdownData
19
+
20
+ if IS_PYDANTIC_V2:
21
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
22
+ else:
23
+
24
+ class Config:
25
+ frozen = True
26
+ smart_union = True
27
+ extra = pydantic.Extra.allow
@@ -0,0 +1,51 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ import pydantic
6
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
7
+
8
+
9
+ class RecommendationsOverviewData(UniversalBaseModel):
10
+ """
11
+ Recommendations overview metrics for a provider
12
+ """
13
+
14
+ total_spend: float = pydantic.Field()
15
+ """
16
+ Total cost from last month's complete billing cycle (from aws_costs_daily)
17
+ """
18
+
19
+ available_savings: float = pydantic.Field()
20
+ """
21
+ Savings opportunities identified and available to execute
22
+ """
23
+
24
+ pending_savings: float = pydantic.Field()
25
+ """
26
+ Savings opportunities pending required actions
27
+ """
28
+
29
+ saved_itd: float = pydantic.Field()
30
+ """
31
+ Total savings implemented inception to date
32
+ """
33
+
34
+ potential_savings: typing.Optional[float] = pydantic.Field(default=None)
35
+ """
36
+ Sum of all recommendations' monthly_savings
37
+ """
38
+
39
+ evaluation_available_savings: typing.Optional[float] = pydantic.Field(default=None)
40
+ """
41
+ Sum of allowed evaluation IDs' monthly_savings
42
+ """
43
+
44
+ if IS_PYDANTIC_V2:
45
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
46
+ else:
47
+
48
+ class Config:
49
+ frozen = True
50
+ smart_union = True
51
+ extra = pydantic.Extra.allow