xgae 0.1.9__tar.gz → 0.1.12__tar.gz

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.

Files changed (52) hide show
  1. {xgae-0.1.9 → xgae-0.1.12}/.env +9 -4
  2. xgae-0.1.12/.idea/ai_toolkit.xml +6 -0
  3. {xgae-0.1.9 → xgae-0.1.12}/.idea/workspace.xml +25 -7
  4. {xgae-0.1.9 → xgae-0.1.12}/PKG-INFO +1 -1
  5. {xgae-0.1.9 → xgae-0.1.12}/pyproject.toml +2 -1
  6. xgae-0.1.12/src/examples/agent/langgraph/react/react_agent.py +206 -0
  7. {xgae-0.1.9 → xgae-0.1.12}/src/examples/engine/run_human_in_loop.py +7 -7
  8. {xgae-0.1.9 → xgae-0.1.12}/src/examples/engine/run_simple.py +6 -3
  9. xgae-0.1.12/src/examples/engine/run_user_prompt.py +30 -0
  10. xgae-0.1.12/src/xgae/__init__.py +4 -0
  11. xgae-0.1.12/src/xgae/cli_app.py +85 -0
  12. {xgae-0.1.9 → xgae-0.1.12}/src/xgae/engine/engine_base.py +3 -3
  13. {xgae-0.1.9 → xgae-0.1.12}/src/xgae/engine/mcp_tool_box.py +4 -4
  14. {xgae-0.1.9 → xgae-0.1.12}/src/xgae/engine/responser/non_stream_responser.py +33 -38
  15. {xgae-0.1.9 → xgae-0.1.12}/src/xgae/engine/responser/responser_base.py +42 -40
  16. xgae-0.1.12/src/xgae/engine/responser/stream_responser.py +138 -0
  17. {xgae-0.1.9 → xgae-0.1.12}/src/xgae/engine/task_engine.py +98 -50
  18. {xgae-0.1.9 → xgae-0.1.12}/src/xgae/engine/task_langfuse.py +8 -6
  19. {xgae-0.1.9 → xgae-0.1.12}/src/xgae/tools/without_general_tools_app.py +2 -3
  20. {xgae-0.1.9 → xgae-0.1.12}/src/xgae/utils/__init__.py +2 -2
  21. {xgae-0.1.9 → xgae-0.1.12}/src/xgae/utils/json_helpers.py +2 -2
  22. {xgae-0.1.9 → xgae-0.1.12}/src/xgae/utils/llm_client.py +42 -32
  23. {xgae-0.1.9 → xgae-0.1.12}/src/xgae/utils/setup_env.py +4 -3
  24. {xgae-0.1.9 → xgae-0.1.12}/test/test_langfuse.py +2 -1
  25. xgae-0.1.12/uv.lock +1386 -0
  26. xgae-0.1.9/src/examples/engine/run_user_prompt.py +0 -32
  27. xgae-0.1.9/src/xgae/__init__.py +0 -0
  28. xgae-0.1.9/src/xgae/engine/responser/stream_responser.py +0 -825
  29. xgae-0.1.9/uv.lock +0 -1386
  30. {xgae-0.1.9 → xgae-0.1.12}/.idea/.gitignore +0 -0
  31. {xgae-0.1.9 → xgae-0.1.12}/.idea/inspectionProfiles/Project_Default.xml +0 -0
  32. {xgae-0.1.9 → xgae-0.1.12}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
  33. {xgae-0.1.9 → xgae-0.1.12}/.idea/misc.xml +0 -0
  34. {xgae-0.1.9 → xgae-0.1.12}/.idea/modules.xml +0 -0
  35. {xgae-0.1.9 → xgae-0.1.12}/.idea/vcs.xml +0 -0
  36. {xgae-0.1.9 → xgae-0.1.12}/.idea/xgae.iml +0 -0
  37. {xgae-0.1.9 → xgae-0.1.12}/.python-version +0 -0
  38. {xgae-0.1.9 → xgae-0.1.12}/README.md +0 -0
  39. {xgae-0.1.9 → xgae-0.1.12}/mcpservers/custom_servers.json +0 -0
  40. {xgae-0.1.9 → xgae-0.1.12}/mcpservers/xga_server.json +0 -0
  41. {xgae-0.1.9 → xgae-0.1.12}/mcpservers/xga_server_sse.json +0 -0
  42. {xgae-0.1.9 → xgae-0.1.12}/src/examples/tools/custom_fault_tools_app.py +0 -0
  43. {xgae-0.1.9 → xgae-0.1.12}/src/xgae/engine/prompt_builder.py +0 -0
  44. {xgae-0.1.9 → xgae-0.1.12}/src/xgae/utils/misc.py +0 -0
  45. {xgae-0.1.9 → xgae-0.1.12}/src/xgae/utils/xml_tool_parser.py +0 -0
  46. {xgae-0.1.9 → xgae-0.1.12}/templates/custom_tool_prompt_template.txt +0 -0
  47. /xgae-0.1.9/templates/example_user_prompt.txt → /xgae-0.1.12/templates/example/fault_user_prompt.txt +0 -0
  48. {xgae-0.1.9 → xgae-0.1.12}/templates/gemini_system_prompt_template.txt +0 -0
  49. {xgae-0.1.9 → xgae-0.1.12}/templates/general_tool_prompt_template.txt +0 -0
  50. {xgae-0.1.9 → xgae-0.1.12}/templates/system_prompt_response_sample.txt +0 -0
  51. {xgae-0.1.9 → xgae-0.1.12}/templates/system_prompt_template.txt +0 -0
  52. {xgae-0.1.9 → xgae-0.1.12}/test/test_litellm_langfuse.py +0 -0
@@ -1,5 +1,5 @@
1
1
  # LOG
2
- LOG_LEVEL=INFO
2
+ LOG_LEVEL=DEBUG
3
3
  LOG_FILE=log/xgae.log
4
4
  LOG_ENABLE=True
5
5
 
@@ -10,15 +10,20 @@ LANGFUSE_HOST=https://cloud.langfuse.com
10
10
 
11
11
  # LLM
12
12
  LLM_MODEL=openai/qwen3-235b-a22b
13
- #LLM_MODEL=openai/qwen-plus
14
13
  LLM_API_BASE=https://dashscope.aliyuncs.com/compatible-mode/v1
15
14
  LLM_API_KEY=
16
15
  LLM_MAX_TOKENS=16384
17
16
  LLM_TEMPERATURE=0.7
18
17
  LLM_MAX_RETRIES=2
18
+ LLM_STREAM=True
19
+ LLM_ENABLE_THINKING=False
19
20
 
20
- # TASK
21
- MAX_AUTO_RUN = 15
21
+ LLM_LANGFUSE_ENABLE=False
22
+
23
+
24
+ # TASK_ENGINE
25
+ MAX_AUTO_RUN=15
26
+ USE_ASSISTANT_CHUNK_MSG=False
22
27
 
23
28
 
24
29
 
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="AI Toolkit Settings">
4
+ <option name="importsOfInterestPresent" value="true" />
5
+ </component>
6
+ </project>
@@ -28,9 +28,12 @@
28
28
  <component name="PropertiesComponent"><![CDATA[{
29
29
  "keyToString": {
30
30
  "ModuleVcsDetector.initialDetectionPerformed": "true",
31
- "Python.llm_client.executor": "Run",
31
+ "Python.__init__.executor": "Run",
32
+ "Python.cli_app.executor": "Run",
33
+ "Python.llm_client.executor": "Debug",
32
34
  "Python.mcp_tool_box.executor": "Run",
33
35
  "Python.message_tools_app.executor": "Run",
36
+ "Python.react_agent.executor": "Run",
34
37
  "Python.responser_base.executor": "Run",
35
38
  "Python.run_engine_with_human_in_loop.executor": "Run",
36
39
  "Python.run_human_in_loop.executor": "Run",
@@ -40,12 +43,14 @@
40
43
  "Python.run_xga_engine.executor": "Run",
41
44
  "Python.setup_env.executor": "Run",
42
45
  "Python.task_engine.executor": "Run",
46
+ "Python.task_langfuse.executor": "Debug",
43
47
  "Python.test_langfuse.executor": "Run",
44
48
  "Python.test_litellm_langfuse.executor": "Run",
45
49
  "Python.utils.executor": "Run",
46
50
  "Python.xga_engine.executor": "Run",
47
51
  "Python.xga_mcp_tool_box.executor": "Debug",
48
52
  "Python.xga_prompt_builder.executor": "Debug",
53
+ "Python.xgae_cli.executor": "Run",
49
54
  "RunOnceActivity.ShowReadmeOnStart": "true",
50
55
  "last_opened_file_path": "/Users/sharkystar/DevProjects/xga/xgae",
51
56
  "node.js.detected.package.eslint": "true",
@@ -59,6 +64,8 @@
59
64
  }]]></component>
60
65
  <component name="RecentsManager">
61
66
  <key name="MoveFile.RECENT_KEYS">
67
+ <recent name="$PROJECT_DIR$/src/examples/agent/langgraph/react" />
68
+ <recent name="$PROJECT_DIR$/src/examples" />
62
69
  <recent name="$PROJECT_DIR$/src/examples/engine" />
63
70
  <recent name="$PROJECT_DIR$/src/xgae/engine/responser" />
64
71
  </key>
@@ -166,7 +173,13 @@
166
173
  <workItem from="1755737435202" duration="48139000" />
167
174
  <workItem from="1756044658912" duration="1248000" />
168
175
  <workItem from="1756082326044" duration="23657000" />
169
- <workItem from="1756168626188" duration="45746000" />
176
+ <workItem from="1756168626188" duration="52435000" />
177
+ <workItem from="1756305726553" duration="2819000" />
178
+ <workItem from="1756340066915" duration="19032000" />
179
+ <workItem from="1756371469253" duration="1657000" />
180
+ <workItem from="1756383619553" duration="2663000" />
181
+ <workItem from="1756386338550" duration="12000" />
182
+ <workItem from="1756429146558" duration="24412000" />
170
183
  </task>
171
184
  <servers />
172
185
  </component>
@@ -185,23 +198,28 @@
185
198
  </breakpoint-manager>
186
199
  </component>
187
200
  <component name="com.intellij.coverage.CoverageDataManagerImpl">
201
+ <SUITE FILE_PATH="coverage/xgae$task_langfuse.coverage" NAME="task_langfuse Coverage Results" MODIFIED="1756306181167" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
188
202
  <SUITE FILE_PATH="coverage/xgae$test_litellm_langfuse.coverage" NAME="test_litellm_langfuse Coverage Results" MODIFIED="1756196476262" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
189
203
  <SUITE FILE_PATH="coverage/xgae$xga_engine.coverage" NAME="xga_engine Coverage Results" MODIFIED="1755580277172" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
190
- <SUITE FILE_PATH="coverage/xgae$run_simple.coverage" NAME="run_simple Coverage Results" MODIFIED="1756280626870" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
204
+ <SUITE FILE_PATH="coverage/xgae$run_simple.coverage" NAME="run_simple Coverage Results" MODIFIED="1756452256460" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
191
205
  <SUITE FILE_PATH="coverage/xgae$run_human_in_loop.coverage" NAME="run_human_in_loop Coverage Results" MODIFIED="1756279131815" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
192
206
  <SUITE FILE_PATH="coverage/xgae$run_xga_engine.coverage" NAME="run_task_engine Coverage Results" MODIFIED="1756111613459" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
207
+ <SUITE FILE_PATH="coverage/xgae$cli_app.coverage" NAME="cli_app Coverage Results" MODIFIED="1756372555094" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
193
208
  <SUITE FILE_PATH="coverage/xgae$message_tools_app.coverage" NAME="message_tools_app Coverage Results" MODIFIED="1756094157566" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
194
209
  <SUITE FILE_PATH="coverage/xgae$run_engine_with_human_in_loop.coverage" NAME="run_engine_with_human_in_loop Coverage Results" MODIFIED="1756089269027" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
210
+ <SUITE FILE_PATH="coverage/xgae$__init__.coverage" NAME="__init__ Coverage Results" MODIFIED="1756345820610" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
211
+ <SUITE FILE_PATH="coverage/xgae$react_agent.coverage" NAME="react_agent Coverage Results" MODIFIED="1756372008835" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
195
212
  <SUITE FILE_PATH="coverage/xgae$xga_prompt_builder.coverage" NAME="xga_prompt_builder Coverage Results" MODIFIED="1755587456555" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
196
213
  <SUITE FILE_PATH="coverage/xgae$test_langfuse.coverage" NAME="test_langfuse Coverage Results" MODIFIED="1756196410142" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
197
- <SUITE FILE_PATH="coverage/xgae$run_task_engine.coverage" NAME="run_task_engine Coverage Results" MODIFIED="1756280748615" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
214
+ <SUITE FILE_PATH="coverage/xgae$run_task_engine.coverage" NAME="run_task_engine Coverage Results" MODIFIED="1756459820516" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
198
215
  <SUITE FILE_PATH="coverage/xgae$responser_base.coverage" NAME="responser_base Coverage Results" MODIFIED="1756103040764" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
199
216
  <SUITE FILE_PATH="coverage/xgae$mcp_tool_box.coverage" NAME="mcp_tool_box Coverage Results" MODIFIED="1756274403389" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
200
217
  <SUITE FILE_PATH="coverage/xgae$utils.coverage" NAME="utils Coverage Results" MODIFIED="1755226923439" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
201
218
  <SUITE FILE_PATH="coverage/xgae$setup_env.coverage" NAME="setup_env Coverage Results" MODIFIED="1756273791782" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
202
- <SUITE FILE_PATH="coverage/xgae$run_user_prompt.coverage" NAME="run_user_prompt Coverage Results" MODIFIED="1756279512361" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
219
+ <SUITE FILE_PATH="coverage/xgae$run_user_prompt.coverage" NAME="run_user_prompt Coverage Results" MODIFIED="1756453021298" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
220
+ <SUITE FILE_PATH="coverage/xgae$xgae_cli.coverage" NAME="xgae_cli Coverage Results" MODIFIED="1756347000850" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
203
221
  <SUITE FILE_PATH="coverage/xgae$xga_mcp_tool_box.coverage" NAME="xga_mcp_tool_box Coverage Results" MODIFIED="1755583099719" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
204
- <SUITE FILE_PATH="coverage/xgae$llm_client.coverage" NAME="llm_client Coverage Results" MODIFIED="1756261767854" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
205
- <SUITE FILE_PATH="coverage/xgae$task_engine.coverage" NAME="task_engine Coverage Results" MODIFIED="1756269353871" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
222
+ <SUITE FILE_PATH="coverage/xgae$llm_client.coverage" NAME="llm_client Coverage Results" MODIFIED="1756429245697" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
223
+ <SUITE FILE_PATH="coverage/xgae$task_engine.coverage" NAME="task_engine Coverage Results" MODIFIED="1756454873435" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
206
224
  </component>
207
225
  </project>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xgae
3
- Version: 0.1.9
3
+ Version: 0.1.12
4
4
  Summary: Extreme General Agent Engine
5
5
  Requires-Python: >=3.13
6
6
  Requires-Dist: colorlog==6.9.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "xgae"
3
- version = "0.1.9"
3
+ version = "0.1.12"
4
4
  description = "Extreme General Agent Engine"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -21,5 +21,6 @@ build-backend = "hatchling.build"
21
21
  exclude = ["log/*"]
22
22
 
23
23
  [project.scripts]
24
+ xgae = "xgae.cli_app:main"
24
25
  xgae-tools = "xgae.tools.without_general_tools_app:main"
25
26
  custom_fault_tools = "examples.tools.custom_fault_tools_app:main"
@@ -0,0 +1,206 @@
1
+ import asyncio
2
+ import logging
3
+ from typing import Any, Dict, List, Annotated, Sequence, TypedDict
4
+
5
+ from langchain_core.messages import BaseMessage, HumanMessage, AIMessage
6
+ from langgraph.checkpoint.memory import MemorySaver
7
+ from langgraph.graph import END, START, StateGraph
8
+ from langgraph.graph.message import add_messages
9
+
10
+ from xgae.engine.engine_base import XGATaskResult, XGAResponseMessage
11
+ from xgae.engine.mcp_tool_box import XGAMcpToolBox
12
+ from xgae.utils.setup_env import setup_langfuse, setup_logging
13
+ from xgae.utils import handle_error
14
+ from xgae.utils.misc import read_file
15
+ from xgae.engine.task_engine import XGATaskEngine
16
+
17
+ class TaskState(TypedDict, total=False):
18
+ """State definition for the agent orchestration graph"""
19
+ messages: Annotated[Sequence[BaseMessage], add_messages]
20
+ user_input: str
21
+ next_node: str
22
+ agent_context: Dict[str, Any]
23
+ system_prompt: str
24
+ custom_tools: List[str]
25
+ general_tools: List[str]
26
+ task_result: XGATaskResult
27
+ iteration_count: int
28
+
29
+ langfuse = setup_langfuse()
30
+
31
+ class XGAReactAgent:
32
+ MAX_TASK_RETRY = 2
33
+
34
+ def __init__(self):
35
+ self.tool_box = XGAMcpToolBox(custom_mcp_server_file="mcpservers/custom_servers.json")
36
+ self.graph = None
37
+
38
+ async def _create_graph(self) -> StateGraph:
39
+ try:
40
+ graph_builder = StateGraph(TaskState)
41
+
42
+ # Add nodes
43
+ graph_builder.add_node("supervisor", self._supervisor_node)
44
+ graph_builder.add_node("select_tool", self._select_tool_node)
45
+ graph_builder.add_node("exec_task", self._exec_task_node)
46
+ graph_builder.add_node("final_result", self._final_result_node)
47
+
48
+ # Add edges
49
+ graph_builder.add_edge(START, "supervisor")
50
+ graph_builder.add_conditional_edges(
51
+ "supervisor",
52
+ self._next_condition,
53
+ {
54
+ "select_tool": "select_tool",
55
+ "exec_task": "exec_task",
56
+ "end": END
57
+ }
58
+ )
59
+
60
+ graph_builder.add_edge("select_tool", "exec_task")
61
+ graph_builder.add_edge("exec_task", "final_result")
62
+
63
+ graph_builder.add_conditional_edges(
64
+ "final_result",
65
+ self._next_condition,
66
+ {
67
+ "supervisor": "supervisor",
68
+ "end": END
69
+ }
70
+ )
71
+
72
+ graph = graph_builder.compile(checkpointer=MemorySaver())
73
+ graph.name = "XGARectAgentGraph"
74
+
75
+ return graph
76
+ except Exception as e:
77
+ logging.error("Failed to create XGARectAgent Graph: %s", str(e))
78
+ raise
79
+
80
+ def _search_system_prompt(self, user_input: str) -> str:
81
+ # You should search RAG use user_input, fetch COT or Prompt for your business
82
+ system_prompt = None if "fault" not in user_input else read_file("templates/example/fault_user_prompt.txt")
83
+ return system_prompt
84
+
85
+ async def _supervisor_node(self, state: TaskState) -> Dict[str, Any]:
86
+ user_input = state.get("user_input", "")
87
+ system_prompt = self._search_system_prompt(user_input)
88
+
89
+ general_tools = [] if system_prompt else ["*"]
90
+ custom_tools = ["*"] if system_prompt else []
91
+
92
+ next_node = "select_tool" if system_prompt else "exec_task"
93
+ return {
94
+ "system_prompt" : system_prompt,
95
+ "next_node" : next_node,
96
+ "general_tools": general_tools,
97
+ "custom_tools": custom_tools,
98
+ }
99
+
100
+ def _select_custom_tools(self, system_prompt: str) -> list[str]:
101
+ custom_tools = ["*"] if system_prompt else []
102
+ return custom_tools
103
+
104
+ async def _select_tool_node(self, state: TaskState) -> Dict[str, Any]:
105
+ system_prompt = state.get("system_prompt",None)
106
+ general_tools = []
107
+ custom_tools = self._select_custom_tools(system_prompt)
108
+ return {
109
+ "general_tools" : general_tools,
110
+ "custom_tools" : custom_tools,
111
+ }
112
+
113
+ async def _exec_task_node(self, state: TaskState) -> Dict[str, Any]:
114
+ user_input = state.get("user_input", "")
115
+ system_prompt = state.get("system_prompt",None)
116
+ general_tools = state.get("general_tools",[])
117
+ custom_tools = state.get("custom_tools",[])
118
+ is_system_prompt = True if system_prompt is not None else False
119
+ try:
120
+ logging.info(f"🔥 XGATaskEngine: run_task_with_final_answer: user_input={user_input}, general_tools={general_tools}, custom_tools={custom_tools}, is_system_prompt={is_system_prompt}")
121
+ engine = XGATaskEngine(tool_box=self.tool_box,
122
+ general_tools=general_tools,
123
+ custom_tools=custom_tools,
124
+ system_prompt=system_prompt)
125
+ task_result = await engine.run_task_with_final_answer(
126
+ task_message={"role": "user", "content": user_input}
127
+ )
128
+ except Exception as e:
129
+ logging.error("Failed to execute task: %s", str(e))
130
+ task_result = XGATaskResult(type="error", content="Failed to execute task")
131
+
132
+ iteration_count = state.get("iteration_count", 0) + 1
133
+ return {
134
+ "task_result" : task_result,
135
+ "iteration_count": iteration_count,
136
+ }
137
+
138
+ async def _final_result_node(self, state: TaskState) -> Dict[str, Any]:
139
+ iteration_count = state.get("iteration_count")
140
+ task_result = state.get("task_result")
141
+ next_node = "end"
142
+ if iteration_count < self.MAX_TASK_RETRY and task_result["type"] == "error":
143
+ next_node = "supervisor"
144
+ return {
145
+ "next_node" : next_node
146
+ }
147
+
148
+ def _next_condition(self, state: TaskState) -> str:
149
+ next_node = state.get("next_node")
150
+ return next_node
151
+
152
+
153
+ async def generate(self, user_input: str) -> XGATaskResult:
154
+ result = None
155
+ try:
156
+ logging.info("****** Start React Agent for user_input: %s", user_input)
157
+
158
+ # Create graph if not already created
159
+ if self.graph is None:
160
+ self.graph = await self._create_graph()
161
+
162
+ # Initialize state
163
+ initial_state = {
164
+ "messages": [HumanMessage(content=f"information for: {user_input}")],
165
+ "user_input": user_input,
166
+ "next_node": None,
167
+ "agent_context": {},
168
+ "iteration_count": 0
169
+ }
170
+
171
+ # Run the retrieval graph with proper configuration
172
+ config = {"recursion_limit": 100,
173
+ "configurable": {"thread_id": "manager_async_generate_thread"}}
174
+ final_state = await self.graph.ainvoke(initial_state, config=config)
175
+
176
+ # Parse and return formatted results
177
+ result = final_state["task_result"]
178
+
179
+ logging.info("=" * 100)
180
+ logging.info("User question: %s", user_input)
181
+ logging.info("User answer: %s", result)
182
+ logging.info("=" * 100)
183
+
184
+ return result
185
+ except Exception as e:
186
+ logging.error("### Error ManagerAgent _agent_work for user_input '%s': %s ###", user_input, str(e))
187
+ handle_error(e)
188
+ result = XGATaskResult(type="error", content="Never get result, Unexpected Error")
189
+ return result
190
+
191
+
192
+ if __name__ == "__main__":
193
+ setup_logging()
194
+
195
+ async def main():
196
+ agent = XGAReactAgent()
197
+ user_inputs = [
198
+ #"locate 10.2.3.4 fault and solution",
199
+ "5+5",
200
+ ]
201
+ for user_input in user_inputs:
202
+ result = await agent.generate(user_input)
203
+ await asyncio.sleep(1)
204
+ print(result)
205
+
206
+ asyncio.run(main())
@@ -2,24 +2,24 @@ import asyncio
2
2
 
3
3
  from xgae.engine.mcp_tool_box import XGAMcpToolBox
4
4
  from xgae.engine.task_engine import XGATaskEngine
5
- from xgae.utils.llm_client import LLMConfig
5
+
6
6
  from xgae.utils.misc import read_file
7
7
 
8
- from xgae.utils.setup_env import setup_langfuse
8
+ from xgae.utils.setup_env import setup_langfuse, setup_logging
9
+
10
+ setup_logging()
11
+ langfuse = setup_langfuse()
9
12
 
10
13
  async def main() -> None:
11
14
  # Before Run Exec: uv run custom_fault_tools
12
15
  tool_box = XGAMcpToolBox(custom_mcp_server_file="mcpservers/custom_servers.json")
13
- system_prompt = read_file("templates/example_user_prompt.txt")
16
+ system_prompt = read_file("templates/example/fault_user_prompt.txt")
14
17
 
15
18
  engine = XGATaskEngine(tool_box=tool_box,
16
19
  general_tools=[],
17
20
  custom_tools=["*"],
18
- llm_config=LLMConfig(stream=False),
19
- system_prompt=system_prompt,
20
- max_auto_run=8)
21
+ system_prompt=system_prompt)
21
22
 
22
- langfuse = setup_langfuse()
23
23
  # Two task run in same langfuse trace
24
24
  trace_id = langfuse.trace(name="xgae_example_run_human_in_loop").trace_id
25
25
 
@@ -1,16 +1,19 @@
1
1
  import asyncio
2
2
 
3
3
  from xgae.engine.task_engine import XGATaskEngine
4
- from xgae.utils.llm_client import LLMConfig
5
4
 
5
+ from xgae.utils.setup_env import setup_logging
6
+
7
+ setup_logging()
6
8
 
7
9
  async def main() -> None:
8
- engine = XGATaskEngine(llm_config=LLMConfig(stream=False), max_auto_run=1)
10
+ engine = XGATaskEngine()
9
11
 
10
12
  final_result = await engine.run_task_with_final_answer(
11
- task_message={"role": "user", "content": "1+1"}
13
+ task_message={"role": "user", "content": "1+7"}
12
14
  )
13
15
 
14
16
  print("FINAL RESULT:", final_result)
15
17
 
18
+
16
19
  asyncio.run(main())
@@ -0,0 +1,30 @@
1
+ import asyncio
2
+
3
+ from xgae.engine.mcp_tool_box import XGAMcpToolBox
4
+ from xgae.engine.task_engine import XGATaskEngine
5
+ from xgae.utils.misc import read_file
6
+
7
+ from xgae.utils.setup_env import setup_logging
8
+
9
+ setup_logging(log_level="ERROR")
10
+
11
+ async def main() -> None:
12
+ # Before Run Exec: uv run custom_fault_tools
13
+ tool_box = XGAMcpToolBox(custom_mcp_server_file="mcpservers/custom_servers.json")
14
+ system_prompt = read_file("templates/example/fault_user_prompt.txt")
15
+
16
+ engine = XGATaskEngine(tool_box=tool_box,
17
+ general_tools=[],
18
+ custom_tools=["*"],
19
+ system_prompt=system_prompt)
20
+
21
+ user_input = "locate 10.2.3.4 fault and solution"
22
+ chunks = []
23
+ async for chunk in engine.run_task(task_message={"role": "user", "content": user_input}):
24
+ chunks.append(chunk)
25
+ print(chunk)
26
+
27
+ final_result = engine.parse_final_result(chunks)
28
+ print(f"\n\nFINAL_RESULT: {final_result}")
29
+
30
+ asyncio.run(main())
@@ -0,0 +1,4 @@
1
+ if __name__ == "__main__":
2
+ from xgae.cli_app import main
3
+
4
+ main()
@@ -0,0 +1,85 @@
1
+ import asyncio
2
+ import sys
3
+
4
+ from xgae.engine.mcp_tool_box import XGAMcpToolBox
5
+ from xgae.engine.task_engine import XGATaskEngine
6
+
7
+ from xgae.utils.misc import read_file
8
+
9
+ from xgae.utils.setup_env import setup_langfuse, setup_env_logging
10
+
11
+ setup_env_logging()
12
+ langfuse = setup_langfuse()
13
+
14
+ def get_user_message(question)-> str:
15
+ while True:
16
+ user_message = input(f"\n💬 {question}: ")
17
+ if user_message.lower() == 'exit':
18
+ print("\n====== Extreme General Agent Engine CLI EXIT ======")
19
+ sys.exit()
20
+
21
+ if not user_message.strip():
22
+ print("\nuser message is empty, input agin !!!\n")
23
+ continue
24
+
25
+ return user_message
26
+
27
+ async def cli() -> None:
28
+ await asyncio.sleep(1)
29
+ print("\n====== Extreme General Agent Engine CLI START ======")
30
+ user_message = input("\n💬 Start Custom MCP Server and Load User Prompt (Yes/No): ")
31
+ tool_box = None
32
+ system_prompt = None
33
+ general_tools = []
34
+ custom_tools = []
35
+ if user_message.lower() == 'yes':
36
+ print(f"--- Start Custom MCP Server in custom_servers.json")
37
+ print(f"--- Load User Prompt in example/fault_user_prompt.txt")
38
+ tool_box = XGAMcpToolBox(custom_mcp_server_file="mcpservers/custom_servers.json")
39
+ system_prompt = read_file("templates/example/fault_user_prompt.txt")
40
+ custom_tools = ["*"]
41
+ else:
42
+ print(f"--- Start General Agent Server")
43
+ print(f"--- Load System Prompt")
44
+ general_tools = ["*"]
45
+
46
+ while True:
47
+ user_message = get_user_message("Enter your message (or 'exit' to quit)")
48
+
49
+ print("\n🔄 Running XGA Engine ...\n")
50
+ engine = XGATaskEngine(tool_box=tool_box,
51
+ general_tools=general_tools,
52
+ custom_tools=custom_tools,
53
+ system_prompt=system_prompt)
54
+
55
+ # Two task run in same langfuse trace
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)")
67
+ final_result = await engine.run_task_with_final_answer(
68
+ task_message={"role": "user", "content": user_message},
69
+ trace_id=trace_id
70
+ )
71
+
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']}")
78
+
79
+
80
+ def main():
81
+ asyncio.run(cli())
82
+
83
+
84
+ if __name__ == "__main__":
85
+ main()
@@ -6,14 +6,14 @@ class XGAError(Exception):
6
6
  """Custom exception for errors in the XGA system."""
7
7
  pass
8
8
 
9
- XGAMsgStatusType = Literal["error", "finish", "tool_error", "tool_started", "tool_completed", "tool_failed", "thread_run_start", "thread_run_end", "assistant_response_start", "assistant_response_end"]
10
- XGAResponseMsgType = Literal["user", "status", "tool", "assistant", "assistant_complete"]
9
+ XGAMsgStatusType = Literal["error", "finish", "tool_started", "tool_completed", "tool_error", "tool_failed"]
10
+ XGAResponseMsgType = Literal["user", "status", "tool", "assistant", "assistant_chunk"]
11
11
 
12
12
  class XGAResponseMessage(TypedDict, total=False):
13
13
  message_id: str
14
14
  type: XGAResponseMsgType
15
15
  is_llm_message: bool
16
- content: Union[Dict[str, Any], List[Any], str]
16
+ content: Union[Dict[str, Any], str]
17
17
  metadata: Dict[str, Any]
18
18
 
19
19
  class XGATaskResult(TypedDict, total=False):
@@ -124,11 +124,11 @@ class XGAMcpToolBox(XGAToolBox):
124
124
  result = XGAToolResult(success=True, output=str(tool_result))
125
125
  except Exception as e:
126
126
  error = f"Call mcp tool '{tool_name}' error: {str(e)}"
127
- logging.error(f"XGAMcpToolBox.call_tool: {error}")
127
+ logging.error(f"McpToolBox call_tool: {error}")
128
128
  result = XGAToolResult(success=False, output=error)
129
129
  else:
130
130
  error = f"No MCP tool found with name: {tool_name}"
131
- logging.info(f"XGAMcpToolBox.call_tool: error={error}")
131
+ logging.info(f"McpToolBox call_tool: error={error}")
132
132
  result = XGAToolResult(success=False, output=error)
133
133
 
134
134
  return result
@@ -179,11 +179,11 @@ class XGAMcpToolBox(XGAToolBox):
179
179
 
180
180
  return server_config
181
181
  else:
182
- logging.warning("MCP servers config file not found at: %s", mcp_config_path)
182
+ logging.warning(f"McpToolBox load_mcp_servers_config: MCP servers config file not found at: {mcp_config_path}")
183
183
  return {"mcpServers": {}}
184
184
 
185
185
  except Exception as e:
186
- logging.error("Failed to load MCP servers config: %s", str(e))
186
+ logging.error(f"McpToolBox load_mcp_servers_config: Failed to load MCP servers config: {e}")
187
187
  return {"mcpServers": {}}
188
188
 
189
189