agently 4.0.7__py3-none-any.whl → 4.0.7.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.
@@ -43,6 +43,7 @@ runtime:
43
43
  show_model_logs: False
44
44
  show_tool_logs: False
45
45
  show_trigger_flow_logs: False
46
+ httpx_log_level: "WARNING"
46
47
  plugins:
47
48
  ToolManager:
48
- activate: AgentlyToolManager
49
+ activate: AgentlyToolManager
agently/base.py CHANGED
@@ -12,6 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ import logging
15
16
  from typing import Any, Literal, Type, TYPE_CHECKING, TypeVar, Generic, cast
16
17
 
17
18
  from agently.utils import Settings, create_logger, FunctionShifter, DataFormatter
@@ -37,6 +38,10 @@ _hook_default_event_handlers(event_center)
37
38
  async_system_message = event_center.async_system_message
38
39
  system_message = event_center.system_message
39
40
  logger = create_logger()
41
+ httpx_level_name = settings.get("runtime.httpx_log_level", "WARNING")
42
+ httpx_level = getattr(logging, str(httpx_level_name).upper(), logging.WARNING)
43
+ logging.getLogger("httpx").setLevel(httpx_level)
44
+ logging.getLogger("httpcore").setLevel(httpx_level)
40
45
  tool = Tool(plugin_manager, settings)
41
46
  _agently_messenger = event_center.create_messenger("Agently")
42
47
 
@@ -70,11 +75,13 @@ settings.update_mappings(
70
75
  "runtime.show_model_logs": True,
71
76
  "runtime.show_tool_logs": True,
72
77
  "runtime.show_trigger_flow_logs": True,
78
+ "runtime.httpx_log_level": "INFO",
73
79
  },
74
80
  False: {
75
81
  "runtime.show_model_logs": False,
76
82
  "runtime.show_tool_logs": False,
77
83
  "runtime.show_trigger_flow_logs": False,
84
+ "runtime.httpx_log_level": "WARNING",
78
85
  },
79
86
  }
80
87
  }
@@ -117,7 +124,16 @@ class AgentlyMain(Generic[A]):
117
124
  self.tool = tool
118
125
  self.AgentType = AgentType
119
126
 
120
- self.set_settings = self.settings.set_settings
127
+ def set_settings(key: str, value: "SerializableValue", *, auto_load_env: bool = False):
128
+ self.settings.set_settings(key, value, auto_load_env=auto_load_env)
129
+ if key in ("runtime.httpx_log_level", "debug"):
130
+ level_name = self.settings.get("runtime.httpx_log_level", "WARNING")
131
+ level = getattr(logging, str(level_name).upper(), logging.WARNING)
132
+ logging.getLogger("httpx").setLevel(level)
133
+ logging.getLogger("httpcore").setLevel(level)
134
+ return self
135
+
136
+ self.set_settings = set_settings
121
137
 
122
138
  def set_debug_console(self, debug_console_status: Literal["ON", "OFF"]):
123
139
  match debug_console_status:
@@ -589,13 +589,29 @@ class AgentlyPromptGenerator(PromptGenerator):
589
589
  fields = {}
590
590
  validators = {}
591
591
 
592
- def ensure_list_and_cast(v: Any, target_type: type):
592
+ def ensure_list_and_cast(v: Any, target_type: Any):
593
593
  if not isinstance(v, list):
594
594
  v = [v]
595
- return [
596
- (target_type(item) if target_type is not Any and not isinstance(item, target_type) else item)
597
- for item in v
598
- ]
595
+ casted = []
596
+ for item in v:
597
+ if target_type is Any or not isinstance(target_type, type):
598
+ casted.append(item)
599
+ continue
600
+ target_type = cast(type, target_type)
601
+ if isinstance(item, target_type):
602
+ casted.append(item)
603
+ continue
604
+ if isinstance(item, Mapping):
605
+ model_validate = getattr(target_type, "model_validate", None)
606
+ if callable(model_validate):
607
+ casted.append(model_validate(item))
608
+ continue
609
+ parse_obj = getattr(target_type, "parse_obj", None)
610
+ if callable(parse_obj):
611
+ casted.append(parse_obj(item))
612
+ continue
613
+ casted.append(target_type(item))
614
+ return casted
599
615
 
600
616
  if isinstance(schema, Mapping):
601
617
  for field_name, field_type_schema in schema.items():
@@ -103,7 +103,7 @@ class Search:
103
103
  ] = "us-en",
104
104
  options: dict[str, Any] | None = None,
105
105
  ):
106
- LazyImport.import_package("ddgs")
106
+ LazyImport.import_package("ddgs", version_constraint=">=9.10.0")
107
107
  from ddgs import DDGS
108
108
 
109
109
  self.proxy = proxy
@@ -153,6 +153,11 @@ class ModelResponseResult:
153
153
  return await self._response_parser.async_get_data(type=type)
154
154
  return await self._response_parser.async_get_data(type=type)
155
155
 
156
+ @overload
157
+ async def async_get_data_object(
158
+ self,
159
+ ) -> "BaseModel | None": ...
160
+
156
161
  @overload
157
162
  async def async_get_data_object(
158
163
  self,
@@ -467,7 +472,7 @@ class ModelRequest:
467
472
  prompt: Any,
468
473
  mappings: dict[str, Any] | None = None,
469
474
  ):
470
- self.prompt.set("system", ["YOU MUST REACT AND RESPOND AS {system.role}!"])
475
+ self.prompt.set("system", ["YOU MUST REACT AND RESPOND AS {system.your_role}!"])
471
476
  self.prompt.set("system.your_role", prompt, mappings)
472
477
  return self
473
478
 
@@ -227,7 +227,7 @@ class TriggerFlow:
227
227
  self,
228
228
  initial_value: Any = None,
229
229
  *,
230
- timeout: int | None = 10,
230
+ timeout: float | None = 10.0,
231
231
  concurrency: int | None = None,
232
232
  ):
233
233
  execution = self.create_execution(concurrency=concurrency)
@@ -294,16 +294,20 @@ class TriggerFlowBaseProcess:
294
294
  chunk = self._flow_chunk(chunk_name)(chunk_func)
295
295
  else:
296
296
  chunk = self._flow_chunk(chunk.__name__)(chunk) if callable(chunk) else chunk
297
+ typed_chunk = cast(TriggerFlowChunk, chunk)
297
298
  triggers_to_wait[chunk.trigger] = False
298
299
  trigger_to_chunk_name[chunk.trigger] = chunk.name
299
300
  results[chunk.name] = None
300
301
 
301
302
  if semaphore is None:
302
- handler = chunk.async_call
303
+ handler = typed_chunk.async_call
303
304
  else:
304
- async def handler(data: "TriggerFlowEventData", _chunk=chunk):
305
- async with semaphore:
306
- return await _chunk.async_call(data)
305
+ def make_handler(bound_chunk: TriggerFlowChunk):
306
+ async def handler(data: "TriggerFlowEventData"):
307
+ async with semaphore:
308
+ return await bound_chunk.async_call(data)
309
+ return handler
310
+ handler = make_handler(typed_chunk)
307
311
 
308
312
  self._blue_print.add_handler(
309
313
  self.trigger_type,
@@ -56,15 +56,21 @@ class DataFormatter:
56
56
  if issubclass(value, BaseModel):
57
57
  extracted_value = {}
58
58
  for name, field in value.model_fields.items():
59
+ annotation = field.annotation
60
+ if hasattr(field, "rebuild_annotation"):
61
+ try:
62
+ annotation = field.rebuild_annotation()
63
+ except Exception:
64
+ annotation = field.annotation
59
65
  extracted_value.update(
60
66
  {
61
67
  name: (
62
68
  (
63
- DataFormatter.sanitize(field.annotation, remain_type=remain_type),
69
+ DataFormatter.sanitize(annotation, remain_type=remain_type),
64
70
  field.description,
65
71
  )
66
72
  if field.description
67
- else (DataFormatter.sanitize(field.annotation, remain_type=remain_type),)
73
+ else (DataFormatter.sanitize(annotation, remain_type=remain_type),)
68
74
  )
69
75
  }
70
76
  )
@@ -21,6 +21,101 @@ if TYPE_CHECKING:
21
21
 
22
22
 
23
23
  class DataLocator:
24
+ @staticmethod
25
+ def _locate_path_parts(
26
+ result: Any,
27
+ path_parts: list[str],
28
+ *,
29
+ style: Literal["dot", "slash"],
30
+ default: Any,
31
+ ):
32
+ if not path_parts:
33
+ return result
34
+ path_part = path_parts[0]
35
+ remaining = path_parts[1:]
36
+ if style == "dot":
37
+ if "[" in path_part:
38
+ path_key_and_index = path_part.split("[")
39
+ path_key = path_key_and_index[0]
40
+ path_index = path_key_and_index[1][:-1]
41
+ if isinstance(result, Mapping):
42
+ result = result.get(path_key, default)
43
+ else:
44
+ return default
45
+ if path_index in ("*", ""):
46
+ if not isinstance(result, str) and isinstance(result, Sequence):
47
+ values = []
48
+ for item in result:
49
+ value = DataLocator._locate_path_parts(
50
+ item,
51
+ remaining,
52
+ style=style,
53
+ default=default,
54
+ )
55
+ if value is default:
56
+ return default
57
+ values.append(value)
58
+ return values
59
+ return default
60
+ try:
61
+ index = int(path_index)
62
+ except Exception:
63
+ return default
64
+ if not isinstance(result, str) and isinstance(result, Sequence):
65
+ try:
66
+ return DataLocator._locate_path_parts(
67
+ result[index],
68
+ remaining,
69
+ style=style,
70
+ default=default,
71
+ )
72
+ except Exception:
73
+ return default
74
+ return default
75
+ else:
76
+ if isinstance(result, Mapping):
77
+ return DataLocator._locate_path_parts(
78
+ result.get(path_part, default),
79
+ remaining,
80
+ style=style,
81
+ default=default,
82
+ )
83
+ return default
84
+ else:
85
+ if path_part == "*":
86
+ if not isinstance(result, str) and isinstance(result, Sequence):
87
+ values = []
88
+ for item in result:
89
+ value = DataLocator._locate_path_parts(
90
+ item,
91
+ remaining,
92
+ style=style,
93
+ default=default,
94
+ )
95
+ if value is default:
96
+ return default
97
+ values.append(value)
98
+ return values
99
+ return default
100
+ if isinstance(result, Mapping):
101
+ return DataLocator._locate_path_parts(
102
+ result.get(path_part, default),
103
+ remaining,
104
+ style=style,
105
+ default=default,
106
+ )
107
+ if not isinstance(result, str) and isinstance(result, Sequence):
108
+ try:
109
+ return DataLocator._locate_path_parts(
110
+ result[int(path_part)],
111
+ remaining,
112
+ style=style,
113
+ default=default,
114
+ )
115
+ except Exception:
116
+ return default
117
+ return default
118
+
24
119
  @staticmethod
25
120
  def locate_path_in_dict(
26
121
  original_dict: dict,
@@ -34,42 +129,24 @@ class DataLocator:
34
129
  match style:
35
130
  case "dot":
36
131
  try:
37
- result = original_dict
38
132
  path_parts = path.split(".")
39
- for path_part in path_parts:
40
- if "[" in path_part:
41
- path_key_and_index = path_part.split("[")
42
- path_key = path_key_and_index[0]
43
- path_index = int(path_key_and_index[1][:-1])
44
- if isinstance(result, Mapping):
45
- result = result[path_key]
46
- else:
47
- return default
48
- if not isinstance(result, str) and isinstance(result, Sequence):
49
- result = result[path_index]
50
- else:
51
- return default
52
- else:
53
- if isinstance(result, Mapping):
54
- result = result[path_part]
55
- else:
56
- return default
57
- return result
133
+ return DataLocator._locate_path_parts(
134
+ original_dict,
135
+ path_parts,
136
+ style="dot",
137
+ default=default,
138
+ )
58
139
  except Exception:
59
140
  return default
60
141
  case "slash":
61
- result = original_dict
62
- path_parts = path.split("/")
63
142
  try:
64
- for path_part in path_parts:
65
- if path_part:
66
- if isinstance(result, Mapping):
67
- result = result[path_part]
68
- elif not isinstance(result, str) and isinstance(result, Sequence):
69
- result = result[int(path_part)]
70
- else:
71
- return default
72
- return result
143
+ path_parts = [part for part in path.split("/") if part]
144
+ return DataLocator._locate_path_parts(
145
+ original_dict,
146
+ path_parts,
147
+ style="slash",
148
+ default=default,
149
+ )
73
150
  except Exception:
74
151
  return default
75
152
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agently
3
- Version: 4.0.7
3
+ Version: 4.0.7.1
4
4
  Summary:
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
@@ -1,7 +1,7 @@
1
1
  agently/__init__.py,sha256=Gf0LL7Czqeuf6hfvHfEGlACLg0d0osQupyMATB0EBlc,884
2
2
  agently/_default_init.py,sha256=AhYwzZYOxqDeIoVb8cvPjJ2BjE5V7wxeuH7R-MNZWyg,2057
3
- agently/_default_settings.yaml,sha256=6woqJ2tjg_jl6kwSOwmTMETfVraHidort2smf0Is_qQ,1357
4
- agently/base.py,sha256=U92SWzoU7h7Gl92r8bEv-7wsGUPrUlxXyDohLX-2qCo,4629
3
+ agently/_default_settings.yaml,sha256=iyi82glfRk0-7d_n7FvuDjNDxBKGDbeaRA-GfHOW6tE,1387
4
+ agently/base.py,sha256=hc5ayuEQiL8Uus9NVrKFTIjyc73SwRKkdwfLFlNsmKo,5543
5
5
  agently/builtins/agent_extensions/AutoFuncExtension.py,sha256=TmwMazwPzb5WXfDqfedY5yZOOMTFIHqaB9Bte29adUc,2433
6
6
  agently/builtins/agent_extensions/ChatSessionExtension.py,sha256=Y6mvnsfAY0rykKtfp-tApwJy5O4SS-YEt2-jaWr83uc,12034
7
7
  agently/builtins/agent_extensions/ConfigurePromptExtension.py,sha256=9wy2zHIDVHbUlj5sI0A03SscUWSzZNc9hNJSEdXFXd0,11390
@@ -12,17 +12,17 @@ agently/builtins/hookers/ConsoleHooker.py,sha256=aJdDj_nG8CiwyelA505zvtpzBSwD52n
12
12
  agently/builtins/hookers/PureLoggerHooker.py,sha256=fzN0OfhQzgns4KeCNH-qcdm-BdQT0W2kqEmt3Zp2pYI,1906
13
13
  agently/builtins/hookers/SystemMessageHooker.py,sha256=1nh1FY70PYyZOAQGfQiGnwIvo4ZF3NSAjeghI3sInn4,7207
14
14
  agently/builtins/plugins/ModelRequester/OpenAICompatible.py,sha256=CFTMZHENOi6qsrUfWtgq19P6Ec7H-8vRybVVr4RZfJQ,26773
15
- agently/builtins/plugins/PromptGenerator/AgentlyPromptGenerator.py,sha256=GRRR9uxgyCXHKgt_r2BinWnhKy8rYUN8CG9ld2P8n4E,30841
15
+ agently/builtins/plugins/PromptGenerator/AgentlyPromptGenerator.py,sha256=9iJYOhVh060vpRJrxFF0BkMP3lAmDjgsl_AWM-dRRtE,31583
16
16
  agently/builtins/plugins/ResponseParser/AgentlyResponseParser.py,sha256=5iF6NLoMjTtEC3hc-DmatFmSWZK2nKkoiyqHK7Q3Yj4,17847
17
17
  agently/builtins/plugins/ToolManager/AgentlyToolManager.py,sha256=oaqte5LAryZQMD6vuEbKhe6kOLUyZTRZswC1MDFiYxw,9138
18
18
  agently/builtins/plugins/__init__.py,sha256=wj4_U9TTekc2CmjppbXKUREDFRXFX1y0ySOW-CxQuok,801
19
19
  agently/builtins/tools/Browse.py,sha256=gIePs-gtsqOI_ZTReGqEcoKvhs4FkBzTxow--QS5_ek,3469
20
- agently/builtins/tools/Search.py,sha256=tUynNiW_ZMAGaB2ua3HRcY_trIbLEoASFE-p2QMQ0Zg,7362
20
+ agently/builtins/tools/Search.py,sha256=GtlHppD5RelxMSFDchFD3jdVhaDndh6lZ3Lu9YH0OzM,7393
21
21
  agently/builtins/tools/__init__.py,sha256=pFOWgH2C3xRvgQo3UVdkj4yHjF9nNtmoVHmOZfoGsyU,647
22
22
  agently/core/Agent.py,sha256=LWkzWG_XXrC4oVkWg4ebnAqAJ81O9UEo1n-qJj7IIrc,10251
23
23
  agently/core/EventCenter.py,sha256=sknU5w9MpGDQgMOF9c5k4PfM4SNT5X_LrpYte2HaFNM,10861
24
24
  agently/core/ExtensionHandlers.py,sha256=88iSAW50bgMshB56cTgKg30eOjZQyXiJY1en4w7afWY,2076
25
- agently/core/ModelRequest.py,sha256=t9tnC0uON89MkuuRHPPOgk3xOLz6G953sInvKDMD00o,24526
25
+ agently/core/ModelRequest.py,sha256=tPuFl_v_P85Mhj669cA5Hi9zAfMNzB5jib8APIXh13s,24630
26
26
  agently/core/PluginManager.py,sha256=fwRxvqPMgXYIrclhRHtkaPsyvn6SaeBFqvL7tTzYwck,4410
27
27
  agently/core/Prompt.py,sha256=uvGGvbND08b0OhkD-UXY0J65yLedllBt4lMqk4NYl1U,6893
28
28
  agently/core/Tool.py,sha256=PNYf_BwVefr8IOqf5asLaVq2fU7hQaFJwJVj3S4fq84,1871
@@ -30,9 +30,9 @@ agently/core/TriggerFlow/BluePrint.py,sha256=H_TYymWOci-ZvQzqyRxpkHjO77zlzXLukLU
30
30
  agently/core/TriggerFlow/Chunk.py,sha256=xPWr_ofpl-iG4jHIJfB5mPanmn70pq7x8GCcz3G8NPc,1583
31
31
  agently/core/TriggerFlow/Execution.py,sha256=EsiZOIeoflyQceRenK5uUL_maML3w7DKgamqlKBQCOE,12500
32
32
  agently/core/TriggerFlow/Process.py,sha256=doIDUa7x0j1TVuOhp-hraC0hHLwpistF-Dksf76NJvQ,837
33
- agently/core/TriggerFlow/TriggerFlow.py,sha256=1y2RmrCE5Ga7iMr67xGUBsTaXykKXIFHR3390deqo-k,8029
33
+ agently/core/TriggerFlow/TriggerFlow.py,sha256=nZfoxtOQocnHmx5hx15ZxK3F9ef-s_CfwRtXUmtwfys,8033
34
34
  agently/core/TriggerFlow/__init__.py,sha256=eHc6ldUIS0kka_1fZXkdaHFnSDoXaGSvXggwVszMAJQ,911
35
- agently/core/TriggerFlow/process/BaseProcess.py,sha256=lIr1kCgxwHxlReZp0-C3kS0wMkPtDbZ1UExI2fKbtOQ,15256
35
+ agently/core/TriggerFlow/process/BaseProcess.py,sha256=tBAMCI2Yd8Ylfi5CpkhlSVLH5Hra2Q_CgWg5LDqhGfo,15473
36
36
  agently/core/TriggerFlow/process/ForEachProcess.py,sha256=DD4frz9mTsKgnPXnHJD53hL6uiiU6h338p7ipud8zMU,4897
37
37
  agently/core/TriggerFlow/process/MatchCaseProcess.py,sha256=MKY5Yh66JiMABhCzamRl8UZOBjbD75TFp84Jw6o_t68,7900
38
38
  agently/core/TriggerFlow/process/__init__.py,sha256=BP5bAr9LRVVD83KFqXeprgTmXA1iCSOSsD509BtoX_E,753
@@ -55,8 +55,8 @@ agently/types/plugins/__init__.py,sha256=gz_EpgBQGndIQHY5vJB2YRzAN5yIb3FZZG7pC8l
55
55
  agently/types/plugins/base.py,sha256=AoNLwsH5IZBQt7_NZfxMWMhAk6PJSOFHR0IYOXp1imI,1167
56
56
  agently/types/trigger_flow/__init__.py,sha256=Gj31SmWBC4qtrOqQedyGsnCfeSkUf3XvZNFrJ2QbMNw,777
57
57
  agently/types/trigger_flow/trigger_flow.py,sha256=6lvhDwizIV5p3h61l1GsmJU_9Tw8v3u-SnHuygkSJdo,3799
58
- agently/utils/DataFormatter.py,sha256=qdPtLPIQs9eCZ-hPBphan5CcPrR7Nz8h8cb7zF8F1j0,12050
59
- agently/utils/DataLocator.py,sha256=ss8OLet9HN0U1PZb-OCHS6KL54kv7vFZph6G0-GBidk,6015
58
+ agently/utils/DataFormatter.py,sha256=D45eBlH9CTEs8xNWrDYw9pxUcNnCGVnm0_y97-VyMuU,12346
59
+ agently/utils/DataLocator.py,sha256=0TSMONLPYQVvdJftoXcW4BMhwGFl2JrovAGH3LTthn4,8652
60
60
  agently/utils/DataPathBuilder.py,sha256=sEzE1i2EWn7NMkCCXDT50gR6_qMzcZ0y0YGkYbXdB3s,10007
61
61
  agently/utils/FunctionShifter.py,sha256=quwugTmf-vzHzRR_2wdv14AxLpr0lwxdUtVoX7Jeq48,5839
62
62
  agently/utils/GeneratorConsumer.py,sha256=EXpz2XGnv6rPdz8bPetJu3LpWIVhMvIi8GLG1Bpe7Ys,7459
@@ -71,7 +71,7 @@ agently/utils/Storage.py,sha256=E7QyNJ9T0yOUafPgdP90La698hgLMSGjhJ7qCEHzxxw,9438
71
71
  agently/utils/StreamingJSONCompleter.py,sha256=aZ9zuGUTQlP-QKbXHUZCf6EtVuG49MKn8xdhw0VhDEA,4292
72
72
  agently/utils/StreamingJSONParser.py,sha256=sPPJOtj5OYvsrukRErcoxRl4yuV1zDuf7pQ_pvw_Zow,21116
73
73
  agently/utils/__init__.py,sha256=Uq3uQdk2_OX_m6gF9wAvs4_scC-tsE4EjNTxN_oDagw,1321
74
- agently-4.0.7.dist-info/METADATA,sha256=pBzUn8zbTtsZscLIDYNBaJ0IiCkEgzZ117Qzgh3TaLY,7110
75
- agently-4.0.7.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
76
- agently-4.0.7.dist-info/licenses/LICENSE,sha256=Y5ZgAdYgMFigPT8dhN18dTLRtBshOSfWhTDRO1t0Cq4,11360
77
- agently-4.0.7.dist-info/RECORD,,
74
+ agently-4.0.7.1.dist-info/METADATA,sha256=WY94JMooQ57E-n3mWTDbPcx32-V_NhFI-JyY66gVOpM,7112
75
+ agently-4.0.7.1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
76
+ agently-4.0.7.1.dist-info/licenses/LICENSE,sha256=Y5ZgAdYgMFigPT8dhN18dTLRtBshOSfWhTDRO1t0Cq4,11360
77
+ agently-4.0.7.1.dist-info/RECORD,,