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.
- {xgae-0.1.9 → xgae-0.1.12}/.env +9 -4
- xgae-0.1.12/.idea/ai_toolkit.xml +6 -0
- {xgae-0.1.9 → xgae-0.1.12}/.idea/workspace.xml +25 -7
- {xgae-0.1.9 → xgae-0.1.12}/PKG-INFO +1 -1
- {xgae-0.1.9 → xgae-0.1.12}/pyproject.toml +2 -1
- xgae-0.1.12/src/examples/agent/langgraph/react/react_agent.py +206 -0
- {xgae-0.1.9 → xgae-0.1.12}/src/examples/engine/run_human_in_loop.py +7 -7
- {xgae-0.1.9 → xgae-0.1.12}/src/examples/engine/run_simple.py +6 -3
- xgae-0.1.12/src/examples/engine/run_user_prompt.py +30 -0
- xgae-0.1.12/src/xgae/__init__.py +4 -0
- xgae-0.1.12/src/xgae/cli_app.py +85 -0
- {xgae-0.1.9 → xgae-0.1.12}/src/xgae/engine/engine_base.py +3 -3
- {xgae-0.1.9 → xgae-0.1.12}/src/xgae/engine/mcp_tool_box.py +4 -4
- {xgae-0.1.9 → xgae-0.1.12}/src/xgae/engine/responser/non_stream_responser.py +33 -38
- {xgae-0.1.9 → xgae-0.1.12}/src/xgae/engine/responser/responser_base.py +42 -40
- xgae-0.1.12/src/xgae/engine/responser/stream_responser.py +138 -0
- {xgae-0.1.9 → xgae-0.1.12}/src/xgae/engine/task_engine.py +98 -50
- {xgae-0.1.9 → xgae-0.1.12}/src/xgae/engine/task_langfuse.py +8 -6
- {xgae-0.1.9 → xgae-0.1.12}/src/xgae/tools/without_general_tools_app.py +2 -3
- {xgae-0.1.9 → xgae-0.1.12}/src/xgae/utils/__init__.py +2 -2
- {xgae-0.1.9 → xgae-0.1.12}/src/xgae/utils/json_helpers.py +2 -2
- {xgae-0.1.9 → xgae-0.1.12}/src/xgae/utils/llm_client.py +42 -32
- {xgae-0.1.9 → xgae-0.1.12}/src/xgae/utils/setup_env.py +4 -3
- {xgae-0.1.9 → xgae-0.1.12}/test/test_langfuse.py +2 -1
- xgae-0.1.12/uv.lock +1386 -0
- xgae-0.1.9/src/examples/engine/run_user_prompt.py +0 -32
- xgae-0.1.9/src/xgae/__init__.py +0 -0
- xgae-0.1.9/src/xgae/engine/responser/stream_responser.py +0 -825
- xgae-0.1.9/uv.lock +0 -1386
- {xgae-0.1.9 → xgae-0.1.12}/.idea/.gitignore +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/.idea/inspectionProfiles/Project_Default.xml +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/.idea/misc.xml +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/.idea/modules.xml +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/.idea/vcs.xml +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/.idea/xgae.iml +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/.python-version +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/README.md +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/mcpservers/custom_servers.json +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/mcpservers/xga_server.json +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/mcpservers/xga_server_sse.json +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/src/examples/tools/custom_fault_tools_app.py +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/src/xgae/engine/prompt_builder.py +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/src/xgae/utils/misc.py +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/src/xgae/utils/xml_tool_parser.py +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/templates/custom_tool_prompt_template.txt +0 -0
- /xgae-0.1.9/templates/example_user_prompt.txt → /xgae-0.1.12/templates/example/fault_user_prompt.txt +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/templates/gemini_system_prompt_template.txt +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/templates/general_tool_prompt_template.txt +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/templates/system_prompt_response_sample.txt +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/templates/system_prompt_template.txt +0 -0
- {xgae-0.1.9 → xgae-0.1.12}/test/test_litellm_langfuse.py +0 -0
{xgae-0.1.9 → xgae-0.1.12}/.env
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# LOG
|
|
2
|
-
LOG_LEVEL=
|
|
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
|
-
|
|
21
|
-
|
|
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
|
|
|
@@ -28,9 +28,12 @@
|
|
|
28
28
|
<component name="PropertiesComponent"><![CDATA[{
|
|
29
29
|
"keyToString": {
|
|
30
30
|
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
|
31
|
-
"Python.
|
|
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="
|
|
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="
|
|
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="
|
|
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="
|
|
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="
|
|
205
|
-
<SUITE FILE_PATH="coverage/xgae$task_engine.coverage" NAME="task_engine Coverage Results" MODIFIED="
|
|
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
|
[project]
|
|
2
2
|
name = "xgae"
|
|
3
|
-
version = "0.1.
|
|
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
|
-
|
|
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/
|
|
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
|
-
|
|
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(
|
|
10
|
+
engine = XGATaskEngine()
|
|
9
11
|
|
|
10
12
|
final_result = await engine.run_task_with_final_answer(
|
|
11
|
-
task_message={"role": "user", "content": "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,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", "
|
|
10
|
-
XGAResponseMsgType = Literal["user", "status", "tool", "assistant", "
|
|
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],
|
|
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"
|
|
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"
|
|
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:
|
|
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:
|
|
186
|
+
logging.error(f"McpToolBox load_mcp_servers_config: Failed to load MCP servers config: {e}")
|
|
187
187
|
return {"mcpServers": {}}
|
|
188
188
|
|
|
189
189
|
|