xgae 0.1.16__py3-none-any.whl → 0.1.18__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.

@@ -21,9 +21,12 @@ class XGATaskResult(TypedDict, total=False):
21
21
  content: str
22
22
  attachments: Optional[List[str]]
23
23
 
24
+ XGAToolType = Literal["general", "custom", "agent"]
25
+
24
26
  @dataclass
25
27
  class XGAToolSchema:
26
28
  tool_name: str
29
+ tool_type: XGAToolType
27
30
  server_name: str
28
31
  description: str
29
32
  input_schema: Dict[str, Any]
@@ -46,7 +49,7 @@ class XGAToolBox(ABC):
46
49
  pass
47
50
 
48
51
  @abstractmethod
49
- def get_task_tool_schemas(self, task_id: str, type: Literal["general_tool", "custom_tool"]) -> List[XGAToolSchema]:
52
+ def get_task_tool_schemas(self, task_id: str, type: XGAToolType) -> List[XGAToolSchema]:
50
53
  pass
51
54
 
52
55
  @abstractmethod
@@ -7,10 +7,11 @@ from typing import List, Any, Dict, Optional, Literal, override
7
7
  from langchain_mcp_adapters.client import MultiServerMCPClient
8
8
  from langchain_mcp_adapters.tools import load_mcp_tools
9
9
 
10
- from xgae.engine.engine_base import XGAError, XGAToolSchema, XGAToolBox, XGAToolResult
10
+ from xgae.engine.engine_base import XGAError, XGAToolSchema, XGAToolBox, XGAToolResult, XGAToolType
11
11
 
12
12
  class XGAMcpToolBox(XGAToolBox):
13
13
  GENERAL_MCP_SERVER_NAME = "xga_general"
14
+ AGENT_MCP_SERVER_PREFIX = "_@_"
14
15
 
15
16
  def __init__(self,
16
17
  custom_mcp_server_file: Optional[str] = None,
@@ -37,7 +38,7 @@ class XGAMcpToolBox(XGAToolBox):
37
38
  @override
38
39
  async def creat_task_tool_box(self, task_id: str, general_tools: List[str], custom_tools: List[str]):
39
40
  task_tool_schemas = {}
40
- general_tool_schemas = self.mcp_tool_schemas.get(XGAMcpToolBox.GENERAL_MCP_SERVER_NAME, {})
41
+ general_tool_schemas = self.mcp_tool_schemas.get(self.GENERAL_MCP_SERVER_NAME, {})
41
42
  if "*" in general_tools:
42
43
  task_tool_schemas = {tool_schema.tool_name: tool_schema for tool_schema in general_tool_schemas}
43
44
  else:
@@ -49,7 +50,7 @@ class XGAMcpToolBox(XGAToolBox):
49
50
  if len(custom_tools) == 1 and custom_tools[0] == "*":
50
51
  custom_tools = []
51
52
  for server_name in self.mcp_server_names:
52
- if server_name != XGAMcpToolBox.GENERAL_MCP_SERVER_NAME:
53
+ if server_name != self.GENERAL_MCP_SERVER_NAME:
53
54
  custom_tools.append(f"{server_name}.*")
54
55
 
55
56
  for server_tool_name in custom_tools:
@@ -76,7 +77,7 @@ class XGAMcpToolBox(XGAToolBox):
76
77
 
77
78
  @override
78
79
  async def destroy_task_tool_box(self, task_id: str):
79
- tool_schemas = self.get_task_tool_schemas(task_id, type="general_tool")
80
+ tool_schemas = self.get_task_tool_schemas(task_id, "general")
80
81
  if len(tool_schemas) > 0:
81
82
  await self.call_tool(task_id, "end_task", {'task_id': task_id})
82
83
  self.task_tool_schemas.pop(task_id, None)
@@ -88,14 +89,12 @@ class XGAMcpToolBox(XGAToolBox):
88
89
  return task_tool_names
89
90
 
90
91
  @override
91
- def get_task_tool_schemas(self, task_id: str, type: Literal["general_tool", "custom_tool"]) -> List[XGAToolSchema]:
92
+ def get_task_tool_schemas(self, task_id: str, tool_type: XGAToolType) -> List[XGAToolSchema]:
92
93
  task_tool_schemas = []
93
94
 
94
95
  all_task_tool_schemas = self.task_tool_schemas.get(task_id, {})
95
96
  for tool_schema in all_task_tool_schemas.values():
96
- if type == "general_tool" and tool_schema.server_name == self.GENERAL_MCP_SERVER_NAME:
97
- task_tool_schemas.append(tool_schema)
98
- elif type == "custom_tool" and tool_schema.server_name != self.GENERAL_MCP_SERVER_NAME:
97
+ if tool_schema.tool_type == tool_type:
99
98
  task_tool_schemas.append(tool_schema)
100
99
 
101
100
  return task_tool_schemas
@@ -114,16 +113,16 @@ class XGAMcpToolBox(XGAToolBox):
114
113
  async with self._mcp_client.session(server_name) as session:
115
114
  tools = await load_mcp_tools(session)
116
115
  mcp_tool = next((t for t in tools if t.name == tool_name), None)
117
- is_general_tool = False
116
+
118
117
  if mcp_tool:
119
118
  tool_args = args or {}
120
- if server_name == self.GENERAL_MCP_SERVER_NAME:
119
+ tool_type = self._get_tool_type(server_name)
120
+ if tool_type == "general" or tool_type == "agent":
121
121
  tool_args = dict({'task_id': task_id}, **tool_args)
122
- is_general_tool = True
123
122
 
124
123
  try:
125
124
  tool_result = await mcp_tool.arun(tool_args)
126
- if is_general_tool:
125
+ if tool_type == "general":
127
126
  tool_result = json.loads(tool_result)
128
127
  result = XGAToolResult(success=tool_result['success'], output=str(tool_result['output']))
129
128
  else:
@@ -144,11 +143,17 @@ class XGAMcpToolBox(XGAToolBox):
144
143
  if not self.is_loaded_tool_schemas:
145
144
  for server_name in self.mcp_server_names:
146
145
  self.mcp_tool_schemas[server_name] = []
147
- mcp_tools = await self._mcp_client.get_tools(server_name=server_name)
146
+ try:
147
+ mcp_tools = await self._mcp_client.get_tools(server_name=server_name)
148
+ except Exception as e:
149
+ logging.error(f"### McpToolBox load_mcp_tools_schema: Langchain mcp get_tools failed, "
150
+ f"need start mcp server '{server_name}' !")
151
+ continue
148
152
 
153
+ tool_type = self._get_tool_type(server_name)
149
154
  for tool in mcp_tools:
150
155
  input_schema = tool.args_schema
151
- if server_name == self.GENERAL_MCP_SERVER_NAME:
156
+ if tool_type == "general" or tool_type == "agent":
152
157
  input_schema['properties'].pop("task_id", None)
153
158
  if 'task_id' in input_schema['required']:
154
159
  input_schema['required'].remove('task_id')
@@ -158,6 +163,7 @@ class XGAMcpToolBox(XGAToolBox):
158
163
 
159
164
  metadata = tool.metadata or {}
160
165
  tool_schema = XGAToolSchema(tool_name=tool.name,
166
+ tool_type=tool_type,
161
167
  server_name=server_name,
162
168
  description=tool.description,
163
169
  input_schema=input_schema,
@@ -169,8 +175,8 @@ class XGAMcpToolBox(XGAToolBox):
169
175
  self.is_loaded_tool_schemas = False
170
176
  await self.load_mcp_tools_schema()
171
177
 
172
- @staticmethod
173
- def _load_mcp_servers_config(mcp_config_path: str) -> Dict[str, Any]:
178
+
179
+ def _load_mcp_servers_config(self, mcp_config_path: str) -> Dict[str, Any]:
174
180
  try:
175
181
  if os.path.exists(mcp_config_path):
176
182
  with open(mcp_config_path, 'r', encoding="utf-8") as f:
@@ -192,6 +198,13 @@ class XGAMcpToolBox(XGAToolBox):
192
198
  logging.error(f"McpToolBox load_mcp_servers_config: Failed to load MCP servers config: {e}")
193
199
  return {'mcpServers': {}}
194
200
 
201
+ def _get_tool_type(self, server_name: str) -> XGAToolType:
202
+ tool_type: XGAToolType = "custom"
203
+ if server_name == self.GENERAL_MCP_SERVER_NAME:
204
+ tool_type = "general"
205
+ elif server_name.startswith(self.AGENT_MCP_SERVER_PREFIX):
206
+ tool_type = "agent"
207
+ return tool_type
195
208
 
196
209
  if __name__ == "__main__":
197
210
  import asyncio
@@ -207,14 +220,14 @@ if __name__ == "__main__":
207
220
 
208
221
  task_id = "task1"
209
222
  await mcp_tool_box.load_mcp_tools_schema()
210
- await mcp_tool_box.creat_task_tool_box(task_id=task_id, general_tools=["*"], custom_tools=["bomc_fault.*"])
211
- tool_schemas = mcp_tool_box.get_task_tool_schemas(task_id, "general_tool")
223
+ await mcp_tool_box.creat_task_tool_box(task_id=task_id, general_tools=["*"], custom_tools=["*"])
224
+ tool_schemas = mcp_tool_box.get_task_tool_schemas(task_id, "general")
212
225
  print("general_tools_schemas" + "*"*50)
213
226
  for tool_schema in tool_schemas:
214
227
  print(asdict(tool_schema))
215
228
  print()
216
229
 
217
- tool_schemas = mcp_tool_box.get_task_tool_schemas(task_id, "custom_tool")
230
+ tool_schemas = mcp_tool_box.get_task_tool_schemas(task_id, "custom")
218
231
  print("custom_tools_schemas" + "*" * 50)
219
232
  for tool_schema in tool_schemas:
220
233
  print(asdict(tool_schema))
@@ -11,7 +11,11 @@ class XGAPromptBuilder():
11
11
  def __init__(self, system_prompt: Optional[str] = None):
12
12
  self.system_prompt = system_prompt
13
13
 
14
- def build_task_prompt(self, model_name: str, general_tool_schemas: List[XGAToolSchema], custom_tool_schemas: List[XGAToolSchema])-> str:
14
+ def build_task_prompt(self,
15
+ model_name: str,
16
+ general_tool_schemas: List[XGAToolSchema],
17
+ custom_tool_schemas: List[XGAToolSchema],
18
+ agent_tool_schemas: List[XGAToolSchema])-> str:
15
19
  if self.system_prompt is None:
16
20
  self.system_prompt = self._load_default_system_prompt(model_name)
17
21
 
@@ -23,6 +27,9 @@ class XGAPromptBuilder():
23
27
  tool_prompt = self.build_custom_tool_prompt(custom_tool_schemas)
24
28
  task_prompt = task_prompt + "\n" + tool_prompt
25
29
 
30
+ tool_prompt = self.build_agent_tool_prompt(agent_tool_schemas)
31
+ task_prompt = task_prompt + "\n" + tool_prompt
32
+
26
33
  return task_prompt
27
34
 
28
35
  def build_general_tool_prompt(self, tool_schemas:List[XGAToolSchema])-> str:
@@ -61,10 +68,18 @@ class XGAPromptBuilder():
61
68
 
62
69
 
63
70
  def build_custom_tool_prompt(self, tool_schemas:List[XGAToolSchema])-> str:
71
+ tool_prompt = self.build_mcp_tool_prompt("templates/custom_tool_prompt_template.txt", tool_schemas)
72
+ return tool_prompt
73
+
74
+ def build_agent_tool_prompt(self, tool_schemas:List[XGAToolSchema])-> str:
75
+ tool_prompt = self.build_mcp_tool_prompt("templates/agent_tool_prompt_template.txt", tool_schemas)
76
+ return tool_prompt
77
+
78
+ def build_mcp_tool_prompt(self, file_path: str, tool_schemas:List[XGAToolSchema])-> str:
64
79
  tool_prompt = ""
65
80
  tool_schemas = tool_schemas or []
66
81
  if len(tool_schemas) > 0:
67
- tool_prompt = read_file("templates/custom_tool_prompt_template.txt")
82
+ tool_prompt = read_file(file_path)
68
83
  tool_info = ""
69
84
  for tool_schema in tool_schemas:
70
85
  description = tool_schema.description if tool_schema.description else 'No description available'
@@ -64,7 +64,7 @@ class NonStreamTaskResponser(TaskResponseProcessor):
64
64
  tool_start_msg = self._add_tool_start_message(tool_context)
65
65
  yield tool_start_msg
66
66
 
67
- tool_message = self._add_tool_messsage(tool_call, tool_result, self.xml_adding_strategy, assistant_msg_id, parsing_details)
67
+ tool_message = self._add_tool_messsage(tool_context, self.xml_adding_strategy)
68
68
 
69
69
  tool_completed_msg = self._add_tool_completed_message(tool_context, tool_message['message_id'])
70
70
  yield tool_completed_msg
@@ -376,19 +376,31 @@ class TaskResponseProcessor(ABC):
376
376
  logging.info(f"TaskProcessor execute_tools_in_parallel: Execution completed for {len(results)} tools, total {tool_num} tools)")
377
377
  return processed_results
378
378
 
379
+ def _create_tool_context(self,
380
+ tool_call: Dict[str, Any],
381
+ tool_index: int,
382
+ assistant_message_id: Optional[str] = None,
383
+ parsing_details: Optional[Dict[str, Any]] = None,
384
+ result: Optional[XGAToolResult] = None,
385
+ ) -> ToolExecutionContext:
386
+ """Create a tool execution context with display name and parsing details populated."""
387
+ return ToolExecutionContext(
388
+ tool_call = tool_call,
389
+ tool_index = tool_index,
390
+ function_name = tool_call['function_name'],
391
+ xml_tag_name = tool_call['xml_tag_name'],
392
+ assistant_message_id = assistant_message_id,
393
+ parsing_details = parsing_details,
394
+ result = result
395
+ )
379
396
 
380
- def _add_tool_messsage(self,
381
- tool_call: Dict[str, Any],
382
- result: XGAToolResult,
383
- strategy: XmlAddingStrategy = "assistant_message",
384
- assistant_message_id: Optional[str] = None,
385
- parsing_details: Optional[Dict[str, Any]] = None
386
- ) -> Optional[Dict[str, Any]]: # Return the full message object
397
+
398
+ def _add_tool_messsage(self,context:ToolExecutionContext, strategy: XmlAddingStrategy) -> Optional[Dict[str, Any]]: # Return the full message object
387
399
  # Create two versions of the structured result
388
400
  # Rich version for the frontend
389
- result_for_frontend = self._create_structured_tool_result(tool_call, result, parsing_details, for_llm=False)
401
+ result_for_frontend = self._create_structured_tool_result(context.tool_call, context.result, context.parsing_details, for_llm=False)
390
402
  # Concise version for the LLM
391
- result_for_llm = self._create_structured_tool_result(tool_call, result, parsing_details, for_llm=True)
403
+ result_for_llm = self._create_structured_tool_result(context.tool_call, context.result, context.parsing_details, for_llm=True)
392
404
 
393
405
  # Add the message with the appropriate role to the conversation history
394
406
  # This allows the LLM to see the tool result in subsequent interactions
@@ -399,11 +411,11 @@ class TaskResponseProcessor(ABC):
399
411
  }
400
412
 
401
413
  metadata = {}
402
- if assistant_message_id:
403
- metadata['assistant_message_id'] = assistant_message_id
414
+ if context.assistant_message_id:
415
+ metadata['assistant_message_id'] = context.assistant_message_id
404
416
 
405
- if parsing_details:
406
- metadata['parsing_details'] = parsing_details
417
+ if context.parsing_details:
418
+ metadata['parsing_details'] = context.parsing_details
407
419
 
408
420
  metadata['frontend_content'] = result_for_frontend
409
421
 
@@ -455,25 +467,6 @@ class TaskResponseProcessor(ABC):
455
467
  return structured_result
456
468
 
457
469
 
458
- def _create_tool_context(self,
459
- tool_call: Dict[str, Any],
460
- tool_index: int,
461
- assistant_message_id: Optional[str] = None,
462
- parsing_details: Optional[Dict[str, Any]] = None,
463
- result: Optional[XGAToolResult] = None,
464
- ) -> ToolExecutionContext:
465
- """Create a tool execution context with display name and parsing details populated."""
466
- return ToolExecutionContext(
467
- tool_call = tool_call,
468
- tool_index = tool_index,
469
- function_name = tool_call['function_name'],
470
- xml_tag_name = tool_call['xml_tag_name'],
471
- assistant_message_id = assistant_message_id,
472
- parsing_details = parsing_details,
473
- result = result
474
- )
475
-
476
-
477
470
  def _add_tool_start_message(self, context: ToolExecutionContext) -> Optional[Dict[str, Any]]:
478
471
  """Formats, saves, and returns a tool started status message."""
479
472
  content = {
@@ -43,8 +43,9 @@ class StreamTaskResponser(TaskResponseProcessor):
43
43
  chunk_content = llm_chunk_msg.content
44
44
  accumulated_content += chunk_content
45
45
 
46
- xml_tool_call_count = len(self._extract_xml_chunks(accumulated_content))
47
- if self.max_xml_tool_calls <= 0 or xml_tool_call_count <= self.max_xml_tool_calls:
46
+ xml_tool_chunks = self._extract_xml_chunks(accumulated_content)
47
+ xml_tool_chunk_len = len(xml_tool_chunks)
48
+ if self.max_xml_tool_calls <= 0 or xml_tool_chunk_len <= self.max_xml_tool_calls:
48
49
  if use_assistant_chunk_msg:
49
50
  message_data = {"role": "assistant", "content": chunk_content}
50
51
  metadata = {"sequence": msg_sequence}
@@ -57,19 +58,13 @@ class StreamTaskResponser(TaskResponseProcessor):
57
58
  else:
58
59
  finish_reason = "xml_tool_limit_reached"
59
60
  logging.warning(f"StreamResp: Over XML Tool Limit, finish_reason='xml_tool_limit_reached', "
60
- f"xml_tool_call_count={xml_tool_call_count}")
61
+ f"xml_tool_chunk_len={xml_tool_chunk_len}")
61
62
  break
62
63
 
64
+ parsed_xml_data = self._parse_xml_tool_calls(accumulated_content)
63
65
  if finish_reason == "xml_tool_limit_reached":
64
- xml_chunks = self._extract_xml_chunks(accumulated_content)
65
- if len(xml_chunks) > self.max_xml_tool_calls:
66
- limited_chunks = xml_chunks[:self.max_xml_tool_calls]
67
- if limited_chunks:
68
- last_chunk = limited_chunks[-1]
69
- last_chunk_pos = accumulated_content.find(last_chunk) + len(last_chunk)
70
- accumulated_content = accumulated_content[:last_chunk_pos]
66
+ parsed_xml_data = parsed_xml_data[:self.max_xml_tool_calls]
71
67
 
72
- parsed_xml_data = self._parse_xml_tool_calls(accumulated_content)
73
68
  should_auto_continue = (can_auto_continue and finish_reason == 'length')
74
69
 
75
70
  self.root_span.event(name=f"stream_processor_start[{self.task_no}]({auto_continue_count})", level="DEFAULT",
@@ -77,13 +72,12 @@ class StreamTaskResponser(TaskResponseProcessor):
77
72
  f"parsed_xml_data_len={len(parsed_xml_data)}, accumulated_content_len={len(accumulated_content)}, "
78
73
  f"should_auto_continue={should_auto_continue}")
79
74
 
80
- assistant_msg = None
75
+ assistant_msg_id = None
81
76
  if accumulated_content and not should_auto_continue:
82
77
  message_data = {"role": "assistant", "content": accumulated_content}
83
78
  assistant_msg = self.add_response_message(type="assistant", content=message_data, is_llm_message=True)
84
79
  yield assistant_msg
85
-
86
- assistant_msg_id = assistant_msg['message_id'] if assistant_msg else None
80
+ assistant_msg_id = assistant_msg['message_id']
87
81
 
88
82
  tool_calls_to_execute = [item['tool_call'] for item in parsed_xml_data]
89
83
  if len(tool_calls_to_execute) > 0 and not should_auto_continue:
@@ -94,12 +88,12 @@ class StreamTaskResponser(TaskResponseProcessor):
94
88
  tool_call = parsed_xml_item['tool_call']
95
89
  parsing_details = parsed_xml_item['parsing_details']
96
90
 
97
- tool_context = self._create_tool_context(tool_call, tool_index, assistant_msg_id,parsing_details, tool_result)
91
+ tool_context = self._create_tool_context(tool_call, tool_index, assistant_msg_id, parsing_details, tool_result)
98
92
 
99
93
  tool_start_msg = self._add_tool_start_message(tool_context)
100
94
  yield tool_start_msg
101
95
 
102
- tool_message = self._add_tool_messsage(tool_call, tool_result, self.xml_adding_strategy,assistant_msg_id, parsing_details)
96
+ tool_message = self._add_tool_messsage(tool_context, self.xml_adding_strategy)
103
97
 
104
98
  tool_completed_msg = self._add_tool_completed_message(tool_context, tool_message['message_id'])
105
99
  yield tool_completed_msg
@@ -114,10 +114,14 @@ class XGATaskEngine:
114
114
  await self.tool_box.load_mcp_tools_schema()
115
115
 
116
116
  await self.tool_box.creat_task_tool_box(self.task_id, general_tools, custom_tools)
117
- general_tool_schemas = self.tool_box.get_task_tool_schemas(self.task_id, "general_tool")
118
- custom_tool_schemas = self.tool_box.get_task_tool_schemas(self.task_id, "custom_tool")
119
-
120
- self.task_prompt = self.prompt_builder.build_task_prompt(self.model_name, general_tool_schemas, custom_tool_schemas)
117
+ general_tool_schemas = self.tool_box.get_task_tool_schemas(self.task_id, "general")
118
+ custom_tool_schemas = self.tool_box.get_task_tool_schemas(self.task_id, "custom")
119
+ agent_tool_schemas = self.tool_box.get_task_tool_schemas(self.task_id, "agent")
120
+
121
+ self.task_prompt = self.prompt_builder.build_task_prompt(self.model_name,
122
+ general_tool_schemas,
123
+ custom_tool_schemas,
124
+ agent_tool_schemas)
121
125
 
122
126
  logging.info("*" * 10 + f" XGATaskEngine Task'{self.task_id}' Initialized " + "*" * 10)
123
127
  logging.info(f"model_name={self.model_name}, is_stream={self.is_stream}")
@@ -10,7 +10,7 @@ mcp = FastMCP(name="XGAE Message Tools")
10
10
  @mcp.tool(
11
11
  description="""A special tool to indicate you have completed all tasks and are about to enter complete state. Use ONLY when: 1) All tasks in todo.md are marked complete [x], 2) The user's original request has been fully addressed, 3) There are no pending actions or follow-ups required, 4) You've delivered all final outputs and results to the user. IMPORTANT: This is the ONLY way to properly terminate execution. Never use this tool unless ALL tasks are complete and verified. Always ensure you've provided all necessary outputs and references before using this tool. Include relevant attachments when the completion relates to specific files or resources."""
12
12
  )
13
- async def complete(task_id: str,
13
+ def complete(task_id: str,
14
14
  text: Annotated[Optional[str], Field(default=None,
15
15
  description="Completion summary. Include: 1) Task summary 2) Key deliverables 3) Next steps 4) Impact achieved")],
16
16
  attachments: Annotated[Optional[str], Field(default=None,
@@ -23,7 +23,7 @@ async def complete(task_id: str,
23
23
  @mcp.tool(
24
24
  description="""Ask user a question and wait for response. Use for: 1) Requesting clarification on ambiguous requirements, 2) Seeking confirmation before proceeding with high-impact changes, 3) Gathering additional information needed to complete a task, 4) Offering options and requesting user preference, 5) Validating assumptions when critical to task success, 6) When encountering unclear or ambiguous results during task execution, 7) When tool results don't match expectations, 8) For natural conversation and follow-up questions, 9) When research reveals multiple entities with the same name, 10) When user requirements are unclear or could be interpreted differently. IMPORTANT: Use this tool when user input is essential to proceed. Always provide clear context and options when applicable. Use natural, conversational language that feels like talking with a helpful friend. Include relevant attachments when the question relates to specific files or resources. CRITICAL: When you discover ambiguity (like multiple people with the same name), immediately stop and ask for clarification rather than making assumptions."""
25
25
  )
26
- async def ask(task_id: str,
26
+ def ask(task_id: str,
27
27
  text: Annotated[str, Field(
28
28
  description="Question text to present to user. Include: 1) Clear question/request 2) Context why input is needed 3) Available options 4) Impact of choices 5) Relevant constraints")],
29
29
  attachments: Annotated[Optional[str], Field(default=None,
@@ -36,7 +36,7 @@ async def ask(task_id: str,
36
36
  @mcp.tool(
37
37
  description="end task, destroy sandbox"
38
38
  )
39
- async def end_task(task_id: str) :
39
+ def end_task(task_id: str) :
40
40
  print(f"<XGAETools-end_task> task_id: {task_id}")
41
41
  return XGAToolResult(success=True, output="")
42
42
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xgae
3
- Version: 0.1.16
3
+ Version: 0.1.18
4
4
  Summary: Extreme General Agent Engine
5
5
  Requires-Python: >=3.13
6
6
  Requires-Dist: colorlog==6.9.0
@@ -0,0 +1,21 @@
1
+ xgae/__init__.py,sha256=OEUd9y9AoGBd3xYerdTTpz9xl4NWkmXeq1a2eil7Qro,72
2
+ xgae/cli_app.py,sha256=ieTaS0b532P_8g9Mz2xda8TOZwYD2hKGnNZiarADAM0,3000
3
+ xgae/engine/engine_base.py,sha256=RR1em2wHiM2jP-peHt77SKdHWjnYOjdIIzN93zT61cA,1715
4
+ xgae/engine/mcp_tool_box.py,sha256=G4hKIMguwg1cO4Us2NMfdloYim8kuikVyVTIPucJr7o,10903
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
8
+ xgae/engine/responser/non_stream_responser.py,sha256=zEJjqCgZVe2B8gkHYRFU7tmBV834f7w2a4Ws25P1N-c,5289
9
+ xgae/engine/responser/responser_base.py,sha256=jhl1Bdz1Fs3KofGEymThNXlQuCORFTTkTAR_U47krds,24403
10
+ xgae/engine/responser/stream_responser.py,sha256=cv4UGcxj8OksEogW7DUGTCvSJabu-DF6GceFyUwaXI4,7627
11
+ xgae/tools/without_general_tools_app.py,sha256=KqsdhxD3hvTpiygaGUVHysRFjvv_1A8zOwMKN1J0J0U,3821
12
+ xgae/utils/__init__.py,sha256=ElaGS-zdeZeu6is41u3Ny7lkvhg7BDSK-jMNg9j6K5A,499
13
+ xgae/utils/json_helpers.py,sha256=WD4G5U9Dh8N6J9O0L5wGyqj-NHi09kcXHGdLD_26nlc,3607
14
+ xgae/utils/llm_client.py,sha256=mWRtvtSMk_8NuzFReT9x52ayHlCNVZMZAltD6TQ-xZ8,14404
15
+ xgae/utils/misc.py,sha256=aMWOvJ9VW52q-L9Lkjl1hvXqLwpJAmyxA-Z8jzqFG0U,907
16
+ xgae/utils/setup_env.py,sha256=MqNG0c2QQBDFU1kI8frxr9kB5d08Mmi3QZ1OoorgIa0,2662
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,,
@@ -1,4 +1,5 @@
1
1
  [console_scripts]
2
+ example-a2a-tools = examples.tools.simu_a2a_tools_app:main
2
3
  example-fault-tools = examples.tools.custom_fault_tools_app:main
3
4
  xgae = xgae.cli_app:main
4
5
  xgae-tools = xgae.tools.without_general_tools_app:main
@@ -1,21 +0,0 @@
1
- xgae/__init__.py,sha256=OEUd9y9AoGBd3xYerdTTpz9xl4NWkmXeq1a2eil7Qro,72
2
- xgae/cli_app.py,sha256=ieTaS0b532P_8g9Mz2xda8TOZwYD2hKGnNZiarADAM0,3000
3
- xgae/engine/engine_base.py,sha256=-QZqLRbQdwRUfbY4l3i7dFfMB-BL267a-wGZR9bMPLc,1662
4
- xgae/engine/mcp_tool_box.py,sha256=iAWUWP_goHAEeYYMUvTKiMkR2VkEOoRtNmjLV9HaIUg,10415
5
- xgae/engine/prompt_builder.py,sha256=dqv0xcB-UWQhqISbMCYCTM1ANtthY6xUe7sJ9vPRqQ4,4364
6
- xgae/engine/task_engine.py,sha256=oEyDORfDqHn7MzodeLrbhITd8TIIZrDIouF09j0twf0,20940
7
- xgae/engine/task_langfuse.py,sha256=n2bajsHq2Zt3jetel8cSlN2lo42mZgTmbR4Zbx9JvsM,2416
8
- xgae/engine/responser/non_stream_responser.py,sha256=HkmeFBIoxORhnFVh6XT0i6ixfF5vNzvN7B_BP6FzPVM,5334
9
- xgae/engine/responser/responser_base.py,sha256=eQ4E1p_PoQISrIOLmjapGRH_RRX-7LOY1P2SrDjvyTM,24624
10
- xgae/engine/responser/stream_responser.py,sha256=P6IkPniGli8XNq_BVciHeMCJiE0k3lNokTvX1GqRRbc,8046
11
- xgae/tools/without_general_tools_app.py,sha256=H3JrwA0u7BIKW69yYBPLDpPesklY5quQIMaSVyvJ4s8,3839
12
- xgae/utils/__init__.py,sha256=ElaGS-zdeZeu6is41u3Ny7lkvhg7BDSK-jMNg9j6K5A,499
13
- xgae/utils/json_helpers.py,sha256=WD4G5U9Dh8N6J9O0L5wGyqj-NHi09kcXHGdLD_26nlc,3607
14
- xgae/utils/llm_client.py,sha256=mWRtvtSMk_8NuzFReT9x52ayHlCNVZMZAltD6TQ-xZ8,14404
15
- xgae/utils/misc.py,sha256=aMWOvJ9VW52q-L9Lkjl1hvXqLwpJAmyxA-Z8jzqFG0U,907
16
- xgae/utils/setup_env.py,sha256=MqNG0c2QQBDFU1kI8frxr9kB5d08Mmi3QZ1OoorgIa0,2662
17
- xgae/utils/xml_tool_parser.py,sha256=Mb0d8kBrfyAEvUwW1Nqir-3BgxZRr0ZX3WymQouuFSo,4859
18
- xgae-0.1.16.dist-info/METADATA,sha256=i9XjQf1XQ-yOhFfVzz7tnOJwLPQOQFjF2gy1XmN7zmY,310
19
- xgae-0.1.16.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
20
- xgae-0.1.16.dist-info/entry_points.txt,sha256=SWN01JNAncV0oApEvFzpH0wsXfnFlB1adCH4IrAJxGc,163
21
- xgae-0.1.16.dist-info/RECORD,,
File without changes