agentle 0.9.23__py3-none-any.whl → 0.9.25__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.
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  import datetime
4
4
  import logging
5
5
  import uuid
6
- from collections.abc import AsyncIterator
6
+ from collections.abc import AsyncGenerator, AsyncIterator
7
7
  from logging import Logger
8
8
  from typing import TYPE_CHECKING, Any, Literal, cast, overload
9
9
 
@@ -88,11 +88,11 @@ class GenerateGenerateContentResponseToGenerationAdapter[T](
88
88
  @overload
89
89
  def adapt(
90
90
  self, _f: AsyncIterator["GenerateContentResponse"]
91
- ) -> AsyncIterator[Generation[T]]: ...
91
+ ) -> AsyncGenerator[Generation[T], None]: ...
92
92
 
93
93
  def adapt(
94
94
  self, _f: "GenerateContentResponse | AsyncIterator[GenerateContentResponse]"
95
- ) -> Generation[T] | AsyncIterator[Generation[T]]:
95
+ ) -> Generation[T] | AsyncGenerator[Generation[T], None]:
96
96
  """
97
97
  Convert Google response(s) to Agentle Generation object(s).
98
98
 
@@ -214,7 +214,7 @@ class GenerateGenerateContentResponseToGenerationAdapter[T](
214
214
 
215
215
  async def _adapt_streaming(
216
216
  self, response_stream: AsyncIterator["GenerateContentResponse"]
217
- ) -> AsyncIterator[Generation[T]]:
217
+ ) -> AsyncGenerator[Generation[T], None]:
218
218
  """Adapt a streaming response with proper text accumulation."""
219
219
  generation_id = self.preferred_id or uuid.uuid4()
220
220
  created_time = datetime.datetime.now()
@@ -21,8 +21,6 @@ def parse_streaming_json[T: BaseModel](potential_json: str | None, model: type[T
21
21
  if potential_json is None:
22
22
  return model()
23
23
 
24
- # print(f"parsing: {potential_json}")
25
-
26
24
  def find_json_boundaries(text: str) -> tuple[int, int]:
27
25
  """Find the start and potential end of JSON in the text."""
28
26
 
@@ -95,17 +93,32 @@ def parse_streaming_json[T: BaseModel](potential_json: str | None, model: type[T
95
93
  # Remove any leading/trailing whitespace
96
94
  json_str = json_str.strip()
97
95
 
98
- # Fix missing closing quotes on string values (at the end)
99
- # Look for patterns like: "key": "value without closing quote
100
- json_str = re.sub(r':\s*"([^"]*?)(?:\s*[,}]|$)', r': "\1"', json_str)
101
-
102
- # Fix missing closing quotes for keys
103
- # Look for patterns like: "key without quotes:
104
- json_str = re.sub(r'"([^"]*?)(?=\s*:)', r'"\1"', json_str)
105
-
106
96
  # Remove trailing commas before closing braces/brackets
107
97
  json_str = re.sub(r",\s*([}\]])", r"\1", json_str)
108
98
 
99
+ # For streaming JSON, we need to handle incomplete strings carefully
100
+ # Check if we have an unclosed string at the end
101
+ in_string = False
102
+ escape_next = False
103
+ last_quote_pos = -1
104
+
105
+ for i, char in enumerate(json_str):
106
+ if escape_next:
107
+ escape_next = False
108
+ continue
109
+ if char == '\\':
110
+ escape_next = True
111
+ continue
112
+ if char == '"':
113
+ in_string = not in_string
114
+ if in_string:
115
+ last_quote_pos = i
116
+
117
+ # If we're in a string at the end (incomplete), close it properly
118
+ if in_string and last_quote_pos != -1:
119
+ # Add closing quote for the incomplete string
120
+ json_str += '"'
121
+
109
122
  # Ensure the JSON has proper closing braces if it appears incomplete
110
123
  open_braces = json_str.count("{") - json_str.count("}")
111
124
  open_brackets = json_str.count("[") - json_str.count("]")
@@ -124,12 +137,25 @@ def parse_streaming_json[T: BaseModel](potential_json: str | None, model: type[T
124
137
  data = {}
125
138
 
126
139
  # Extract string key-value pairs with quoted keys
127
- # Pattern: "key": "value" or 'key': 'value'
128
- string_pattern = r'["\']([^"\']+)["\']:\s*["\']([^"\']*)["\']?'
129
- string_matches = re.findall(string_pattern, json_str)
140
+ # IMPROVED: Handle long strings that may contain newlines, special chars, etc.
141
+ # Pattern: "key": "value..." - capture everything until the next unescaped quote or EOF
142
+ string_pattern = r'["\']([\w]+)["\']:\s*["\']([^"\']*?)(?:["\']|$)'
143
+ string_matches = re.findall(string_pattern, json_str, re.DOTALL)
144
+
145
+ # Also try to capture very long strings that span multiple lines
146
+ # This catches incomplete strings during streaming
147
+ long_string_pattern = r'["\']([\w_]+)["\']:\s*["\'](.+?)(?:["\'],?\s*["}]|$)'
148
+ long_matches = re.findall(long_string_pattern, json_str, re.DOTALL)
130
149
 
131
150
  for key, value in string_matches:
132
151
  data[key] = value
152
+
153
+ # Prefer long_matches for fields that might be truncated in string_matches
154
+ for key, value in long_matches:
155
+ # Only override if the long match has more content
156
+ existing = data.get(key, "")
157
+ if key not in data or (isinstance(existing, str) and len(value) > len(existing)):
158
+ data[key] = value
133
159
 
134
160
  # Extract string key-value pairs with unquoted keys
135
161
  # Pattern: key: "value" (no quotes around key)
agentle/web/extractor.py CHANGED
@@ -1,11 +1,13 @@
1
- from rsb.coroutines.run_sync import run_sync
2
1
  from collections.abc import Sequence
3
2
  from textwrap import dedent
4
3
 
5
4
  from html_to_markdown import convert
6
5
  from playwright.async_api import Geolocation, ViewportSize
6
+ from rsb.coroutines.run_sync import run_sync
7
7
  from rsb.models import Field
8
8
  from rsb.models.base_model import BaseModel
9
+ from rsb.models.config_dict import ConfigDict
10
+
9
11
  from agentle.generations.models.generation.generation import Generation
10
12
  from agentle.generations.providers.base.generation_provider import GenerationProvider
11
13
  from agentle.prompts.models.prompt import Prompt
@@ -60,6 +62,8 @@ class Extractor(BaseModel):
60
62
  model: str | None = Field(default=None)
61
63
  max_output_tokens: int | None = Field(default=None)
62
64
 
65
+ model_config = ConfigDict(arbitrary_types_allowed=True)
66
+
63
67
  def extract[T: BaseModel](
64
68
  self,
65
69
  urls: Sequence[str],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentle
3
- Version: 0.9.23
3
+ Version: 0.9.25
4
4
  Summary: ...
5
5
  Author-email: Arthur Brenno <64020210+arthurbrenno@users.noreply.github.com>
6
6
  License-File: LICENSE
@@ -1,13 +1,13 @@
1
1
  agentle/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  agentle/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  agentle/agents/__init__.py,sha256=Y_Vh4954BlEehGOufH79lCvWlgDaVPN6TF9bo4OXioY,10
4
- agentle/agents/agent.py,sha256=jNMLHAQy8Ywv9ZXGzKkLP3uvcSyO3brDoYZxRipBCPw,205204
4
+ agentle/agents/agent.py,sha256=e5tiq87bBfGI8gp5FU8mIVlxEs81GUpg-JTkptA0EeU,213449
5
5
  agentle/agents/agent_config.py,sha256=tkssVo-cmldiQ6rDDkJ2xeK5NRIG3F-NgVhlXZGwCbM,4555
6
6
  agentle/agents/agent_config_dict.py,sha256=BzGyKdm0Hv86P0_r7xzK4HtzNVdwM0HtrtuDVCSGbI8,2813
7
7
  agentle/agents/agent_input.py,sha256=qckT3_pOGHclT8UViOjUeKCuGo0qigB_h6tYxOtwTXs,1447
8
8
  agentle/agents/agent_pipeline.py,sha256=YJAMoHUfcChiwYLwe_vTXaS2QCkgq3DAThsjb0WxA_A,17160
9
9
  agentle/agents/agent_protocol.py,sha256=7UTKSLwoM37zgWNWZxSPgEpBctPAxA4Zqiz4qiq6yCM,771
10
- agentle/agents/agent_run_output.py,sha256=O2WcdJW9rEBiQGvMAoTTpfiRtHQpOHWLkapWTEHeSE0,22419
10
+ agentle/agents/agent_run_output.py,sha256=UsFT48FsPlzWT8aQgNfajkt7IjXBbugI9EbRaXQ40tA,22669
11
11
  agentle/agents/agent_team.py,sha256=bUQzLMhOp2UXmj1XhevqB0ZBqqzkhrTAUNV3BwSv7hc,30193
12
12
  agentle/agents/context.py,sha256=ap8gSTqiBvYGrAegPOE5O2rz_dWPbiAgOJ5uahi1e0M,16391
13
13
  agentle/agents/context_state.py,sha256=4EMxfuRvmAkNbH1ImdoP7MDFQSm9NYORsaCSaAicus0,135
@@ -136,9 +136,10 @@ agentle/agents/templates/data_collection/progressive_profilling_agent.py,sha256=
136
136
  agentle/agents/ui/__init__.py,sha256=IjHRV0k2DNwvFrEHebmsXiBvmITE8nQUnsR07h9tVkU,7
137
137
  agentle/agents/ui/streamlit.py,sha256=9afICL0cxtG1o2pWh6vH39-NdKiVfADKiXo405F2aB0,42829
138
138
  agentle/agents/whatsapp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
139
- agentle/agents/whatsapp/whatsapp_bot.py,sha256=qaL-PDisEWQOKKf8TmbAnQlIxbnZo4Bq8hgyjFUy-g0,135345
139
+ agentle/agents/whatsapp/human_delay_calculator.py,sha256=BGCDeoNTPsMn4d_QYmG0BWGCG8SiUJC6Fk295ulAsAk,18268
140
+ agentle/agents/whatsapp/whatsapp_bot.py,sha256=D51UD2Wbi47RKgxUU8J7iWsxNMqV99Rzujz6TV1DjGw,160179
140
141
  agentle/agents/whatsapp/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
141
- agentle/agents/whatsapp/models/audio_message.py,sha256=Cb4uYi4O4ANam8NGZkKVjwsrl8nCeuaHVwV9RvqvE8M,2656
142
+ agentle/agents/whatsapp/models/audio_message.py,sha256=kUqG1HdNW6DCYD-CqscJ6WHlAyv9ufmTSKMdjio9XWk,2705
142
143
  agentle/agents/whatsapp/models/context_info.py,sha256=sk80KuNE36S6VRnLh7n6UXmzZCXIB4E4lNxnRyVizg8,563
143
144
  agentle/agents/whatsapp/models/data.py,sha256=iertlmc2zbzjuIdTubkO-4RuwB0ni1qx7UvvW7Dlhuo,1245
144
145
  agentle/agents/whatsapp/models/device_list_metadata.py,sha256=Nki7esmgi9Zq70L2t4yjJH77clvaljStchVGrXiDlbU,808
@@ -151,7 +152,7 @@ agentle/agents/whatsapp/models/message_context_info.py,sha256=msCSuu8uMN3G9GDaXd
151
152
  agentle/agents/whatsapp/models/quoted_message.py,sha256=QC4sp7eLPE9g9i-_f3avb0sDO7gKpkzZR2qkbxqptts,1073
152
153
  agentle/agents/whatsapp/models/video_message.py,sha256=-wujSwdYaE3tst7K_rUYCvx6v4lySTW1JZ5burF6slg,3422
153
154
  agentle/agents/whatsapp/models/whatsapp_audio_message.py,sha256=AAcnjzJC1O5VjyWZaSWpG_tmZFc2-CdcPn9abjyLrpc,378
154
- agentle/agents/whatsapp/models/whatsapp_bot_config.py,sha256=yLRGwu8pE5PVQmWH0VSjOoCteKfURKdyeNnPlYhniOs,20945
155
+ agentle/agents/whatsapp/models/whatsapp_bot_config.py,sha256=hkbOAdSZbSt634mZEARuPQSer7wf3biL7dL9TFW-a7o,37164
155
156
  agentle/agents/whatsapp/models/whatsapp_contact.py,sha256=6iO6xmFs7z9hd1N9kZzGyNHYvCaUoCHn3Yi1DAJN4YU,240
156
157
  agentle/agents/whatsapp/models/whatsapp_document_message.py,sha256=ECM_hXF-3IbC9itbtZI0eA_XRNXFVefw9Mr-Lo_lrH0,323
157
158
  agentle/agents/whatsapp/models/whatsapp_image_message.py,sha256=xOAPRRSgqj9gQ2ZZOGdFWfOgtmNpE1W8mIUAmB5YTpo,314
@@ -177,6 +178,15 @@ agentle/agents/whatsapp/providers/twilio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5
177
178
  agentle/agents/whatsapp/providers/twilio/twilio_api_config.py,sha256=Xd9Ui5w3eAMfB12zJb_uQfzMFN5Gbx1Dgz7OIlUk0Yo,1580
178
179
  agentle/agents/whatsapp/providers/twilio/twilio_api_provider.py,sha256=7QbHEuQGozNVTf8xpxOR5RkYeA3om60nUlYbB4zmn5Y,29250
179
180
  agentle/agents/whatsapp/providers/twilio/twilio_webhook_parser.py,sha256=j9KCOZlbv9horcaFeQJ9fM9bGOr1YWsGqBWGuIhkFqY,10274
181
+ agentle/agents/whatsapp/v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
182
+ agentle/agents/whatsapp/v2/batch_processor_manager.py,sha256=2cwnFSstbfgIVdlHeMyf5qAr4fEQx_V7Jlt_4O5scWA,55
183
+ agentle/agents/whatsapp/v2/bot_config.py,sha256=eRuDZgrb5EvnRUh8qWSOcyoWZfjOZ2dTEAWZtdHCYVc,7705
184
+ agentle/agents/whatsapp/v2/in_memory_batch_processor_manager.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
185
+ agentle/agents/whatsapp/v2/message_limit.py,sha256=ea-ISLPNtm-jGsMLKF-gr0hQPDpB7HLqX7N5mh1WN28,199
186
+ agentle/agents/whatsapp/v2/payload.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
187
+ agentle/agents/whatsapp/v2/whatsapp_bot.py,sha256=B6wrsv7oJswATxsjvwgBLJxCpFjpgf9crzuhcLmmz8g,413
188
+ agentle/agents/whatsapp/v2/whatsapp_cloud_api_provider.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
189
+ agentle/agents/whatsapp/v2/whatsapp_provider.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
180
190
  agentle/autonomous_systems/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
181
191
  agentle/autonomous_systems/agent.py,sha256=tGrYTD4Rs4hgCF4mfHhjgMLPM0rNQZ5JACU_kA2cXe8,5078
182
192
  agentle/autonomous_systems/agent_input_type.py,sha256=mnzELBiKwgj0EYYM4U8GE50XRkys3m6ds_VR7aS-SGA,201
@@ -319,7 +329,7 @@ agentle/generations/providers/google/function_calling_config.py,sha256=5ZL1FDCfe
319
329
  agentle/generations/providers/google/google_generation_provider.py,sha256=9Dl8D7npzpHL7qwO7Mgqiu6fzmWzPh-7jfvB6ZuUdYI,25590
320
330
  agentle/generations/providers/google/adapters/__init__.py,sha256=sUwLR-CDzvWHn6hwqSsHYztws6DGx6ZiKp32vYeVMfk,1003
321
331
  agentle/generations/providers/google/adapters/agentle_tool_to_google_tool_adapter.py,sha256=XQM_aL5zVfrRbNwtO_lDwXqvT8iX83trDNbEPSjZLmI,28482
322
- agentle/generations/providers/google/adapters/generate_generate_content_response_to_generation_adapter.py,sha256=Z9v7c3NnnUFb-sqXQJHe_3ERb-o0eYzO_1JIGa2bRIM,17197
332
+ agentle/generations/providers/google/adapters/generate_generate_content_response_to_generation_adapter.py,sha256=akzh75PmFnRF3X4L0QmF-lRokOTB9PR0ZFBv7nPTB3A,17234
323
333
  agentle/generations/providers/google/adapters/google_content_to_generated_assistant_message_adapter.py,sha256=4sOcT9VLr58YfEnkOm392odhNzzmbTspnnmrz5K6bHc,7829
324
334
  agentle/generations/providers/google/adapters/google_part_to_part_adapter.py,sha256=infqHs_LVjpzIOipIVbRHQesXTKoOHVLiTUFaPhaBV8,6520
325
335
  agentle/generations/providers/google/adapters/message_to_google_content_adapter.py,sha256=sJ6MEn_R-KkLTEsNhxmKhBDbzlKwOUYqinydag6hqi4,6071
@@ -960,7 +970,7 @@ agentle/utils/file_validation.py,sha256=Rv6y_ylBrDoslscCk2lkfr3LRMarY0J8qWhKJjZj
960
970
  agentle/utils/fix_base64_padding.py,sha256=IWBlMP3FYcWs17Y72tVxG7w1lzEKnstaDC9HRKmI56Y,1109
961
971
  agentle/utils/make_fields_optional.py,sha256=pu2u-jJ1pNyoQRyGQzxwXnYbWSzZ2G4ssebJvjYsH8A,7800
962
972
  agentle/utils/needs.py,sha256=JRTVvgVP0w0bpq1_w2Jly2lxXiONdHOYAYMvReFQcJM,5110
963
- agentle/utils/parse_streaming_json.py,sha256=OTEfPhack0s-hgmYR2dNqTaE_SUG_bj9SbscjoIA96o,30710
973
+ agentle/utils/parse_streaming_json.py,sha256=9otgyfU37F-X9qbWHxgFmoYi9MSa9PPCarJ5CJ1Tcr0,31890
964
974
  agentle/utils/raise_error.py,sha256=EYX6WJS5gzJxgTyFYYOFHc-klEyU0tP20N5k_-ze5nQ,138
965
975
  agentle/utils/safe_b64decode.py,sha256=2nkdwUzkeVgtf3kb_zypjJY2KHe7dlLwa4ynjY2Yy1E,1272
966
976
  agentle/utils/safe_dill_dumps.py,sha256=yXQ51P05uSiWnREKJ6UWVjCKnRQTjgPVzoE1nylBbJI,237
@@ -993,7 +1003,7 @@ agentle/voice_cloning/voice_cloner.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
993
1003
  agentle/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
994
1004
  agentle/web/extraction_preferences.py,sha256=Xb4X6ZgnbDuu4Pp7cI0sdPcv6LaR1Q94FPTNEoHVTGg,985
995
1005
  agentle/web/extraction_result.py,sha256=IsbRdT_wA9RVYGToCiz17XRoWMTtiFzxky96Zwqa4ZY,318
996
- agentle/web/extractor.py,sha256=HIqag1SEfWoQ97iwn2fYOfhEpjC4OJXnkn_WSAUsMs0,10889
1006
+ agentle/web/extractor.py,sha256=x3KlbJkKSnTaUD9vAx3n2jev-PKgcAlnGJxBPOdwFoM,10997
997
1007
  agentle/web/location.py,sha256=RZgqb2rW7wUdcbw3PnmDtfr4FkTSSovW0j70ZOvoRiw,64
998
1008
  agentle/web/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
999
1009
  agentle/web/actions/action.py,sha256=krxW5vXaqB1_JfnPpuo5cVJyANrlElu9P0B0TrF_aZs,723
@@ -1007,7 +1017,7 @@ agentle/web/actions/scroll.py,sha256=WqVVAORNDK3BL1oASZBPmXJYeSVkPgAOmWA8ibYO82I
1007
1017
  agentle/web/actions/viewport.py,sha256=KCwm88Pri19Qc6GLHC69HsRxmdJz1gEEAODfggC_fHo,287
1008
1018
  agentle/web/actions/wait.py,sha256=IKEywjf-KC4ni9Gkkv4wgc7bY-hk7HwD4F-OFWlyf2w,571
1009
1019
  agentle/web/actions/write_text.py,sha256=9mxfHcpKs_L7BsDnJvOYHQwG8M0GWe61SRJAsKk3xQ8,748
1010
- agentle-0.9.23.dist-info/METADATA,sha256=OQxUrAm6kxfo2dh5nIh5rkJ2ZYconQ_QzC5D7AgSFqQ,86849
1011
- agentle-0.9.23.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
1012
- agentle-0.9.23.dist-info/licenses/LICENSE,sha256=T90S9vqRS6qP-voULxAcvwEs558wRRo6dHuZrjgcOUI,1085
1013
- agentle-0.9.23.dist-info/RECORD,,
1020
+ agentle-0.9.25.dist-info/METADATA,sha256=FQFBCmIzX4o197z2k9UyswQwuTBJOuAfRqEQelGDtwo,86849
1021
+ agentle-0.9.25.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
1022
+ agentle-0.9.25.dist-info/licenses/LICENSE,sha256=T90S9vqRS6qP-voULxAcvwEs558wRRo6dHuZrjgcOUI,1085
1023
+ agentle-0.9.25.dist-info/RECORD,,