agently 4.0.6.10__py3-none-any.whl → 4.0.6.11__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.
agently/base.py CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
  from typing import Any, Literal, Type, TYPE_CHECKING, TypeVar, Generic, cast
16
16
 
17
- from agently.utils import Settings, create_logger, FunctionShifter
17
+ from agently.utils import Settings, create_logger, FunctionShifter, DataFormatter
18
18
  from agently.core import PluginManager, EventCenter, Tool, Prompt, ModelRequest, BaseAgent
19
19
  from agently._default_init import _load_default_settings, _load_default_plugins, _hook_default_event_handlers
20
20
 
@@ -117,6 +117,8 @@ class AgentlyMain(Generic[A]):
117
117
  self.tool = tool
118
118
  self.AgentType = AgentType
119
119
 
120
+ self.set_settings = self.settings.set_settings
121
+
120
122
  def set_debug_console(self, debug_console_status: Literal["ON", "OFF"]):
121
123
  match debug_console_status:
122
124
  case "OFF":
@@ -130,10 +132,6 @@ class AgentlyMain(Generic[A]):
130
132
  self.logger.setLevel(log_level)
131
133
  return self
132
134
 
133
- def set_settings(self, key: str, value: "SerializableValue"):
134
- self.settings.set_settings(key, value)
135
- return self
136
-
137
135
  def create_prompt(self, name: str = "agently_prompt") -> Prompt:
138
136
  return Prompt(
139
137
  self.plugin_manager,
@@ -21,6 +21,7 @@ from typing import Any
21
21
  from json import JSONDecodeError
22
22
 
23
23
  from agently.core import BaseAgent
24
+ from agently.utils import DataLocator
24
25
 
25
26
 
26
27
  class ConfigurePromptExtension(BaseAgent):
@@ -168,46 +169,74 @@ class ConfigurePromptExtension(BaseAgent):
168
169
  variable_mappings,
169
170
  )
170
171
 
171
- def load_yaml_prompt(self, path_or_content: str, mappings: dict[str, Any] | None = None):
172
+ def load_yaml_prompt(
173
+ self,
174
+ path_or_content: str | Path,
175
+ mappings: dict[str, Any] | None = None,
176
+ *,
177
+ prompt_key_path: str | None = None,
178
+ encoding: str | None = "utf-8",
179
+ ):
172
180
  path = Path(path_or_content)
173
181
  if path.exists() and path.is_file():
174
182
  try:
175
- with path.open("r", encoding="utf-8") as file:
183
+ with path.open("r", encoding=encoding) as file:
176
184
  prompt = yaml.safe_load(file)
177
185
  except yaml.YAMLError as e:
178
186
  raise ValueError(f"Cannot load YAML file '{ path_or_content }'.\nError: { e }")
179
187
  else:
180
188
  try:
181
- prompt = yaml.safe_load(path_or_content)
189
+ prompt = yaml.safe_load(str(path_or_content))
182
190
  except yaml.YAMLError as e:
183
191
  raise ValueError(f"Cannot load YAML content or file path not existed.\nError: { e }")
192
+ if not isinstance(prompt, dict):
193
+ raise TypeError(
194
+ "Cannot execute YAML prompt configures, expect prompt configures as a dictionary data but got:"
195
+ f"{ prompt }"
196
+ )
197
+ if prompt_key_path is not None:
198
+ prompt = DataLocator.locate_path_in_dict(prompt, prompt_key_path)
184
199
  if isinstance(prompt, dict):
185
200
  self._execute_prompt_configure(prompt, mappings)
186
201
  else:
187
202
  raise TypeError(
188
- "Cannot execute YAML prompt configures, expect prompt configures as a dictionary data but got:"
203
+ f"Cannot execute YAML prompt configures, expect prompt configures{ ' from [' + prompt_key_path + '] ' if prompt_key_path is not None else '' } as a dictionary data but got:"
189
204
  f"{ prompt }"
190
205
  )
191
206
  return self
192
207
 
193
- def load_json_prompt(self, path_or_content: str, mappings: dict[str, Any] | None = None):
208
+ def load_json_prompt(
209
+ self,
210
+ path_or_content: str | Path,
211
+ mappings: dict[str, Any] | None = None,
212
+ *,
213
+ prompt_key_path: str | None = None,
214
+ encoding: str | None = "utf-8",
215
+ ):
194
216
  path = Path(path_or_content)
195
217
  if path.exists() and path.is_file():
196
218
  try:
197
- with path.open("r", encoding="utf-8") as file:
219
+ with path.open("r", encoding=encoding) as file:
198
220
  prompt = json5.load(file)
199
221
  except JSONDecodeError as e:
200
222
  raise ValueError(f"Cannot load JSON file '{ path_or_content }'.\nError: { e }")
201
223
  else:
202
224
  try:
203
- prompt = json5.loads(path_or_content)
204
- except yaml.YAMLError as e:
225
+ prompt = json5.loads(str(path_or_content))
226
+ except JSONDecodeError as e:
205
227
  raise ValueError(f"Cannot load JSON content or file path not existed.\nError: { e }")
228
+ if not isinstance(prompt, dict):
229
+ raise TypeError(
230
+ "Cannot execute JSON prompt configures, expect prompt configures as a dictionary data but got:"
231
+ f"{ prompt }"
232
+ )
233
+ if prompt_key_path is not None:
234
+ prompt = DataLocator.locate_path_in_dict(prompt, prompt_key_path)
206
235
  if isinstance(prompt, dict):
207
236
  self._execute_prompt_configure(prompt, mappings)
208
237
  else:
209
238
  raise TypeError(
210
- "Cannot execute JSON prompt configures, expect prompt configures as a dictionary data but got:"
239
+ f"Cannot execute JSON prompt configures, expect prompt configures{ ' from [' + prompt_key_path + '] ' if prompt_key_path is not None else '' }as a dictionary data but got:"
211
240
  f"{ prompt }"
212
241
  )
213
242
  return self
@@ -45,6 +45,7 @@ if TYPE_CHECKING:
45
45
  class ContentMapping(TypedDict):
46
46
  id: str | None
47
47
  role: str | None
48
+ reasoning: str | None
48
49
  delta: str | None
49
50
  tool_calls: str | None
50
51
  done: str | None
@@ -114,6 +115,7 @@ class OpenAICompatible(ModelRequester):
114
115
  "content_mapping": {
115
116
  "id": "id",
116
117
  "role": "choices[0].delta.role",
118
+ "reasoning": "choices[0].delta.reasoning_content",
117
119
  "delta": "choices[0].delta.content",
118
120
  "tool_calls": "choices[0].delta.tool_calls",
119
121
  "done": None,
@@ -124,6 +126,7 @@ class OpenAICompatible(ModelRequester):
124
126
  },
125
127
  "extra_done": None,
126
128
  },
129
+ "yield_extra_content_separately": True,
127
130
  "content_mapping_style": "dot",
128
131
  "timeout": {
129
132
  "connect": 30.0,
@@ -505,6 +508,7 @@ class OpenAICompatible(ModelRequester):
505
508
  async def broadcast_response(self, response_generator: AsyncGenerator) -> "AgentlyResponseGenerator":
506
509
  meta = {}
507
510
  message_record = {}
511
+ reasoning_buffer = ""
508
512
  content_buffer = ""
509
513
 
510
514
  content_mapping = cast(
@@ -516,6 +520,7 @@ class OpenAICompatible(ModelRequester):
516
520
  )
517
521
  id_mapping = content_mapping["id"]
518
522
  role_mapping = content_mapping["role"]
523
+ reasoning_mapping = content_mapping["reasoning"]
519
524
  delta_mapping = content_mapping["delta"]
520
525
  tool_calls_mapping = content_mapping["tool_calls"]
521
526
  done_mapping = content_mapping["done"]
@@ -523,6 +528,7 @@ class OpenAICompatible(ModelRequester):
523
528
  finish_reason_mapping = content_mapping["finish_reason"]
524
529
  extra_delta_mapping = content_mapping["extra_delta"]
525
530
  extra_done_mapping = content_mapping["extra_done"]
531
+ yield_extra_content_separately = self.plugin_settings.get("yield_extra_content_separately", True)
526
532
 
527
533
  content_mapping_style = str(self.plugin_settings.get("content_mapping_style"))
528
534
  if content_mapping_style not in ("dot", "slash"):
@@ -552,6 +558,15 @@ class OpenAICompatible(ModelRequester):
552
558
  )
553
559
  if role:
554
560
  meta.update({"role": role})
561
+ if reasoning_mapping:
562
+ reasoning = DataLocator.locate_path_in_dict(
563
+ loaded_message,
564
+ reasoning_mapping,
565
+ style=content_mapping_style,
566
+ )
567
+ if reasoning:
568
+ reasoning_buffer += str(reasoning)
569
+ yield "reasoning_delta", reasoning
555
570
  if delta_mapping:
556
571
  delta = DataLocator.locate_path_in_dict(
557
572
  loaded_message,
@@ -578,6 +593,8 @@ class OpenAICompatible(ModelRequester):
578
593
  )
579
594
  if extra_value:
580
595
  yield "extra", {extra_key: extra_value}
596
+ if yield_extra_content_separately:
597
+ yield extra_key, extra_value # type: ignore
581
598
  else:
582
599
  done_content = None
583
600
  if self.model_type == "embeddings" and done_mapping is None:
@@ -593,6 +610,17 @@ class OpenAICompatible(ModelRequester):
593
610
  yield "done", done_content
594
611
  else:
595
612
  yield "done", content_buffer
613
+ reasoning_content = None
614
+ if reasoning_mapping:
615
+ reasoning_content = DataLocator.locate_path_in_dict(
616
+ message_record,
617
+ reasoning_mapping,
618
+ style=content_mapping_style,
619
+ )
620
+ if reasoning_content:
621
+ yield "reasoning_done", reasoning_content
622
+ else:
623
+ yield "reasoning_done", reasoning_buffer
596
624
  match self.model_type:
597
625
  case "embeddings":
598
626
  yield "original_done", message_record
@@ -282,8 +282,10 @@ class AgentlyResponseParser(ResponseParser):
282
282
 
283
283
  async def get_async_generator(
284
284
  self,
285
- type: Literal['all', 'delta', 'typed_delta', 'original', 'instant', 'streaming_parse'] | None = "delta",
286
- content: Literal['all', 'delta', 'typed_delta', 'original', 'instant', 'streaming_parse'] | None = "delta",
285
+ type: Literal['all', 'delta', 'specific', 'original', 'instant', 'streaming_parse'] | None = "delta",
286
+ content: Literal['all', 'delta', 'specific', 'original', 'instant', 'streaming_parse'] | None = "delta",
287
+ *,
288
+ specific: list[str] | str | None = ["reasoning_delta", "delta", "reasoning_done", "done", "tool_calls"],
287
289
  ) -> AsyncGenerator:
288
290
  await self._ensure_consumer()
289
291
  parsed_generator = cast(GeneratorConsumer, self._response_consumer).get_async_generator()
@@ -300,11 +302,13 @@ class AgentlyResponseParser(ResponseParser):
300
302
  case "delta":
301
303
  if event == "delta":
302
304
  yield data
303
- case "typed_delta":
304
- if event == "delta":
305
- yield "delta", data
306
- elif event == "tool_calls":
307
- yield "tool_calls", data
305
+ case "specific":
306
+ if specific is None:
307
+ specific = ["delta"]
308
+ elif isinstance(specific, str):
309
+ specific = [specific]
310
+ if event in specific:
311
+ yield event, data
308
312
  case "instant" | "streaming_parse":
309
313
  if self._streaming_json_parser is not None:
310
314
  streaming_parsed = None
@@ -325,8 +329,10 @@ class AgentlyResponseParser(ResponseParser):
325
329
 
326
330
  def get_generator(
327
331
  self,
328
- type: Literal['all', 'delta', 'typed_delta', 'original', 'instant', 'streaming_parse'] | None = "delta",
329
- content: Literal['all', 'delta', 'typed_delta', 'original', 'instant', 'streaming_parse'] | None = "delta",
332
+ type: Literal['all', 'delta', 'specific', 'original', 'instant', 'streaming_parse'] | None = "delta",
333
+ content: Literal['all', 'delta', 'specific', 'original', 'instant', 'streaming_parse'] | None = "delta",
334
+ *,
335
+ specific: list[str] | str | None = ["reasoning_delta", "delta", "reasoning_done", "done", "tool_calls"],
330
336
  ) -> Generator:
331
337
  asyncio.run(self._ensure_consumer())
332
338
  parsed_generator = cast(GeneratorConsumer, self._response_consumer).get_generator()
@@ -343,11 +349,13 @@ class AgentlyResponseParser(ResponseParser):
343
349
  case "delta":
344
350
  if event == "delta":
345
351
  yield data
346
- case "typed_delta":
347
- if event == "delta":
348
- yield "delta", data
349
- elif event == "tool_calls":
350
- yield "tool_calls", data
352
+ case "specific":
353
+ if specific is None:
354
+ specific = ["delta"]
355
+ elif isinstance(specific, str):
356
+ specific = [specific]
357
+ if event in specific:
358
+ yield event, data
351
359
  case "instant" | "streaming_parse":
352
360
  if self._streaming_json_parser is not None:
353
361
  streaming_parsed = None
agently/core/Agent.py CHANGED
@@ -66,6 +66,8 @@ class BaseAgent:
66
66
  self.request_prompt = self.request.prompt
67
67
  self.prompt = self.request_prompt
68
68
 
69
+ self.set_settings = self.settings.set_settings
70
+
69
71
  self.get_response = self.request.get_response
70
72
  self.get_result = self.request.get_result
71
73
  self.get_meta = self.request.get_meta
@@ -83,10 +85,6 @@ class BaseAgent:
83
85
  self.async_start = self.async_get_data
84
86
 
85
87
  # Basic Methods
86
- def set_settings(self, key: str, value: "SerializableValue"):
87
- self.settings.set_settings(key, value)
88
- return self
89
-
90
88
  def set_agent_prompt(
91
89
  self,
92
90
  key: "PromptStandardSlot | str",
@@ -425,14 +425,13 @@ class ModelRequest:
425
425
  parent=parent_extension_handlers,
426
426
  )
427
427
 
428
+ self.set_settings = self.settings.set_settings
429
+
428
430
  self.get_meta = FunctionShifter.syncify(self.async_get_meta)
429
431
  self.get_text = FunctionShifter.syncify(self.async_get_text)
430
432
  self.get_data = FunctionShifter.syncify(self.async_get_data)
431
433
  self.get_data_object = FunctionShifter.syncify(self.async_get_data_object)
432
434
 
433
- def set_settings(self, key: str, value: "SerializableValue"):
434
- self.settings.set_settings(key, value)
435
-
436
435
  def set_prompt(
437
436
  self,
438
437
  key: "PromptStandardSlot | str",
@@ -590,58 +589,84 @@ class ModelRequest:
590
589
  def get_generator(
591
590
  self,
592
591
  type: Literal["instant", "streaming_parse"],
592
+ *,
593
+ specific: list[str] | str | None = ["reasoning_delta", "delta", "reasoning_done", "done", "tool_calls"],
593
594
  ) -> Generator["StreamingData", None, None]: ...
594
595
 
595
596
  @overload
596
597
  def get_generator(
597
598
  self,
598
599
  type: Literal["all"],
600
+ *,
601
+ specific: list[str] | str | None = ["reasoning_delta", "delta", "reasoning_done", "done", "tool_calls"],
599
602
  ) -> Generator[tuple[str, Any], None, None]: ...
600
603
 
601
604
  @overload
602
605
  def get_generator(
603
606
  self,
604
- type: Literal["delta", "typed_delta", "original"],
607
+ type: Literal["delta", "specific", "original"],
608
+ *,
609
+ specific: list[str] | str | None = ["reasoning_delta", "delta", "reasoning_done", "done", "tool_calls"],
605
610
  ) -> Generator[str, None, None]: ...
606
611
 
607
612
  @overload
608
613
  def get_generator(
609
614
  self,
610
- type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
615
+ type: Literal["all", "original", "delta", "specific", "instant", "streaming_parse"] | None = "delta",
616
+ *,
617
+ specific: list[str] | str | None = ["reasoning_delta", "delta", "reasoning_done", "done", "tool_calls"],
611
618
  ) -> Generator: ...
612
619
 
613
620
  def get_generator(
614
621
  self,
615
- type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
622
+ type: Literal["all", "original", "delta", "specific", "instant", "streaming_parse"] | None = "delta",
623
+ *,
624
+ specific: list[str] | str | None = ["reasoning_delta", "delta", "reasoning_done", "done", "tool_calls"],
616
625
  ) -> Generator:
617
- return self.get_response().get_generator(type=type)
626
+ return self.get_response().get_generator(
627
+ type=type,
628
+ specific=specific,
629
+ )
618
630
 
619
631
  @overload
620
632
  def get_async_generator(
621
633
  self,
622
634
  type: Literal["instant", "streaming_parse"],
635
+ *,
636
+ specific: list[str] | str | None = ["reasoning_delta", "delta", "reasoning_done", "done", "tool_calls"],
623
637
  ) -> AsyncGenerator["StreamingData", None]: ...
624
638
 
625
639
  @overload
626
640
  def get_async_generator(
627
641
  self,
628
642
  type: Literal["all"],
643
+ *,
644
+ specific: list[str] | str | None = ["reasoning_delta", "delta", "reasoning_done", "done", "tool_calls"],
629
645
  ) -> AsyncGenerator[tuple[str, Any], None]: ...
630
646
 
631
647
  @overload
632
648
  def get_async_generator(
633
649
  self,
634
- type: Literal["delta", "typed_delta", "original"],
650
+ type: Literal["delta", "specific", "original"],
651
+ *,
652
+ specific: list[str] | str | None = ["reasoning_delta", "delta", "reasoning_done", "done", "tool_calls"],
635
653
  ) -> AsyncGenerator[str, None]: ...
636
654
 
637
655
  @overload
638
656
  def get_async_generator(
639
657
  self,
640
- type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
658
+ type: Literal["all", "original", "delta", "specific", "instant", "streaming_parse"] | None = "delta",
659
+ *,
660
+ specific: list[str] | str | None = ["reasoning_delta", "delta", "reasoning_done", "done", "tool_calls"],
641
661
  ) -> AsyncGenerator: ...
642
662
 
643
663
  def get_async_generator(
644
664
  self,
645
- type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
665
+ type: Literal["all", "original", "delta", "specific", "instant", "streaming_parse"] | None = "delta",
666
+ *,
667
+ specific: list[str] | str | None = ["reasoning_delta", "delta", "reasoning_done", "done", "tool_calls"],
646
668
  ) -> AsyncGenerator:
647
- return self.get_response().get_async_generator(type=type)
669
+ return self.get_response().get_async_generator(
670
+ type=type,
671
+ specific=specific,
672
+ )
@@ -36,6 +36,8 @@ class PluginManager:
36
36
  parent=parent.plugins if parent is not None else None,
37
37
  )
38
38
 
39
+ self.set_settings = self.settings.set_settings
40
+
39
41
  def register(
40
42
  self,
41
43
  plugin_type: AgentlyPluginType,
agently/core/Prompt.py CHANGED
@@ -14,9 +14,9 @@
14
14
 
15
15
  import re
16
16
  from textwrap import dedent
17
- from typing import Any, Literal, Mapping, Sequence, TYPE_CHECKING, cast, overload, TypeVar
17
+ from typing import Any, Literal, TYPE_CHECKING, cast, overload, TypeVar
18
18
 
19
- from agently.utils import RuntimeData, Settings
19
+ from agently.utils import RuntimeData, Settings, DataFormatter
20
20
 
21
21
  if TYPE_CHECKING:
22
22
  from agently.types.data.prompt import ChatMessage, PromptStandardSlot
@@ -80,8 +80,6 @@ class Prompt(RuntimeData):
80
80
  ):
81
81
  super().__init__(prompt_dict, parent=parent_prompt, name=name)
82
82
 
83
- self._placeholder_pattern = re.compile(r"\$\{\s*([^}]+?)\s*\}")
84
-
85
83
  self.settings = Settings(
86
84
  name="Prompt-Settings",
87
85
  parent=parent_settings,
@@ -103,42 +101,6 @@ class Prompt(RuntimeData):
103
101
  self.to_json_prompt = self.prompt_generator.to_json_prompt
104
102
  self.to_yaml_prompt = self.prompt_generator.to_yaml_prompt
105
103
 
106
- def _substitute_placeholder(self, obj: T, variable_mappings: dict[str, Any]) -> T | Any:
107
- if not isinstance(variable_mappings, dict):
108
- raise TypeError(f"Variable mappings require a dictionary but got: { variable_mappings }")
109
-
110
- if isinstance(obj, str):
111
- full_match = self._placeholder_pattern.fullmatch(obj)
112
- if full_match:
113
- key = full_match.group(1).strip()
114
- return variable_mappings.get(key, obj)
115
- else:
116
-
117
- def replacer(match):
118
- key = match.group(1).strip()
119
- return str(variable_mappings.get(key, match.group(0)))
120
-
121
- return self._placeholder_pattern.sub(replacer, obj)
122
-
123
- if isinstance(obj, Mapping):
124
- return {
125
- self._substitute_placeholder(key, variable_mappings): self._substitute_placeholder(
126
- value, variable_mappings
127
- )
128
- for key, value in obj.items()
129
- }
130
-
131
- if isinstance(obj, Sequence) and not isinstance(obj, (str, bytes, bytearray)):
132
- if isinstance(obj, tuple):
133
- return tuple(self._substitute_placeholder(value, variable_mappings) for value in obj)
134
- else:
135
- return [self._substitute_placeholder(value, variable_mappings) for value in obj]
136
-
137
- if isinstance(obj, set):
138
- return {self._substitute_placeholder(value, variable_mappings) for value in obj}
139
-
140
- return obj
141
-
142
104
  @overload
143
105
  def set(
144
106
  self,
@@ -165,8 +127,8 @@ class Prompt(RuntimeData):
165
127
  value = dedent(value.strip())
166
128
  if mappings is not None:
167
129
  super().set(
168
- self._substitute_placeholder(key, mappings),
169
- self._substitute_placeholder(value, mappings),
130
+ DataFormatter.substitute_placeholder(key, mappings),
131
+ DataFormatter.substitute_placeholder(value, mappings),
170
132
  )
171
133
  else:
172
134
  super().set(key, value)
@@ -178,7 +140,7 @@ class Prompt(RuntimeData):
178
140
  ):
179
141
  if mappings is not None:
180
142
  super().update(
181
- self._substitute_placeholder(new, mappings),
143
+ DataFormatter.substitute_placeholder(new, mappings),
182
144
  )
183
145
  else:
184
146
  super().update(new)
@@ -193,8 +155,8 @@ class Prompt(RuntimeData):
193
155
  value = dedent(value.strip())
194
156
  if mappings is not None:
195
157
  super().append(
196
- self._substitute_placeholder(key, mappings),
197
- self._substitute_placeholder(value, mappings),
158
+ DataFormatter.substitute_placeholder(key, mappings),
159
+ DataFormatter.substitute_placeholder(value, mappings),
198
160
  )
199
161
  else:
200
162
  super().append(key, value)
@@ -30,9 +30,10 @@ class TriggerFlowChunk:
30
30
  *,
31
31
  name: str | None = None,
32
32
  ):
33
- self.name = name if name is not None else uuid.uuid4().hex
33
+ self.id = uuid.uuid4().hex
34
+ self.name = name if name is not None else self.id
34
35
  self._handler = handler
35
- self.trigger = f"Chunk[{ handler.__name__ }]-{ self.name }"
36
+ self.trigger = f"Chunk[{ handler.__name__ }]-{ self.id }"
36
37
 
37
38
  async def async_call(self, data: "TriggerFlowEventData"):
38
39
  result = await FunctionShifter.asyncify(self._handler)(data)
@@ -51,6 +51,7 @@ class TriggerFlow:
51
51
  self._skip_exceptions = skip_exceptions
52
52
  self._executions: dict[str, "TriggerFlowExecution"] = {}
53
53
  self._start_process = TriggerFlowProcess(
54
+ flow_chunk=self.chunk,
54
55
  trigger_event="START",
55
56
  blue_print=self._blue_print,
56
57
  block_data=TriggerFlowBlockData(
@@ -60,6 +61,8 @@ class TriggerFlow:
60
61
 
61
62
  self.chunks = self._blue_print.chunks
62
63
 
64
+ self.set_settings = self.settings.set_settings
65
+
63
66
  self.get_flow_data = self._flow_data.get
64
67
  self.set_flow_data = FunctionShifter.syncify(self.async_set_flow_data)
65
68
  self.append_flow_data = FunctionShifter.syncify(self.async_append_flow_data)
@@ -74,10 +77,6 @@ class TriggerFlow:
74
77
  self.start_execution = FunctionShifter.syncify(self.async_start_execution)
75
78
  self.start = FunctionShifter.syncify(self.async_start)
76
79
 
77
- def set_settings(self, key: str, value: "SerializableValue"):
78
- self.settings.set_settings(key, value)
79
- return self
80
-
81
80
  @overload
82
81
  def chunk(self, handler_or_name: "TriggerFlowHandler") -> TriggerFlowChunk: ...
83
82
 
@@ -17,7 +17,7 @@ import uuid
17
17
  from asyncio import Event
18
18
  from threading import Lock
19
19
 
20
- from typing import Any, Literal, TYPE_CHECKING, overload
20
+ from typing import Callable, Any, Literal, TYPE_CHECKING, overload, cast
21
21
  from typing_extensions import Self
22
22
 
23
23
 
@@ -31,15 +31,18 @@ from agently.types.trigger_flow import TriggerFlowBlockData
31
31
 
32
32
 
33
33
  class TriggerFlowBaseProcess:
34
+
34
35
  def __init__(
35
36
  self,
36
37
  *,
38
+ flow_chunk,
37
39
  trigger_event: str,
38
40
  blue_print: "TriggerFlowBluePrint",
39
41
  block_data: "TriggerFlowBlockData",
40
42
  trigger_type: Literal["event", "runtime_data", "flow_data"] = "event",
41
43
  **options,
42
44
  ):
45
+ self._flow_chunk = flow_chunk
43
46
  self.trigger_event = trigger_event
44
47
  self.trigger_type: Literal["event", "runtime_data", "flow_data"] = trigger_type
45
48
  self._blue_print = blue_print
@@ -55,6 +58,7 @@ class TriggerFlowBaseProcess:
55
58
  **options,
56
59
  ):
57
60
  return type(self)(
61
+ flow_chunk=self._flow_chunk,
58
62
  trigger_event=trigger_event,
59
63
  trigger_type=trigger_type,
60
64
  blue_print=blue_print,
@@ -112,8 +116,12 @@ class TriggerFlowBaseProcess:
112
116
  if isinstance(trigger_or_triggers, TriggerFlowChunk):
113
117
  trigger_or_triggers = trigger_or_triggers.trigger
114
118
  if isinstance(trigger_or_triggers, str):
119
+ if trigger_or_triggers in self._blue_print.chunks:
120
+ trigger = self._blue_print.chunks[trigger_or_triggers].trigger
121
+ else:
122
+ trigger = trigger_or_triggers
115
123
  return self._new(
116
- trigger_event=trigger_or_triggers,
124
+ trigger_event=trigger,
117
125
  trigger_type="event",
118
126
  blue_print=self._blue_print,
119
127
  block_data=TriggerFlowBlockData(
@@ -225,9 +233,10 @@ class TriggerFlowBaseProcess:
225
233
  elif isinstance(chunk, tuple):
226
234
  chunk_name = chunk[0]
227
235
  chunk_func = chunk[1]
228
- chunk = TriggerFlowChunk(chunk_func, name=chunk_name)
236
+ chunk = self._flow_chunk(chunk_name)(chunk_func)
229
237
  else:
230
- chunk = TriggerFlowChunk(chunk, name=name) if callable(chunk) else chunk
238
+ chunk = self._flow_chunk(name or chunk.__name__)(chunk) if callable(chunk) else chunk
239
+ assert isinstance(chunk, TriggerFlowChunk)
231
240
  self._blue_print.add_handler(
232
241
  self.trigger_type,
233
242
  self.trigger_event,
@@ -280,9 +289,9 @@ class TriggerFlowBaseProcess:
280
289
  if isinstance(chunk, tuple):
281
290
  chunk_name = chunk[0]
282
291
  chunk_func = chunk[1]
283
- chunk = TriggerFlowChunk(chunk_func, name=chunk_name)
292
+ chunk = self._flow_chunk(chunk_name)(chunk_func)
284
293
  else:
285
- chunk = TriggerFlowChunk(chunk) if callable(chunk) else chunk
294
+ chunk = self._flow_chunk(chunk.__name__)(chunk) if callable(chunk) else chunk
286
295
  triggers_to_wait[chunk.trigger] = False
287
296
  trigger_to_chunk_name[chunk.trigger] = chunk.name
288
297
  results[chunk.name] = None
@@ -1,3 +1,18 @@
1
+ # Copyright 2023-2025 AgentEra(Agently.Tech)
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
1
16
  from agently.utils import LazyImport
2
17
 
3
18
  LazyImport.import_package("chromadb")
@@ -24,7 +24,16 @@ if TYPE_CHECKING:
24
24
  from agently.types.data.serializable import SerializableValue
25
25
 
26
26
  AgentlyModelResponseEvent = Literal[
27
- "error", "original_delta", "delta", "tool_calls", "original_done", "done", "meta", "extra"
27
+ "error",
28
+ "original_delta",
29
+ "reasoning_delta",
30
+ "delta",
31
+ "tool_calls",
32
+ "original_done",
33
+ "reasoning_done",
34
+ "done",
35
+ "meta",
36
+ "extra",
28
37
  ]
29
38
 
30
39
  AgentlyModelResponseMessage: TypeAlias = tuple[AgentlyModelResponseEvent, Any]
@@ -77,29 +77,39 @@ class ResponseParser(AgentlyPlugin, Protocol):
77
77
  def get_async_generator(
78
78
  self,
79
79
  type: Literal["instant", "streaming_parse"],
80
+ *,
81
+ specific: list[str] | str | None = None,
80
82
  ) -> AsyncGenerator["StreamingData", None]: ...
81
83
 
82
84
  @overload
83
85
  def get_async_generator(
84
86
  self,
85
87
  type: Literal["all"],
88
+ *,
89
+ specific: list[str] | str | None = None,
86
90
  ) -> AsyncGenerator[tuple[str, Any], None]: ...
87
91
 
88
92
  @overload
89
93
  def get_async_generator(
90
94
  self,
91
- type: Literal["delta", "typed_delta", "original"],
95
+ type: Literal["delta", "specific", "original"],
96
+ *,
97
+ specific: list[str] | str | None = None,
92
98
  ) -> AsyncGenerator[str, None]: ...
93
99
 
94
100
  @overload
95
101
  def get_async_generator(
96
102
  self,
97
- type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
103
+ type: Literal["all", "original", "delta", "specific", "instant", "streaming_parse"] | None = "delta",
104
+ *,
105
+ specific: list[str] | str | None = None,
98
106
  ) -> AsyncGenerator: ...
99
107
 
100
108
  def get_async_generator(
101
109
  self,
102
- type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
110
+ type: Literal["all", "original", "delta", "specific", "instant", "streaming_parse"] | None = "delta",
111
+ *,
112
+ specific: list[str] | str | None = None,
103
113
  ) -> AsyncGenerator:
104
114
  """
105
115
  'instant' is Agently v3 compatible for 'streaming_parse'
@@ -110,29 +120,39 @@ class ResponseParser(AgentlyPlugin, Protocol):
110
120
  def get_generator(
111
121
  self,
112
122
  type: Literal["instant", "streaming_parse"],
123
+ *,
124
+ specific: list[str] | str | None = None,
113
125
  ) -> Generator["StreamingData", None, None]: ...
114
126
 
115
127
  @overload
116
128
  def get_generator(
117
129
  self,
118
130
  type: Literal["all"],
131
+ *,
132
+ specific: list[str] | str | None = None,
119
133
  ) -> Generator[tuple[str, Any], None, None]: ...
120
134
 
121
135
  @overload
122
136
  def get_generator(
123
137
  self,
124
- type: Literal["delta", "typed_delta", "original"],
138
+ type: Literal["delta", "specific", "original"],
139
+ *,
140
+ specific: list[str] | str | None = None,
125
141
  ) -> Generator[str, None, None]: ...
126
142
 
127
143
  @overload
128
144
  def get_generator(
129
145
  self,
130
- type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
146
+ type: Literal["all", "original", "delta", "specific", "instant", "streaming_parse"] | None = "delta",
147
+ *,
148
+ specific: list[str] | str | None = None,
131
149
  ) -> Generator: ...
132
150
 
133
151
  def get_generator(
134
152
  self,
135
- type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
153
+ type: Literal["all", "original", "delta", "specific", "instant", "streaming_parse"] | None = "delta",
154
+ *,
155
+ specific: list[str] | str | None = None,
136
156
  ) -> Generator:
137
157
  """
138
158
  'instant' is Agently v3 compatible for 'streaming_parse'
@@ -12,12 +12,14 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ import re
15
16
  import datetime
16
17
  import warnings
17
18
  from typing import (
18
19
  Any,
19
20
  Literal,
20
21
  Mapping,
22
+ Sequence,
21
23
  Union,
22
24
  get_origin,
23
25
  get_args,
@@ -29,9 +31,12 @@ from pydantic import BaseModel
29
31
 
30
32
  if TYPE_CHECKING:
31
33
  from agently.types.data import SerializableValue, KwargsType
34
+ from re import Pattern
32
35
 
33
36
  T = TypeVar("T")
34
37
 
38
+ DEFAULT_PLACEHOLDER_PATTERN = re.compile(r"\$\{\s*([^}]+?)\s*\}")
39
+
35
40
 
36
41
  class DataFormatter:
37
42
  @staticmethod
@@ -246,3 +251,75 @@ class DataFormatter:
246
251
  return kwargs_format or None
247
252
 
248
253
  return None
254
+
255
+ @staticmethod
256
+ def substitute_placeholder(
257
+ obj: T,
258
+ variable_mappings: dict[str, Any],
259
+ *,
260
+ placeholder_pattern: "Pattern | None" = None,
261
+ ) -> T | Any:
262
+ if placeholder_pattern is None:
263
+ placeholder_pattern = DEFAULT_PLACEHOLDER_PATTERN
264
+
265
+ if not isinstance(variable_mappings, dict):
266
+ raise TypeError(f"Variable mappings require a dictionary but got: { variable_mappings }")
267
+
268
+ if isinstance(obj, str):
269
+ full_match = placeholder_pattern.fullmatch(obj)
270
+ if full_match:
271
+ key = full_match.group(1).strip()
272
+ return variable_mappings.get(key, obj)
273
+ else:
274
+
275
+ def replacer(match):
276
+ key = match.group(1).strip()
277
+ return str(variable_mappings.get(key, match.group(0)))
278
+
279
+ return placeholder_pattern.sub(replacer, obj)
280
+
281
+ if isinstance(obj, Mapping):
282
+ return {
283
+ DataFormatter.substitute_placeholder(
284
+ key,
285
+ variable_mappings,
286
+ placeholder_pattern=placeholder_pattern,
287
+ ): DataFormatter.substitute_placeholder(
288
+ value,
289
+ variable_mappings,
290
+ placeholder_pattern=placeholder_pattern,
291
+ )
292
+ for key, value in obj.items()
293
+ }
294
+
295
+ if isinstance(obj, Sequence) and not isinstance(obj, (str, bytes, bytearray)):
296
+ if isinstance(obj, tuple):
297
+ return tuple(
298
+ DataFormatter.substitute_placeholder(
299
+ value,
300
+ variable_mappings,
301
+ placeholder_pattern=placeholder_pattern,
302
+ )
303
+ for value in obj
304
+ )
305
+ else:
306
+ return [
307
+ DataFormatter.substitute_placeholder(
308
+ value,
309
+ variable_mappings,
310
+ placeholder_pattern=placeholder_pattern,
311
+ )
312
+ for value in obj
313
+ ]
314
+
315
+ if isinstance(obj, set):
316
+ return {
317
+ DataFormatter.substitute_placeholder(
318
+ value,
319
+ variable_mappings,
320
+ placeholder_pattern=placeholder_pattern,
321
+ )
322
+ for value in obj
323
+ }
324
+
325
+ return obj
@@ -0,0 +1,101 @@
1
+ # Copyright 2023-2025 AgentEra(Agently.Tech)
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ from types import MappingProxyType
17
+ from typing import Any
18
+
19
+ SAFE_BUILTINS = {
20
+ "abs": abs,
21
+ "min": min,
22
+ "max": max,
23
+ "sum": sum,
24
+ "len": len,
25
+ "range": range,
26
+ "enumerate": enumerate,
27
+ "list": list,
28
+ "dict": dict,
29
+ "set": set,
30
+ "tuple": tuple,
31
+ "print": print,
32
+ "sorted": sorted,
33
+ "str": str,
34
+ "int": int,
35
+ "float": float,
36
+ "list": list,
37
+ "dict": dict,
38
+ "bool": bool,
39
+ }
40
+
41
+ SAFE_TYPES = [int, float, str, list, dict, set, tuple, bool, type(None)]
42
+
43
+
44
+ class PythonSandbox:
45
+ def __init__(
46
+ self,
47
+ preset_objects: dict[str, object] | None = None,
48
+ base_vars: dict[str, Any] | None = None,
49
+ allowed_return_types: list[type] = SAFE_TYPES,
50
+ ):
51
+ self.preset_objects = preset_objects or {}
52
+ self.base_vars = base_vars or {}
53
+ self.allowed_return_types = allowed_return_types
54
+
55
+ self.safe_globals = MappingProxyType(
56
+ {
57
+ "__builtins__": SAFE_BUILTINS,
58
+ **self.preset_objects,
59
+ **self.base_vars,
60
+ }
61
+ )
62
+
63
+ def _check_safe_value(self, value):
64
+ if isinstance(value, tuple(self.allowed_return_types)):
65
+ return value
66
+ raise ValueError(f"Type of return '{ type(value) }' can not be used in Python Sandbox.")
67
+
68
+ def _wrap_obj(self, obj):
69
+ sandbox = self
70
+
71
+ class ObjectWrapper:
72
+ def __init__(self, obj):
73
+ self._obj = obj
74
+
75
+ def __getattr__(self, name):
76
+ if name.startswith("_"):
77
+ raise AttributeError(f"Can not access private attribute '{name}'.")
78
+ attr = getattr(self._obj, name)
79
+ if callable(attr):
80
+
81
+ def method(*args, **kwargs):
82
+ result = attr(*args, **kwargs)
83
+ return sandbox._check_safe_value(result)
84
+
85
+ return method
86
+ return sandbox._check_safe_value(attr)
87
+
88
+ self.allowed_return_types.append(ObjectWrapper)
89
+
90
+ return ObjectWrapper(obj)
91
+
92
+ def run(self, code: str):
93
+ safe_objects = {k: self._wrap_obj(v) for k, v in self.preset_objects.items()}
94
+ globals_dict = dict(self.safe_globals)
95
+ globals_dict.update(safe_objects)
96
+
97
+ local_vars = {}
98
+ exec(code, globals_dict, local_vars)
99
+ for k, v in local_vars.items():
100
+ self._check_safe_value(v)
101
+ return local_vars
agently/utils/Settings.py CHANGED
@@ -12,11 +12,14 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ import re
15
16
  import json
16
17
  import yaml
17
18
  import toml
18
19
  from typing import TYPE_CHECKING, Literal, cast
19
- from agently.utils import SerializableRuntimeData, SerializableRuntimeDataNamespace
20
+ from .SerializableRuntimeData import SerializableRuntimeData, SerializableRuntimeDataNamespace
21
+ from .LazyImport import LazyImport
22
+ from .DataFormatter import DataFormatter
20
23
 
21
24
  if TYPE_CHECKING:
22
25
  from agently.types.data import SerializableData, SerializableValue
@@ -114,7 +117,21 @@ class Settings(SerializableRuntimeData):
114
117
  else:
115
118
  raise TypeError(f"[Agently Settings] Cannot load parsed data, expect dictionary type, got: { type(data) }")
116
119
 
117
- def set_settings(self, key: str, value: "SerializableValue"):
120
+ def set_settings(self, key: str, value: "SerializableValue", *, auto_load_env: bool = False):
121
+ if auto_load_env:
122
+ import os
123
+
124
+ LazyImport.import_package("dotenv")
125
+ from dotenv import load_dotenv, find_dotenv
126
+
127
+ load_dotenv(find_dotenv())
128
+
129
+ environ = dict(os.environ)
130
+ value = DataFormatter.substitute_placeholder(
131
+ value,
132
+ environ,
133
+ placeholder_pattern=re.compile(r"\$\{\s*ENV\.([^}]+?)\s*\}"),
134
+ )
118
135
  if key in self._path_mappings:
119
136
  self.update({str(self._path_mappings[key]): value})
120
137
  return self
agently/utils/__init__.py CHANGED
@@ -27,3 +27,4 @@ from .DataLocator import DataLocator
27
27
  from .GeneratorConsumer import GeneratorConsumer
28
28
  from .StreamingJSONCompleter import StreamingJSONCompleter
29
29
  from .StreamingJSONParser import StreamingJSONParser
30
+ from .PythonSandbox import PythonSandbox
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agently
3
- Version: 4.0.6.10
3
+ Version: 4.0.6.11
4
4
  Summary:
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
@@ -1,61 +1,61 @@
1
1
  agently/__init__.py,sha256=Gf0LL7Czqeuf6hfvHfEGlACLg0d0osQupyMATB0EBlc,884
2
2
  agently/_default_init.py,sha256=AhYwzZYOxqDeIoVb8cvPjJ2BjE5V7wxeuH7R-MNZWyg,2057
3
3
  agently/_default_settings.yaml,sha256=6woqJ2tjg_jl6kwSOwmTMETfVraHidort2smf0Is_qQ,1357
4
- agently/base.py,sha256=PY-HgIQesv3_oBsU25Fwe96C35C4GgpaFdxLBUwh-AA,4692
4
+ agently/base.py,sha256=U92SWzoU7h7Gl92r8bEv-7wsGUPrUlxXyDohLX-2qCo,4629
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
- agently/builtins/agent_extensions/ConfigurePromptExtension.py,sha256=vURsWcy5UnKppBNOAy0ZnY03yMY3QqH7j3ZeixS8VOo,10230
7
+ agently/builtins/agent_extensions/ConfigurePromptExtension.py,sha256=9wy2zHIDVHbUlj5sI0A03SscUWSzZNc9hNJSEdXFXd0,11390
8
8
  agently/builtins/agent_extensions/KeyWaiterExtension.py,sha256=Rf8dB8Yt3_9IJifpiE-Rn6lLIXqZjaNp94lnX6Betgw,5555
9
9
  agently/builtins/agent_extensions/ToolExtension.py,sha256=S3jjumHiauEQ-m46Zkh-1I9ih02kKoj8sBEU82woz1E,6886
10
10
  agently/builtins/agent_extensions/__init__.py,sha256=IxWRQogF8PCVNXeY7D4qhGukEx3JFvfLlUW2x0FbyfA,852
11
11
  agently/builtins/hookers/ConsoleHooker.py,sha256=aJdDj_nG8CiwyelA505zvtpzBSwD52nFIkBRDJGgq3Y,8099
12
12
  agently/builtins/hookers/PureLoggerHooker.py,sha256=fzN0OfhQzgns4KeCNH-qcdm-BdQT0W2kqEmt3Zp2pYI,1906
13
13
  agently/builtins/hookers/SystemMessageHooker.py,sha256=1nh1FY70PYyZOAQGfQiGnwIvo4ZF3NSAjeghI3sInn4,7207
14
- agently/builtins/plugins/ModelRequester/OpenAICompatible.py,sha256=Druzptw_aKtCAI-a3wqFO4KgtzAP0L6HZZ_2I7t2u80,25397
14
+ agently/builtins/plugins/ModelRequester/OpenAICompatible.py,sha256=CFTMZHENOi6qsrUfWtgq19P6Ec7H-8vRybVVr4RZfJQ,26773
15
15
  agently/builtins/plugins/PromptGenerator/AgentlyPromptGenerator.py,sha256=GRRR9uxgyCXHKgt_r2BinWnhKy8rYUN8CG9ld2P8n4E,30841
16
- agently/builtins/plugins/ResponseParser/AgentlyResponseParser.py,sha256=FEhfsiHB4Bx7HfghnObklLj08j8IVwGh0WEVD6U-G3U,17445
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
20
  agently/builtins/tools/Search.py,sha256=tUynNiW_ZMAGaB2ua3HRcY_trIbLEoASFE-p2QMQ0Zg,7362
21
21
  agently/builtins/tools/__init__.py,sha256=pFOWgH2C3xRvgQo3UVdkj4yHjF9nNtmoVHmOZfoGsyU,647
22
- agently/core/Agent.py,sha256=hxRR3ca71XAabViIZGL31EYF4CAxmQS2KJrktCUs39k,10329
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=Sagd7HQozPPM41gbhYU9Lzj68IKPgR_xa00PA7lzpF4,23171
26
- agently/core/PluginManager.py,sha256=oUnXbe1ilQTOWwnENxtGtV6wG-yZriCxniqfuxuTFO0,4354
27
- agently/core/Prompt.py,sha256=oAxRZ7kG07mM6G7p6gP_zX41TgGb8vA-IilcnCb_Gc4,8432
25
+ agently/core/ModelRequest.py,sha256=KNNjO8BiV1qS9jcFcp0V7ACXUC4CcZRdmcXjPUNqHbw,24443
26
+ agently/core/PluginManager.py,sha256=fwRxvqPMgXYIrclhRHtkaPsyvn6SaeBFqvL7tTzYwck,4410
27
+ agently/core/Prompt.py,sha256=uvGGvbND08b0OhkD-UXY0J65yLedllBt4lMqk4NYl1U,6893
28
28
  agently/core/Tool.py,sha256=PNYf_BwVefr8IOqf5asLaVq2fU7hQaFJwJVj3S4fq84,1871
29
29
  agently/core/TriggerFlow/BluePrint.py,sha256=Lz-wbA0f79t7VjvX0knH-9AC_Qz9wts0QFemL97R3jo,4810
30
- agently/core/TriggerFlow/Chunk.py,sha256=d5cdK8fL-Ayg4-6qJom0J3wDIZFevoCw_kHGYMXBKOU,1559
30
+ agently/core/TriggerFlow/Chunk.py,sha256=xPWr_ofpl-iG4jHIJfB5mPanmn70pq7x8GCcz3G8NPc,1583
31
31
  agently/core/TriggerFlow/Execution.py,sha256=sXxDt5l9m2ZWMG6JZjnt50akyDFEu4I-YB2yhW-UP5E,11640
32
32
  agently/core/TriggerFlow/Process.py,sha256=doIDUa7x0j1TVuOhp-hraC0hHLwpistF-Dksf76NJvQ,837
33
- agently/core/TriggerFlow/TriggerFlow.py,sha256=03xC1EdWiNfnRbAocH-97JcxyzfCnChivI1KmvPt6-E,7671
33
+ agently/core/TriggerFlow/TriggerFlow.py,sha256=lu0MSaIfQ7HwELuWjIBQHvkdC0L9d5x7mX-eNEmi3aQ,7628
34
34
  agently/core/TriggerFlow/__init__.py,sha256=eHc6ldUIS0kka_1fZXkdaHFnSDoXaGSvXggwVszMAJQ,911
35
- agently/core/TriggerFlow/process/BaseProcess.py,sha256=oUlsj0AgK39e24kGWCZY6pXDlpbSVJ-mh-UPhJrqgRI,14467
35
+ agently/core/TriggerFlow/process/BaseProcess.py,sha256=3pf2t6-tTKIttAzFbL89RdmzjISKys4N65UGzPnFAIc,14847
36
36
  agently/core/TriggerFlow/process/ForEachProcess.py,sha256=rjUVouZENnuGFp7GXGTgWJT7uMEhczHamWr9cFugsh0,4549
37
37
  agently/core/TriggerFlow/process/MatchCaseProcess.py,sha256=MKY5Yh66JiMABhCzamRl8UZOBjbD75TFp84Jw6o_t68,7900
38
38
  agently/core/TriggerFlow/process/__init__.py,sha256=BP5bAr9LRVVD83KFqXeprgTmXA1iCSOSsD509BtoX_E,753
39
39
  agently/core/__init__.py,sha256=CPglSpW5oEEmWpCpdvv9wK4myXmVipjuZm5HtMq6Vxo,1214
40
- agently/integrations/chromadb.py,sha256=hLrjwsU_d4SOGRX0bf-55uiA73YarIzRa8ORFnwu3W8,9797
40
+ agently/integrations/chromadb.py,sha256=iULT9sK2MIZe5pyqMdL9M1yBkWqQhShwEyLmGnKUuew,10390
41
41
  agently/types/__init__.py,sha256=xb8GMY-ULncO_PY9rfRUsyi12wAQQJx8gAAnoM30uZA,592
42
42
  agently/types/data/__init__.py,sha256=qladqSEqcAUW_XzdTDl4cvaraq_DpANy3aZbIPxoygk,1627
43
43
  agently/types/data/event.py,sha256=LFQW7MN_QGOis3XV-8K6jNXWsLvT7tYxo4BZbUBCpfI,1790
44
44
  agently/types/data/prompt.py,sha256=DiszVM_3OHe66waf-99mBH7bzRr0cpbCHSpDI-2EjPs,5163
45
45
  agently/types/data/request.py,sha256=Do-9g5QxZRMYjaoHCZYwHbj28r-t4noAAtOebw764P4,1924
46
- agently/types/data/response.py,sha256=vjKIILaVyd5TVz5nvmytVRJPZg-RP0sRydhg_AzU6y0,3700
46
+ agently/types/data/response.py,sha256=QYrrZXh_fXsHRltKtd6FKIfmJlgV-stsg6B0AIXueto,3774
47
47
  agently/types/data/serializable.py,sha256=v2KlyKNOKp4L6J_Ueupb-gCyrnngvBskFUwNPSJQgnA,844
48
48
  agently/types/data/tool.py,sha256=wE8Dda2JtY5cojpHUuQrw7PNeVZ6Zma968bn-pUmS7I,1529
49
49
  agently/types/plugins/EventHooker.py,sha256=kb80-baVc3fVlrddW5syv9uSD8a2Mcw8Fd3I2HQhY_Y,1030
50
50
  agently/types/plugins/ModelRequester.py,sha256=urG1zFX0b4U6ZKSO50IbW5IHK3ydmRgUom7O7Niqk8s,3875
51
51
  agently/types/plugins/PromptGenerator.py,sha256=V8kqT0Eeq09AQqfGA-SZ5mNKeit1UrmqlDQCquSMzUU,4752
52
- agently/types/plugins/ResponseParser.py,sha256=_IRbQhT-G1ZNg2zkJgCYNF5qRaIzrDfbxLC7kO-tdK4,3984
52
+ agently/types/plugins/ResponseParser.py,sha256=6dCVWz61gaHOxsX9e5sYFqcWRZ5hBnNXAarT0-9uCUY,4566
53
53
  agently/types/plugins/ToolManager.py,sha256=q1Y3G_tzh1AU3s13H-zTDZIkR4W1mjh9E6AKudFOvyg,2421
54
54
  agently/types/plugins/__init__.py,sha256=gz_EpgBQGndIQHY5vJB2YRzAN5yIb3FZZG7pC8lB1lM,848
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=0P92t81vnp-rJSJvlbTF3yM-PRiteB19BNEQ8cmvmns,9444
58
+ agently/utils/DataFormatter.py,sha256=qdPtLPIQs9eCZ-hPBphan5CcPrR7Nz8h8cb7zF8F1j0,12050
59
59
  agently/utils/DataLocator.py,sha256=ss8OLet9HN0U1PZb-OCHS6KL54kv7vFZph6G0-GBidk,6015
60
60
  agently/utils/DataPathBuilder.py,sha256=sEzE1i2EWn7NMkCCXDT50gR6_qMzcZ0y0YGkYbXdB3s,10007
61
61
  agently/utils/FunctionShifter.py,sha256=quwugTmf-vzHzRR_2wdv14AxLpr0lwxdUtVoX7Jeq48,5839
@@ -63,14 +63,15 @@ agently/utils/GeneratorConsumer.py,sha256=EXpz2XGnv6rPdz8bPetJu3LpWIVhMvIi8GLG1B
63
63
  agently/utils/LazyImport.py,sha256=PfXc2iILXb7WVj6UD45_3qInow6z0cvhFlDqxTK-HfY,9120
64
64
  agently/utils/Logger.py,sha256=reIj6a7mNtLYDx3brLKEf0I8LbNkhXmL8Yc-DXnnsCU,2967
65
65
  agently/utils/Messenger.py,sha256=dLasJvDt1HxJttt6X9dutwGPvyAtL7yp6BZ3TDxuFDI,729
66
+ agently/utils/PythonSandbox.py,sha256=6HYbd64p8BnTysYQjUvumLf0YzEOq-7uhCuObAG3Q6U,3037
66
67
  agently/utils/RuntimeData.py,sha256=SewZ8D1fljuDwfVZTAqZ0XTNEcU2cuAr7QlVqk0vzrE,21925
67
68
  agently/utils/SerializableRuntimeData.py,sha256=bVVwin50VnOs30W881ClFepSXAK8GCOUZnVd-SiolRw,3314
68
- agently/utils/Settings.py,sha256=_s300H2doCMKcvMAmFwW3cLQqmd0N8BVmb226tAfVec,5294
69
+ agently/utils/Settings.py,sha256=0vWNhVBKZLRKwuIKoXn-tYNZMajMQHLHdqrGhBA2S3Q,5854
69
70
  agently/utils/Storage.py,sha256=E7QyNJ9T0yOUafPgdP90La698hgLMSGjhJ7qCEHzxxw,9438
70
71
  agently/utils/StreamingJSONCompleter.py,sha256=aZ9zuGUTQlP-QKbXHUZCf6EtVuG49MKn8xdhw0VhDEA,4292
71
72
  agently/utils/StreamingJSONParser.py,sha256=sPPJOtj5OYvsrukRErcoxRl4yuV1zDuf7pQ_pvw_Zow,21116
72
- agently/utils/__init__.py,sha256=7MDln5OVkqFEdhhuG8VTdr2q02UWwCj-udndwzWV_iQ,1280
73
- agently-4.0.6.10.dist-info/METADATA,sha256=FfpitXk1hlaWpkToJ08XHQhbkpC_zijeCMN2UaZI0Xs,7113
74
- agently-4.0.6.10.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
75
- agently-4.0.6.10.dist-info/licenses/LICENSE,sha256=Y5ZgAdYgMFigPT8dhN18dTLRtBshOSfWhTDRO1t0Cq4,11360
76
- agently-4.0.6.10.dist-info/RECORD,,
73
+ agently/utils/__init__.py,sha256=Uq3uQdk2_OX_m6gF9wAvs4_scC-tsE4EjNTxN_oDagw,1321
74
+ agently-4.0.6.11.dist-info/METADATA,sha256=goiOxI7yRqvMAMM62e5Af2MsiIt7tgSVHgn1OpDismA,7113
75
+ agently-4.0.6.11.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
76
+ agently-4.0.6.11.dist-info/licenses/LICENSE,sha256=Y5ZgAdYgMFigPT8dhN18dTLRtBshOSfWhTDRO1t0Cq4,11360
77
+ agently-4.0.6.11.dist-info/RECORD,,