xgae 0.1.18__py3-none-any.whl → 0.1.19__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/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  if __name__ == "__main__":
2
- from xgae.cli_app import main
2
+ from xgae.engine_cli_app import main
3
3
 
4
4
  main()
@@ -17,8 +17,9 @@ from xgae.engine.responser.responser_base import TaskResponserContext, TaskRespo
17
17
 
18
18
  class XGATaskEngine:
19
19
  def __init__(self,
20
- session_id: Optional[str] = None,
21
20
  task_id: Optional[str] = None,
21
+ session_id: Optional[str] = None,
22
+ user_id: Optional[str] = None,
22
23
  agent_id: Optional[str] = None,
23
24
  general_tools: Optional[List[str]] = None,
24
25
  custom_tools: Optional[List[str]] = None,
@@ -29,8 +30,9 @@ class XGATaskEngine:
29
30
  prompt_builder: Optional[XGAPromptBuilder] = None,
30
31
  tool_box: Optional[XGAToolBox] = None):
31
32
  self.task_id = task_id if task_id else f"xga_task_{uuid4()}"
32
- self.agent_id = agent_id
33
33
  self.session_id = session_id
34
+ self.user_id = user_id
35
+ self.agent_id = agent_id
34
36
 
35
37
  self.llm_client = LLMClient(llm_config)
36
38
  self.model_name = self.llm_client.model_name
@@ -56,16 +58,16 @@ class XGATaskEngine:
56
58
  self.task_response_msgs: List[XGAResponseMessage] = []
57
59
 
58
60
  async def run_task_with_final_answer(self,
59
- task_message: Dict[str, Any],
61
+ task_input: Dict[str, Any],
60
62
  trace_id: Optional[str] = None) -> XGATaskResult:
61
- final_result:XGATaskResult = None
63
+ final_result: XGATaskResult = None
62
64
  try:
63
65
  await self._init_task()
64
66
 
65
- self.task_langfuse.start_root_span("run_task_with_final_answer", task_message, trace_id)
67
+ self.task_langfuse.start_root_span("run_task_with_final_answer", task_input, trace_id)
66
68
 
67
69
  chunks = []
68
- async for chunk in self.run_task(task_message=task_message, trace_id=trace_id):
70
+ async for chunk in self.run_task(task_input, trace_id):
69
71
  chunks.append(chunk)
70
72
 
71
73
  if len(chunks) > 0:
@@ -79,14 +81,14 @@ class XGATaskEngine:
79
81
 
80
82
 
81
83
  async def run_task(self,
82
- task_message: Dict[str, Any],
84
+ task_input: Dict[str, Any],
83
85
  trace_id: Optional[str] = None) -> AsyncGenerator[Dict[str, Any], None]:
84
86
  try:
85
87
  await self._init_task()
86
88
 
87
- self.task_langfuse.start_root_span("run_task", task_message, trace_id)
89
+ self.task_langfuse.start_root_span("run_task", task_input, trace_id)
88
90
 
89
- self.add_response_message(type="user", content=task_message, is_llm_message=True)
91
+ self.add_response_message(type="user", content=task_input, is_llm_message=True)
90
92
 
91
93
  async for chunk in self._run_task_auto():
92
94
  yield chunk
@@ -153,30 +155,30 @@ class XGATaskEngine:
153
155
  status_content = chunk['content']
154
156
  status_type = status_content['status_type']
155
157
  if status_type == "error":
156
- logging.error(f"TaskEngine run_task_auto: task_response error: {chunk.get('message')}")
158
+ logging.error(f"XGATaskEngine run_task_auto: task_response error: {chunk.get('message')}")
157
159
  auto_continue = False
158
160
  break
159
161
  elif status_type == "finish":
160
162
  finish_reason = status_content['finish_reason']
161
163
  if finish_reason == "completed":
162
- logging.info(f"TaskEngine run_task_auto: Detected finish_reason='completed', TASK_COMPLETE Success !")
164
+ logging.info(f"XGATaskEngine run_task_auto: Detected finish_reason='completed', TASK_COMPLETE Success !")
163
165
  auto_continue = False
164
166
  break
165
167
  elif finish_reason == "xml_tool_limit_reached":
166
- logging.warning(f"TaskEngine run_task_auto: Detected finish_reason='xml_tool_limit_reached', stop auto-continue")
168
+ logging.warning(f"XGATaskEngine run_task_auto: Detected finish_reason='xml_tool_limit_reached', stop auto-continue")
167
169
  auto_continue = False
168
170
  break
169
171
  elif finish_reason == "non_tool_call":
170
- logging.warning(f"TaskEngine run_task_auto: Detected finish_reason='non_tool_call', stop auto-continue")
172
+ logging.warning(f"XGATaskEngine run_task_auto: Detected finish_reason='non_tool_call', stop auto-continue")
171
173
  auto_continue = False
172
174
  break
173
175
  elif finish_reason in ["stop", "length"]: # 'length' occur on some LLM
174
176
  auto_continue_count += 1
175
177
  auto_continue = True if auto_continue_count < self.max_auto_run else False
176
178
  update_continuous_state(auto_continue_count, auto_continue)
177
- logging.info(f"TaskEngine run_task_auto: Detected finish_reason='{finish_reason}', auto-continuing ({auto_continue_count}/{self.max_auto_run})")
179
+ logging.info(f"XGATaskEngine run_task_auto: Detected finish_reason='{finish_reason}', auto-continuing ({auto_continue_count}/{self.max_auto_run})")
178
180
  except Exception as parse_error:
179
- trace = log_trace(parse_error,f"TaskEngine run_task_auto: Parse chunk error, chunk: {chunk}")
181
+ trace = log_trace(parse_error,f"XGATaskEngine run_task_auto: Parse chunk error, chunk: {chunk}")
180
182
  self.task_langfuse.root_span.event(name="engine_parse_chunk_error", level="ERROR",
181
183
  status_message=f"Task Engine parse chunk error: {parse_error}",
182
184
  metadata={"content": chunk, "trace": trace})
@@ -185,7 +187,7 @@ class XGATaskEngine:
185
187
  error_msg = self.add_response_message(type="status", content=status_content, is_llm_message=False)
186
188
  yield error_msg
187
189
  except Exception as run_error:
188
- trace = log_trace(run_error, "TaskEngine run_task_auto: Call task_run_once")
190
+ trace = log_trace(run_error, "XGATaskEngine run_task_auto: Call task_run_once")
189
191
  self.task_langfuse.root_span.event(name="engine_task_run_once_error", level="ERROR",
190
192
  status_message=f"Call task_run_once error: {run_error}",
191
193
  metadata={"trace": trace})
@@ -271,7 +273,7 @@ class XGATaskEngine:
271
273
  logging.warning(f"❌ FINAL_RESULT: LLM Result is EMPTY, finish_reason={finish_reason}")
272
274
  final_result = XGATaskResult(type="error", content="LLM has no answer")
273
275
  except Exception as e:
274
- trace = log_trace(e, f"TaskEngine parse_final_result: Parse message chunk error, chunk: {chunk}")
276
+ trace = log_trace(e, f"XGATaskEngine parse_final_result: Parse message chunk error, chunk: {chunk}")
275
277
  self.task_langfuse.root_span.event(name="engine_parse_final_result_error", level="ERROR",
276
278
  status_message=f"Task Engine parse final result error: {e}",
277
279
  metadata={"content": chunk, "trace": trace})
@@ -285,11 +287,12 @@ class XGATaskEngine:
285
287
  is_llm_message: bool,
286
288
  metadata: Optional[Dict[str, Any]]=None)-> XGAResponseMessage:
287
289
  metadata = metadata or {}
288
- metadata["task_id"] = self.task_id
289
- metadata["task_run_id"] = self.task_run_id
290
- metadata["trace_id"] = self.task_langfuse.trace_id
291
- metadata["session_id"] = self.session_id
292
- metadata["agent_id"] = self.agent_id
290
+ metadata['task_id'] = self.task_id
291
+ metadata['task_run_id'] = self.task_run_id
292
+ metadata['trace_id'] = self.task_langfuse.trace_id
293
+ metadata['session_id'] = self.session_id
294
+ metadata['user_id'] = self.user_id
295
+ metadata['agent_id'] = self.agent_id
293
296
 
294
297
  message = XGAResponseMessage(
295
298
  message_id = f"xga_msg_{uuid4()}",
@@ -359,7 +362,14 @@ class XGATaskEngine:
359
362
 
360
363
 
361
364
  def _create_task_langfuse(self)-> XGATaskLangFuse:
362
- return XGATaskLangFuse(self.session_id, self.task_id, self.task_run_id, self.task_no, self.agent_id)
365
+ return XGATaskLangFuse(
366
+ task_id = self.task_id,
367
+ task_run_id = self.task_run_id,
368
+ task_no = self.task_no,
369
+ session_id = self.session_id,
370
+ agent_id = self.agent_id,
371
+ user_id = self.user_id
372
+ )
363
373
 
364
374
 
365
375
  def _logging_reponse_chunk(self, chunk, auto_count: int)-> None:
@@ -384,11 +394,11 @@ class XGATaskEngine:
384
394
  pretty_content = json.dumps(status_content, ensure_ascii=False, indent=2)
385
395
 
386
396
  if chunk_type == "assistant_chunk":
387
- logging.debug(f"TASK_RESP_CHUNK[{auto_count}]<{chunk_type}{prefix}> content: {pretty_content}")
397
+ logging.debug(f"TASK_RESP_CHUNK[{self.task_no}]({auto_count})<{chunk_type}{prefix}> content: {pretty_content}")
388
398
  else:
389
- logging.info(f"TASK_RESP_CHUNK[{auto_count}]<{chunk_type}{prefix}> content: {pretty_content}")
399
+ logging.info(f"TASK_RESP_CHUNK[{self.task_no}]({auto_count})<{chunk_type}{prefix}> content: {pretty_content}")
390
400
  except Exception as e:
391
- logging.error(f"TaskEngine logging_reponse_chunk: Decorate chunk={chunk}, error: {e}")
401
+ logging.error(f"XGATaskEngine logging_reponse_chunk: Decorate chunk={chunk}, error: {e}")
392
402
 
393
403
 
394
404
 
@@ -410,7 +420,7 @@ if __name__ == "__main__":
410
420
  agent_id="agent_1"
411
421
  )
412
422
  user_input = "locate 10.0.0.1 fault and solution"
413
- final_result = await engine.run_task_with_final_answer(task_message={'role': "user", 'content': user_input})
423
+ final_result = await engine.run_task_with_final_answer(task_input={'role': "user", 'content': user_input})
414
424
  print(f"FINAL RESULT:{final_result}")
415
425
 
416
426
 
@@ -1,4 +1,4 @@
1
-
1
+ import logging
2
2
  from typing import Any, Dict, Optional
3
3
  from langfuse import Langfuse
4
4
 
@@ -10,10 +10,11 @@ class XGATaskLangFuse:
10
10
  langfuse: Langfuse = None
11
11
 
12
12
  def __init__(self,
13
- session_id: str,
14
13
  task_id:str,
15
14
  task_run_id: str,
16
15
  task_no: int,
16
+ session_id: str,
17
+ user_id: str,
17
18
  agent_id: str) -> None:
18
19
  if XGATaskLangFuse.langfuse is None:
19
20
  XGATaskLangFuse.langfuse = setup_langfuse()
@@ -22,6 +23,7 @@ class XGATaskLangFuse:
22
23
  self.task_id = task_id
23
24
  self.task_run_id = task_run_id
24
25
  self.task_no = task_no
26
+ self.user_id = user_id
25
27
  self.agent_id = agent_id
26
28
 
27
29
  self.trace_id = None
@@ -31,7 +33,7 @@ class XGATaskLangFuse:
31
33
 
32
34
  def start_root_span(self,
33
35
  root_span_name: str,
34
- task_message: Dict[str, Any],
36
+ task_input: Dict[str, Any],
35
37
  trace_id: Optional[str] = None):
36
38
  if self.root_span is None:
37
39
  trace = None
@@ -39,13 +41,23 @@ class XGATaskLangFuse:
39
41
  self.trace_id = trace_id
40
42
  trace = XGATaskLangFuse.langfuse.trace(id=trace_id)
41
43
  else:
42
- trace = XGATaskLangFuse.langfuse.trace(name="xga_task_engine")
44
+ trace = XGATaskLangFuse.langfuse.trace(name="xga_task_engine", session_id=self.session_id)
43
45
  self.trace_id = trace.id
44
46
 
45
- metadata = {'task_id': self.task_id, 'session_id': self.session_id, 'agent_id': self.agent_id}
46
- self.root_span = trace.span(id=self.task_run_id, name=root_span_name, input=task_message,metadata=metadata)
47
+ metadata = {
48
+ 'task_id' : self.task_id,
49
+ 'session_id' : self.session_id,
50
+ 'user_id' : self.user_id,
51
+ 'agent_id' : self.agent_id
52
+ }
53
+
54
+ self.root_span = trace.span(id=self.task_run_id,
55
+ name=f"{root_span_name}[{self.task_no}]",
56
+ input=task_input,
57
+ metadata=metadata)
47
58
  self.root_span_name = root_span_name
48
59
 
60
+ logging.info(f"{root_span_name} TASK_INPUT: {task_input}")
49
61
 
50
62
  def end_root_span(self, root_span_name:str, output: Optional[XGATaskResult]=None):
51
63
  if self.root_span and self.root_span_name == root_span_name:
@@ -55,7 +67,7 @@ class XGATaskLangFuse:
55
67
 
56
68
 
57
69
  def create_llm_langfuse_meta(self, llm_count:int)-> LangfuseMetadata:
58
- generation_name = f"xga_task_engine_llm_completion[{self.task_no}]({llm_count})"
70
+ generation_name = f"xga_engine_llm_completion[{self.task_no}]({llm_count})"
59
71
  generation_id = f"{self.task_run_id}({llm_count})"
60
72
  return LangfuseMetadata(
61
73
  generation_name = generation_name,
@@ -14,7 +14,7 @@ langfuse = setup_langfuse()
14
14
  def get_user_message(question)-> str:
15
15
  while True:
16
16
  user_message = input(f"\n💬 {question}: ")
17
- if user_message.lower() == 'exit':
17
+ if user_message.lower() == 'exit' or user_message.lower() == 'quit':
18
18
  print("\n====== Extreme General Agent Engine CLI EXIT ======")
19
19
  sys.exit()
20
20
 
@@ -44,7 +44,7 @@ async def cli() -> None:
44
44
  general_tools = ["*"]
45
45
 
46
46
  while True:
47
- user_message = get_user_message("Enter your message (or 'exit' to quit)")
47
+ user_message = get_user_message("Enter your task input message (or 'exit' to quit)")
48
48
 
49
49
  print("\n🔄 Running XGA Engine ...\n")
50
50
  engine = XGATaskEngine(tool_box=tool_box,
@@ -54,27 +54,24 @@ async def cli() -> None:
54
54
 
55
55
  # Two task run in same langfuse trace
56
56
  trace_id = langfuse.trace(name="xgae_cli").trace_id
57
-
58
- final_result = await engine.run_task_with_final_answer(
59
- task_message={'role': "user", 'content': user_message},
60
- trace_id=trace_id
61
- )
62
-
63
- if final_result["type"] == "ask":
64
- await asyncio.sleep(1)
65
- print(f"\n📌 ASK INFO: {final_result['content']}")
66
- user_message = get_user_message("Enter ASK information (or 'exit' to quit)")
57
+ auto_continue = True
58
+ while auto_continue:
59
+ auto_continue = False
67
60
  final_result = await engine.run_task_with_final_answer(
68
- task_message={'role': "user", 'content': user_message},
61
+ task_input={'role': "user", 'content': user_message},
69
62
  trace_id=trace_id
70
63
  )
71
64
 
72
- await asyncio.sleep(1)
73
- result_prefix = "✅" if final_result["type"] == "answer" else "❌"
74
- if final_result["type"] == "ask":
75
- print("\n *** IMPORTANT: XGA CLI only support showing ONE TURN ASK !")
76
- result_prefix = "⚠️"
77
- print(f"\n {result_prefix} FINAL RESULT: {final_result['content']}")
65
+ if final_result["type"] == "ask":
66
+ await asyncio.sleep(1)
67
+ print(f"\n📌 ASK INFO: {final_result['content']}")
68
+ user_message = get_user_message("Enter ASK information (or 'exit' to quit)")
69
+ auto_continue = True
70
+ continue
71
+
72
+ await asyncio.sleep(1)
73
+ result_prefix = "✅" if final_result["type"] == "answer" else "❌"
74
+ print(f"\n {result_prefix} FINAL RESULT: {final_result['content']}")
78
75
 
79
76
 
80
77
  def main():
@@ -1,10 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xgae
3
- Version: 0.1.18
3
+ Version: 0.1.19
4
4
  Summary: Extreme General Agent Engine
5
5
  Requires-Python: >=3.13
6
6
  Requires-Dist: colorlog==6.9.0
7
7
  Requires-Dist: langchain-mcp-adapters==0.1.9
8
+ Requires-Dist: langchain==0.3.27
8
9
  Requires-Dist: langfuse==2.60.9
9
10
  Requires-Dist: langgraph==0.6.5
10
11
  Requires-Dist: litellm==1.74.15
@@ -1,10 +1,10 @@
1
- xgae/__init__.py,sha256=OEUd9y9AoGBd3xYerdTTpz9xl4NWkmXeq1a2eil7Qro,72
2
- xgae/cli_app.py,sha256=ieTaS0b532P_8g9Mz2xda8TOZwYD2hKGnNZiarADAM0,3000
1
+ xgae/__init__.py,sha256=oBX_YzTliM-343BAlR-sD7BUZmsCJ7PY2oYrGBhsdLM,79
2
+ xgae/engine_cli_app.py,sha256=FdmIpq8KDsgyZNfwCDgNX7FEZFeRFyGOt_H1oZF8aKs,2890
3
3
  xgae/engine/engine_base.py,sha256=RR1em2wHiM2jP-peHt77SKdHWjnYOjdIIzN93zT61cA,1715
4
4
  xgae/engine/mcp_tool_box.py,sha256=G4hKIMguwg1cO4Us2NMfdloYim8kuikVyVTIPucJr7o,10903
5
5
  xgae/engine/prompt_builder.py,sha256=6I5rjgvNJ27QJ8DDuBTplutoPZdGs9LYFv3TSgT7zmc,5045
6
- xgae/engine/task_engine.py,sha256=_GfIpWGBd83jf2xnS0vDvgyQR0mqQSb6ZrGoBFFrMt4,21249
7
- xgae/engine/task_langfuse.py,sha256=n2bajsHq2Zt3jetel8cSlN2lo42mZgTmbR4Zbx9JvsM,2416
6
+ xgae/engine/task_engine.py,sha256=7B7nbERTh9HDgDH4lXS_s4KTsVU41AgR7rnN4jKLozQ,21588
7
+ xgae/engine/task_langfuse.py,sha256=J9suOhlIGSJor-mZsggPZf3XQld9dTkfpHAS2fVirvM,2859
8
8
  xgae/engine/responser/non_stream_responser.py,sha256=zEJjqCgZVe2B8gkHYRFU7tmBV834f7w2a4Ws25P1N-c,5289
9
9
  xgae/engine/responser/responser_base.py,sha256=jhl1Bdz1Fs3KofGEymThNXlQuCORFTTkTAR_U47krds,24403
10
10
  xgae/engine/responser/stream_responser.py,sha256=cv4UGcxj8OksEogW7DUGTCvSJabu-DF6GceFyUwaXI4,7627
@@ -15,7 +15,7 @@ xgae/utils/llm_client.py,sha256=mWRtvtSMk_8NuzFReT9x52ayHlCNVZMZAltD6TQ-xZ8,1440
15
15
  xgae/utils/misc.py,sha256=aMWOvJ9VW52q-L9Lkjl1hvXqLwpJAmyxA-Z8jzqFG0U,907
16
16
  xgae/utils/setup_env.py,sha256=MqNG0c2QQBDFU1kI8frxr9kB5d08Mmi3QZ1OoorgIa0,2662
17
17
  xgae/utils/xml_tool_parser.py,sha256=Mb0d8kBrfyAEvUwW1Nqir-3BgxZRr0ZX3WymQouuFSo,4859
18
- xgae-0.1.18.dist-info/METADATA,sha256=zMbJrDIxmWY79uRRluq-HuNOtxdE7jOQELEcRvVB57w,310
19
- xgae-0.1.18.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
20
- xgae-0.1.18.dist-info/entry_points.txt,sha256=KdL6b_heFPyb1XIq5_L8Rgydpn64VDExFZafU_Qd9ow,222
21
- xgae-0.1.18.dist-info/RECORD,,
18
+ xgae-0.1.19.dist-info/METADATA,sha256=MHUqZkPIWB9Tn_sLyFkFBw4XZKPAQqC_z0QudI1s5hk,343
19
+ xgae-0.1.19.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
20
+ xgae-0.1.19.dist-info/entry_points.txt,sha256=wmvgtMQbtzTbDPETS-tbQJD7jVlcs4hp0w6wOB0ooCc,229
21
+ xgae-0.1.19.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  [console_scripts]
2
2
  example-a2a-tools = examples.tools.simu_a2a_tools_app:main
3
3
  example-fault-tools = examples.tools.custom_fault_tools_app:main
4
- xgae = xgae.cli_app:main
4
+ xgae = xgae.engine_cli_app:main
5
5
  xgae-tools = xgae.tools.without_general_tools_app:main
File without changes