smallestai 3.1.0__py3-none-any.whl → 4.0.1__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.

Potentially problematic release.


This version of smallestai might be problematic. Click here for more details.

Files changed (135) hide show
  1. smallestai/__init__.py +35 -45
  2. smallestai/atoms/__init__.py +249 -123
  3. smallestai/atoms/api/__init__.py +0 -1
  4. smallestai/atoms/api/agent_templates_api.py +26 -26
  5. smallestai/atoms/api/agents_api.py +1316 -190
  6. smallestai/atoms/api/calls_api.py +29 -29
  7. smallestai/atoms/api/campaigns_api.py +165 -165
  8. smallestai/atoms/api/knowledge_base_api.py +290 -290
  9. smallestai/atoms/api/logs_api.py +13 -13
  10. smallestai/atoms/api/organization_api.py +13 -13
  11. smallestai/atoms/api/user_api.py +13 -13
  12. smallestai/atoms/atoms_client.py +77 -49
  13. smallestai/atoms/models/__init__.py +103 -43
  14. smallestai/atoms/models/agent_agent_id_webhook_subscriptions_delete200_response.py +89 -0
  15. smallestai/atoms/models/{get_agent_templates200_response.py → agent_agent_id_webhook_subscriptions_get200_response.py} +7 -7
  16. smallestai/atoms/models/agent_agent_id_webhook_subscriptions_get404_response.py +89 -0
  17. smallestai/atoms/models/agent_agent_id_webhook_subscriptions_post201_response.py +89 -0
  18. smallestai/atoms/models/agent_agent_id_webhook_subscriptions_post400_response.py +89 -0
  19. smallestai/atoms/models/agent_agent_id_webhook_subscriptions_post_request.py +97 -0
  20. smallestai/atoms/models/agent_dto.py +8 -6
  21. smallestai/atoms/models/agent_dto_language.py +17 -3
  22. smallestai/atoms/models/agent_dto_language_switching.py +95 -0
  23. smallestai/atoms/models/agent_dto_synthesizer.py +1 -1
  24. smallestai/atoms/models/{create_agent_from_template200_response.py → agent_from_template_post200_response.py} +4 -4
  25. smallestai/atoms/models/{get_agents200_response.py → agent_get200_response.py} +7 -7
  26. smallestai/atoms/models/{get_agents200_response_data.py → agent_get200_response_data.py} +9 -13
  27. smallestai/atoms/models/{delete_agent200_response.py → agent_id_delete200_response.py} +4 -4
  28. smallestai/atoms/models/{get_agent_by_id200_response.py → agent_id_get200_response.py} +4 -4
  29. smallestai/atoms/models/{update_agent200_response.py → agent_id_patch200_response.py} +4 -4
  30. smallestai/atoms/models/{update_agent_request.py → agent_id_patch_request.py} +17 -15
  31. smallestai/atoms/models/{update_agent_request_language.py → agent_id_patch_request_language.py} +14 -10
  32. smallestai/atoms/models/agent_id_patch_request_language_switching.py +96 -0
  33. smallestai/atoms/models/{update_agent_request_synthesizer.py → agent_id_patch_request_synthesizer.py} +6 -6
  34. smallestai/atoms/models/{update_agent_request_synthesizer_voice_config.py → agent_id_patch_request_synthesizer_voice_config.py} +27 -27
  35. smallestai/atoms/models/{update_agent_request_synthesizer_voice_config_one_of.py → agent_id_patch_request_synthesizer_voice_config_one_of.py} +4 -4
  36. smallestai/atoms/models/{update_agent_request_synthesizer_voice_config_one_of1.py → agent_id_patch_request_synthesizer_voice_config_one_of1.py} +4 -4
  37. smallestai/atoms/models/{get_campaign_by_id200_response.py → agent_id_workflow_get200_response.py} +7 -7
  38. smallestai/atoms/models/agent_id_workflow_get200_response_data.py +105 -0
  39. smallestai/atoms/models/agent_id_workflow_get200_response_data_edges_inner.py +127 -0
  40. smallestai/atoms/models/agent_id_workflow_get200_response_data_edges_inner_data.py +91 -0
  41. smallestai/atoms/models/agent_id_workflow_get200_response_data_edges_inner_marker_end.py +91 -0
  42. smallestai/atoms/models/agent_id_workflow_get200_response_data_nodes_inner.py +114 -0
  43. smallestai/atoms/models/agent_id_workflow_get200_response_data_nodes_inner_data.py +115 -0
  44. smallestai/atoms/models/agent_id_workflow_get200_response_data_nodes_inner_data_variables.py +97 -0
  45. smallestai/atoms/models/agent_id_workflow_get200_response_data_nodes_inner_data_variables_data_inner.py +91 -0
  46. smallestai/atoms/models/agent_id_workflow_get200_response_data_nodes_inner_position.py +89 -0
  47. smallestai/atoms/models/agent_id_workflow_get404_response.py +89 -0
  48. smallestai/atoms/models/agent_template_get200_response.py +97 -0
  49. smallestai/atoms/models/{get_agent_templates200_response_data_inner.py → agent_template_get200_response_data_inner.py} +6 -6
  50. smallestai/atoms/models/{get_campaigns200_response.py → audience_get200_response.py} +7 -7
  51. smallestai/atoms/models/{create_campaign201_response_data.py → audience_get200_response_data_inner.py} +16 -18
  52. smallestai/atoms/models/audience_id_delete200_response.py +89 -0
  53. smallestai/atoms/models/audience_id_delete400_response.py +89 -0
  54. smallestai/atoms/models/{get_current_user200_response.py → audience_id_get200_response.py} +7 -7
  55. smallestai/atoms/models/audience_id_get400_response.py +89 -0
  56. smallestai/atoms/models/audience_id_get403_response.py +89 -0
  57. smallestai/atoms/models/audience_id_get404_response.py +89 -0
  58. smallestai/atoms/models/audience_id_members_delete200_response.py +93 -0
  59. smallestai/atoms/models/audience_id_members_delete200_response_data.py +87 -0
  60. smallestai/atoms/models/audience_id_members_delete_request.py +87 -0
  61. smallestai/atoms/models/audience_id_members_get200_response.py +93 -0
  62. smallestai/atoms/models/audience_id_members_get200_response_data.py +101 -0
  63. smallestai/atoms/models/{get_campaigns200_response_data_inner_audience.py → audience_id_members_get200_response_data_members_inner.py} +8 -8
  64. smallestai/atoms/models/audience_id_members_get400_response.py +89 -0
  65. smallestai/atoms/models/audience_id_members_get500_response.py +89 -0
  66. smallestai/atoms/models/audience_id_members_post200_response.py +97 -0
  67. smallestai/atoms/models/audience_id_members_post200_response_data_inner.py +93 -0
  68. smallestai/atoms/models/audience_id_members_post200_response_data_inner_data.py +89 -0
  69. smallestai/atoms/models/audience_id_members_post400_response.py +89 -0
  70. smallestai/atoms/models/audience_id_members_post403_response.py +89 -0
  71. smallestai/atoms/models/audience_id_members_post_request.py +87 -0
  72. smallestai/atoms/models/audience_id_members_search_get200_response.py +93 -0
  73. smallestai/atoms/models/audience_id_members_search_get200_response_data.py +101 -0
  74. smallestai/atoms/models/audience_id_members_search_get200_response_data_search_info.py +103 -0
  75. smallestai/atoms/models/audience_id_members_search_get400_response.py +89 -0
  76. smallestai/atoms/models/audience_id_members_search_get500_response.py +89 -0
  77. smallestai/atoms/models/{create_campaign201_response.py → audience_post200_response.py} +7 -7
  78. smallestai/atoms/models/audience_post200_response_data.py +104 -0
  79. smallestai/atoms/models/audience_post400_response.py +89 -0
  80. smallestai/atoms/models/campaign_get200_response.py +93 -0
  81. smallestai/atoms/models/campaign_get200_response_data.py +87 -0
  82. smallestai/atoms/models/{get_campaigns_request.py → campaign_get_request.py} +4 -4
  83. smallestai/atoms/models/campaign_id_get200_response.py +93 -0
  84. smallestai/atoms/models/{get_campaign_by_id200_response_data.py → campaign_id_get200_response_data.py} +4 -4
  85. smallestai/atoms/models/campaign_post201_response.py +89 -0
  86. smallestai/atoms/models/{create_campaign_request.py → campaign_post_request.py} +4 -4
  87. smallestai/atoms/models/{start_outbound_call200_response.py → conversation_id_get200_response.py} +7 -7
  88. smallestai/atoms/models/{get_conversation_logs200_response_data.py → conversation_id_get200_response_data.py} +4 -4
  89. smallestai/atoms/models/conversation_outbound_post200_response.py +93 -0
  90. smallestai/atoms/models/{start_outbound_call200_response_data.py → conversation_outbound_post200_response_data.py} +4 -4
  91. smallestai/atoms/models/{start_outbound_call_request.py → conversation_outbound_post_request.py} +4 -4
  92. smallestai/atoms/models/create_agent_request.py +10 -6
  93. smallestai/atoms/models/create_agent_request_language.py +11 -7
  94. smallestai/atoms/models/create_agent_request_language_synthesizer_voice_config.py +24 -24
  95. smallestai/atoms/models/{knowledge_base_dto.py → knowledge_base.py} +15 -8
  96. smallestai/atoms/models/{knowledge_base_item_dto.py → knowledge_base_item.py} +19 -17
  97. smallestai/atoms/models/{get_knowledge_bases200_response.py → knowledgebase_get200_response.py} +7 -7
  98. smallestai/atoms/models/{get_knowledge_base_by_id200_response.py → knowledgebase_id_get200_response.py} +7 -7
  99. smallestai/atoms/models/{get_knowledge_base_items200_response.py → knowledgebase_id_items_get200_response.py} +7 -7
  100. smallestai/atoms/models/{upload_text_to_knowledge_base_request.py → knowledgebase_id_items_upload_text_post_request.py} +4 -4
  101. smallestai/atoms/models/{create_knowledge_base201_response.py → knowledgebase_post201_response.py} +4 -4
  102. smallestai/atoms/models/{create_knowledge_base_request.py → knowledgebase_post_request.py} +4 -4
  103. smallestai/atoms/models/{get_organization200_response.py → organization_get200_response.py} +7 -7
  104. smallestai/atoms/models/{get_organization200_response_data.py → organization_get200_response_data.py} +10 -10
  105. smallestai/atoms/models/{get_organization200_response_data_members_inner.py → organization_get200_response_data_members_inner.py} +4 -4
  106. smallestai/atoms/models/{get_organization200_response_data_subscription.py → organization_get200_response_data_subscription.py} +4 -4
  107. smallestai/atoms/models/product_phone_numbers_get200_response.py +97 -0
  108. smallestai/atoms/models/product_phone_numbers_get200_response_data_inner.py +100 -0
  109. smallestai/atoms/models/product_phone_numbers_get200_response_data_inner_attributes.py +89 -0
  110. smallestai/atoms/models/user_get200_response.py +93 -0
  111. smallestai/atoms/models/{get_current_user200_response_data.py → user_get200_response_data.py} +4 -4
  112. smallestai/atoms/models/webhook.py +124 -0
  113. smallestai/atoms/models/{get_campaigns200_response_data_inner_agent.py → webhook_agent.py} +8 -6
  114. smallestai/atoms/models/webhook_event.py +98 -0
  115. smallestai/atoms/models/webhook_get200_response.py +93 -0
  116. smallestai/atoms/models/webhook_get200_response_data.py +140 -0
  117. smallestai/atoms/models/webhook_id_delete404_response.py +89 -0
  118. smallestai/atoms/models/webhook_post201_response.py +89 -0
  119. smallestai/atoms/models/webhook_post_request.py +99 -0
  120. smallestai/atoms/models/webhook_post_request_events_inner.py +99 -0
  121. smallestai/atoms/models/webhook_subscription.py +108 -0
  122. smallestai/atoms/models/webhook_subscription_populated.py +112 -0
  123. smallestai/waves/__init__.py +2 -2
  124. smallestai/waves/async_waves_client.py +42 -69
  125. smallestai/waves/stream_tts.py +189 -254
  126. smallestai/waves/utils.py +3 -49
  127. smallestai/waves/waves_client.py +41 -69
  128. {smallestai-3.1.0.dist-info → smallestai-4.0.1.dist-info}/METADATA +3 -2
  129. smallestai-4.0.1.dist-info/RECORD +147 -0
  130. {smallestai-3.1.0.dist-info → smallestai-4.0.1.dist-info}/WHEEL +1 -1
  131. smallestai/atoms/models/get_campaigns200_response_data_inner.py +0 -118
  132. smallestai/atoms/models/get_conversation_logs200_response.py +0 -93
  133. smallestai-3.1.0.dist-info/RECORD +0 -87
  134. {smallestai-3.1.0.dist-info → smallestai-4.0.1.dist-info}/licenses/LICENSE +0 -0
  135. {smallestai-3.1.0.dist-info → smallestai-4.0.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,99 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Agent Management API
5
+
6
+ API for managing agents, their templates, and call logs
7
+
8
+ The version of the OpenAPI document: 1.0.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator
21
+ from typing import Any, ClassVar, Dict, List, Optional
22
+ from typing import Optional, Set
23
+ from typing_extensions import Self
24
+
25
+ class WebhookPostRequestEventsInner(BaseModel):
26
+ """
27
+ WebhookPostRequestEventsInner
28
+ """ # noqa: E501
29
+ agent_id: Optional[StrictStr] = Field(default=None, description="The ID of the agent", alias="agentId")
30
+ event_type: Optional[StrictStr] = Field(default=None, description="The type of event to subscribe to", alias="eventType")
31
+ __properties: ClassVar[List[str]] = ["agentId", "eventType"]
32
+
33
+ @field_validator('event_type')
34
+ def event_type_validate_enum(cls, value):
35
+ """Validates the enum"""
36
+ if value is None:
37
+ return value
38
+
39
+ if value not in set(['pre-conversation', 'post-conversation']):
40
+ raise ValueError("must be one of enum values ('pre-conversation', 'post-conversation')")
41
+ return value
42
+
43
+ model_config = ConfigDict(
44
+ populate_by_name=True,
45
+ validate_assignment=True,
46
+ protected_namespaces=(),
47
+ )
48
+
49
+
50
+ def to_str(self) -> str:
51
+ """Returns the string representation of the model using alias"""
52
+ return pprint.pformat(self.model_dump(by_alias=True))
53
+
54
+ def to_json(self) -> str:
55
+ """Returns the JSON representation of the model using alias"""
56
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
57
+ return json.dumps(self.to_dict())
58
+
59
+ @classmethod
60
+ def from_json(cls, json_str: str) -> Optional[Self]:
61
+ """Create an instance of WebhookPostRequestEventsInner from a JSON string"""
62
+ return cls.from_dict(json.loads(json_str))
63
+
64
+ def to_dict(self) -> Dict[str, Any]:
65
+ """Return the dictionary representation of the model using alias.
66
+
67
+ This has the following differences from calling pydantic's
68
+ `self.model_dump(by_alias=True)`:
69
+
70
+ * `None` is only added to the output dict for nullable fields that
71
+ were set at model initialization. Other fields with value `None`
72
+ are ignored.
73
+ """
74
+ excluded_fields: Set[str] = set([
75
+ ])
76
+
77
+ _dict = self.model_dump(
78
+ by_alias=True,
79
+ exclude=excluded_fields,
80
+ exclude_none=True,
81
+ )
82
+ return _dict
83
+
84
+ @classmethod
85
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
86
+ """Create an instance of WebhookPostRequestEventsInner from a dict"""
87
+ if obj is None:
88
+ return None
89
+
90
+ if not isinstance(obj, dict):
91
+ return cls.model_validate(obj)
92
+
93
+ _obj = cls.model_validate({
94
+ "agentId": obj.get("agentId"),
95
+ "eventType": obj.get("eventType")
96
+ })
97
+ return _obj
98
+
99
+
@@ -0,0 +1,108 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Agent Management API
5
+
6
+ API for managing agents, their templates, and call logs
7
+
8
+ The version of the OpenAPI document: 1.0.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from datetime import datetime
21
+ from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator
22
+ from typing import Any, ClassVar, Dict, List, Optional
23
+ from typing import Optional, Set
24
+ from typing_extensions import Self
25
+
26
+ class WebhookSubscription(BaseModel):
27
+ """
28
+ WebhookSubscription
29
+ """ # noqa: E501
30
+ id: Optional[StrictStr] = Field(default=None, description="The unique identifier for the subscription", alias="_id")
31
+ webhook_id: Optional[StrictStr] = Field(default=None, description="The ID of the webhook", alias="webhookId")
32
+ agent_id: Optional[StrictStr] = Field(default=None, description="The ID of the agent", alias="agentId")
33
+ event_type: Optional[StrictStr] = Field(default=None, description="The type of event subscribed to", alias="eventType")
34
+ created_at: Optional[datetime] = Field(default=None, description="The date and time when the subscription was created", alias="createdAt")
35
+ updated_at: Optional[datetime] = Field(default=None, description="The date and time when the subscription was last updated", alias="updatedAt")
36
+ __properties: ClassVar[List[str]] = ["_id", "webhookId", "agentId", "eventType", "createdAt", "updatedAt"]
37
+
38
+ @field_validator('event_type')
39
+ def event_type_validate_enum(cls, value):
40
+ """Validates the enum"""
41
+ if value is None:
42
+ return value
43
+
44
+ if value not in set(['pre-conversation', 'post-conversation']):
45
+ raise ValueError("must be one of enum values ('pre-conversation', 'post-conversation')")
46
+ return value
47
+
48
+ model_config = ConfigDict(
49
+ populate_by_name=True,
50
+ validate_assignment=True,
51
+ protected_namespaces=(),
52
+ )
53
+
54
+
55
+ def to_str(self) -> str:
56
+ """Returns the string representation of the model using alias"""
57
+ return pprint.pformat(self.model_dump(by_alias=True))
58
+
59
+ def to_json(self) -> str:
60
+ """Returns the JSON representation of the model using alias"""
61
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
62
+ return json.dumps(self.to_dict())
63
+
64
+ @classmethod
65
+ def from_json(cls, json_str: str) -> Optional[Self]:
66
+ """Create an instance of WebhookSubscription from a JSON string"""
67
+ return cls.from_dict(json.loads(json_str))
68
+
69
+ def to_dict(self) -> Dict[str, Any]:
70
+ """Return the dictionary representation of the model using alias.
71
+
72
+ This has the following differences from calling pydantic's
73
+ `self.model_dump(by_alias=True)`:
74
+
75
+ * `None` is only added to the output dict for nullable fields that
76
+ were set at model initialization. Other fields with value `None`
77
+ are ignored.
78
+ """
79
+ excluded_fields: Set[str] = set([
80
+ ])
81
+
82
+ _dict = self.model_dump(
83
+ by_alias=True,
84
+ exclude=excluded_fields,
85
+ exclude_none=True,
86
+ )
87
+ return _dict
88
+
89
+ @classmethod
90
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
91
+ """Create an instance of WebhookSubscription from a dict"""
92
+ if obj is None:
93
+ return None
94
+
95
+ if not isinstance(obj, dict):
96
+ return cls.model_validate(obj)
97
+
98
+ _obj = cls.model_validate({
99
+ "_id": obj.get("_id"),
100
+ "webhookId": obj.get("webhookId"),
101
+ "agentId": obj.get("agentId"),
102
+ "eventType": obj.get("eventType"),
103
+ "createdAt": obj.get("createdAt"),
104
+ "updatedAt": obj.get("updatedAt")
105
+ })
106
+ return _obj
107
+
108
+
@@ -0,0 +1,112 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Agent Management API
5
+
6
+ API for managing agents, their templates, and call logs
7
+
8
+ The version of the OpenAPI document: 1.0.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from datetime import datetime
21
+ from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator
22
+ from typing import Any, ClassVar, Dict, List, Optional
23
+ from smallestai.atoms.models.webhook_agent import WebhookAgent
24
+ from typing import Optional, Set
25
+ from typing_extensions import Self
26
+
27
+ class WebhookSubscriptionPopulated(BaseModel):
28
+ """
29
+ WebhookSubscriptionPopulated
30
+ """ # noqa: E501
31
+ id: Optional[StrictStr] = Field(default=None, description="The unique identifier for the subscription", alias="_id")
32
+ webhook_id: Optional[StrictStr] = Field(default=None, description="The ID of the webhook", alias="webhookId")
33
+ agent_id: Optional[WebhookAgent] = Field(default=None, alias="agentId")
34
+ event_type: Optional[StrictStr] = Field(default=None, description="The type of event subscribed to", alias="eventType")
35
+ created_at: Optional[datetime] = Field(default=None, description="The date and time when the subscription was created", alias="createdAt")
36
+ updated_at: Optional[datetime] = Field(default=None, description="The date and time when the subscription was last updated", alias="updatedAt")
37
+ __properties: ClassVar[List[str]] = ["_id", "webhookId", "agentId", "eventType", "createdAt", "updatedAt"]
38
+
39
+ @field_validator('event_type')
40
+ def event_type_validate_enum(cls, value):
41
+ """Validates the enum"""
42
+ if value is None:
43
+ return value
44
+
45
+ if value not in set(['pre-conversation', 'post-conversation']):
46
+ raise ValueError("must be one of enum values ('pre-conversation', 'post-conversation')")
47
+ return value
48
+
49
+ model_config = ConfigDict(
50
+ populate_by_name=True,
51
+ validate_assignment=True,
52
+ protected_namespaces=(),
53
+ )
54
+
55
+
56
+ def to_str(self) -> str:
57
+ """Returns the string representation of the model using alias"""
58
+ return pprint.pformat(self.model_dump(by_alias=True))
59
+
60
+ def to_json(self) -> str:
61
+ """Returns the JSON representation of the model using alias"""
62
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
63
+ return json.dumps(self.to_dict())
64
+
65
+ @classmethod
66
+ def from_json(cls, json_str: str) -> Optional[Self]:
67
+ """Create an instance of WebhookSubscriptionPopulated from a JSON string"""
68
+ return cls.from_dict(json.loads(json_str))
69
+
70
+ def to_dict(self) -> Dict[str, Any]:
71
+ """Return the dictionary representation of the model using alias.
72
+
73
+ This has the following differences from calling pydantic's
74
+ `self.model_dump(by_alias=True)`:
75
+
76
+ * `None` is only added to the output dict for nullable fields that
77
+ were set at model initialization. Other fields with value `None`
78
+ are ignored.
79
+ """
80
+ excluded_fields: Set[str] = set([
81
+ ])
82
+
83
+ _dict = self.model_dump(
84
+ by_alias=True,
85
+ exclude=excluded_fields,
86
+ exclude_none=True,
87
+ )
88
+ # override the default output from pydantic by calling `to_dict()` of agent_id
89
+ if self.agent_id:
90
+ _dict['agentId'] = self.agent_id.to_dict()
91
+ return _dict
92
+
93
+ @classmethod
94
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
95
+ """Create an instance of WebhookSubscriptionPopulated from a dict"""
96
+ if obj is None:
97
+ return None
98
+
99
+ if not isinstance(obj, dict):
100
+ return cls.model_validate(obj)
101
+
102
+ _obj = cls.model_validate({
103
+ "_id": obj.get("_id"),
104
+ "webhookId": obj.get("webhookId"),
105
+ "agentId": WebhookAgent.from_dict(obj["agentId"]) if obj.get("agentId") is not None else None,
106
+ "eventType": obj.get("eventType"),
107
+ "createdAt": obj.get("createdAt"),
108
+ "updatedAt": obj.get("updatedAt")
109
+ })
110
+ return _obj
111
+
112
+
@@ -1,5 +1,5 @@
1
1
  from smallestai.waves.waves_client import WavesClient
2
2
  from smallestai.waves.async_waves_client import AsyncWavesClient
3
- from smallestai.waves.stream_tts import TextToAudioStream
3
+ from smallestai.waves.stream_tts import WavesStreamingTTS, TTSConfig
4
4
 
5
- __all__ = ["WavesClient", "AsyncWavesClient", "TextToAudioStream"]
5
+ __all__ = ["WavesClient", "AsyncWavesClient", "WavesStreamingTTS", "TTSConfig"]
@@ -4,10 +4,10 @@ import json
4
4
  import aiohttp
5
5
  import aiofiles
6
6
  import requests
7
- from typing import Optional, Union, List, AsyncIterator
7
+ from typing import Optional, Union, List
8
8
 
9
9
  from smallestai.waves.exceptions import TTSError, APIError
10
- from smallestai.waves.utils import (TTSOptions, validate_input, preprocess_text, add_wav_header, chunk_text,
10
+ from smallestai.waves.utils import (TTSOptions, validate_input,
11
11
  get_smallest_languages, get_smallest_models, ALLOWED_AUDIO_EXTENSIONS, API_BASE_URL)
12
12
 
13
13
 
@@ -22,7 +22,8 @@ class AsyncWavesClient:
22
22
  consistency: Optional[float] = 0.5,
23
23
  similarity: Optional[float] = 0.0,
24
24
  enhancement: Optional[int] = 1,
25
- add_wav_header: Optional[bool] = True
25
+ language: Optional[str] = "en",
26
+ output_format: Optional[str] = "wav"
26
27
  ) -> None:
27
28
  """
28
29
  AsyncSmallest Instance for asynchronous text-to-speech synthesis.
@@ -40,7 +41,8 @@ class AsyncWavesClient:
40
41
  - consistency (float): This parameter controls word repetition and skipping. Decrease it to prevent skipped words, and increase it to prevent repetition. Only supported in `lightning-large` model. Range - [0, 1]
41
42
  - similarity (float): This parameter controls the similarity between the synthesized audio and the reference audio. Increase it to make the speech more similar to the reference audio. Only supported in `lightning-large` model. Range - [0, 1]
42
43
  - enhancement (int): Enhances speech quality at the cost of increased latency. Only supported in `lightning-large` model. Range - [0, 2].
43
- - add_wav_header (bool): Whether to add a WAV header to the output audio.
44
+ - language (str): The language for synthesis. Default is "en".
45
+ - output_format (str): The output audio format. Options: "pcm", "mp3", "wav", "mulaw". Default is "pcm".
44
46
 
45
47
  Methods:
46
48
  - get_languages: Returns a list of available languages for synthesis.
@@ -61,11 +63,12 @@ class AsyncWavesClient:
61
63
  sample_rate=sample_rate,
62
64
  voice_id=voice_id,
63
65
  api_key=self.api_key,
64
- add_wav_header=add_wav_header,
65
66
  speed=speed,
66
67
  consistency=consistency,
67
68
  similarity=similarity,
68
- enhancement=enhancement
69
+ enhancement=enhancement,
70
+ language=language,
71
+ output_format=output_format
69
72
  )
70
73
  self.session = None
71
74
 
@@ -130,18 +133,14 @@ class AsyncWavesClient:
130
133
  async def synthesize(
131
134
  self,
132
135
  text: str,
133
- stream: Optional[bool] = False,
134
- save_as: Optional[str] = None,
135
136
  **kwargs
136
- ) -> Union[bytes, None, AsyncIterator[bytes]]:
137
+ ) -> Union[bytes]:
137
138
  """
138
139
  Asynchronously synthesize speech from the provided text.
139
140
 
140
141
  Args:
141
142
  - text (str): The text to be converted to speech.
142
143
  - stream (Optional[bool]): If True, returns an iterator yielding audio chunks instead of a full byte array.
143
- - save_as (Optional[str]): If provided, the synthesized audio will be saved to this file path.
144
- The file must have a .wav extension.
145
144
  - kwargs: Additional optional parameters to override `__init__` options for this call.
146
145
 
147
146
  Returns:
@@ -151,7 +150,7 @@ class AsyncWavesClient:
151
150
  - Otherwise, returns the synthesized audio content as bytes.
152
151
 
153
152
  Raises:
154
- - TTSError: If the provided file name does not have a .wav extension when `save_as` is specified.
153
+ - TTSError: If the provided file name does not have a .wav or .mp3 extension when `save_as` is specified.
155
154
  - APIError: If the API request fails or returns an error.
156
155
  - ValueError: If an unexpected parameter is passed in `kwargs`.
157
156
  """
@@ -172,65 +171,40 @@ class AsyncWavesClient:
172
171
  for key, value in kwargs.items():
173
172
  setattr(opts, key, value)
174
173
 
175
- text = preprocess_text(text)
176
174
  validate_input(text, opts.model, opts.sample_rate, opts.speed, opts.consistency, opts.similarity, opts.enhancement)
177
175
 
178
- self.chunk_size = 250
179
- if opts.model == 'lightning-large' or opts.model == "lightning-v2":
180
- self.chunk_size = 140
181
-
182
- chunks = chunk_text(text, self.chunk_size)
183
-
184
- async def audio_stream():
185
- for chunk in chunks:
186
- payload = {
187
- "text": chunk,
188
- "sample_rate": opts.sample_rate,
189
- "voice_id": opts.voice_id,
190
- "add_wav_header": False,
191
- "speed": opts.speed,
192
- "model": opts.model
193
- }
194
-
195
- if opts.model == "lightning-large" or opts.model == "lightning-v2":
196
- if opts.consistency is not None:
197
- payload["consistency"] = opts.consistency
198
- if opts.similarity is not None:
199
- payload["similarity"] = opts.similarity
200
- if opts.enhancement is not None:
201
- payload["enhancement"] = opts.enhancement
202
-
203
-
204
- headers = {
205
- "Authorization": f"Bearer {self.api_key}",
206
- "Content-Type": "application/json",
207
- }
208
-
209
- async with self.session.post(f"{API_BASE_URL}/{opts.model}/get_speech", json=payload, headers=headers) as res:
210
- if res.status != 200:
211
- raise APIError(f"Failed to synthesize speech: {await res.text()}. For more information, visit https://waves.smallest.ai/")
212
-
213
- yield await res.read()
176
+ payload = {
177
+ "text": text,
178
+ "voice_id": opts.voice_id,
179
+ "sample_rate": opts.sample_rate,
180
+ "speed": opts.speed,
181
+ "consistency": opts.consistency,
182
+ "similarity": opts.similarity,
183
+ "enhancement": opts.enhancement,
184
+ "language": opts.language,
185
+ "output_format": opts.output_format
186
+ }
214
187
 
215
- if stream:
216
- return audio_stream()
217
-
218
- audio_content = b"".join([chunk async for chunk in audio_stream()])
219
-
220
- if save_as:
221
- if not save_as.endswith(".wav"):
222
- raise TTSError("Invalid file name. Extension must be .wav")
223
-
224
- async with aiofiles.open(save_as, mode='wb') as f:
225
- await f.write(add_wav_header(audio_content, opts.sample_rate))
226
-
227
- return None
228
-
229
- if opts.add_wav_header:
230
- return add_wav_header(audio_content, opts.sample_rate)
188
+ if opts.model == "lightning-large" or opts.model == "lightning-v2":
189
+ if opts.consistency is not None:
190
+ payload["consistency"] = opts.consistency
191
+ if opts.similarity is not None:
192
+ payload["similarity"] = opts.similarity
193
+ if opts.enhancement is not None:
194
+ payload["enhancement"] = opts.enhancement
195
+
196
+ headers = {
197
+ "Authorization": f"Bearer {self.api_key}",
198
+ "Content-Type": "application/json",
199
+ }
231
200
 
232
- return audio_content
201
+ async with self.session.post(f"{API_BASE_URL}/{opts.model}/get_speech", json=payload, headers=headers) as res:
202
+ if res.status != 200:
203
+ raise APIError(f"Failed to synthesize speech: {await res.text()}. For more information, visit https://waves.smallest.ai/")
204
+
205
+ audio_bytes = await res.content.read()
233
206
 
207
+ return audio_bytes
234
208
  finally:
235
209
  if should_cleanup and self.session:
236
210
  await self.session.close()
@@ -316,9 +290,8 @@ class AsyncWavesClient:
316
290
  if res.status != 200:
317
291
  raise APIError(f"Failed to delete voice: {await res.text()}. For more information, visit https://waves.smallest.ai/")
318
292
 
319
- return await res.text()
320
-
293
+ return json.dumps(await res.json(), indent=4, ensure_ascii=False)
321
294
  finally:
322
295
  if should_cleanup and self.session:
323
296
  await self.session.close()
324
- self.session = None
297
+ self.session = None