agentle 0.9.26__py3-none-any.whl → 0.9.28__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.
- agentle/agents/apis/endpoint.py +3 -1
- agentle/agents/whatsapp/models/key.py +2 -2
- agentle/agents/whatsapp/models/whatsapp_response_base.py +31 -0
- agentle/agents/whatsapp/whatsapp_bot.py +53 -12
- {agentle-0.9.26.dist-info → agentle-0.9.28.dist-info}/METADATA +1 -1
- {agentle-0.9.26.dist-info → agentle-0.9.28.dist-info}/RECORD +8 -7
- {agentle-0.9.26.dist-info → agentle-0.9.28.dist-info}/WHEEL +0 -0
- {agentle-0.9.26.dist-info → agentle-0.9.28.dist-info}/licenses/LICENSE +0 -0
agentle/agents/apis/endpoint.py
CHANGED
|
@@ -592,9 +592,11 @@ class Endpoint(BaseModel):
|
|
|
592
592
|
|
|
593
593
|
tool_parameters[param.name] = param_info
|
|
594
594
|
|
|
595
|
+
tool_name = "_".join(self.name.lower().split())
|
|
596
|
+
|
|
595
597
|
# Create the tool
|
|
596
598
|
tool = Tool(
|
|
597
|
-
name=
|
|
599
|
+
name=tool_name,
|
|
598
600
|
description=self.get_enhanced_description(),
|
|
599
601
|
parameters=tool_parameters,
|
|
600
602
|
)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from rsb.models
|
|
1
|
+
from rsb.models import BaseModel, Field
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class Key(BaseModel):
|
|
@@ -11,6 +11,6 @@ class Key(BaseModel):
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
remoteJid: str
|
|
14
|
-
remoteJidAlt: str
|
|
14
|
+
remoteJidAlt: str = Field(default="")
|
|
15
15
|
fromMe: bool
|
|
16
16
|
id: str
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Em: agentle/agents/whatsapp/models/whatsapp_response_base.py
|
|
2
|
+
|
|
3
|
+
from rsb.models.base_model import BaseModel
|
|
4
|
+
from rsb.models.field import Field
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class WhatsAppResponseBase(BaseModel):
|
|
8
|
+
"""
|
|
9
|
+
Base class for WhatsApp bot structured responses.
|
|
10
|
+
|
|
11
|
+
This class ensures that all structured outputs from the WhatsApp bot
|
|
12
|
+
contain a 'response' field with the text to be sent to the user.
|
|
13
|
+
|
|
14
|
+
Developers can extend this class to add additional structured data
|
|
15
|
+
that they want to extract from the conversation.
|
|
16
|
+
|
|
17
|
+
Example:
|
|
18
|
+
```python
|
|
19
|
+
class CustomerServiceResponse(WhatsAppResponseBase):
|
|
20
|
+
response: str # Inherited - text to send to user
|
|
21
|
+
sentiment: Literal["happy", "neutral", "frustrated", "angry"]
|
|
22
|
+
urgency: int = Field(ge=1, le=5, description="Urgency level 1-5")
|
|
23
|
+
requires_human: bool = False
|
|
24
|
+
suggested_actions: list[str] = Field(default_factory=list)
|
|
25
|
+
```
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
response: str = Field(
|
|
29
|
+
...,
|
|
30
|
+
description="The text response that will be sent to the WhatsApp user. This field is required.",
|
|
31
|
+
)
|
|
@@ -33,6 +33,7 @@ from agentle.agents.whatsapp.models.whatsapp_document_message import (
|
|
|
33
33
|
from agentle.agents.whatsapp.models.whatsapp_image_message import WhatsAppImageMessage
|
|
34
34
|
from agentle.agents.whatsapp.models.whatsapp_media_message import WhatsAppMediaMessage
|
|
35
35
|
from agentle.agents.whatsapp.models.whatsapp_message import WhatsAppMessage
|
|
36
|
+
from agentle.agents.whatsapp.models.whatsapp_response_base import WhatsAppResponseBase
|
|
36
37
|
from agentle.agents.whatsapp.models.whatsapp_session import WhatsAppSession
|
|
37
38
|
from agentle.agents.whatsapp.models.whatsapp_text_message import WhatsAppTextMessage
|
|
38
39
|
from agentle.agents.whatsapp.models.whatsapp_video_message import WhatsAppVideoMessage
|
|
@@ -128,14 +129,42 @@ class CallbackWithContext:
|
|
|
128
129
|
context: dict[str, Any] = field(default_factory=dict)
|
|
129
130
|
|
|
130
131
|
|
|
131
|
-
class WhatsAppBot(BaseModel):
|
|
132
|
+
class WhatsAppBot[T_Schema: WhatsAppResponseBase = WhatsAppResponseBase](BaseModel):
|
|
132
133
|
"""
|
|
133
134
|
WhatsApp bot that wraps an Agentle agent with enhanced message batching and spam protection.
|
|
134
135
|
|
|
135
|
-
Now
|
|
136
|
+
Now supports structured outputs through generic type parameter T_Schema.
|
|
137
|
+
The schema must extend WhatsAppResponseBase to ensure a 'response' field is always present.
|
|
138
|
+
|
|
139
|
+
Examples:
|
|
140
|
+
```python
|
|
141
|
+
# Basic usage (no structured output)
|
|
142
|
+
agent = Agent(...)
|
|
143
|
+
bot = WhatsAppBot(agent=agent, provider=provider)
|
|
144
|
+
|
|
145
|
+
# With structured output
|
|
146
|
+
class MyResponse(WhatsAppResponseBase):
|
|
147
|
+
sentiment: Literal["happy", "sad", "neutral"]
|
|
148
|
+
urgency_level: int
|
|
149
|
+
|
|
150
|
+
agent = Agent[MyResponse](
|
|
151
|
+
response_schema=MyResponse,
|
|
152
|
+
instructions="Extract sentiment and urgency from the conversation..."
|
|
153
|
+
)
|
|
154
|
+
bot = WhatsAppBot[MyResponse](agent=agent, provider=provider)
|
|
155
|
+
|
|
156
|
+
# Access structured data in callbacks
|
|
157
|
+
async def my_callback(phone, chat_id, response, context):
|
|
158
|
+
if response and response.parsed:
|
|
159
|
+
print(f"Sentiment: {response.parsed.sentiment}")
|
|
160
|
+
print(f"Urgency: {response.parsed.urgency_level}")
|
|
161
|
+
# response.parsed.response is automatically sent to WhatsApp
|
|
162
|
+
|
|
163
|
+
bot.add_response_callback(my_callback)
|
|
164
|
+
```
|
|
136
165
|
"""
|
|
137
166
|
|
|
138
|
-
agent: Agent[
|
|
167
|
+
agent: Agent[T_Schema]
|
|
139
168
|
provider: WhatsAppProvider
|
|
140
169
|
tts_provider: TtsProvider | None = Field(default=None)
|
|
141
170
|
file_storage_manager: FileStorageManager | None = Field(default=None)
|
|
@@ -1302,7 +1331,7 @@ class WhatsAppBot(BaseModel):
|
|
|
1302
1331
|
|
|
1303
1332
|
async def _process_message_batch(
|
|
1304
1333
|
self, phone_number: PhoneNumber, session: WhatsAppSession, processing_token: str
|
|
1305
|
-
) -> GeneratedAssistantMessage[
|
|
1334
|
+
) -> GeneratedAssistantMessage[T_Schema] | None:
|
|
1306
1335
|
"""Process a batch of messages for a user with enhanced timeout protection.
|
|
1307
1336
|
|
|
1308
1337
|
This method processes multiple messages that were received in quick succession
|
|
@@ -1504,7 +1533,7 @@ class WhatsAppBot(BaseModel):
|
|
|
1504
1533
|
message: WhatsAppMessage,
|
|
1505
1534
|
session: WhatsAppSession,
|
|
1506
1535
|
chat_id: ChatId | None = None,
|
|
1507
|
-
) -> GeneratedAssistantMessage[
|
|
1536
|
+
) -> GeneratedAssistantMessage[T_Schema]:
|
|
1508
1537
|
"""Process a single message immediately with quote message support."""
|
|
1509
1538
|
logger.info(
|
|
1510
1539
|
"[SINGLE_MESSAGE] ═══════════ SINGLE MESSAGE PROCESSING START ═══════════"
|
|
@@ -2207,7 +2236,7 @@ class WhatsAppBot(BaseModel):
|
|
|
2207
2236
|
async def _send_response(
|
|
2208
2237
|
self,
|
|
2209
2238
|
to: PhoneNumber,
|
|
2210
|
-
response: GeneratedAssistantMessage[
|
|
2239
|
+
response: GeneratedAssistantMessage[T_Schema] | str,
|
|
2211
2240
|
reply_to: str | None = None,
|
|
2212
2241
|
) -> None:
|
|
2213
2242
|
"""Send response message(s) to user with enhanced error handling and retry logic.
|
|
@@ -2255,12 +2284,24 @@ class WhatsAppBot(BaseModel):
|
|
|
2255
2284
|
... reply_to="msg_123"
|
|
2256
2285
|
... )
|
|
2257
2286
|
"""
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
if
|
|
2262
|
-
|
|
2263
|
-
|
|
2287
|
+
response_text = ""
|
|
2288
|
+
|
|
2289
|
+
if isinstance(response, GeneratedAssistantMessage):
|
|
2290
|
+
# Check if we have structured output (parsed)
|
|
2291
|
+
if response.parsed:
|
|
2292
|
+
# Use the 'response' field from structured output
|
|
2293
|
+
response_text = response.parsed.response
|
|
2294
|
+
logger.debug(
|
|
2295
|
+
"[SEND_RESPONSE] Using structured output 'response' field "
|
|
2296
|
+
+ f"(schema: {type(response.parsed).__name__})"
|
|
2297
|
+
)
|
|
2298
|
+
else:
|
|
2299
|
+
# Fallback to text field
|
|
2300
|
+
response_text = response.text
|
|
2301
|
+
logger.debug("[SEND_RESPONSE] Using standard text response")
|
|
2302
|
+
else:
|
|
2303
|
+
# Direct string
|
|
2304
|
+
response_text = response
|
|
2264
2305
|
|
|
2265
2306
|
# Apply WhatsApp-specific markdown formatting
|
|
2266
2307
|
response_text = self._format_whatsapp_markdown(response_text)
|
|
@@ -78,7 +78,7 @@ agentle/agents/apis/cache_strategy.py,sha256=uoAvmUm1EE8426anuLR4PoygLgO4SPN1Qm_
|
|
|
78
78
|
agentle/agents/apis/circuit_breaker.py,sha256=9yopLPoZ6WMlPMWPoacayORoGN1CZq2EGWB0gCu3GOY,2371
|
|
79
79
|
agentle/agents/apis/circuit_breaker_error.py,sha256=I5XyCWwFCXTDzhvS7CpMZwBRxMyCk96g7MfBLBqAvhg,127
|
|
80
80
|
agentle/agents/apis/circuit_breaker_state.py,sha256=6IwcWWKNmE0cnpogcfsnhpy_EVIk7crQ7WiDN9YkkbE,277
|
|
81
|
-
agentle/agents/apis/endpoint.py,sha256=
|
|
81
|
+
agentle/agents/apis/endpoint.py,sha256=MEaWIGJHK7uq9QZONTf6aGum9ak5gCN8cLqWJ9ltdVE,22657
|
|
82
82
|
agentle/agents/apis/endpoint_parameter.py,sha256=A_SVje6AyNeeJNDxWL__uGc4ZNZ2se6GvawS--kUYEU,20230
|
|
83
83
|
agentle/agents/apis/endpoints_to_tools.py,sha256=5KzxRLjfUYx7MGKHe65NMPHyTKOcd8tdK0uYzfGnO5g,999
|
|
84
84
|
agentle/agents/apis/file_upload.py,sha256=PzJ1197EKLCdBHrLDztgifM3WWFQZ8K2CKkTeeYpJas,587
|
|
@@ -137,7 +137,7 @@ agentle/agents/ui/__init__.py,sha256=IjHRV0k2DNwvFrEHebmsXiBvmITE8nQUnsR07h9tVkU
|
|
|
137
137
|
agentle/agents/ui/streamlit.py,sha256=9afICL0cxtG1o2pWh6vH39-NdKiVfADKiXo405F2aB0,42829
|
|
138
138
|
agentle/agents/whatsapp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
139
139
|
agentle/agents/whatsapp/human_delay_calculator.py,sha256=BGCDeoNTPsMn4d_QYmG0BWGCG8SiUJC6Fk295ulAsAk,18268
|
|
140
|
-
agentle/agents/whatsapp/whatsapp_bot.py,sha256=
|
|
140
|
+
agentle/agents/whatsapp/whatsapp_bot.py,sha256=7B1ZCQYMJ6qgRINFzSQVSshDr-4L1F5H3MHqJYI7w3g,161962
|
|
141
141
|
agentle/agents/whatsapp/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
142
142
|
agentle/agents/whatsapp/models/audio_message.py,sha256=kUqG1HdNW6DCYD-CqscJ6WHlAyv9ufmTSKMdjio9XWk,2705
|
|
143
143
|
agentle/agents/whatsapp/models/context_info.py,sha256=sk80KuNE36S6VRnLh7n6UXmzZCXIB4E4lNxnRyVizg8,563
|
|
@@ -146,7 +146,7 @@ agentle/agents/whatsapp/models/device_list_metadata.py,sha256=Nki7esmgi9Zq70L2t4
|
|
|
146
146
|
agentle/agents/whatsapp/models/document_message.py,sha256=aZaJCp33GwP1fP5j2DVSWBSVQ4udoE0vj21mc3zjbWQ,2502
|
|
147
147
|
agentle/agents/whatsapp/models/downloaded_media.py,sha256=TAZEX2oyXp4m4Dk8eRcgoaQCjDyUTN3E6BqkA4pIB9k,204
|
|
148
148
|
agentle/agents/whatsapp/models/image_message.py,sha256=9inTFNzJq-VJbUaUNzeHfrI7l6Qx7gSM5ydNF0FuRLY,3859
|
|
149
|
-
agentle/agents/whatsapp/models/key.py,sha256=
|
|
149
|
+
agentle/agents/whatsapp/models/key.py,sha256=BXntl5i2qL110Bja3ZE2INQqC-tf_rone2YU6JVpqbI,434
|
|
150
150
|
agentle/agents/whatsapp/models/message.py,sha256=HqCqra8vOn3fig53SxnxPgtph20tBEjODlXTLiSErps,1446
|
|
151
151
|
agentle/agents/whatsapp/models/message_context_info.py,sha256=msCSuu8uMN3G9GDaXdP6mefmOxSjeY-7iL-gN6Q9-i8,741
|
|
152
152
|
agentle/agents/whatsapp/models/quoted_message.py,sha256=QC4sp7eLPE9g9i-_f3avb0sDO7gKpkzZR2qkbxqptts,1073
|
|
@@ -161,6 +161,7 @@ agentle/agents/whatsapp/models/whatsapp_media_message.py,sha256=-FY15vezGILzGMiU
|
|
|
161
161
|
agentle/agents/whatsapp/models/whatsapp_message.py,sha256=QtGAJKOF1ykZycsNDld25gk-JUeg3uV7hNXx0ZXO0Rg,1217
|
|
162
162
|
agentle/agents/whatsapp/models/whatsapp_message_status.py,sha256=jDWShdvSve5EhkgtDkh1jZmpRVNoXCokv4M6at1eSIU,214
|
|
163
163
|
agentle/agents/whatsapp/models/whatsapp_message_type.py,sha256=GctIGOC1Bc_D_L0ehEmEwgxePFx0ioTEUoBlZEdxdG8,279
|
|
164
|
+
agentle/agents/whatsapp/models/whatsapp_response_base.py,sha256=IIDONx9Ipt593tAZvoc8dPDUISeNH-WOpRP1x_-Q6Gk,1145
|
|
164
165
|
agentle/agents/whatsapp/models/whatsapp_session.py,sha256=9G1HC-A2G9jTdpwYy3w9bnYkOGK2vvA7kdYAf32oWMU,15640
|
|
165
166
|
agentle/agents/whatsapp/models/whatsapp_text_message.py,sha256=GpSwFrPC4qpQlVCWKKgYjQJKNv0qvwgYfuoD3ttLzdQ,441
|
|
166
167
|
agentle/agents/whatsapp/models/whatsapp_video_message.py,sha256=-d-4hnkkxyLVNoje3a1pOEAvzWqoCLFcBn70wUpnyXY,346
|
|
@@ -1017,7 +1018,7 @@ agentle/web/actions/scroll.py,sha256=WqVVAORNDK3BL1oASZBPmXJYeSVkPgAOmWA8ibYO82I
|
|
|
1017
1018
|
agentle/web/actions/viewport.py,sha256=KCwm88Pri19Qc6GLHC69HsRxmdJz1gEEAODfggC_fHo,287
|
|
1018
1019
|
agentle/web/actions/wait.py,sha256=IKEywjf-KC4ni9Gkkv4wgc7bY-hk7HwD4F-OFWlyf2w,571
|
|
1019
1020
|
agentle/web/actions/write_text.py,sha256=9mxfHcpKs_L7BsDnJvOYHQwG8M0GWe61SRJAsKk3xQ8,748
|
|
1020
|
-
agentle-0.9.
|
|
1021
|
-
agentle-0.9.
|
|
1022
|
-
agentle-0.9.
|
|
1023
|
-
agentle-0.9.
|
|
1021
|
+
agentle-0.9.28.dist-info/METADATA,sha256=ZY7T2Si68vQ1uj1qjcgtbqbY7XDWEcnvUkOo-pbF7C8,86849
|
|
1022
|
+
agentle-0.9.28.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
1023
|
+
agentle-0.9.28.dist-info/licenses/LICENSE,sha256=T90S9vqRS6qP-voULxAcvwEs558wRRo6dHuZrjgcOUI,1085
|
|
1024
|
+
agentle-0.9.28.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|