xgae 0.1.7__py3-none-any.whl → 0.1.9__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.
Potentially problematic release.
This version of xgae might be problematic. Click here for more details.
- xgae/engine/engine_base.py +2 -2
- xgae/engine/mcp_tool_box.py +7 -6
- xgae/engine/prompt_builder.py +1 -1
- xgae/engine/responser/non_stream_responser.py +8 -7
- xgae/engine/responser/responser_base.py +54 -56
- xgae/engine/responser/stream_responser.py +24 -25
- xgae/engine/task_engine.py +64 -61
- xgae/engine/task_langfuse.py +63 -0
- xgae/tools/without_general_tools_app.py +1 -1
- xgae/utils/__init__.py +7 -5
- xgae/utils/json_helpers.py +7 -13
- xgae/utils/llm_client.py +62 -39
- xgae/utils/misc.py +3 -1
- xgae/utils/setup_env.py +36 -33
- xgae/utils/xml_tool_parser.py +4 -80
- xgae-0.1.9.dist-info/METADATA +11 -0
- xgae-0.1.9.dist-info/RECORD +20 -0
- {xgae-0.1.7.dist-info → xgae-0.1.9.dist-info}/entry_points.txt +1 -0
- xgae-0.1.7.dist-info/METADATA +0 -11
- xgae-0.1.7.dist-info/RECORD +0 -19
- {xgae-0.1.7.dist-info → xgae-0.1.9.dist-info}/WHEEL +0 -0
xgae/utils/setup_env.py
CHANGED
|
@@ -1,22 +1,17 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import os
|
|
3
3
|
|
|
4
|
+
from dotenv import load_dotenv
|
|
4
5
|
from langfuse import Langfuse
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
import colorlog
|
|
8
|
-
from dotenv import load_dotenv
|
|
9
|
-
load_dotenv()
|
|
7
|
+
from xgae.utils import to_bool
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
env_log_file = os.getenv("LOG_FILE", "log/xga.log")
|
|
13
|
-
log_level = getattr(logging, env_log_level.upper(), logging.INFO)
|
|
9
|
+
load_dotenv()
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
os.remove(env_log_file)
|
|
11
|
+
def setup_logging(log_file: str=None, log_level: str="INFO") :
|
|
12
|
+
import colorlog
|
|
13
|
+
|
|
14
|
+
logging_level = getattr(logging, log_level.upper(), logging.INFO)
|
|
20
15
|
|
|
21
16
|
logger = logging.getLogger()
|
|
22
17
|
for handler in logger.handlers[:]:
|
|
@@ -35,46 +30,54 @@ def setup_logging() -> None:
|
|
|
35
30
|
datefmt='%Y-%m-%d %H:%M:%S'
|
|
36
31
|
)
|
|
37
32
|
|
|
38
|
-
file_formatter = logging.Formatter(
|
|
39
|
-
'%(asctime)s -%(levelname)-8s %(message)s',
|
|
40
|
-
datefmt='%Y-%m-%d %H:%M:%S'
|
|
41
|
-
)
|
|
42
|
-
|
|
43
33
|
console_handler = logging.StreamHandler()
|
|
44
34
|
console_handler.setFormatter(console_formatter)
|
|
35
|
+
logger.addHandler(console_handler)
|
|
45
36
|
|
|
46
|
-
|
|
47
|
-
|
|
37
|
+
if log_file:
|
|
38
|
+
log_dir = os.path.dirname(log_file)
|
|
39
|
+
if log_dir and not os.path.exists(log_dir):
|
|
40
|
+
os.makedirs(log_dir, exist_ok=True)
|
|
41
|
+
else:
|
|
42
|
+
os.remove(log_file)
|
|
48
43
|
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
file_formatter = logging.Formatter(
|
|
45
|
+
'%(asctime)s -%(levelname)-8s %(message)s',
|
|
46
|
+
datefmt='%Y-%m-%d %H:%M:%S'
|
|
47
|
+
)
|
|
51
48
|
|
|
52
|
-
|
|
49
|
+
file_handler = logging.FileHandler(log_file, encoding='utf-8')
|
|
50
|
+
file_handler.setFormatter(file_formatter)
|
|
51
|
+
logger.addHandler(file_handler)
|
|
53
52
|
|
|
54
|
-
|
|
53
|
+
logger.setLevel(logging_level)
|
|
55
54
|
|
|
55
|
+
logging.info(f"📡 XGAE_LOGGING is initialized, log_level={log_level}, log_file={log_file}")
|
|
56
|
+
|
|
57
|
+
def setup_env_logging():
|
|
58
|
+
log_enable = to_bool(os.getenv("LOG_ENABLE", True))
|
|
59
|
+
log_level = os.getenv("LOG_LEVEL", "INFO")
|
|
60
|
+
log_file = os.getenv("LOG_FILE", "log/xga.log")
|
|
61
|
+
if log_enable :
|
|
62
|
+
setup_logging(log_file, log_level)
|
|
56
63
|
|
|
57
64
|
def setup_langfuse() -> Langfuse:
|
|
58
|
-
_langfuse = None
|
|
59
65
|
env_public_key = os.getenv("LANGFUSE_PUBLIC_KEY")
|
|
60
66
|
env_secret_key = os.getenv("LANGFUSE_SECRET_KEY")
|
|
61
67
|
env_host = os.getenv("LANGFUSE_HOST", "https://cloud.langfuse.com")
|
|
62
68
|
if env_public_key and env_secret_key:
|
|
63
|
-
_langfuse = Langfuse(
|
|
69
|
+
_langfuse = Langfuse(enabled=True,
|
|
64
70
|
public_key=env_public_key,
|
|
65
71
|
secret_key=env_secret_key,
|
|
66
72
|
host=env_host)
|
|
67
73
|
|
|
68
|
-
logging.info("
|
|
74
|
+
logging.info("📡 XGAE_LANGFUSE initialized Successfully by Key !")
|
|
69
75
|
else:
|
|
70
|
-
_langfuse = Langfuse(
|
|
71
|
-
logging.warning("Not set key, Langfuse is disabled!")
|
|
76
|
+
_langfuse = Langfuse(enabled=False)
|
|
77
|
+
logging.warning("📡 XGAE_LANGFUSE Not set key, Langfuse is disabled!")
|
|
72
78
|
|
|
73
79
|
return _langfuse
|
|
74
80
|
|
|
75
|
-
|
|
76
81
|
if __name__ == "__main__":
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
trace_id = langfuse.create_trace_id()
|
|
80
|
-
logging.warning(f"trace_id={trace_id}")
|
|
82
|
+
langfuse = setup_langfuse()
|
|
83
|
+
logging.warning(f"langfuse is enable={langfuse.enabled}")
|
xgae/utils/xml_tool_parser.py
CHANGED
|
@@ -68,16 +68,16 @@ class XMLToolParser:
|
|
|
68
68
|
# Find function_calls blocks
|
|
69
69
|
function_calls_matches = self.FUNCTION_CALLS_PATTERN.findall(content)
|
|
70
70
|
|
|
71
|
-
for
|
|
71
|
+
for func_content in function_calls_matches:
|
|
72
72
|
# Find all invoke blocks within this function_calls block
|
|
73
|
-
invoke_matches = self.INVOKE_PATTERN.findall(
|
|
73
|
+
invoke_matches = self.INVOKE_PATTERN.findall(func_content)
|
|
74
74
|
|
|
75
75
|
for function_name, invoke_content in invoke_matches:
|
|
76
76
|
try:
|
|
77
77
|
tool_call = self._parse_invoke_block(
|
|
78
78
|
function_name,
|
|
79
79
|
invoke_content,
|
|
80
|
-
|
|
80
|
+
func_content
|
|
81
81
|
)
|
|
82
82
|
if tool_call:
|
|
83
83
|
tool_calls.append(tool_call)
|
|
@@ -98,17 +98,11 @@ class XMLToolParser:
|
|
|
98
98
|
"function_name": function_name,
|
|
99
99
|
"raw_parameters": {}
|
|
100
100
|
}
|
|
101
|
-
|
|
102
|
-
# Extract all parameters
|
|
101
|
+
|
|
103
102
|
param_matches = self.PARAMETER_PATTERN.findall(invoke_content)
|
|
104
|
-
|
|
105
103
|
for param_name, param_value in param_matches:
|
|
106
|
-
# Clean up the parameter value
|
|
107
104
|
param_value = param_value.strip()
|
|
108
|
-
|
|
109
|
-
# Try to parse as JSON if it looks like JSON
|
|
110
105
|
parsed_value = self._parse_parameter_value(param_value)
|
|
111
|
-
|
|
112
106
|
parameters[param_name] = parsed_value
|
|
113
107
|
parsing_details["raw_parameters"][param_name] = param_value
|
|
114
108
|
|
|
@@ -161,73 +155,3 @@ class XMLToolParser:
|
|
|
161
155
|
|
|
162
156
|
# Return as string
|
|
163
157
|
return value
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
def format_tool_call(self, function_name: str, parameters: Dict[str, Any]) -> str:
|
|
167
|
-
"""
|
|
168
|
-
Format a tool call in the XML format.
|
|
169
|
-
|
|
170
|
-
Args:
|
|
171
|
-
function_name: Name of the function to call
|
|
172
|
-
parameters: Dictionary of parameters
|
|
173
|
-
|
|
174
|
-
Returns:
|
|
175
|
-
Formatted XML string
|
|
176
|
-
"""
|
|
177
|
-
lines = ['<function_calls>', '<invoke name="{}">'.format(function_name)]
|
|
178
|
-
|
|
179
|
-
for param_name, param_value in parameters.items():
|
|
180
|
-
# Convert value to string representation
|
|
181
|
-
if isinstance(param_value, (dict, list)):
|
|
182
|
-
value_str = json.dumps(param_value)
|
|
183
|
-
elif isinstance(param_value, bool):
|
|
184
|
-
value_str = str(param_value).lower()
|
|
185
|
-
else:
|
|
186
|
-
value_str = str(param_value)
|
|
187
|
-
|
|
188
|
-
lines.append('<parameter name="{}">{}</parameter>'.format(
|
|
189
|
-
param_name, value_str
|
|
190
|
-
))
|
|
191
|
-
|
|
192
|
-
lines.extend(['</invoke>', '</function_calls>'])
|
|
193
|
-
return '\n'.join(lines)
|
|
194
|
-
|
|
195
|
-
def validate_tool_call(self, tool_call: XMLToolCall, expected_params: Optional[Dict[str, type]] = None) -> Tuple[bool, Optional[str]]:
|
|
196
|
-
"""
|
|
197
|
-
Validate a tool call against expected parameters.
|
|
198
|
-
|
|
199
|
-
Args:
|
|
200
|
-
tool_call: The XMLToolCall to validate
|
|
201
|
-
expected_params: Optional dict of parameter names to expected types
|
|
202
|
-
|
|
203
|
-
Returns:
|
|
204
|
-
Tuple of (is_valid, error_message)
|
|
205
|
-
"""
|
|
206
|
-
if not tool_call.function_name:
|
|
207
|
-
return False, "Function name is required"
|
|
208
|
-
|
|
209
|
-
if expected_params:
|
|
210
|
-
for param_name, expected_type in expected_params.items():
|
|
211
|
-
if param_name not in tool_call.parameters:
|
|
212
|
-
return False, f"Missing required parameter: {param_name}"
|
|
213
|
-
|
|
214
|
-
param_value = tool_call.parameters[param_name]
|
|
215
|
-
if not isinstance(param_value, expected_type):
|
|
216
|
-
return False, f"Parameter {param_name} should be of type {expected_type.__name__}"
|
|
217
|
-
|
|
218
|
-
return True, None
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
# Convenience function for quick parsing
|
|
222
|
-
def parse_xml_tool_calls(content: str) -> List[XMLToolCall]:
|
|
223
|
-
"""
|
|
224
|
-
Parse XML tool calls from content.
|
|
225
|
-
|
|
226
|
-
Args:
|
|
227
|
-
content: The text content potentially containing XML tool calls
|
|
228
|
-
|
|
229
|
-
Returns:
|
|
230
|
-
List of parsed XMLToolCall objects
|
|
231
|
-
"""
|
|
232
|
-
parser = XMLToolParser()
|
|
233
|
-
return parser.parse_content(content)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: xgae
|
|
3
|
+
Version: 0.1.9
|
|
4
|
+
Summary: Extreme General Agent Engine
|
|
5
|
+
Requires-Python: >=3.13
|
|
6
|
+
Requires-Dist: colorlog==6.9.0
|
|
7
|
+
Requires-Dist: langchain-mcp-adapters==0.1.9
|
|
8
|
+
Requires-Dist: langfuse==2.60.9
|
|
9
|
+
Requires-Dist: langgraph==0.6.5
|
|
10
|
+
Requires-Dist: litellm==1.74.15
|
|
11
|
+
Requires-Dist: mcp==1.13.0
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
xgae/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
xgae/engine/engine_base.py,sha256=ioywuTpDMHEmyVcd6BInoU-vR70PhQStE2MVRWoEiJg,1768
|
|
3
|
+
xgae/engine/mcp_tool_box.py,sha256=ZSCBSXRWhISwyZ1uEIbt3esjesM46g-ktv6CxvyPVDU,10030
|
|
4
|
+
xgae/engine/prompt_builder.py,sha256=X9bS7YIms6LYplCpNHeUmi74xFP5MwFXmXNqOt1Xz-Q,4356
|
|
5
|
+
xgae/engine/task_engine.py,sha256=BLy32wJUbBFGkjAPfHcbSpCUPQm2uZAmLHtZVqvXwx0,18026
|
|
6
|
+
xgae/engine/task_langfuse.py,sha256=-WMnlMcBGfDuJpV0ZYKnVzlO0HizGOfFVGyzVkP6Rag,2260
|
|
7
|
+
xgae/engine/responser/non_stream_responser.py,sha256=80ZFcitjXpQJANxbYpQ0LlhVzIxmURNJi9Fbo953Uak,6349
|
|
8
|
+
xgae/engine/responser/responser_base.py,sha256=8PcsvQHP68FEhu6v3dT9hDCc_rLKs38i4txWLcJD4ck,29851
|
|
9
|
+
xgae/engine/responser/stream_responser.py,sha256=oPGtrT1nedGMjiBAwPzUlu6Z_rPWeVSODC1xQ6D8cTY,52055
|
|
10
|
+
xgae/tools/without_general_tools_app.py,sha256=FGMV6njcOKwwfitc0j_nUov0RC-eWlhO1IP8_KHz1tQ,3788
|
|
11
|
+
xgae/utils/__init__.py,sha256=tMSYguPrubusr7IyKZn6iPYE6qbN7sOsEVDeJPRdPa8,351
|
|
12
|
+
xgae/utils/json_helpers.py,sha256=6BkqiyEF3jV3Irb4Z6-wGY2_FNaLlxE1WKlMJHHT6E0,4645
|
|
13
|
+
xgae/utils/llm_client.py,sha256=nOhPlllUj4mASdj2dU5HkSmDqYZ8ZMpDa7AKQwUWJnQ,13600
|
|
14
|
+
xgae/utils/misc.py,sha256=M8lMXYp1pHiY6Ee8ZTUG88GpOAsE5fbYoRO_hcBFUCE,953
|
|
15
|
+
xgae/utils/setup_env.py,sha256=XD6WmGNyMFDKVzNU_ufYtqJNd2Otq4hzLs9YZ2aSz6g,2613
|
|
16
|
+
xgae/utils/xml_tool_parser.py,sha256=I9xAZC_ElwBY19PNUq-WLXe9FSIJMeAv2Xs-VlajI7Y,4782
|
|
17
|
+
xgae-0.1.9.dist-info/METADATA,sha256=q4_B-_Kt2hswi0kGX9B_H3uI_7C7SWiJOo6HnzoMF8g,309
|
|
18
|
+
xgae-0.1.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
19
|
+
xgae-0.1.9.dist-info/entry_points.txt,sha256=bYzQ-1iabCduosArMzq1hktJrCjp8jq4_E8Sg8-gEic,137
|
|
20
|
+
xgae-0.1.9.dist-info/RECORD,,
|
xgae-0.1.7.dist-info/METADATA
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: xgae
|
|
3
|
-
Version: 0.1.7
|
|
4
|
-
Summary: Extreme General Agent Engine
|
|
5
|
-
Requires-Python: >=3.13
|
|
6
|
-
Requires-Dist: colorlog>=6.9.0
|
|
7
|
-
Requires-Dist: langchain-mcp-adapters>=0.1.4
|
|
8
|
-
Requires-Dist: langfuse>=2.60.5
|
|
9
|
-
Requires-Dist: langgraph>=0.3.21
|
|
10
|
-
Requires-Dist: litellm>=1.74.8
|
|
11
|
-
Requires-Dist: mcp>=1.12.1
|
xgae-0.1.7.dist-info/RECORD
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
xgae/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
xgae/engine/engine_base.py,sha256=ySERuLy1YWsf-3s0NFKcyTnXQ4g69wR-cQhtnG0OFmU,1747
|
|
3
|
-
xgae/engine/mcp_tool_box.py,sha256=iBfCLWXvbkKWd1JnSgBLA1T1KdSdpEZCrROkC_cXp7g,10132
|
|
4
|
-
xgae/engine/prompt_builder.py,sha256=8_rNRJksn2QLV_K98S0x0qNeHcmxhU0kB_53IZJTGOU,4366
|
|
5
|
-
xgae/engine/task_engine.py,sha256=mjS7oDlJH-1wBohzz1FfFng2nE_K0xL-QaNZDuQss3A,17986
|
|
6
|
-
xgae/engine/responser/non_stream_responser.py,sha256=kOP9kDEhHtrDKMyVnBPWEx0yO-xTvVacfXGJJqFtONU,6395
|
|
7
|
-
xgae/engine/responser/responser_base.py,sha256=rn3-LkS_alZUwdIxPfDGC_zAH_CncSQ2I-euYA6a45w,30524
|
|
8
|
-
xgae/engine/responser/stream_responser.py,sha256=5KzCHApiPplZ-zN_sbbEbSvj2rtvKWBshJKe_-x7RDI,52927
|
|
9
|
-
xgae/tools/without_general_tools_app.py,sha256=QknIF4OW9xvOad8gx-F_sCBwQYXqMalnNFvYvZXkQ_I,3789
|
|
10
|
-
xgae/utils/__init__.py,sha256=jChvD-p_p5gsrCZUVYPUGJs4CS9gIdNFcSOpkRpcM4Y,317
|
|
11
|
-
xgae/utils/json_helpers.py,sha256=K1ja6GJCatrAheW9bEWAYSQbDI42__boBCZgtsv1gtk,4865
|
|
12
|
-
xgae/utils/llm_client.py,sha256=RvID4bL9yZon096uvuoFZPlqAPiHhET9-9qYp6sUERc,12605
|
|
13
|
-
xgae/utils/misc.py,sha256=EK94YesZp8AmRUqWfN-CjTxyEHPWdIIWpFNO17dzm9g,915
|
|
14
|
-
xgae/utils/setup_env.py,sha256=EVk0KG92Sk6ejBxXZbDDr_dc3KM8GFMofMA4HvXqSfM,2409
|
|
15
|
-
xgae/utils/xml_tool_parser.py,sha256=EJ6BjpD4CSdmS_LqViUJ6P8H9GY2R1e4Dh8rLCR6nSE,7474
|
|
16
|
-
xgae-0.1.7.dist-info/METADATA,sha256=AbGuJUOv4574WF9a2nQNaTxuOKEN2K_U7RaACci2PME,309
|
|
17
|
-
xgae-0.1.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
18
|
-
xgae-0.1.7.dist-info/entry_points.txt,sha256=rhQ9Vksnu8nA78lPTjiJxOCZ5k6sH6s5YNMR68y7C-A,73
|
|
19
|
-
xgae-0.1.7.dist-info/RECORD,,
|
|
File without changes
|