agently 4.0.6.7__py3-none-any.whl → 4.0.6.10__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/builtins/agent_extensions/ConfigurePromptExtension.py +2 -0
- agently/builtins/hookers/SystemMessageHooker.py +51 -7
- agently/builtins/plugins/ModelRequester/OpenAICompatible.py +4 -0
- agently/builtins/plugins/PromptGenerator/AgentlyPromptGenerator.py +64 -1
- agently/core/Agent.py +65 -23
- agently/core/ModelRequest.py +178 -16
- agently/core/Prompt.py +8 -0
- agently/core/TriggerFlow/Chunk.py +2 -2
- agently/core/TriggerFlow/Execution.py +2 -2
- agently/core/TriggerFlow/process/BaseProcess.py +40 -17
- agently/core/TriggerFlow/process/ForEachProcess.py +3 -3
- agently/core/TriggerFlow/process/MatchCaseProcess.py +6 -6
- agently/types/plugins/PromptGenerator.py +5 -1
- agently/types/trigger_flow/trigger_flow.py +6 -6
- {agently-4.0.6.7.dist-info → agently-4.0.6.10.dist-info}/METADATA +1 -1
- {agently-4.0.6.7.dist-info → agently-4.0.6.10.dist-info}/RECORD +18 -18
- {agently-4.0.6.7.dist-info → agently-4.0.6.10.dist-info}/WHEEL +0 -0
- {agently-4.0.6.7.dist-info → agently-4.0.6.10.dist-info}/licenses/LICENSE +0 -0
|
@@ -188,6 +188,7 @@ class ConfigurePromptExtension(BaseAgent):
|
|
|
188
188
|
"Cannot execute YAML prompt configures, expect prompt configures as a dictionary data but got:"
|
|
189
189
|
f"{ prompt }"
|
|
190
190
|
)
|
|
191
|
+
return self
|
|
191
192
|
|
|
192
193
|
def load_json_prompt(self, path_or_content: str, mappings: dict[str, Any] | None = None):
|
|
193
194
|
path = Path(path_or_content)
|
|
@@ -209,3 +210,4 @@ class ConfigurePromptExtension(BaseAgent):
|
|
|
209
210
|
"Cannot execute JSON prompt configures, expect prompt configures as a dictionary data but got:"
|
|
210
211
|
f"{ prompt }"
|
|
211
212
|
)
|
|
213
|
+
return self
|
|
@@ -17,6 +17,32 @@ from typing import TYPE_CHECKING
|
|
|
17
17
|
|
|
18
18
|
from agently.types.plugins import EventHooker
|
|
19
19
|
|
|
20
|
+
COLORS = {
|
|
21
|
+
"black": 30,
|
|
22
|
+
"red": 31,
|
|
23
|
+
"green": 32,
|
|
24
|
+
"yellow": 33,
|
|
25
|
+
"blue": 34,
|
|
26
|
+
"magenta": 35,
|
|
27
|
+
"cyan": 36,
|
|
28
|
+
"white": 37,
|
|
29
|
+
"gray": 90,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def color_text(text: str, color: str | None = None, bold: bool = False, underline: bool = False) -> str:
|
|
34
|
+
codes = []
|
|
35
|
+
if bold:
|
|
36
|
+
codes.append("1")
|
|
37
|
+
if underline:
|
|
38
|
+
codes.append("4")
|
|
39
|
+
if color and color in COLORS:
|
|
40
|
+
codes.append(str(COLORS[color]))
|
|
41
|
+
if not codes:
|
|
42
|
+
return text
|
|
43
|
+
return f"\x1b[{';'.join(codes)}m{text}\x1b[0m"
|
|
44
|
+
|
|
45
|
+
|
|
20
46
|
if TYPE_CHECKING:
|
|
21
47
|
from agently.types.data import EventMessage, AgentlySystemEvent
|
|
22
48
|
|
|
@@ -72,12 +98,18 @@ class SystemMessageHooker(EventHooker):
|
|
|
72
98
|
and SystemMessageHooker._current_meta["row_id"] == message_data["response_id"]
|
|
73
99
|
and SystemMessageHooker._current_meta["stage"] == content["stage"]
|
|
74
100
|
):
|
|
75
|
-
print(content["detail"], end="")
|
|
101
|
+
print(color_text(content["detail"], color="gray"), end="", flush=True)
|
|
76
102
|
else:
|
|
77
|
-
|
|
78
|
-
f"[Agent-{ message_data['agent_name'] }] - [Request-{ message_data['response_id'] }]
|
|
79
|
-
|
|
103
|
+
header = color_text(
|
|
104
|
+
f"[Agent-{ message_data['agent_name'] }] - [Request-{ message_data['response_id'] }]",
|
|
105
|
+
color="blue",
|
|
106
|
+
bold=True,
|
|
80
107
|
)
|
|
108
|
+
stage_label = color_text("Stage:", color="cyan", bold=True)
|
|
109
|
+
stage_val = color_text(content["stage"], color="yellow", underline=True)
|
|
110
|
+
detail_label = color_text("Detail:\n", color="cyan", bold=True)
|
|
111
|
+
detail = color_text(content["detail"], color="green")
|
|
112
|
+
print(f"{header}\n{stage_label} {stage_val}\n{detail_label}{detail}", end="")
|
|
81
113
|
SystemMessageHooker._current_meta["table_name"] = message_data["agent_name"]
|
|
82
114
|
SystemMessageHooker._current_meta["row_id"] = message_data["response_id"]
|
|
83
115
|
SystemMessageHooker._current_meta["stage"] = content["stage"]
|
|
@@ -99,28 +131,40 @@ class SystemMessageHooker(EventHooker):
|
|
|
99
131
|
},
|
|
100
132
|
)
|
|
101
133
|
if settings["runtime.show_model_logs"]:
|
|
134
|
+
header = color_text(
|
|
135
|
+
f"[Agent-{ message_data['agent_name'] }] - [Response-{ message_data['response_id'] }]",
|
|
136
|
+
color="blue",
|
|
137
|
+
bold=True,
|
|
138
|
+
)
|
|
139
|
+
stage_label = color_text("Stage:", color="cyan", bold=True)
|
|
140
|
+
stage_val = color_text(content["stage"], color="yellow", underline=True)
|
|
141
|
+
detail_label = color_text("Detail:\n", color="cyan", bold=True)
|
|
142
|
+
detail = color_text(f"{content['detail']}", color="gray")
|
|
102
143
|
await event_center.async_emit(
|
|
103
144
|
"log",
|
|
104
145
|
{
|
|
105
146
|
"level": "INFO",
|
|
106
|
-
"content": f"
|
|
147
|
+
"content": f"{header}\n{stage_label} {stage_val}\n{detail_label}{detail}",
|
|
107
148
|
},
|
|
108
149
|
)
|
|
109
150
|
case "TOOL":
|
|
110
151
|
if settings["runtime.show_tool_logs"]:
|
|
152
|
+
tool_title = color_text("[Tool Using Result]:", color="blue", bold=True)
|
|
153
|
+
tool_body = color_text(str(message.content["data"]), color="gray")
|
|
111
154
|
await event_center.async_emit(
|
|
112
155
|
"log",
|
|
113
156
|
{
|
|
114
157
|
"level": "INFO",
|
|
115
|
-
"content": f"
|
|
158
|
+
"content": f"{tool_title}\n{tool_body}",
|
|
116
159
|
},
|
|
117
160
|
)
|
|
118
161
|
case "TRIGGER_FLOW":
|
|
119
162
|
if settings["runtime.show_trigger_flow_logs"]:
|
|
163
|
+
trigger = color_text(f"[TriggerFlow] { message.content['data'] }", color="yellow", bold=True)
|
|
120
164
|
await event_center.async_emit(
|
|
121
165
|
"log",
|
|
122
166
|
{
|
|
123
167
|
"level": "INFO",
|
|
124
|
-
"content":
|
|
168
|
+
"content": trigger,
|
|
125
169
|
},
|
|
126
170
|
)
|
|
@@ -146,6 +146,10 @@ class OpenAICompatible(ModelRequester):
|
|
|
146
146
|
self.model_type = cast(str, self.plugin_settings.get("model_type"))
|
|
147
147
|
self._messenger = event_center.create_messenger(self.name)
|
|
148
148
|
|
|
149
|
+
# check if has attachment prompt
|
|
150
|
+
if self.prompt["attachment"]:
|
|
151
|
+
self.plugin_settings["rich_content"] = True
|
|
152
|
+
|
|
149
153
|
@staticmethod
|
|
150
154
|
def _on_register():
|
|
151
155
|
pass
|
|
@@ -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 json
|
|
15
16
|
import yaml
|
|
16
17
|
|
|
17
18
|
from typing import (
|
|
@@ -38,6 +39,7 @@ from agently.utils import SettingsNamespace, DataFormatter
|
|
|
38
39
|
|
|
39
40
|
if TYPE_CHECKING:
|
|
40
41
|
from pydantic import BaseModel
|
|
42
|
+
from agently.types.data import SerializableData
|
|
41
43
|
from agently.core import Prompt
|
|
42
44
|
from agently.utils import Settings
|
|
43
45
|
|
|
@@ -649,7 +651,12 @@ class AgentlyPromptGenerator(PromptGenerator):
|
|
|
649
651
|
}
|
|
650
652
|
)
|
|
651
653
|
|
|
652
|
-
return create_model(
|
|
654
|
+
return create_model(
|
|
655
|
+
name,
|
|
656
|
+
__config__={'extra': 'allow'},
|
|
657
|
+
**fields,
|
|
658
|
+
**validators,
|
|
659
|
+
)
|
|
653
660
|
else:
|
|
654
661
|
item_type = Any
|
|
655
662
|
if len(schema) > 0:
|
|
@@ -698,3 +705,59 @@ class AgentlyPromptGenerator(PromptGenerator):
|
|
|
698
705
|
"AgentlyOutput",
|
|
699
706
|
{"list": DataFormatter.sanitize(output_prompt, remain_type=True)},
|
|
700
707
|
)
|
|
708
|
+
|
|
709
|
+
def _to_serializable_output_prompt(self, output_prompt_part: Any):
|
|
710
|
+
if not isinstance(output_prompt_part, (Mapping, Sequence)) or isinstance(output_prompt_part, str):
|
|
711
|
+
return output_prompt_part
|
|
712
|
+
|
|
713
|
+
if isinstance(output_prompt_part, Mapping):
|
|
714
|
+
result = {}
|
|
715
|
+
for key, value in output_prompt_part.items():
|
|
716
|
+
result[key] = self._to_serializable_output_prompt(value)
|
|
717
|
+
return result
|
|
718
|
+
else:
|
|
719
|
+
if isinstance(output_prompt_part, tuple):
|
|
720
|
+
match len(output_prompt_part):
|
|
721
|
+
case 0:
|
|
722
|
+
return []
|
|
723
|
+
case 1:
|
|
724
|
+
return {
|
|
725
|
+
"$type": output_prompt_part[0],
|
|
726
|
+
}
|
|
727
|
+
case _:
|
|
728
|
+
desc_text = ";".join([item for item in output_prompt_part[1:] if item])
|
|
729
|
+
if desc_text:
|
|
730
|
+
return {
|
|
731
|
+
"$type": output_prompt_part[0],
|
|
732
|
+
"$desc": desc_text,
|
|
733
|
+
}
|
|
734
|
+
else:
|
|
735
|
+
return {
|
|
736
|
+
"$type": output_prompt_part[0],
|
|
737
|
+
}
|
|
738
|
+
else:
|
|
739
|
+
return list(output_prompt_part)
|
|
740
|
+
|
|
741
|
+
def to_serializable_prompt_data(self, inherit: bool = False) -> "SerializableData":
|
|
742
|
+
prompt_data = self.prompt.get(
|
|
743
|
+
default={},
|
|
744
|
+
inherit=inherit,
|
|
745
|
+
)
|
|
746
|
+
if "output" in prompt_data:
|
|
747
|
+
prompt_data["output"] = self._to_serializable_output_prompt(prompt_data["output"])
|
|
748
|
+
return DataFormatter.sanitize(prompt_data)
|
|
749
|
+
|
|
750
|
+
def to_json_prompt(self, inherit: bool = False):
|
|
751
|
+
return json.dumps(
|
|
752
|
+
self.to_serializable_prompt_data(inherit),
|
|
753
|
+
indent=2,
|
|
754
|
+
ensure_ascii=False,
|
|
755
|
+
)
|
|
756
|
+
|
|
757
|
+
def to_yaml_prompt(self, inherit: bool = False):
|
|
758
|
+
return yaml.safe_dump(
|
|
759
|
+
self.to_serializable_prompt_data(inherit),
|
|
760
|
+
indent=2,
|
|
761
|
+
allow_unicode=True,
|
|
762
|
+
sort_keys=False,
|
|
763
|
+
)
|
agently/core/Agent.py
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import uuid
|
|
16
|
+
import yaml
|
|
17
|
+
import json
|
|
16
18
|
|
|
17
19
|
from typing import Any, TYPE_CHECKING
|
|
18
20
|
|
|
@@ -91,7 +93,7 @@ class BaseAgent:
|
|
|
91
93
|
value: Any,
|
|
92
94
|
mappings: dict[str, Any] | None = None,
|
|
93
95
|
):
|
|
94
|
-
self.
|
|
96
|
+
self.agent_prompt.set(key, value, mappings)
|
|
95
97
|
return self
|
|
96
98
|
|
|
97
99
|
def set_request_prompt(
|
|
@@ -104,7 +106,7 @@ class BaseAgent:
|
|
|
104
106
|
return self
|
|
105
107
|
|
|
106
108
|
def remove_agent_prompt(self, key: "PromptStandardSlot | str"):
|
|
107
|
-
self.
|
|
109
|
+
self.agent_prompt.set(key, None)
|
|
108
110
|
return self
|
|
109
111
|
|
|
110
112
|
def remove_request_prompt(self, key: "PromptStandardSlot | str"):
|
|
@@ -112,34 +114,34 @@ class BaseAgent:
|
|
|
112
114
|
return self
|
|
113
115
|
|
|
114
116
|
def reset_chat_history(self):
|
|
115
|
-
if "chat_history" in self.
|
|
116
|
-
self.
|
|
117
|
+
if "chat_history" in self.agent_prompt:
|
|
118
|
+
self.agent_prompt.set("chat_history", [])
|
|
117
119
|
return self
|
|
118
120
|
|
|
119
121
|
def set_chat_history(self, chat_history: "list[dict[str, Any] | ChatMessage]"):
|
|
120
122
|
self.reset_chat_history()
|
|
121
123
|
if not isinstance(chat_history, list):
|
|
122
124
|
chat_history = [chat_history]
|
|
123
|
-
self.
|
|
125
|
+
self.agent_prompt.set("chat_history", chat_history)
|
|
124
126
|
return self
|
|
125
127
|
|
|
126
128
|
def add_chat_history(self, chat_history: "list[dict[str, Any] | ChatMessage] | dict[str, Any] | ChatMessage"):
|
|
127
129
|
if not isinstance(chat_history, list):
|
|
128
130
|
chat_history = [chat_history]
|
|
129
|
-
self.
|
|
131
|
+
self.agent_prompt.set("chat_history", chat_history)
|
|
130
132
|
return self
|
|
131
133
|
|
|
132
134
|
def reset_action_results(self):
|
|
133
|
-
if "action_results" in self.
|
|
134
|
-
del self.
|
|
135
|
+
if "action_results" in self.agent_prompt:
|
|
136
|
+
del self.agent_prompt["action_results"]
|
|
135
137
|
return self
|
|
136
138
|
|
|
137
139
|
def set_action_results(self, action_results: list[dict[str, Any]]):
|
|
138
|
-
self.
|
|
140
|
+
self.agent_prompt.set("action_results", action_results)
|
|
139
141
|
return self
|
|
140
142
|
|
|
141
143
|
def add_action_results(self, action: str, result: Any):
|
|
142
|
-
self.
|
|
144
|
+
self.agent_prompt.append("action_results", {action: result})
|
|
143
145
|
return self
|
|
144
146
|
|
|
145
147
|
# Quick Prompt
|
|
@@ -151,7 +153,7 @@ class BaseAgent:
|
|
|
151
153
|
always: bool = False,
|
|
152
154
|
):
|
|
153
155
|
if always:
|
|
154
|
-
self.
|
|
156
|
+
self.agent_prompt.set("input", prompt, mappings)
|
|
155
157
|
else:
|
|
156
158
|
self.request.prompt.set("input", prompt, mappings)
|
|
157
159
|
return self
|
|
@@ -164,8 +166,8 @@ class BaseAgent:
|
|
|
164
166
|
always: bool = False,
|
|
165
167
|
):
|
|
166
168
|
if always:
|
|
167
|
-
self.
|
|
168
|
-
self.
|
|
169
|
+
self.agent_prompt.set("instruct", ["{system.rule} ARE IMPORTANT RULES YOU SHALL FOLLOW!"])
|
|
170
|
+
self.agent_prompt.set("system.rule", prompt, mappings)
|
|
169
171
|
else:
|
|
170
172
|
self.request.prompt.set("instruct", ["{system.rule} ARE IMPORTANT RULES YOU SHALL FOLLOW!"])
|
|
171
173
|
self.request.prompt.set("system.rule", prompt, mappings)
|
|
@@ -179,8 +181,8 @@ class BaseAgent:
|
|
|
179
181
|
always: bool = False,
|
|
180
182
|
):
|
|
181
183
|
if always:
|
|
182
|
-
self.
|
|
183
|
-
self.
|
|
184
|
+
self.agent_prompt.set("instruct", ["YOU MUST REACT AND RESPOND AS {system.role}!"])
|
|
185
|
+
self.agent_prompt.set("system.your_role", prompt, mappings)
|
|
184
186
|
else:
|
|
185
187
|
self.request.prompt.set("instruct", ["YOU MUST REACT AND RESPOND AS {system.role}!"])
|
|
186
188
|
self.request.prompt.set("system.your_role", prompt, mappings)
|
|
@@ -194,8 +196,8 @@ class BaseAgent:
|
|
|
194
196
|
always: bool = False,
|
|
195
197
|
):
|
|
196
198
|
if always:
|
|
197
|
-
self.
|
|
198
|
-
self.
|
|
199
|
+
self.agent_prompt.set("instruct", ["{system.user_info} IS IMPORTANT INFORMATION ABOUT USER!"])
|
|
200
|
+
self.agent_prompt.set("system.user_info", prompt, mappings)
|
|
199
201
|
else:
|
|
200
202
|
self.request.prompt.set("instruct", ["{system.user_info} IS IMPORTANT INFORMATION ABOUT USER!"])
|
|
201
203
|
self.request.prompt.set("system.user_info", prompt, mappings)
|
|
@@ -209,7 +211,7 @@ class BaseAgent:
|
|
|
209
211
|
always: bool = False,
|
|
210
212
|
):
|
|
211
213
|
if always:
|
|
212
|
-
self.
|
|
214
|
+
self.agent_prompt.set("input", prompt, mappings)
|
|
213
215
|
else:
|
|
214
216
|
self.request.prompt.set("input", prompt, mappings)
|
|
215
217
|
return self
|
|
@@ -222,7 +224,7 @@ class BaseAgent:
|
|
|
222
224
|
always: bool = False,
|
|
223
225
|
):
|
|
224
226
|
if always:
|
|
225
|
-
self.
|
|
227
|
+
self.agent_prompt.set("info", prompt, mappings)
|
|
226
228
|
else:
|
|
227
229
|
self.request.prompt.set("info", prompt, mappings)
|
|
228
230
|
return self
|
|
@@ -235,7 +237,7 @@ class BaseAgent:
|
|
|
235
237
|
always: bool = False,
|
|
236
238
|
):
|
|
237
239
|
if always:
|
|
238
|
-
self.
|
|
240
|
+
self.agent_prompt.set("instruct", prompt, mappings)
|
|
239
241
|
else:
|
|
240
242
|
self.request.prompt.set("instruct", prompt, mappings)
|
|
241
243
|
return self
|
|
@@ -248,7 +250,7 @@ class BaseAgent:
|
|
|
248
250
|
always: bool = False,
|
|
249
251
|
):
|
|
250
252
|
if always:
|
|
251
|
-
self.
|
|
253
|
+
self.agent_prompt.set("examples", prompt, mappings)
|
|
252
254
|
else:
|
|
253
255
|
self.request.prompt.set("examples", prompt, mappings)
|
|
254
256
|
return self
|
|
@@ -266,11 +268,24 @@ class BaseAgent:
|
|
|
266
268
|
always: bool = False,
|
|
267
269
|
):
|
|
268
270
|
if always:
|
|
269
|
-
self.
|
|
271
|
+
self.agent_prompt.set("output", prompt, mappings)
|
|
270
272
|
else:
|
|
271
273
|
self.request.prompt.set("output", prompt, mappings)
|
|
272
274
|
return self
|
|
273
275
|
|
|
276
|
+
def attachment(
|
|
277
|
+
self,
|
|
278
|
+
prompt: list[dict[str, Any]],
|
|
279
|
+
mappings: dict[str, Any] | None = None,
|
|
280
|
+
*,
|
|
281
|
+
always: bool = False,
|
|
282
|
+
):
|
|
283
|
+
if always:
|
|
284
|
+
self.agent_prompt.set("attachment", prompt, mappings)
|
|
285
|
+
else:
|
|
286
|
+
self.request_prompt.set("attachment", prompt, mappings)
|
|
287
|
+
return self
|
|
288
|
+
|
|
274
289
|
def options(
|
|
275
290
|
self,
|
|
276
291
|
options: dict[str, Any],
|
|
@@ -278,7 +293,34 @@ class BaseAgent:
|
|
|
278
293
|
always: bool = False,
|
|
279
294
|
):
|
|
280
295
|
if always:
|
|
281
|
-
self.
|
|
296
|
+
self.agent_prompt.set("options", options)
|
|
282
297
|
else:
|
|
283
298
|
self.request.prompt.set("options", options)
|
|
284
299
|
return self
|
|
300
|
+
|
|
301
|
+
# Prompt
|
|
302
|
+
def get_prompt_text(self):
|
|
303
|
+
return self.request_prompt.to_text()[6:][:-11]
|
|
304
|
+
|
|
305
|
+
def get_json_prompt(self):
|
|
306
|
+
prompt_data = {
|
|
307
|
+
".agent": self.agent_prompt.to_serializable_prompt_data(),
|
|
308
|
+
".request": self.request_prompt.to_serializable_prompt_data(),
|
|
309
|
+
}
|
|
310
|
+
return json.dumps(
|
|
311
|
+
prompt_data,
|
|
312
|
+
indent=2,
|
|
313
|
+
ensure_ascii=False,
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
def get_yaml_prompt(self):
|
|
317
|
+
prompt_data = {
|
|
318
|
+
".agent": self.agent_prompt.to_serializable_prompt_data(),
|
|
319
|
+
".request": self.request_prompt.to_serializable_prompt_data(),
|
|
320
|
+
}
|
|
321
|
+
return yaml.safe_dump(
|
|
322
|
+
prompt_data,
|
|
323
|
+
indent=2,
|
|
324
|
+
allow_unicode=True,
|
|
325
|
+
sort_keys=False,
|
|
326
|
+
)
|
agently/core/ModelRequest.py
CHANGED
|
@@ -22,12 +22,13 @@ ContentKindTuple: TypeAlias = Literal["all", "delta", "original"]
|
|
|
22
22
|
ContentKindStreaming: TypeAlias = Literal["instant", "streaming_parse"]
|
|
23
23
|
|
|
24
24
|
from agently.core import Prompt, ExtensionHandlers
|
|
25
|
-
from agently.utils import Settings, FunctionShifter, DataFormatter
|
|
25
|
+
from agently.utils import Settings, FunctionShifter, DataFormatter, DataLocator
|
|
26
26
|
|
|
27
27
|
if TYPE_CHECKING:
|
|
28
28
|
from agently.core import PluginManager
|
|
29
29
|
from agently.types.data import AgentlyModelResponseMessage, PromptStandardSlot, StreamingData, SerializableValue
|
|
30
30
|
from agently.types.plugins import ModelRequester, ResponseParser
|
|
31
|
+
from pydantic import BaseModel
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
class ModelResponseResult:
|
|
@@ -39,6 +40,7 @@ class ModelResponseResult:
|
|
|
39
40
|
response_generator: AsyncGenerator["AgentlyModelResponseMessage", None],
|
|
40
41
|
plugin_manager: "PluginManager",
|
|
41
42
|
settings: Settings,
|
|
43
|
+
extension_handlers: ExtensionHandlers,
|
|
42
44
|
):
|
|
43
45
|
self.agent_name = agent_name
|
|
44
46
|
self.plugin_manager = plugin_manager
|
|
@@ -50,19 +52,145 @@ class ModelResponseResult:
|
|
|
50
52
|
str(self.settings["plugins.ResponseParser.activate"]),
|
|
51
53
|
),
|
|
52
54
|
)
|
|
53
|
-
|
|
55
|
+
self._response_id = response_id
|
|
56
|
+
self._extension_handlers = extension_handlers
|
|
57
|
+
self._response_parser = ResponseParser(agent_name, response_id, prompt, response_generator, self.settings)
|
|
54
58
|
self.prompt = prompt
|
|
55
|
-
self.full_result_data = _response_parser.full_result_data
|
|
56
|
-
self.get_meta = _response_parser.get_meta
|
|
57
|
-
self.async_get_meta = _response_parser.async_get_meta
|
|
58
|
-
self.get_text = _response_parser.get_text
|
|
59
|
-
self.async_get_text = _response_parser.async_get_text
|
|
60
|
-
self.get_data = _response_parser.get_data
|
|
61
|
-
self.async_get_data = _response_parser.async_get_data
|
|
62
|
-
self.get_data_object = _response_parser.get_data_object
|
|
63
|
-
self.async_get_data_object = _response_parser.async_get_data_object
|
|
64
|
-
self.
|
|
65
|
-
self.
|
|
59
|
+
self.full_result_data = self._response_parser.full_result_data
|
|
60
|
+
self.get_meta = self._response_parser.get_meta
|
|
61
|
+
self.async_get_meta = self._response_parser.async_get_meta
|
|
62
|
+
self.get_text = self._response_parser.get_text
|
|
63
|
+
self.async_get_text = self._response_parser.async_get_text
|
|
64
|
+
# self.get_data = self._response_parser.get_data
|
|
65
|
+
# self.async_get_data = self._response_parser.async_get_data
|
|
66
|
+
# self.get_data_object = self._response_parser.get_data_object
|
|
67
|
+
# self.async_get_data_object = self._response_parser.async_get_data_object
|
|
68
|
+
self.get_data = FunctionShifter.syncify(self.async_get_data)
|
|
69
|
+
self.get_data_object = FunctionShifter.syncify(self.async_get_data_object)
|
|
70
|
+
self.get_generator = self._response_parser.get_generator
|
|
71
|
+
self.get_async_generator = self._response_parser.get_async_generator
|
|
72
|
+
|
|
73
|
+
@overload
|
|
74
|
+
async def async_get_data(
|
|
75
|
+
self,
|
|
76
|
+
*,
|
|
77
|
+
type: Literal['parsed'],
|
|
78
|
+
ensure_keys: list[str],
|
|
79
|
+
key_style: Literal["dot", "slash"] = "dot",
|
|
80
|
+
max_retries: int = 3,
|
|
81
|
+
raise_ensure_failure: bool = True,
|
|
82
|
+
_retry_count: int = 0,
|
|
83
|
+
) -> dict[str, Any]: ...
|
|
84
|
+
|
|
85
|
+
@overload
|
|
86
|
+
async def async_get_data(
|
|
87
|
+
self,
|
|
88
|
+
*,
|
|
89
|
+
type: Literal['original', 'parsed', 'all'] = "parsed",
|
|
90
|
+
ensure_keys: list[str] | None = None,
|
|
91
|
+
key_style: Literal["dot", "slash"] = "dot",
|
|
92
|
+
max_retries: int = 3,
|
|
93
|
+
raise_ensure_failure: bool = True,
|
|
94
|
+
_retry_count: int = 0,
|
|
95
|
+
) -> Any: ...
|
|
96
|
+
|
|
97
|
+
async def async_get_data(
|
|
98
|
+
self,
|
|
99
|
+
*,
|
|
100
|
+
type: Literal['original', 'parsed', 'all'] = "parsed",
|
|
101
|
+
ensure_keys: list[str] | None = None,
|
|
102
|
+
key_style: Literal["dot", "slash"] = "dot",
|
|
103
|
+
max_retries: int = 3,
|
|
104
|
+
raise_ensure_failure: bool = True,
|
|
105
|
+
_retry_count: int = 0,
|
|
106
|
+
) -> Any:
|
|
107
|
+
if type == "parsed" and ensure_keys:
|
|
108
|
+
try:
|
|
109
|
+
data = await self._response_parser.async_get_data(type=type)
|
|
110
|
+
for ensure_key in ensure_keys:
|
|
111
|
+
EMPTY = object()
|
|
112
|
+
if DataLocator.locate_path_in_dict(data, ensure_key, key_style, default=EMPTY) is EMPTY:
|
|
113
|
+
raise
|
|
114
|
+
return data
|
|
115
|
+
except:
|
|
116
|
+
from agently.base import async_system_message
|
|
117
|
+
|
|
118
|
+
await async_system_message(
|
|
119
|
+
"MODEL_REQUEST",
|
|
120
|
+
{
|
|
121
|
+
"agent_name": self.agent_name,
|
|
122
|
+
"response_id": self._response_id,
|
|
123
|
+
"content": {
|
|
124
|
+
"stage": "No Target Data in Response, Preparing Retry",
|
|
125
|
+
"detail": f"\n[Response]: { await self.async_get_text() }\n"
|
|
126
|
+
f"[Retried Times]: { _retry_count }",
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
self.settings,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
if _retry_count < max_retries:
|
|
133
|
+
return await ModelResponse(
|
|
134
|
+
self.agent_name,
|
|
135
|
+
self.plugin_manager,
|
|
136
|
+
self.settings,
|
|
137
|
+
self.prompt,
|
|
138
|
+
self._extension_handlers,
|
|
139
|
+
).result.async_get_data(
|
|
140
|
+
type=type,
|
|
141
|
+
ensure_keys=ensure_keys,
|
|
142
|
+
key_style=key_style,
|
|
143
|
+
max_retries=max_retries,
|
|
144
|
+
raise_ensure_failure=raise_ensure_failure,
|
|
145
|
+
_retry_count=_retry_count + 1,
|
|
146
|
+
)
|
|
147
|
+
else:
|
|
148
|
+
if raise_ensure_failure:
|
|
149
|
+
raise ValueError(
|
|
150
|
+
f"Can not generate ensure keys { ensure_keys } within { max_retries } retires."
|
|
151
|
+
)
|
|
152
|
+
else:
|
|
153
|
+
return await self._response_parser.async_get_data(type=type)
|
|
154
|
+
return await self._response_parser.async_get_data(type=type)
|
|
155
|
+
|
|
156
|
+
@overload
|
|
157
|
+
async def async_get_data_object(
|
|
158
|
+
self,
|
|
159
|
+
*,
|
|
160
|
+
ensure_keys: list[str],
|
|
161
|
+
key_style: Literal["dot", "slash"] = "dot",
|
|
162
|
+
max_retries: int = 3,
|
|
163
|
+
raise_ensure_failure: bool = True,
|
|
164
|
+
) -> "BaseModel": ...
|
|
165
|
+
|
|
166
|
+
@overload
|
|
167
|
+
async def async_get_data_object(
|
|
168
|
+
self,
|
|
169
|
+
*,
|
|
170
|
+
ensure_keys: None,
|
|
171
|
+
key_style: Literal["dot", "slash"] = "dot",
|
|
172
|
+
max_retries: int = 3,
|
|
173
|
+
raise_ensure_failure: bool = True,
|
|
174
|
+
) -> "BaseModel | None": ...
|
|
175
|
+
|
|
176
|
+
async def async_get_data_object(
|
|
177
|
+
self,
|
|
178
|
+
*,
|
|
179
|
+
ensure_keys: list[str] | None = None,
|
|
180
|
+
key_style: Literal["dot", "slash"] = "dot",
|
|
181
|
+
max_retries: int = 3,
|
|
182
|
+
raise_ensure_failure: bool = True,
|
|
183
|
+
):
|
|
184
|
+
if ensure_keys:
|
|
185
|
+
await self.async_get_data(
|
|
186
|
+
ensure_keys=ensure_keys,
|
|
187
|
+
key_style=key_style,
|
|
188
|
+
max_retries=max_retries,
|
|
189
|
+
_retry_count=0,
|
|
190
|
+
raise_ensure_failure=raise_ensure_failure,
|
|
191
|
+
)
|
|
192
|
+
return await self._response_parser.async_get_data_object()
|
|
193
|
+
return await self._response_parser.async_get_data_object()
|
|
66
194
|
|
|
67
195
|
|
|
68
196
|
class ModelResponse:
|
|
@@ -98,6 +226,7 @@ class ModelResponse:
|
|
|
98
226
|
self._get_response_generator(),
|
|
99
227
|
self.plugin_manager,
|
|
100
228
|
self.settings,
|
|
229
|
+
self.extension_handlers,
|
|
101
230
|
)
|
|
102
231
|
self.get_meta = self.result.get_meta
|
|
103
232
|
self.async_get_meta = self.result.async_get_meta
|
|
@@ -394,6 +523,15 @@ class ModelRequest:
|
|
|
394
523
|
self.prompt.set("output", prompt, mappings)
|
|
395
524
|
return self
|
|
396
525
|
|
|
526
|
+
def attachment(
|
|
527
|
+
self,
|
|
528
|
+
prompt: list[dict[str, Any]],
|
|
529
|
+
mappings: dict[str, Any] | None = None,
|
|
530
|
+
):
|
|
531
|
+
self.prompt.set("attachment", prompt, mappings)
|
|
532
|
+
return self
|
|
533
|
+
|
|
534
|
+
# Response & Result
|
|
397
535
|
def get_response(self):
|
|
398
536
|
response = ModelResponse(
|
|
399
537
|
self.agent_name,
|
|
@@ -418,11 +556,35 @@ class ModelRequest:
|
|
|
418
556
|
self,
|
|
419
557
|
*,
|
|
420
558
|
type: Literal['original', 'parsed', 'all'] = "parsed",
|
|
559
|
+
ensure_keys: list[str] | None = None,
|
|
560
|
+
key_style: Literal["dot", "slash"] = "dot",
|
|
561
|
+
max_retries: int = 3,
|
|
562
|
+
raise_ensure_failure: bool = True,
|
|
421
563
|
):
|
|
422
|
-
|
|
564
|
+
response = self.get_response()
|
|
565
|
+
return await response.async_get_data(
|
|
566
|
+
type=type,
|
|
567
|
+
ensure_keys=ensure_keys,
|
|
568
|
+
key_style=key_style,
|
|
569
|
+
max_retries=max_retries,
|
|
570
|
+
raise_ensure_failure=raise_ensure_failure,
|
|
571
|
+
)
|
|
423
572
|
|
|
424
|
-
async def async_get_data_object(
|
|
425
|
-
|
|
573
|
+
async def async_get_data_object(
|
|
574
|
+
self,
|
|
575
|
+
*,
|
|
576
|
+
ensure_keys: list[str] | None = None,
|
|
577
|
+
key_style: Literal["dot", "slash"] = "dot",
|
|
578
|
+
max_retries: int = 3,
|
|
579
|
+
raise_ensure_failure: bool = True,
|
|
580
|
+
):
|
|
581
|
+
response = self.get_response()
|
|
582
|
+
return await response.async_get_data_object(
|
|
583
|
+
ensure_keys=ensure_keys,
|
|
584
|
+
key_style=key_style,
|
|
585
|
+
max_retries=max_retries,
|
|
586
|
+
raise_ensure_failure=raise_ensure_failure,
|
|
587
|
+
)
|
|
426
588
|
|
|
427
589
|
@overload
|
|
428
590
|
def get_generator(
|
agently/core/Prompt.py
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import re
|
|
16
|
+
from textwrap import dedent
|
|
16
17
|
from typing import Any, Literal, Mapping, Sequence, TYPE_CHECKING, cast, overload, TypeVar
|
|
17
18
|
|
|
18
19
|
from agently.utils import RuntimeData, Settings
|
|
@@ -98,6 +99,9 @@ class Prompt(RuntimeData):
|
|
|
98
99
|
self.to_messages = self.prompt_generator.to_messages
|
|
99
100
|
self.to_prompt_object = self.prompt_generator.to_prompt_object
|
|
100
101
|
self.to_output_model = self.prompt_generator.to_output_model
|
|
102
|
+
self.to_serializable_prompt_data = self.prompt_generator.to_serializable_prompt_data
|
|
103
|
+
self.to_json_prompt = self.prompt_generator.to_json_prompt
|
|
104
|
+
self.to_yaml_prompt = self.prompt_generator.to_yaml_prompt
|
|
101
105
|
|
|
102
106
|
def _substitute_placeholder(self, obj: T, variable_mappings: dict[str, Any]) -> T | Any:
|
|
103
107
|
if not isinstance(variable_mappings, dict):
|
|
@@ -157,6 +161,8 @@ class Prompt(RuntimeData):
|
|
|
157
161
|
value: Any,
|
|
158
162
|
mappings: dict[str, Any] | None = None,
|
|
159
163
|
):
|
|
164
|
+
if isinstance(value, str):
|
|
165
|
+
value = dedent(value.strip())
|
|
160
166
|
if mappings is not None:
|
|
161
167
|
super().set(
|
|
162
168
|
self._substitute_placeholder(key, mappings),
|
|
@@ -183,6 +189,8 @@ class Prompt(RuntimeData):
|
|
|
183
189
|
value: Any,
|
|
184
190
|
mappings: dict[str, Any] | None = None,
|
|
185
191
|
):
|
|
192
|
+
if isinstance(value, str):
|
|
193
|
+
value = dedent(value.strip())
|
|
186
194
|
if mappings is not None:
|
|
187
195
|
super().append(
|
|
188
196
|
self._substitute_placeholder(key, mappings),
|
|
@@ -36,10 +36,10 @@ class TriggerFlowChunk:
|
|
|
36
36
|
|
|
37
37
|
async def async_call(self, data: "TriggerFlowEventData"):
|
|
38
38
|
result = await FunctionShifter.asyncify(self._handler)(data)
|
|
39
|
-
await data.async_emit(self.trigger, result,
|
|
39
|
+
await data.async_emit(self.trigger, result, _layer_marks=data._layer_marks.copy())
|
|
40
40
|
return result
|
|
41
41
|
|
|
42
42
|
def call(self, data: "TriggerFlowEventData"):
|
|
43
43
|
result = FunctionShifter.syncify(self._handler)(data)
|
|
44
|
-
data.emit(self.trigger, result,
|
|
44
|
+
data.emit(self.trigger, result, _layer_marks=data._layer_marks.copy())
|
|
45
45
|
return result
|
|
@@ -97,7 +97,7 @@ class TriggerFlowExecution:
|
|
|
97
97
|
self,
|
|
98
98
|
trigger_event: str,
|
|
99
99
|
value: Any = None,
|
|
100
|
-
|
|
100
|
+
_layer_marks: list[str] | None = None,
|
|
101
101
|
*,
|
|
102
102
|
trigger_type: Literal["event", "runtime_data", "flow_data"] = "event",
|
|
103
103
|
):
|
|
@@ -134,7 +134,7 @@ class TriggerFlowExecution:
|
|
|
134
134
|
trigger_type=trigger_type,
|
|
135
135
|
value=value,
|
|
136
136
|
execution=self,
|
|
137
|
-
|
|
137
|
+
_layer_marks=_layer_marks,
|
|
138
138
|
)
|
|
139
139
|
)
|
|
140
140
|
)
|
|
@@ -178,7 +178,7 @@ class TriggerFlowBaseProcess:
|
|
|
178
178
|
if mode == "simple_or"
|
|
179
179
|
else (data.trigger_type, data.trigger_event, data.value)
|
|
180
180
|
),
|
|
181
|
-
|
|
181
|
+
_layer_marks=data._layer_marks.copy(),
|
|
182
182
|
)
|
|
183
183
|
case "and":
|
|
184
184
|
if data.trigger_type in values and data.trigger_event in values[trigger_type]: # type: ignore
|
|
@@ -191,7 +191,7 @@ class TriggerFlowBaseProcess:
|
|
|
191
191
|
await data.async_emit(
|
|
192
192
|
when_trigger,
|
|
193
193
|
values,
|
|
194
|
-
|
|
194
|
+
_layer_marks=data._layer_marks.copy(),
|
|
195
195
|
)
|
|
196
196
|
|
|
197
197
|
for trigger_type, trigger_event_dict in values.items():
|
|
@@ -213,15 +213,21 @@ class TriggerFlowBaseProcess:
|
|
|
213
213
|
|
|
214
214
|
def to(
|
|
215
215
|
self,
|
|
216
|
-
chunk: "TriggerFlowChunk | TriggerFlowHandler | str",
|
|
216
|
+
chunk: "TriggerFlowChunk | TriggerFlowHandler | str | tuple[str, TriggerFlowHandler]",
|
|
217
217
|
side_branch: bool = False,
|
|
218
|
+
name: str | None = None,
|
|
218
219
|
):
|
|
219
220
|
if isinstance(chunk, str):
|
|
220
221
|
if chunk in self._blue_print.chunks:
|
|
221
222
|
chunk = self._blue_print.chunks[chunk]
|
|
222
223
|
else:
|
|
223
224
|
raise NotImplementedError(f"Cannot find chunk named '{ chunk }'")
|
|
224
|
-
|
|
225
|
+
elif isinstance(chunk, tuple):
|
|
226
|
+
chunk_name = chunk[0]
|
|
227
|
+
chunk_func = chunk[1]
|
|
228
|
+
chunk = TriggerFlowChunk(chunk_func, name=chunk_name)
|
|
229
|
+
else:
|
|
230
|
+
chunk = TriggerFlowChunk(chunk, name=name) if callable(chunk) else chunk
|
|
225
231
|
self._blue_print.add_handler(
|
|
226
232
|
self.trigger_type,
|
|
227
233
|
self.trigger_event,
|
|
@@ -235,34 +241,51 @@ class TriggerFlowBaseProcess:
|
|
|
235
241
|
**self._options,
|
|
236
242
|
)
|
|
237
243
|
|
|
238
|
-
def side_branch(
|
|
239
|
-
|
|
244
|
+
def side_branch(
|
|
245
|
+
self,
|
|
246
|
+
chunk: "TriggerFlowChunk | TriggerFlowHandler",
|
|
247
|
+
*,
|
|
248
|
+
name: str | None = None,
|
|
249
|
+
):
|
|
250
|
+
return self.to(
|
|
251
|
+
chunk,
|
|
252
|
+
side_branch=True,
|
|
253
|
+
name=name,
|
|
254
|
+
)
|
|
240
255
|
|
|
241
256
|
def batch(
|
|
242
257
|
self,
|
|
243
|
-
*chunks: "TriggerFlowChunk | TriggerFlowHandler",
|
|
258
|
+
*chunks: "TriggerFlowChunk | TriggerFlowHandler | tuple[str, TriggerFlowHandler]",
|
|
244
259
|
side_branch: bool = False,
|
|
245
260
|
):
|
|
246
261
|
batch_trigger = f"Batch-{ uuid.uuid4().hex }"
|
|
247
262
|
results = {}
|
|
248
|
-
|
|
263
|
+
triggers_to_wait = {}
|
|
264
|
+
trigger_to_chunk_name = {}
|
|
249
265
|
|
|
250
266
|
async def wait_all_chunks(data: "TriggerFlowEventData"):
|
|
251
|
-
if data.event in
|
|
252
|
-
results[data.event] = data.value
|
|
253
|
-
|
|
254
|
-
for done in
|
|
267
|
+
if data.event in triggers_to_wait:
|
|
268
|
+
results[trigger_to_chunk_name[data.event]] = data.value
|
|
269
|
+
triggers_to_wait[data.event] = True
|
|
270
|
+
for done in triggers_to_wait.values():
|
|
255
271
|
if done is False:
|
|
256
272
|
return
|
|
257
273
|
await data.async_emit(
|
|
258
274
|
batch_trigger,
|
|
259
275
|
results,
|
|
260
|
-
|
|
276
|
+
_layer_marks=data._layer_marks.copy(),
|
|
261
277
|
)
|
|
262
278
|
|
|
263
279
|
for chunk in chunks:
|
|
264
|
-
|
|
265
|
-
|
|
280
|
+
if isinstance(chunk, tuple):
|
|
281
|
+
chunk_name = chunk[0]
|
|
282
|
+
chunk_func = chunk[1]
|
|
283
|
+
chunk = TriggerFlowChunk(chunk_func, name=chunk_name)
|
|
284
|
+
else:
|
|
285
|
+
chunk = TriggerFlowChunk(chunk) if callable(chunk) else chunk
|
|
286
|
+
triggers_to_wait[chunk.trigger] = False
|
|
287
|
+
trigger_to_chunk_name[chunk.trigger] = chunk.name
|
|
288
|
+
results[chunk.name] = None
|
|
266
289
|
self._blue_print.add_handler(
|
|
267
290
|
self.trigger_type,
|
|
268
291
|
self.trigger_event,
|
|
@@ -299,13 +322,13 @@ class TriggerFlowBaseProcess:
|
|
|
299
322
|
await data.async_emit(
|
|
300
323
|
collect_trigger,
|
|
301
324
|
self._block_data.global_data.get(f"collections.{ collection_name}"),
|
|
302
|
-
|
|
325
|
+
_layer_marks=data._layer_marks.copy(),
|
|
303
326
|
)
|
|
304
327
|
elif mode == "filled_then_empty":
|
|
305
328
|
await data.async_emit(
|
|
306
329
|
collect_trigger,
|
|
307
330
|
self._block_data.global_data.get(f"collections.{ collection_name}"),
|
|
308
|
-
|
|
331
|
+
_layer_marks=data._layer_marks.copy(),
|
|
309
332
|
)
|
|
310
333
|
del self._block_data.global_data[f"collections.{ collection_name}"]
|
|
311
334
|
|
|
@@ -49,7 +49,7 @@ class TriggerFlowForEachProcess(TriggerFlowBaseProcess):
|
|
|
49
49
|
data.async_emit(
|
|
50
50
|
send_item_trigger,
|
|
51
51
|
item,
|
|
52
|
-
data.
|
|
52
|
+
data._layer_marks.copy(),
|
|
53
53
|
)
|
|
54
54
|
)
|
|
55
55
|
data.layer_out()
|
|
@@ -62,7 +62,7 @@ class TriggerFlowForEachProcess(TriggerFlowBaseProcess):
|
|
|
62
62
|
await data.async_emit(
|
|
63
63
|
send_item_trigger,
|
|
64
64
|
data.value,
|
|
65
|
-
data.
|
|
65
|
+
data._layer_marks.copy(),
|
|
66
66
|
)
|
|
67
67
|
data.layer_out()
|
|
68
68
|
|
|
@@ -103,7 +103,7 @@ class TriggerFlowForEachProcess(TriggerFlowBaseProcess):
|
|
|
103
103
|
await data.async_emit(
|
|
104
104
|
end_for_each_trigger,
|
|
105
105
|
list(for_each_results[for_each_instance_id].values()),
|
|
106
|
-
data.
|
|
106
|
+
data._layer_marks.copy(),
|
|
107
107
|
)
|
|
108
108
|
for_each_results.delete(for_each_instance_id)
|
|
109
109
|
|
|
@@ -58,7 +58,7 @@ class TriggerFlowMatchCaseProcess(TriggerFlowBaseProcess):
|
|
|
58
58
|
await data.async_emit(
|
|
59
59
|
f"Match-{ match_id }-Case-{ case_id }",
|
|
60
60
|
data.value,
|
|
61
|
-
|
|
61
|
+
_layer_marks=data._layer_marks.copy(),
|
|
62
62
|
)
|
|
63
63
|
return
|
|
64
64
|
elif mode == "hit_all":
|
|
@@ -71,7 +71,7 @@ class TriggerFlowMatchCaseProcess(TriggerFlowBaseProcess):
|
|
|
71
71
|
data.async_emit(
|
|
72
72
|
f"Match-{ match_id }-Case-{ case_id }",
|
|
73
73
|
data.value,
|
|
74
|
-
|
|
74
|
+
_layer_marks=data._layer_marks.copy(),
|
|
75
75
|
)
|
|
76
76
|
)
|
|
77
77
|
data.layer_out()
|
|
@@ -81,13 +81,13 @@ class TriggerFlowMatchCaseProcess(TriggerFlowBaseProcess):
|
|
|
81
81
|
await data.async_emit(
|
|
82
82
|
f"Match-{ match_id }-Else",
|
|
83
83
|
data.value,
|
|
84
|
-
|
|
84
|
+
_layer_marks=data._layer_marks.copy(),
|
|
85
85
|
)
|
|
86
86
|
else:
|
|
87
87
|
await data.async_emit(
|
|
88
88
|
f"Match-{ match_id }-Result",
|
|
89
89
|
data.value,
|
|
90
|
-
|
|
90
|
+
_layer_marks=data._layer_marks.copy(),
|
|
91
91
|
)
|
|
92
92
|
|
|
93
93
|
self.to(match_case)
|
|
@@ -164,7 +164,7 @@ class TriggerFlowMatchCaseProcess(TriggerFlowBaseProcess):
|
|
|
164
164
|
await data.async_emit(
|
|
165
165
|
f"Match-{ match_id }-Result",
|
|
166
166
|
list(match_results.values()),
|
|
167
|
-
|
|
167
|
+
_layer_marks=data._layer_marks.copy(),
|
|
168
168
|
)
|
|
169
169
|
del data._system_runtime_data[f"match_results.{ data.upper_layer_mark }"]
|
|
170
170
|
else:
|
|
@@ -172,7 +172,7 @@ class TriggerFlowMatchCaseProcess(TriggerFlowBaseProcess):
|
|
|
172
172
|
await data.async_emit(
|
|
173
173
|
f"Match-{ match_id }-Result",
|
|
174
174
|
data.value,
|
|
175
|
-
|
|
175
|
+
_layer_marks=data._layer_marks.copy(),
|
|
176
176
|
)
|
|
177
177
|
|
|
178
178
|
for trigger in branch_ends:
|
|
@@ -16,7 +16,7 @@ from typing import Any, Protocol, TYPE_CHECKING
|
|
|
16
16
|
from .base import AgentlyPlugin
|
|
17
17
|
|
|
18
18
|
if TYPE_CHECKING:
|
|
19
|
-
from agently.types.data import PromptModel
|
|
19
|
+
from agently.types.data import PromptModel, SerializableData
|
|
20
20
|
from agently.core import Prompt
|
|
21
21
|
from agently.utils import Settings
|
|
22
22
|
from pydantic import BaseModel
|
|
@@ -130,3 +130,7 @@ class PromptGenerator(AgentlyPlugin, Protocol):
|
|
|
130
130
|
- For list outputs: use `BaseModel(list=output_result)` to validate.
|
|
131
131
|
"""
|
|
132
132
|
...
|
|
133
|
+
|
|
134
|
+
def to_serializable_prompt_data(self, *args, **kwargs) -> "SerializableData": ...
|
|
135
|
+
def to_json_prompt(self, *args, **kwargs) -> str: ...
|
|
136
|
+
def to_yaml_prompt(self, *args, **kwargs) -> str: ...
|
|
@@ -43,7 +43,7 @@ class TriggerFlowEventData:
|
|
|
43
43
|
trigger_type: Literal["event", "runtime_data", "flow_data"],
|
|
44
44
|
value: Any,
|
|
45
45
|
execution: "TriggerFlowExecution",
|
|
46
|
-
|
|
46
|
+
_layer_marks: list[str] | None = None,
|
|
47
47
|
):
|
|
48
48
|
self.trigger_event = trigger_event
|
|
49
49
|
self.trigger_type = trigger_type
|
|
@@ -51,7 +51,7 @@ class TriggerFlowEventData:
|
|
|
51
51
|
self.type = trigger_type
|
|
52
52
|
self.value = value
|
|
53
53
|
self.execution_id = execution.id
|
|
54
|
-
self.
|
|
54
|
+
self._layer_marks = _layer_marks if _layer_marks is not None else []
|
|
55
55
|
self.settings = execution.settings
|
|
56
56
|
|
|
57
57
|
self.get_flow_data = execution.get_flow_data
|
|
@@ -84,17 +84,17 @@ class TriggerFlowEventData:
|
|
|
84
84
|
|
|
85
85
|
@property
|
|
86
86
|
def upper_layer_mark(self):
|
|
87
|
-
return self.
|
|
87
|
+
return self._layer_marks[-2] if len(self._layer_marks) > 1 else None
|
|
88
88
|
|
|
89
89
|
@property
|
|
90
90
|
def layer_mark(self):
|
|
91
|
-
return self.
|
|
91
|
+
return self._layer_marks[-1] if len(self._layer_marks) > 0 else None
|
|
92
92
|
|
|
93
93
|
def layer_in(self):
|
|
94
|
-
self.
|
|
94
|
+
self._layer_marks.append(uuid.uuid4().hex)
|
|
95
95
|
|
|
96
96
|
def layer_out(self):
|
|
97
|
-
self.
|
|
97
|
+
self._layer_marks = self._layer_marks[:-1] if len(self._layer_marks) > 0 else []
|
|
98
98
|
|
|
99
99
|
|
|
100
100
|
TriggerFlowHandler = Callable[[TriggerFlowEventData], Any]
|
|
@@ -4,37 +4,37 @@ agently/_default_settings.yaml,sha256=6woqJ2tjg_jl6kwSOwmTMETfVraHidort2smf0Is_q
|
|
|
4
4
|
agently/base.py,sha256=PY-HgIQesv3_oBsU25Fwe96C35C4GgpaFdxLBUwh-AA,4692
|
|
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=
|
|
7
|
+
agently/builtins/agent_extensions/ConfigurePromptExtension.py,sha256=vURsWcy5UnKppBNOAy0ZnY03yMY3QqH7j3ZeixS8VOo,10230
|
|
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
|
-
agently/builtins/hookers/SystemMessageHooker.py,sha256=
|
|
14
|
-
agently/builtins/plugins/ModelRequester/OpenAICompatible.py,sha256=
|
|
15
|
-
agently/builtins/plugins/PromptGenerator/AgentlyPromptGenerator.py,sha256=
|
|
13
|
+
agently/builtins/hookers/SystemMessageHooker.py,sha256=1nh1FY70PYyZOAQGfQiGnwIvo4ZF3NSAjeghI3sInn4,7207
|
|
14
|
+
agently/builtins/plugins/ModelRequester/OpenAICompatible.py,sha256=Druzptw_aKtCAI-a3wqFO4KgtzAP0L6HZZ_2I7t2u80,25397
|
|
15
|
+
agently/builtins/plugins/PromptGenerator/AgentlyPromptGenerator.py,sha256=GRRR9uxgyCXHKgt_r2BinWnhKy8rYUN8CG9ld2P8n4E,30841
|
|
16
16
|
agently/builtins/plugins/ResponseParser/AgentlyResponseParser.py,sha256=FEhfsiHB4Bx7HfghnObklLj08j8IVwGh0WEVD6U-G3U,17445
|
|
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=
|
|
22
|
+
agently/core/Agent.py,sha256=hxRR3ca71XAabViIZGL31EYF4CAxmQS2KJrktCUs39k,10329
|
|
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=
|
|
25
|
+
agently/core/ModelRequest.py,sha256=Sagd7HQozPPM41gbhYU9Lzj68IKPgR_xa00PA7lzpF4,23171
|
|
26
26
|
agently/core/PluginManager.py,sha256=oUnXbe1ilQTOWwnENxtGtV6wG-yZriCxniqfuxuTFO0,4354
|
|
27
|
-
agently/core/Prompt.py,sha256=
|
|
27
|
+
agently/core/Prompt.py,sha256=oAxRZ7kG07mM6G7p6gP_zX41TgGb8vA-IilcnCb_Gc4,8432
|
|
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=
|
|
31
|
-
agently/core/TriggerFlow/Execution.py,sha256=
|
|
30
|
+
agently/core/TriggerFlow/Chunk.py,sha256=d5cdK8fL-Ayg4-6qJom0J3wDIZFevoCw_kHGYMXBKOU,1559
|
|
31
|
+
agently/core/TriggerFlow/Execution.py,sha256=sXxDt5l9m2ZWMG6JZjnt50akyDFEu4I-YB2yhW-UP5E,11640
|
|
32
32
|
agently/core/TriggerFlow/Process.py,sha256=doIDUa7x0j1TVuOhp-hraC0hHLwpistF-Dksf76NJvQ,837
|
|
33
33
|
agently/core/TriggerFlow/TriggerFlow.py,sha256=03xC1EdWiNfnRbAocH-97JcxyzfCnChivI1KmvPt6-E,7671
|
|
34
34
|
agently/core/TriggerFlow/__init__.py,sha256=eHc6ldUIS0kka_1fZXkdaHFnSDoXaGSvXggwVszMAJQ,911
|
|
35
|
-
agently/core/TriggerFlow/process/BaseProcess.py,sha256=
|
|
36
|
-
agently/core/TriggerFlow/process/ForEachProcess.py,sha256=
|
|
37
|
-
agently/core/TriggerFlow/process/MatchCaseProcess.py,sha256
|
|
35
|
+
agently/core/TriggerFlow/process/BaseProcess.py,sha256=oUlsj0AgK39e24kGWCZY6pXDlpbSVJ-mh-UPhJrqgRI,14467
|
|
36
|
+
agently/core/TriggerFlow/process/ForEachProcess.py,sha256=rjUVouZENnuGFp7GXGTgWJT7uMEhczHamWr9cFugsh0,4549
|
|
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
40
|
agently/integrations/chromadb.py,sha256=hLrjwsU_d4SOGRX0bf-55uiA73YarIzRa8ORFnwu3W8,9797
|
|
@@ -48,13 +48,13 @@ agently/types/data/serializable.py,sha256=v2KlyKNOKp4L6J_Ueupb-gCyrnngvBskFUwNPS
|
|
|
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
|
-
agently/types/plugins/PromptGenerator.py,sha256=
|
|
51
|
+
agently/types/plugins/PromptGenerator.py,sha256=V8kqT0Eeq09AQqfGA-SZ5mNKeit1UrmqlDQCquSMzUU,4752
|
|
52
52
|
agently/types/plugins/ResponseParser.py,sha256=_IRbQhT-G1ZNg2zkJgCYNF5qRaIzrDfbxLC7kO-tdK4,3984
|
|
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
|
-
agently/types/trigger_flow/trigger_flow.py,sha256=
|
|
57
|
+
agently/types/trigger_flow/trigger_flow.py,sha256=6lvhDwizIV5p3h61l1GsmJU_9Tw8v3u-SnHuygkSJdo,3799
|
|
58
58
|
agently/utils/DataFormatter.py,sha256=0P92t81vnp-rJSJvlbTF3yM-PRiteB19BNEQ8cmvmns,9444
|
|
59
59
|
agently/utils/DataLocator.py,sha256=ss8OLet9HN0U1PZb-OCHS6KL54kv7vFZph6G0-GBidk,6015
|
|
60
60
|
agently/utils/DataPathBuilder.py,sha256=sEzE1i2EWn7NMkCCXDT50gR6_qMzcZ0y0YGkYbXdB3s,10007
|
|
@@ -70,7 +70,7 @@ agently/utils/Storage.py,sha256=E7QyNJ9T0yOUafPgdP90La698hgLMSGjhJ7qCEHzxxw,9438
|
|
|
70
70
|
agently/utils/StreamingJSONCompleter.py,sha256=aZ9zuGUTQlP-QKbXHUZCf6EtVuG49MKn8xdhw0VhDEA,4292
|
|
71
71
|
agently/utils/StreamingJSONParser.py,sha256=sPPJOtj5OYvsrukRErcoxRl4yuV1zDuf7pQ_pvw_Zow,21116
|
|
72
72
|
agently/utils/__init__.py,sha256=7MDln5OVkqFEdhhuG8VTdr2q02UWwCj-udndwzWV_iQ,1280
|
|
73
|
-
agently-4.0.6.
|
|
74
|
-
agently-4.0.6.
|
|
75
|
-
agently-4.0.6.
|
|
76
|
-
agently-4.0.6.
|
|
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,,
|
|
File without changes
|
|
File without changes
|