universal-mcp-agents 0.1.19rc1__py3-none-any.whl → 0.1.24rc3__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.
Files changed (57) hide show
  1. universal_mcp/agents/__init__.py +15 -16
  2. universal_mcp/agents/base.py +46 -35
  3. universal_mcp/agents/bigtool/state.py +1 -1
  4. universal_mcp/agents/cli.py +2 -5
  5. universal_mcp/agents/codeact0/__init__.py +2 -3
  6. universal_mcp/agents/codeact0/__main__.py +4 -7
  7. universal_mcp/agents/codeact0/agent.py +444 -96
  8. universal_mcp/agents/codeact0/langgraph_agent.py +1 -1
  9. universal_mcp/agents/codeact0/llm_tool.py +2 -254
  10. universal_mcp/agents/codeact0/prompts.py +247 -137
  11. universal_mcp/agents/codeact0/sandbox.py +52 -18
  12. universal_mcp/agents/codeact0/state.py +26 -6
  13. universal_mcp/agents/codeact0/tools.py +400 -74
  14. universal_mcp/agents/codeact0/utils.py +175 -11
  15. universal_mcp/agents/codeact00/__init__.py +3 -0
  16. universal_mcp/agents/{unified → codeact00}/__main__.py +4 -6
  17. universal_mcp/agents/codeact00/agent.py +578 -0
  18. universal_mcp/agents/codeact00/config.py +77 -0
  19. universal_mcp/agents/{unified → codeact00}/langgraph_agent.py +2 -2
  20. universal_mcp/agents/{unified → codeact00}/llm_tool.py +1 -1
  21. universal_mcp/agents/codeact00/prompts.py +364 -0
  22. universal_mcp/agents/{unified → codeact00}/sandbox.py +52 -18
  23. universal_mcp/agents/codeact00/state.py +66 -0
  24. universal_mcp/agents/codeact00/tools.py +525 -0
  25. universal_mcp/agents/codeact00/utils.py +678 -0
  26. universal_mcp/agents/codeact01/__init__.py +3 -0
  27. universal_mcp/agents/{codeact → codeact01}/__main__.py +4 -11
  28. universal_mcp/agents/codeact01/agent.py +413 -0
  29. universal_mcp/agents/codeact01/config.py +77 -0
  30. universal_mcp/agents/codeact01/langgraph_agent.py +14 -0
  31. universal_mcp/agents/codeact01/llm_tool.py +25 -0
  32. universal_mcp/agents/codeact01/prompts.py +246 -0
  33. universal_mcp/agents/codeact01/sandbox.py +162 -0
  34. universal_mcp/agents/{unified → codeact01}/state.py +26 -10
  35. universal_mcp/agents/codeact01/tools.py +648 -0
  36. universal_mcp/agents/{unified → codeact01}/utils.py +175 -11
  37. universal_mcp/agents/llm.py +14 -4
  38. universal_mcp/agents/react.py +3 -3
  39. universal_mcp/agents/sandbox.py +124 -69
  40. universal_mcp/applications/llm/app.py +76 -24
  41. {universal_mcp_agents-0.1.19rc1.dist-info → universal_mcp_agents-0.1.24rc3.dist-info}/METADATA +6 -5
  42. universal_mcp_agents-0.1.24rc3.dist-info/RECORD +66 -0
  43. universal_mcp/agents/codeact/__init__.py +0 -3
  44. universal_mcp/agents/codeact/agent.py +0 -240
  45. universal_mcp/agents/codeact/models.py +0 -11
  46. universal_mcp/agents/codeact/prompts.py +0 -82
  47. universal_mcp/agents/codeact/sandbox.py +0 -85
  48. universal_mcp/agents/codeact/state.py +0 -11
  49. universal_mcp/agents/codeact/utils.py +0 -68
  50. universal_mcp/agents/codeact0/playbook_agent.py +0 -355
  51. universal_mcp/agents/unified/README.md +0 -45
  52. universal_mcp/agents/unified/__init__.py +0 -3
  53. universal_mcp/agents/unified/agent.py +0 -289
  54. universal_mcp/agents/unified/prompts.py +0 -192
  55. universal_mcp/agents/unified/tools.py +0 -188
  56. universal_mcp_agents-0.1.19rc1.dist-info/RECORD +0 -64
  57. {universal_mcp_agents-0.1.19rc1.dist-info → universal_mcp_agents-0.1.24rc3.dist-info}/WHEEL +0 -0
@@ -3,32 +3,29 @@ from typing import Literal
3
3
  from universal_mcp.agents.base import BaseAgent
4
4
  from universal_mcp.agents.bigtool import BigToolAgent
5
5
  from universal_mcp.agents.builder.builder import BuilderAgent
6
- from universal_mcp.agents.codeact import CodeActAgent as CodeActScript
7
- from universal_mcp.agents.codeact0 import CodeActPlaybookAgent as CodeActRepl
6
+ from universal_mcp.agents.codeact0 import CodeActPlaybookAgent
8
7
  from universal_mcp.agents.react import ReactAgent
9
8
  from universal_mcp.agents.simple import SimpleAgent
10
- from universal_mcp.agents.unified import UnifiedAgent
9
+ from universal_mcp.agents.codeact00 import CodeActPlaybookAgent as CodeAct00Agent
10
+ from universal_mcp.agents.codeact01 import CodeActPlaybookAgent as CodeAct01Agent
11
11
 
12
12
 
13
- def get_agent(agent_name: Literal["react", "simple", "builder", "bigtool", "codeact-script", "codeact-repl"]):
13
+ def get_agent(
14
+ agent_name: Literal["react", "simple", "builder", "bigtool", "codeact-repl", "codeact-00", "codeact-01"],
15
+ ):
16
+ print("agent_name", agent_name)
14
17
  if agent_name == "react":
15
18
  return ReactAgent
16
19
  elif agent_name == "simple":
17
20
  return SimpleAgent
18
- elif agent_name == "builder":
19
- return BuilderAgent
20
- elif agent_name == "bigtool":
21
- return BigToolAgent
22
- elif agent_name == "codeact-script":
23
- return CodeActScript
24
21
  elif agent_name == "codeact-repl":
25
- return CodeActRepl
26
- elif agent_name == "unified":
27
- return UnifiedAgent
22
+ return CodeActPlaybookAgent
23
+ elif agent_name == "codeact-00":
24
+ return CodeAct00Agent
25
+ elif agent_name == "codeact-01":
26
+ return CodeAct01Agent
28
27
  else:
29
- raise ValueError(
30
- f"Unknown agent: {agent_name}. Possible values: react, simple, builder, bigtool, codeact-script, codeact-repl"
31
- )
28
+ raise ValueError(f"Unknown agent: {agent_name}. Possible values: react, simple, codeact-repl, codeact-00, codeact-01")
32
29
 
33
30
 
34
31
  __all__ = [
@@ -39,4 +36,6 @@ __all__ = [
39
36
  "BigToolAgent",
40
37
  "CodeActScript",
41
38
  "CodeActRepl",
39
+ "CodeAct00Agent",
40
+ "CodeAct01Agent",
42
41
  ]
@@ -1,4 +1,4 @@
1
- # agents/base.py
1
+ import asyncio
2
2
  from typing import cast
3
3
  from uuid import uuid4
4
4
 
@@ -49,44 +49,55 @@ class BaseAgent:
49
49
  run_metadata.update(metadata)
50
50
 
51
51
  run_config = {
52
+ "recursion_limit": 50,
52
53
  "configurable": {"thread_id": thread_id},
53
54
  "metadata": run_metadata,
55
+ "run_id": thread_id,
56
+ "run_name": self.name,
54
57
  }
55
58
 
56
- async for event, meta in self._graph.astream(
57
- {"messages": [{"role": "user", "content": user_input}]},
58
- config=run_config,
59
- context={"system_prompt": self.instructions, "model": self.model},
60
- stream_mode="messages",
61
- stream_usage=True,
62
- ):
63
- # Only forward assistant token chunks that are not tool-related.
64
- type_ = type(event)
65
- tags = meta.get("tags", []) if isinstance(meta, dict) else []
66
- is_quiet = isinstance(tags, list) and ("quiet" in tags)
67
- if is_quiet:
68
- continue
69
- # Handle different types of messages
70
- if type_ == AIMessageChunk:
71
- # Accumulate billing and aggregate message
72
- aggregate = event if aggregate is None else aggregate + event
73
- # Ignore intermeddite finish messages
74
- if "finish_reason" in event.response_metadata:
75
- # Got LLM finish reason ignore it
76
- logger.debug(
77
- f"Finish event: {event}, reason: {event.response_metadata['finish_reason']}, Metadata: {meta}"
78
- )
79
- pass
80
- else:
81
- logger.debug(f"Event: {event}, Metadata: {meta}")
59
+ last_ai_chunk = None
60
+ try:
61
+ async for event, meta in self._graph.astream(
62
+ {"messages": [{"role": "user", "content": user_input}]},
63
+ config=run_config,
64
+ context={"system_prompt": self.instructions, "model": self.model},
65
+ stream_mode=["messages", "custom"],
66
+ stream_usage=True,
67
+ ):
68
+ if event == "messages" and isinstance(meta, (tuple, list)) and len(meta) == 2: # noqa: PLR2004
69
+ payload, meta_dict = meta
70
+ metadata = getattr(payload, "metadata", {}) or {}
71
+ if metadata and "quiet" in metadata.get("tags"):
72
+ continue
73
+ if meta_dict.get("tags") and "quiet" in meta_dict.get("tags"):
74
+ continue
75
+ if isinstance(payload, AIMessageChunk):
76
+ last_ai_chunk = payload
77
+ aggregate = payload if aggregate is None else aggregate + payload
78
+ if "finish_reason" in payload.response_metadata:
79
+ logger.debug(
80
+ f"Finish event: {payload}, reason: {payload.response_metadata['finish_reason']}, Metadata: {meta_dict}"
81
+ )
82
+ pass
83
+ logger.debug(f"Event: {payload}, Metadata: {meta_dict}")
84
+ yield payload
85
+
86
+ if event == "custom":
87
+ yield meta
88
+
89
+ except asyncio.CancelledError:
90
+ logger.info(f"Stream for thread_id {thread_id} was cancelled by the user.")
91
+ # Perform any cleanup here if necessary
92
+ finally:
93
+ # This block will run whether the stream finished normally or was cancelled
94
+ # Send a final finished message if we saw any AI chunks (to carry usage)
95
+ if last_ai_chunk is not None and aggregate is not None:
96
+ event = cast(AIMessageChunk, last_ai_chunk)
97
+ event.usage_metadata = aggregate.usage_metadata
98
+ logger.debug(f"Usage metadata: {event.usage_metadata}")
99
+ event.content = "" # Clear the message
82
100
  yield event
83
- # Send a final finished message
84
- # The last event would be finish
85
- event = cast(AIMessageChunk, event)
86
- event.usage_metadata = aggregate.usage_metadata
87
- logger.debug(f"Usage metadata: {event.usage_metadata}")
88
- event.content = "" # Clear the message since it would have already been streamed above
89
- yield event
90
101
 
91
102
  async def stream_interactive(self, thread_id: str, user_input: str):
92
103
  await self.ainit()
@@ -113,7 +124,7 @@ class BaseAgent:
113
124
  run_metadata.update(metadata)
114
125
 
115
126
  run_config = {
116
- "recursion_limit": 25,
127
+ "recursion_limit": 50,
117
128
  "configurable": {"thread_id": thread_id},
118
129
  "metadata": run_metadata,
119
130
  "run_id": thread_id,
@@ -1,6 +1,6 @@
1
1
  from typing import Annotated
2
2
 
3
- from langgraph.prebuilt.chat_agent_executor import AgentState
3
+ from langchain.agents import AgentState
4
4
 
5
5
 
6
6
  def _enqueue(left: list, right: list) -> list:
@@ -18,19 +18,16 @@ app = Typer()
18
18
  mcp client run --config client_config.json
19
19
  """,
20
20
  )
21
- def run(name: str = "react"):
21
+ def run(name: str = "codeact-repl"):
22
22
  """Run the agent CLI"""
23
23
 
24
24
  setup_logger(log_file=None, level="ERROR")
25
25
  client = AgentrClient()
26
26
  params = {
27
27
  "instructions": "You are a helpful assistant",
28
- "model": "anthropic/claude-sonnet-4-20250514",
28
+ "model": "anthropic:claude-4-sonnet-20250514",
29
29
  "registry": AgentrRegistry(client=client),
30
30
  "memory": MemorySaver(),
31
- "tools": {
32
- "google_mail": ["send_email"],
33
- },
34
31
  }
35
32
  agent_cls = get_agent(name)
36
33
  agent = agent_cls(name=name, **params)
@@ -1,4 +1,3 @@
1
- from .agent import CodeActAgent
2
- from .playbook_agent import CodeActPlaybookAgent
1
+ from .agent import CodeActPlaybookAgent
3
2
 
4
- __all__ = ["CodeActAgent", "CodeActPlaybookAgent"]
3
+ __all__ = ["CodeActPlaybookAgent"]
@@ -4,24 +4,21 @@ from langgraph.checkpoint.memory import MemorySaver
4
4
  from rich import print
5
5
  from universal_mcp.agentr.registry import AgentrRegistry
6
6
 
7
- from universal_mcp.agents.codeact0.agent import CodeActAgent
7
+ from universal_mcp.agents.codeact0.agent import CodeActPlaybookAgent
8
8
  from universal_mcp.agents.utils import messages_to_list
9
9
 
10
10
 
11
11
  async def main():
12
12
  memory = MemorySaver()
13
- agent = CodeActAgent(
13
+ agent = CodeActPlaybookAgent(
14
14
  name="CodeAct Agent",
15
15
  instructions="Be very concise in your answers.",
16
- model="anthropic:claude-4-sonnet-20250514",
17
- tools={"google_mail": ["list_messages"]},
16
+ model="azure/gpt-4.1",
18
17
  registry=AgentrRegistry(),
19
18
  memory=memory,
20
19
  )
21
20
  print("Starting agent...")
22
- result = await agent.invoke(
23
- user_input="Fetch unsubscribe links from my Gmail inbox for promo emails I have received in the last 7 days"
24
- )
21
+ result = await agent.invoke(user_input="Check my google calendar and show my todays agenda")
25
22
  print(messages_to_list(result["messages"]))
26
23
 
27
24