agentle 0.9.4__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/agent.py +175 -10
- agentle/agents/agent_run_output.py +8 -1
- agentle/agents/apis/__init__.py +79 -6
- agentle/agents/apis/api.py +342 -73
- agentle/agents/apis/api_key_authentication.py +43 -0
- agentle/agents/apis/api_key_location.py +11 -0
- agentle/agents/apis/api_metrics.py +16 -0
- agentle/agents/apis/auth_type.py +17 -0
- agentle/agents/apis/authentication.py +32 -0
- agentle/agents/apis/authentication_base.py +42 -0
- agentle/agents/apis/authentication_config.py +117 -0
- agentle/agents/apis/basic_authentication.py +34 -0
- agentle/agents/apis/bearer_authentication.py +52 -0
- agentle/agents/apis/cache_strategy.py +12 -0
- agentle/agents/apis/circuit_breaker.py +69 -0
- agentle/agents/apis/circuit_breaker_error.py +7 -0
- agentle/agents/apis/circuit_breaker_state.py +11 -0
- agentle/agents/apis/endpoint.py +413 -254
- agentle/agents/apis/file_upload.py +23 -0
- agentle/agents/apis/hmac_authentication.py +56 -0
- agentle/agents/apis/no_authentication.py +27 -0
- agentle/agents/apis/oauth2_authentication.py +111 -0
- agentle/agents/apis/oauth2_grant_type.py +12 -0
- agentle/agents/apis/object_schema.py +86 -1
- agentle/agents/apis/params/__init__.py +10 -1
- agentle/agents/apis/params/boolean_param.py +44 -0
- agentle/agents/apis/params/number_param.py +56 -0
- agentle/agents/apis/rate_limit_error.py +7 -0
- agentle/agents/apis/rate_limiter.py +57 -0
- agentle/agents/apis/request_config.py +126 -4
- agentle/agents/apis/request_hook.py +16 -0
- agentle/agents/apis/response_cache.py +49 -0
- agentle/agents/apis/retry_strategy.py +12 -0
- agentle/agents/whatsapp/human_delay_calculator.py +462 -0
- agentle/agents/whatsapp/models/audio_message.py +6 -4
- agentle/agents/whatsapp/models/key.py +2 -2
- agentle/agents/whatsapp/models/whatsapp_bot_config.py +375 -21
- agentle/agents/whatsapp/models/whatsapp_response_base.py +31 -0
- agentle/agents/whatsapp/models/whatsapp_webhook_payload.py +5 -1
- agentle/agents/whatsapp/providers/base/whatsapp_provider.py +51 -0
- agentle/agents/whatsapp/providers/evolution/evolution_api_provider.py +237 -10
- agentle/agents/whatsapp/providers/meta/meta_whatsapp_provider.py +126 -0
- agentle/agents/whatsapp/v2/batch_processor_manager.py +4 -0
- agentle/agents/whatsapp/v2/bot_config.py +188 -0
- agentle/agents/whatsapp/v2/message_limit.py +9 -0
- agentle/agents/whatsapp/v2/payload.py +0 -0
- agentle/agents/whatsapp/v2/whatsapp_bot.py +13 -0
- agentle/agents/whatsapp/v2/whatsapp_cloud_api_provider.py +0 -0
- agentle/agents/whatsapp/v2/whatsapp_provider.py +0 -0
- agentle/agents/whatsapp/whatsapp_bot.py +827 -45
- agentle/generations/providers/google/adapters/generate_generate_content_response_to_generation_adapter.py +13 -10
- agentle/generations/providers/google/google_generation_provider.py +35 -5
- agentle/generations/providers/openrouter/_adapters/openrouter_message_to_generated_assistant_message_adapter.py +35 -1
- agentle/mcp/servers/stdio_mcp_server.py +23 -4
- agentle/parsing/parsers/docx.py +8 -0
- agentle/parsing/parsers/file_parser.py +4 -0
- agentle/parsing/parsers/pdf.py +7 -1
- agentle/storage/__init__.py +11 -0
- agentle/storage/file_storage_manager.py +44 -0
- agentle/storage/local_file_storage_manager.py +122 -0
- agentle/storage/s3_file_storage_manager.py +124 -0
- agentle/tts/audio_format.py +6 -0
- agentle/tts/elevenlabs_tts_provider.py +108 -0
- agentle/tts/output_format_type.py +26 -0
- agentle/tts/speech_config.py +14 -0
- agentle/tts/speech_result.py +15 -0
- agentle/tts/tts_provider.py +16 -0
- agentle/tts/voice_settings.py +30 -0
- agentle/utils/parse_streaming_json.py +39 -13
- agentle/voice_cloning/__init__.py +0 -0
- agentle/voice_cloning/voice_cloner.py +0 -0
- agentle/web/extractor.py +282 -148
- {agentle-0.9.4.dist-info → agentle-0.9.28.dist-info}/METADATA +1 -1
- {agentle-0.9.4.dist-info → agentle-0.9.28.dist-info}/RECORD +78 -39
- agentle/tts/real_time/definitions/audio_data.py +0 -20
- agentle/tts/real_time/definitions/speech_config.py +0 -27
- agentle/tts/real_time/definitions/speech_result.py +0 -14
- agentle/tts/real_time/definitions/tts_stream_chunk.py +0 -15
- agentle/tts/real_time/definitions/voice_gender.py +0 -9
- agentle/tts/real_time/definitions/voice_info.py +0 -18
- agentle/tts/real_time/real_time_speech_to_text_provider.py +0 -66
- /agentle/{tts/real_time → agents/whatsapp/v2}/__init__.py +0 -0
- /agentle/{tts/real_time/definitions/__init__.py → agents/whatsapp/v2/in_memory_batch_processor_manager.py} +0 -0
- {agentle-0.9.4.dist-info → agentle-0.9.28.dist-info}/WHEEL +0 -0
- {agentle-0.9.4.dist-info → agentle-0.9.28.dist-info}/licenses/LICENSE +0 -0
|
@@ -6,9 +6,69 @@ from typing import Any
|
|
|
6
6
|
from rsb.models.base_model import BaseModel
|
|
7
7
|
from rsb.models.field import Field
|
|
8
8
|
|
|
9
|
+
from agentle.tts.speech_config import SpeechConfig
|
|
10
|
+
|
|
9
11
|
|
|
10
12
|
class WhatsAppBotConfig(BaseModel):
|
|
11
|
-
"""Configuration for WhatsApp bot behavior with simplified constructors and better organization.
|
|
13
|
+
"""Configuration for WhatsApp bot behavior with simplified constructors and better organization.
|
|
14
|
+
|
|
15
|
+
This configuration class provides comprehensive control over WhatsApp bot behavior including:
|
|
16
|
+
- Core bot behavior (typing indicators, message reading, quoting)
|
|
17
|
+
- Message batching for handling rapid message sequences
|
|
18
|
+
- Spam protection and rate limiting
|
|
19
|
+
- Human-like delays to simulate realistic human behavior patterns
|
|
20
|
+
- Text-to-speech integration
|
|
21
|
+
- Error handling and retry logic
|
|
22
|
+
- Debug and monitoring settings
|
|
23
|
+
|
|
24
|
+
Human-Like Delays Feature:
|
|
25
|
+
The human-like delays feature simulates realistic human behavior patterns by introducing
|
|
26
|
+
configurable delays at three critical points in message processing:
|
|
27
|
+
|
|
28
|
+
1. Read Delay: Time between receiving a message and marking it as read
|
|
29
|
+
- Simulates the time a human takes to read and comprehend a message
|
|
30
|
+
- Calculated based on message length using realistic reading speeds
|
|
31
|
+
|
|
32
|
+
2. Typing Delay: Time between generating a response and sending it
|
|
33
|
+
- Simulates the time a human takes to compose and type a response
|
|
34
|
+
- Calculated based on response length using realistic typing speeds
|
|
35
|
+
|
|
36
|
+
3. Send Delay: Brief final delay before message transmission
|
|
37
|
+
- Simulates the final review time before a human sends a message
|
|
38
|
+
- Random delay within configured bounds
|
|
39
|
+
|
|
40
|
+
These delays help prevent platform detection and account restrictions while
|
|
41
|
+
maintaining natural interaction timing. All delays support jitter (random variation)
|
|
42
|
+
to prevent detectable patterns.
|
|
43
|
+
|
|
44
|
+
Configuration Presets:
|
|
45
|
+
Use the class methods to create pre-configured instances optimized for specific use cases:
|
|
46
|
+
- development(): Fast iteration with delays disabled
|
|
47
|
+
- production(): Balanced configuration with delays enabled
|
|
48
|
+
- high_volume(): Optimized for throughput with balanced delays
|
|
49
|
+
- customer_service(): Professional timing with thoughtful delays
|
|
50
|
+
- minimal(): Bare minimum configuration with delays disabled
|
|
51
|
+
|
|
52
|
+
Examples:
|
|
53
|
+
>>> # Create a production configuration with default delay settings
|
|
54
|
+
>>> config = WhatsAppBotConfig.production()
|
|
55
|
+
|
|
56
|
+
>>> # Create a custom configuration with specific delay bounds
|
|
57
|
+
>>> config = WhatsAppBotConfig(
|
|
58
|
+
... enable_human_delays=True,
|
|
59
|
+
... min_read_delay_seconds=3.0,
|
|
60
|
+
... max_read_delay_seconds=20.0,
|
|
61
|
+
... min_typing_delay_seconds=5.0,
|
|
62
|
+
... max_typing_delay_seconds=60.0
|
|
63
|
+
... )
|
|
64
|
+
|
|
65
|
+
>>> # Override delay settings on an existing configuration
|
|
66
|
+
>>> prod_config = WhatsAppBotConfig.production()
|
|
67
|
+
>>> custom_config = prod_config.with_overrides(
|
|
68
|
+
... min_read_delay_seconds=5.0,
|
|
69
|
+
... max_typing_delay_seconds=90.0
|
|
70
|
+
... )
|
|
71
|
+
"""
|
|
12
72
|
|
|
13
73
|
# === Core Bot Behavior ===
|
|
14
74
|
typing_indicator: bool = Field(
|
|
@@ -85,6 +145,18 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
85
145
|
default=10.0, description="Threshold for logging slow responses"
|
|
86
146
|
)
|
|
87
147
|
|
|
148
|
+
# === Text-to-Speech (TTS) ===
|
|
149
|
+
speech_play_chance: float = Field(
|
|
150
|
+
default=0.0,
|
|
151
|
+
ge=0.0,
|
|
152
|
+
le=1.0,
|
|
153
|
+
description="Probability (0.0-1.0) of sending audio response instead of text",
|
|
154
|
+
)
|
|
155
|
+
speech_config: SpeechConfig | None = Field(
|
|
156
|
+
default=None,
|
|
157
|
+
description="Optional SpeechConfig for TTS provider customization",
|
|
158
|
+
)
|
|
159
|
+
|
|
88
160
|
# === Error Handling ===
|
|
89
161
|
retry_failed_messages: bool = Field(
|
|
90
162
|
default=True, description="Retry processing failed messages"
|
|
@@ -96,6 +168,56 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
96
168
|
default=1.0, description="Delay between retry attempts"
|
|
97
169
|
)
|
|
98
170
|
|
|
171
|
+
# === Human-Like Delays ===
|
|
172
|
+
enable_human_delays: bool = Field(
|
|
173
|
+
default=False,
|
|
174
|
+
description="Enable human-like delays for message processing to simulate realistic human behavior patterns",
|
|
175
|
+
)
|
|
176
|
+
min_read_delay_seconds: float = Field(
|
|
177
|
+
default=2.0,
|
|
178
|
+
ge=0.0,
|
|
179
|
+
description="Minimum delay before marking message as read (seconds). Simulates time to read incoming messages.",
|
|
180
|
+
)
|
|
181
|
+
max_read_delay_seconds: float = Field(
|
|
182
|
+
default=15.0,
|
|
183
|
+
ge=0.0,
|
|
184
|
+
description="Maximum delay before marking message as read (seconds). Prevents excessively long read delays.",
|
|
185
|
+
)
|
|
186
|
+
min_typing_delay_seconds: float = Field(
|
|
187
|
+
default=3.0,
|
|
188
|
+
ge=0.0,
|
|
189
|
+
description="Minimum delay before sending response (seconds). Simulates time to compose a response.",
|
|
190
|
+
)
|
|
191
|
+
max_typing_delay_seconds: float = Field(
|
|
192
|
+
default=45.0,
|
|
193
|
+
ge=0.0,
|
|
194
|
+
description="Maximum delay before sending response (seconds). Prevents excessively long typing delays.",
|
|
195
|
+
)
|
|
196
|
+
min_send_delay_seconds: float = Field(
|
|
197
|
+
default=0.5,
|
|
198
|
+
ge=0.0,
|
|
199
|
+
description="Minimum delay before message transmission (seconds). Simulates final message review time.",
|
|
200
|
+
)
|
|
201
|
+
max_send_delay_seconds: float = Field(
|
|
202
|
+
default=4.0,
|
|
203
|
+
ge=0.0,
|
|
204
|
+
description="Maximum delay before message transmission (seconds). Prevents excessively long send delays.",
|
|
205
|
+
)
|
|
206
|
+
enable_delay_jitter: bool = Field(
|
|
207
|
+
default=True,
|
|
208
|
+
description="Enable random variation (±20%) in delay calculations to prevent detectable patterns and simulate natural human behavior variability",
|
|
209
|
+
)
|
|
210
|
+
show_typing_during_delay: bool = Field(
|
|
211
|
+
default=True,
|
|
212
|
+
description="Show typing indicator during typing delays to provide visual feedback to users while the bot is 'composing' a response",
|
|
213
|
+
)
|
|
214
|
+
batch_read_compression_factor: float = Field(
|
|
215
|
+
default=0.7,
|
|
216
|
+
ge=0.1,
|
|
217
|
+
le=1.0,
|
|
218
|
+
description="Compression factor (0.1-1.0) applied to batch read delays. Lower values simulate faster batch reading (e.g., 0.7 = 30% faster than reading individually)",
|
|
219
|
+
)
|
|
220
|
+
|
|
99
221
|
# === Backward Compatibility (Deprecated) ===
|
|
100
222
|
# These are kept for backward compatibility but map to the simplified parameters
|
|
101
223
|
@property
|
|
@@ -153,6 +275,20 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
153
275
|
retry_failed_messages: bool | None = None,
|
|
154
276
|
max_retry_attempts: int | None = None,
|
|
155
277
|
retry_delay_seconds: float | None = None,
|
|
278
|
+
# Text-to-Speech
|
|
279
|
+
speech_play_chance: float | None = None,
|
|
280
|
+
speech_config: SpeechConfig | None = None,
|
|
281
|
+
# Human-Like Delays
|
|
282
|
+
enable_human_delays: bool | None = None,
|
|
283
|
+
min_read_delay_seconds: float | None = None,
|
|
284
|
+
max_read_delay_seconds: float | None = None,
|
|
285
|
+
min_typing_delay_seconds: float | None = None,
|
|
286
|
+
max_typing_delay_seconds: float | None = None,
|
|
287
|
+
min_send_delay_seconds: float | None = None,
|
|
288
|
+
max_send_delay_seconds: float | None = None,
|
|
289
|
+
enable_delay_jitter: bool | None = None,
|
|
290
|
+
show_typing_during_delay: bool | None = None,
|
|
291
|
+
batch_read_compression_factor: float | None = None,
|
|
156
292
|
) -> "WhatsAppBotConfig":
|
|
157
293
|
"""
|
|
158
294
|
Create a new configuration instance with specified parameters overridden.
|
|
@@ -191,6 +327,16 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
191
327
|
... base_config=hv_config,
|
|
192
328
|
... welcome_message="Welcome to our high-volume support!"
|
|
193
329
|
... )
|
|
330
|
+
|
|
331
|
+
>>> # Enable human-like delays with custom timing
|
|
332
|
+
>>> prod_config = WhatsAppBotConfig.production()
|
|
333
|
+
>>> natural_config = prod_config.with_overrides(
|
|
334
|
+
... enable_human_delays=True,
|
|
335
|
+
... min_read_delay_seconds=3.0,
|
|
336
|
+
... max_read_delay_seconds=20.0,
|
|
337
|
+
... min_typing_delay_seconds=5.0,
|
|
338
|
+
... max_typing_delay_seconds=60.0
|
|
339
|
+
... )
|
|
194
340
|
"""
|
|
195
341
|
# Determine starting configuration
|
|
196
342
|
if base_config is not None:
|
|
@@ -259,6 +405,34 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
259
405
|
if retry_delay_seconds is not None:
|
|
260
406
|
overrides["retry_delay_seconds"] = retry_delay_seconds
|
|
261
407
|
|
|
408
|
+
# Text-to-Speech
|
|
409
|
+
if speech_play_chance is not None:
|
|
410
|
+
overrides["speech_play_chance"] = speech_play_chance
|
|
411
|
+
if speech_config is not None:
|
|
412
|
+
overrides["speech_config"] = speech_config
|
|
413
|
+
|
|
414
|
+
# Human-Like Delays
|
|
415
|
+
if enable_human_delays is not None:
|
|
416
|
+
overrides["enable_human_delays"] = enable_human_delays
|
|
417
|
+
if min_read_delay_seconds is not None:
|
|
418
|
+
overrides["min_read_delay_seconds"] = min_read_delay_seconds
|
|
419
|
+
if max_read_delay_seconds is not None:
|
|
420
|
+
overrides["max_read_delay_seconds"] = max_read_delay_seconds
|
|
421
|
+
if min_typing_delay_seconds is not None:
|
|
422
|
+
overrides["min_typing_delay_seconds"] = min_typing_delay_seconds
|
|
423
|
+
if max_typing_delay_seconds is not None:
|
|
424
|
+
overrides["max_typing_delay_seconds"] = max_typing_delay_seconds
|
|
425
|
+
if min_send_delay_seconds is not None:
|
|
426
|
+
overrides["min_send_delay_seconds"] = min_send_delay_seconds
|
|
427
|
+
if max_send_delay_seconds is not None:
|
|
428
|
+
overrides["max_send_delay_seconds"] = max_send_delay_seconds
|
|
429
|
+
if enable_delay_jitter is not None:
|
|
430
|
+
overrides["enable_delay_jitter"] = enable_delay_jitter
|
|
431
|
+
if show_typing_during_delay is not None:
|
|
432
|
+
overrides["show_typing_during_delay"] = show_typing_during_delay
|
|
433
|
+
if batch_read_compression_factor is not None:
|
|
434
|
+
overrides["batch_read_compression_factor"] = batch_read_compression_factor
|
|
435
|
+
|
|
262
436
|
# Update configuration with overrides
|
|
263
437
|
current_config.update(overrides)
|
|
264
438
|
|
|
@@ -279,10 +453,22 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
279
453
|
Create a configuration optimized for development.
|
|
280
454
|
|
|
281
455
|
Features:
|
|
282
|
-
- Debug mode enabled
|
|
283
|
-
- Faster response times
|
|
284
|
-
- Lenient rate limiting
|
|
285
|
-
- Detailed logging
|
|
456
|
+
- Debug mode enabled for comprehensive logging
|
|
457
|
+
- Faster response times for quick iteration
|
|
458
|
+
- Lenient rate limiting (100 messages/minute)
|
|
459
|
+
- Detailed logging and performance tracking
|
|
460
|
+
- Human-like delays DISABLED for fast iteration and testing
|
|
461
|
+
- Fast batching (1s delay, 5s timeout)
|
|
462
|
+
|
|
463
|
+
Delay Settings:
|
|
464
|
+
- enable_human_delays: False (disabled for development speed)
|
|
465
|
+
|
|
466
|
+
Use this preset during development and testing when you need fast feedback
|
|
467
|
+
and don't want to wait for realistic human-like delays.
|
|
468
|
+
|
|
469
|
+
Example:
|
|
470
|
+
>>> config = WhatsAppBotConfig.development()
|
|
471
|
+
>>> bot = WhatsAppBot(agent=agent, provider=provider, config=config)
|
|
286
472
|
"""
|
|
287
473
|
return cls(
|
|
288
474
|
# Core behavior
|
|
@@ -306,6 +492,8 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
306
492
|
# Error handling
|
|
307
493
|
retry_failed_messages=True,
|
|
308
494
|
max_retry_attempts=2,
|
|
495
|
+
# Human-like delays (disabled for development)
|
|
496
|
+
enable_human_delays=False,
|
|
309
497
|
)
|
|
310
498
|
|
|
311
499
|
@classmethod
|
|
@@ -320,10 +508,29 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
320
508
|
Create a configuration optimized for production.
|
|
321
509
|
|
|
322
510
|
Features:
|
|
323
|
-
- Robust spam protection
|
|
324
|
-
- Efficient batching
|
|
325
|
-
- Conservative rate limiting
|
|
326
|
-
- Minimal debug output
|
|
511
|
+
- Robust spam protection (20 messages/minute limit)
|
|
512
|
+
- Efficient batching (10s delay, 60s timeout)
|
|
513
|
+
- Conservative rate limiting with 60s cooldown
|
|
514
|
+
- Minimal debug output for performance
|
|
515
|
+
- Human-like delays ENABLED with recommended baseline values
|
|
516
|
+
- Typing indicators shown during delays for user feedback
|
|
517
|
+
|
|
518
|
+
Delay Settings:
|
|
519
|
+
- enable_human_delays: True
|
|
520
|
+
- Read delays: 2.0s - 15.0s (simulates reading incoming messages)
|
|
521
|
+
- Typing delays: 3.0s - 45.0s (simulates composing responses)
|
|
522
|
+
- Send delays: 0.5s - 4.0s (simulates final review)
|
|
523
|
+
- Jitter enabled: ±20% random variation
|
|
524
|
+
- Typing indicator: Shown during typing delays
|
|
525
|
+
- Batch compression: 0.7x (30% faster batch reading)
|
|
526
|
+
|
|
527
|
+
These delay settings provide a good balance between natural behavior and
|
|
528
|
+
reasonable response times. They help prevent platform detection while
|
|
529
|
+
maintaining acceptable user experience.
|
|
530
|
+
|
|
531
|
+
Example:
|
|
532
|
+
>>> config = WhatsAppBotConfig.production()
|
|
533
|
+
>>> bot = WhatsAppBot(agent=agent, provider=provider, config=config)
|
|
327
534
|
"""
|
|
328
535
|
return cls(
|
|
329
536
|
# Core behavior
|
|
@@ -349,6 +556,17 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
349
556
|
retry_failed_messages=True,
|
|
350
557
|
max_retry_attempts=3,
|
|
351
558
|
retry_delay_seconds=1.0,
|
|
559
|
+
# Human-like delays (enabled with baseline values)
|
|
560
|
+
enable_human_delays=True,
|
|
561
|
+
min_read_delay_seconds=2.0,
|
|
562
|
+
max_read_delay_seconds=15.0,
|
|
563
|
+
min_typing_delay_seconds=3.0,
|
|
564
|
+
max_typing_delay_seconds=45.0,
|
|
565
|
+
min_send_delay_seconds=0.5,
|
|
566
|
+
max_send_delay_seconds=4.0,
|
|
567
|
+
enable_delay_jitter=True,
|
|
568
|
+
show_typing_during_delay=True,
|
|
569
|
+
batch_read_compression_factor=0.7,
|
|
352
570
|
)
|
|
353
571
|
|
|
354
572
|
@classmethod
|
|
@@ -362,10 +580,29 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
362
580
|
Create a configuration optimized for high-volume scenarios.
|
|
363
581
|
|
|
364
582
|
Features:
|
|
365
|
-
- Aggressive batching
|
|
366
|
-
- Strong rate limiting
|
|
367
|
-
- Fast processing
|
|
368
|
-
-
|
|
583
|
+
- Aggressive batching (1s delay, 10s timeout, up to 20 messages)
|
|
584
|
+
- Strong rate limiting (15 messages/minute, 120s cooldown)
|
|
585
|
+
- Fast processing with minimal overhead
|
|
586
|
+
- Typing indicators disabled for performance
|
|
587
|
+
- Human-like delays ENABLED with balanced timing optimized for throughput
|
|
588
|
+
|
|
589
|
+
Delay Settings:
|
|
590
|
+
- enable_human_delays: True
|
|
591
|
+
- Read delays: 1.5s - 12.0s (shorter for faster processing)
|
|
592
|
+
- Typing delays: 2.5s - 35.0s (shorter for faster responses)
|
|
593
|
+
- Send delays: 0.3s - 3.0s (shorter for faster transmission)
|
|
594
|
+
- Jitter enabled: ±20% random variation
|
|
595
|
+
- Typing indicator: DISABLED for performance
|
|
596
|
+
- Batch compression: 0.7x (30% faster batch reading)
|
|
597
|
+
|
|
598
|
+
These delay settings are optimized for high-volume scenarios where throughput
|
|
599
|
+
is important but you still want to maintain natural behavior patterns to
|
|
600
|
+
prevent platform detection. Delays are shorter than production but still
|
|
601
|
+
provide realistic timing.
|
|
602
|
+
|
|
603
|
+
Example:
|
|
604
|
+
>>> config = WhatsAppBotConfig.high_volume()
|
|
605
|
+
>>> bot = WhatsAppBot(agent=agent, provider=provider, config=config)
|
|
369
606
|
"""
|
|
370
607
|
return cls(
|
|
371
608
|
# Fast core behavior
|
|
@@ -390,6 +627,17 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
390
627
|
retry_failed_messages=True,
|
|
391
628
|
max_retry_attempts=2, # Fewer retries
|
|
392
629
|
retry_delay_seconds=0.5, # Faster retries
|
|
630
|
+
# Human-like delays (enabled with balanced timing)
|
|
631
|
+
enable_human_delays=True,
|
|
632
|
+
min_read_delay_seconds=1.5,
|
|
633
|
+
max_read_delay_seconds=12.0,
|
|
634
|
+
min_typing_delay_seconds=2.5,
|
|
635
|
+
max_typing_delay_seconds=35.0,
|
|
636
|
+
min_send_delay_seconds=0.3,
|
|
637
|
+
max_send_delay_seconds=3.0,
|
|
638
|
+
enable_delay_jitter=True,
|
|
639
|
+
show_typing_during_delay=False, # Disabled for performance
|
|
640
|
+
batch_read_compression_factor=0.7,
|
|
393
641
|
)
|
|
394
642
|
|
|
395
643
|
@classmethod
|
|
@@ -404,10 +652,30 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
404
652
|
Create a configuration optimized for customer service.
|
|
405
653
|
|
|
406
654
|
Features:
|
|
407
|
-
- Message quoting for context
|
|
408
|
-
- Moderate batching
|
|
409
|
-
- Professional response times
|
|
410
|
-
- Welcome message
|
|
655
|
+
- Message quoting enabled for conversation context
|
|
656
|
+
- Moderate batching (5s delay, 20s timeout, up to 8 messages)
|
|
657
|
+
- Professional response times with thoughtful delays
|
|
658
|
+
- Welcome message for first-time users
|
|
659
|
+
- Human-like delays ENABLED with thoughtful, professional timing
|
|
660
|
+
- Typing indicators shown for premium user experience
|
|
661
|
+
|
|
662
|
+
Delay Settings:
|
|
663
|
+
- enable_human_delays: True
|
|
664
|
+
- Read delays: 5.0s - 30.0s (longer for thoughtful reading)
|
|
665
|
+
- Typing delays: 10.0s - 90.0s (longer for careful composition)
|
|
666
|
+
- Send delays: 1.0s - 5.0s (longer for final review)
|
|
667
|
+
- Jitter enabled: ±20% random variation
|
|
668
|
+
- Typing indicator: Shown during typing delays
|
|
669
|
+
- Batch compression: 0.7x (30% faster batch reading)
|
|
670
|
+
|
|
671
|
+
These delay settings are optimized for customer service scenarios where
|
|
672
|
+
users expect thoughtful, professional responses. Longer delays give the
|
|
673
|
+
impression of careful consideration and attention to detail, which can
|
|
674
|
+
improve perceived service quality.
|
|
675
|
+
|
|
676
|
+
Example:
|
|
677
|
+
>>> config = WhatsAppBotConfig.customer_service()
|
|
678
|
+
>>> bot = WhatsAppBot(agent=agent, provider=provider, config=config)
|
|
411
679
|
"""
|
|
412
680
|
return cls(
|
|
413
681
|
# Professional behavior
|
|
@@ -436,6 +704,17 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
436
704
|
# Custom error message for customer service
|
|
437
705
|
error_message=support_hours_message
|
|
438
706
|
or "I apologize for the inconvenience. Please try again, or contact our support team if the issue persists.",
|
|
707
|
+
# Human-like delays (enabled with thoughtful timing)
|
|
708
|
+
enable_human_delays=True,
|
|
709
|
+
min_read_delay_seconds=5.0,
|
|
710
|
+
max_read_delay_seconds=30.0,
|
|
711
|
+
min_typing_delay_seconds=10.0,
|
|
712
|
+
max_typing_delay_seconds=90.0,
|
|
713
|
+
min_send_delay_seconds=1.0,
|
|
714
|
+
max_send_delay_seconds=5.0,
|
|
715
|
+
enable_delay_jitter=True,
|
|
716
|
+
show_typing_during_delay=True,
|
|
717
|
+
batch_read_compression_factor=0.7,
|
|
439
718
|
)
|
|
440
719
|
|
|
441
720
|
@classmethod
|
|
@@ -448,10 +727,25 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
448
727
|
Create a minimal configuration with basic functionality.
|
|
449
728
|
|
|
450
729
|
Features:
|
|
451
|
-
- No batching
|
|
730
|
+
- No batching for immediate processing
|
|
452
731
|
- No spam protection
|
|
453
|
-
- Immediate responses
|
|
454
|
-
- Minimal overhead
|
|
732
|
+
- Immediate responses with no delays
|
|
733
|
+
- Minimal overhead and resource usage
|
|
734
|
+
- Human-like delays DISABLED for minimal configuration
|
|
735
|
+
- No typing indicators
|
|
736
|
+
- No retry logic
|
|
737
|
+
|
|
738
|
+
Delay Settings:
|
|
739
|
+
- enable_human_delays: False (disabled for minimal overhead)
|
|
740
|
+
|
|
741
|
+
This preset provides the absolute minimum configuration with no delays,
|
|
742
|
+
batching, or spam protection. Use this only when you need the fastest
|
|
743
|
+
possible responses and don't care about natural behavior patterns or
|
|
744
|
+
platform detection.
|
|
745
|
+
|
|
746
|
+
Example:
|
|
747
|
+
>>> config = WhatsAppBotConfig.minimal()
|
|
748
|
+
>>> bot = WhatsAppBot(agent=agent, provider=provider, config=config)
|
|
455
749
|
"""
|
|
456
750
|
return cls(
|
|
457
751
|
# Basic behavior
|
|
@@ -469,14 +763,36 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
469
763
|
# Basic error handling
|
|
470
764
|
retry_failed_messages=False,
|
|
471
765
|
max_retry_attempts=1,
|
|
766
|
+
# Human-like delays (disabled for minimal overhead)
|
|
767
|
+
enable_human_delays=False,
|
|
472
768
|
)
|
|
473
769
|
|
|
474
770
|
def validate_config(self) -> list[str]:
|
|
475
771
|
"""
|
|
476
772
|
Validate configuration and return list of warnings/issues.
|
|
477
773
|
|
|
774
|
+
This method performs comprehensive validation of all configuration parameters,
|
|
775
|
+
including timing conflicts, rate limiting settings, retry configuration, and
|
|
776
|
+
human-like delay parameters.
|
|
777
|
+
|
|
778
|
+
Delay Validation:
|
|
779
|
+
When human-like delays are enabled, this method validates:
|
|
780
|
+
- All minimum delay values are non-negative (>= 0.0)
|
|
781
|
+
- All maximum delay values are >= their corresponding minimum values
|
|
782
|
+
- Batch read compression factor is between 0.1 and 1.0
|
|
783
|
+
|
|
478
784
|
Returns:
|
|
479
|
-
List of validation messages (empty if
|
|
785
|
+
List of validation messages (empty if configuration is valid).
|
|
786
|
+
Each message describes a specific configuration issue or warning.
|
|
787
|
+
|
|
788
|
+
Example:
|
|
789
|
+
>>> config = WhatsAppBotConfig.production()
|
|
790
|
+
>>> issues = config.validate_config()
|
|
791
|
+
>>> if issues:
|
|
792
|
+
... for issue in issues:
|
|
793
|
+
... print(f"Warning: {issue}")
|
|
794
|
+
... else:
|
|
795
|
+
... print("Configuration is valid")
|
|
480
796
|
"""
|
|
481
797
|
issues = []
|
|
482
798
|
|
|
@@ -519,6 +835,44 @@ class WhatsAppBotConfig(BaseModel):
|
|
|
519
835
|
+ "Messages will be truncated."
|
|
520
836
|
)
|
|
521
837
|
|
|
838
|
+
# Check human-like delay configuration
|
|
839
|
+
if self.enable_human_delays:
|
|
840
|
+
# Validate read delays
|
|
841
|
+
if self.min_read_delay_seconds < 0.0:
|
|
842
|
+
issues.append(
|
|
843
|
+
f"min_read_delay_seconds ({self.min_read_delay_seconds}) must be non-negative (>= 0.0)."
|
|
844
|
+
)
|
|
845
|
+
if self.max_read_delay_seconds < self.min_read_delay_seconds:
|
|
846
|
+
issues.append(
|
|
847
|
+
f"max_read_delay_seconds ({self.max_read_delay_seconds}) must be >= min_read_delay_seconds ({self.min_read_delay_seconds})."
|
|
848
|
+
)
|
|
849
|
+
|
|
850
|
+
# Validate typing delays
|
|
851
|
+
if self.min_typing_delay_seconds < 0.0:
|
|
852
|
+
issues.append(
|
|
853
|
+
f"min_typing_delay_seconds ({self.min_typing_delay_seconds}) must be non-negative (>= 0.0)."
|
|
854
|
+
)
|
|
855
|
+
if self.max_typing_delay_seconds < self.min_typing_delay_seconds:
|
|
856
|
+
issues.append(
|
|
857
|
+
f"max_typing_delay_seconds ({self.max_typing_delay_seconds}) must be >= min_typing_delay_seconds ({self.min_typing_delay_seconds})."
|
|
858
|
+
)
|
|
859
|
+
|
|
860
|
+
# Validate send delays
|
|
861
|
+
if self.min_send_delay_seconds < 0.0:
|
|
862
|
+
issues.append(
|
|
863
|
+
f"min_send_delay_seconds ({self.min_send_delay_seconds}) must be non-negative (>= 0.0)."
|
|
864
|
+
)
|
|
865
|
+
if self.max_send_delay_seconds < self.min_send_delay_seconds:
|
|
866
|
+
issues.append(
|
|
867
|
+
f"max_send_delay_seconds ({self.max_send_delay_seconds}) must be >= min_send_delay_seconds ({self.min_send_delay_seconds})."
|
|
868
|
+
)
|
|
869
|
+
|
|
870
|
+
# Validate batch read compression factor
|
|
871
|
+
if not (0.1 <= self.batch_read_compression_factor <= 1.0):
|
|
872
|
+
issues.append(
|
|
873
|
+
f"batch_read_compression_factor ({self.batch_read_compression_factor}) must be between 0.1 and 1.0."
|
|
874
|
+
)
|
|
875
|
+
|
|
522
876
|
return issues
|
|
523
877
|
|
|
524
878
|
def __str__(self) -> 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
|
+
)
|
|
@@ -83,4 +83,8 @@ class WhatsAppWebhookPayload(BaseModel):
|
|
|
83
83
|
|
|
84
84
|
key = self.data.key
|
|
85
85
|
if "@lid" in key.remoteJid:
|
|
86
|
-
self.phone_number_id = key.remoteJidAlt.split(
|
|
86
|
+
self.phone_number_id = key.remoteJidAlt.split("@")[0]
|
|
87
|
+
self.data.key.remoteJid = key.remoteJidAlt
|
|
88
|
+
return
|
|
89
|
+
|
|
90
|
+
self.phone_number_id = key.remoteJid.split("@")[0]
|
|
@@ -81,6 +81,46 @@ class WhatsAppProvider(abc.ABC):
|
|
|
81
81
|
"""
|
|
82
82
|
pass
|
|
83
83
|
|
|
84
|
+
@abstractmethod
|
|
85
|
+
async def send_audio_message(
|
|
86
|
+
self,
|
|
87
|
+
to: str,
|
|
88
|
+
audio_base64: str,
|
|
89
|
+
quoted_message_id: str | None = None,
|
|
90
|
+
) -> WhatsAppMediaMessage:
|
|
91
|
+
"""
|
|
92
|
+
Send an audio message (optimized for voice/TTS).
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
to: Recipient phone number
|
|
96
|
+
audio_base64: Base64-encoded audio data
|
|
97
|
+
quoted_message_id: Optional ID of message to quote/reply to
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
The sent audio message
|
|
101
|
+
"""
|
|
102
|
+
pass
|
|
103
|
+
|
|
104
|
+
@abstractmethod
|
|
105
|
+
async def send_audio_message_by_url(
|
|
106
|
+
self,
|
|
107
|
+
to: str,
|
|
108
|
+
audio_url: str,
|
|
109
|
+
quoted_message_id: str | None = None,
|
|
110
|
+
) -> WhatsAppMediaMessage:
|
|
111
|
+
"""
|
|
112
|
+
Send an audio message via URL.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
to: Recipient phone number
|
|
116
|
+
audio_url: URL of the audio file
|
|
117
|
+
quoted_message_id: Optional ID of message to quote/reply to
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
The sent audio message
|
|
121
|
+
"""
|
|
122
|
+
pass
|
|
123
|
+
|
|
84
124
|
@abstractmethod
|
|
85
125
|
async def send_typing_indicator(self, to: str, duration: int = 3) -> None:
|
|
86
126
|
"""
|
|
@@ -92,6 +132,17 @@ class WhatsAppProvider(abc.ABC):
|
|
|
92
132
|
"""
|
|
93
133
|
pass
|
|
94
134
|
|
|
135
|
+
@abstractmethod
|
|
136
|
+
async def send_recording_indicator(self, to: str, duration: int = 3) -> None:
|
|
137
|
+
"""
|
|
138
|
+
Send recording indicator to show the bot is recording audio.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
to: Recipient phone number
|
|
142
|
+
duration: Duration in seconds to show recording
|
|
143
|
+
"""
|
|
144
|
+
pass
|
|
145
|
+
|
|
95
146
|
@abstractmethod
|
|
96
147
|
async def mark_message_as_read(self, message_id: str) -> None:
|
|
97
148
|
"""Mark a message as read."""
|