universal-mcp-agents 0.1.23rc3__py3-none-any.whl → 0.1.23rc5__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 universal-mcp-agents might be problematic. Click here for more details.
- universal_mcp/agents/__init__.py +1 -7
- universal_mcp/agents/base.py +1 -1
- universal_mcp/agents/bigtool/state.py +1 -1
- universal_mcp/agents/codeact0/__main__.py +1 -1
- universal_mcp/agents/codeact0/agent.py +58 -33
- universal_mcp/agents/codeact0/prompts.py +26 -44
- universal_mcp/agents/codeact0/sandbox.py +10 -3
- universal_mcp/agents/codeact0/state.py +1 -1
- universal_mcp/agents/codeact0/tools.py +11 -9
- universal_mcp/agents/codeact0/utils.py +76 -1
- universal_mcp/agents/react.py +3 -3
- universal_mcp/agents/sandbox.py +104 -71
- {universal_mcp_agents-0.1.23rc3.dist-info → universal_mcp_agents-0.1.23rc5.dist-info}/METADATA +5 -4
- {universal_mcp_agents-0.1.23rc3.dist-info → universal_mcp_agents-0.1.23rc5.dist-info}/RECORD +15 -15
- {universal_mcp_agents-0.1.23rc3.dist-info → universal_mcp_agents-0.1.23rc5.dist-info}/WHEEL +0 -0
universal_mcp/agents/__init__.py
CHANGED
|
@@ -15,16 +15,10 @@ def get_agent(
|
|
|
15
15
|
return ReactAgent
|
|
16
16
|
elif agent_name == "simple":
|
|
17
17
|
return SimpleAgent
|
|
18
|
-
elif agent_name == "builder":
|
|
19
|
-
return BuilderAgent
|
|
20
|
-
elif agent_name == "bigtool":
|
|
21
|
-
return BigToolAgent
|
|
22
18
|
elif agent_name == "codeact-repl":
|
|
23
19
|
return CodeActPlaybookAgent
|
|
24
20
|
else:
|
|
25
|
-
raise ValueError(
|
|
26
|
-
f"Unknown agent: {agent_name}. Possible values: react, simple, builder, bigtool, codeact-repl"
|
|
27
|
-
)
|
|
21
|
+
raise ValueError(f"Unknown agent: {agent_name}. Possible values: react, simple, codeact-repl")
|
|
28
22
|
|
|
29
23
|
|
|
30
24
|
__all__ = [
|
universal_mcp/agents/base.py
CHANGED
|
@@ -64,7 +64,7 @@ class BaseAgent:
|
|
|
64
64
|
stream_mode=["messages", "custom"],
|
|
65
65
|
stream_usage=True,
|
|
66
66
|
):
|
|
67
|
-
if event == "messages" and isinstance(meta, (tuple, list)) and len(meta) == 2:
|
|
67
|
+
if event == "messages" and isinstance(meta, (tuple, list)) and len(meta) == 2: # noqa: PLR2004
|
|
68
68
|
payload, meta_dict = meta
|
|
69
69
|
is_agent_builder = isinstance(meta_dict, dict) and meta_dict.get("langgraph_node") == "agent_builder"
|
|
70
70
|
additional_kwargs = getattr(payload, "additional_kwargs", {}) or {}
|
|
@@ -18,7 +18,7 @@ async def main():
|
|
|
18
18
|
memory=memory,
|
|
19
19
|
)
|
|
20
20
|
print("Starting agent...")
|
|
21
|
-
result = await agent.invoke(user_input="
|
|
21
|
+
result = await agent.invoke(user_input="Check my google calendar and show my todays agenda")
|
|
22
22
|
print(messages_to_list(result["messages"]))
|
|
23
23
|
|
|
24
24
|
|
|
@@ -3,10 +3,10 @@ import json
|
|
|
3
3
|
import re
|
|
4
4
|
import uuid
|
|
5
5
|
from typing import Literal, cast
|
|
6
|
+
from types import SimpleNamespace
|
|
6
7
|
|
|
7
8
|
from langchain_anthropic import ChatAnthropic
|
|
8
9
|
from langchain_core.messages import AIMessage, ToolMessage
|
|
9
|
-
from langchain_core.tools import StructuredTool
|
|
10
10
|
from langgraph.checkpoint.base import BaseCheckpointSaver
|
|
11
11
|
from langgraph.graph import START, StateGraph
|
|
12
12
|
from langgraph.types import Command, RetryPolicy, StreamWriter
|
|
@@ -22,13 +22,12 @@ from universal_mcp.agents.codeact0.prompts import (
|
|
|
22
22
|
create_default_prompt,
|
|
23
23
|
)
|
|
24
24
|
from universal_mcp.agents.codeact0.sandbox import eval_unsafe, execute_ipython_cell, handle_execute_ipython_cell
|
|
25
|
-
from universal_mcp.agents.codeact0.state import
|
|
25
|
+
from universal_mcp.agents.codeact0.state import AgentBuilderCode, AgentBuilderMeta, AgentBuilderPlan, CodeActState
|
|
26
26
|
from universal_mcp.agents.codeact0.tools import (
|
|
27
27
|
create_meta_tools,
|
|
28
28
|
enter_agent_builder_mode,
|
|
29
|
-
get_valid_tools,
|
|
30
29
|
)
|
|
31
|
-
from universal_mcp.agents.codeact0.utils import build_anthropic_cache_message, get_connected_apps_string
|
|
30
|
+
from universal_mcp.agents.codeact0.utils import build_anthropic_cache_message, get_connected_apps_string, create_agent_call
|
|
32
31
|
from universal_mcp.agents.llm import load_chat_model
|
|
33
32
|
from universal_mcp.agents.utils import convert_tool_ids_to_dict, filter_retry_on, get_message_text
|
|
34
33
|
|
|
@@ -57,6 +56,8 @@ class CodeActPlaybookAgent(BaseAgent):
|
|
|
57
56
|
self.registry = registry
|
|
58
57
|
self.agent_builder_registry = agent_builder_registry
|
|
59
58
|
self.agent = agent_builder_registry.get_agent() if agent_builder_registry else None
|
|
59
|
+
|
|
60
|
+
|
|
60
61
|
self.tools_config = self.agent.tools if self.agent else {}
|
|
61
62
|
self.eval_fn = eval_unsafe
|
|
62
63
|
self.sandbox_timeout = sandbox_timeout
|
|
@@ -65,14 +66,11 @@ class CodeActPlaybookAgent(BaseAgent):
|
|
|
65
66
|
}
|
|
66
67
|
self.final_instructions = ""
|
|
67
68
|
self.tools_context = {}
|
|
68
|
-
self.exported_tools = []
|
|
69
69
|
|
|
70
|
-
async def _build_graph(self):
|
|
70
|
+
async def _build_graph(self): # noqa: PLR0915
|
|
71
|
+
"""Build the graph for the CodeAct Playbook Agent."""
|
|
71
72
|
meta_tools = create_meta_tools(self.registry)
|
|
72
|
-
additional_tools = [smart_print, meta_tools["web_search"]]
|
|
73
|
-
self.additional_tools = [
|
|
74
|
-
t if isinstance(t, StructuredTool) else StructuredTool.from_function(t) for t in additional_tools
|
|
75
|
-
]
|
|
73
|
+
self.additional_tools = [smart_print, meta_tools["web_search"]]
|
|
76
74
|
|
|
77
75
|
if self.tools_config:
|
|
78
76
|
if isinstance(self.tools_config, dict):
|
|
@@ -81,9 +79,8 @@ class CodeActPlaybookAgent(BaseAgent):
|
|
|
81
79
|
]
|
|
82
80
|
if not self.registry:
|
|
83
81
|
raise ValueError("Tools are configured but no registry is provided")
|
|
84
|
-
await self.registry.
|
|
85
|
-
|
|
86
|
-
await self.registry.export_tools(self.default_tools_config, ToolFormat.LANGCHAIN)
|
|
82
|
+
await self.registry.load_tools(self.tools_config) # Load the default tools
|
|
83
|
+
await self.registry.load_tools(self.default_tools_config) # Load more tools
|
|
87
84
|
|
|
88
85
|
async def call_model(state: CodeActState) -> Command[Literal["execute_tools"]]:
|
|
89
86
|
"""This node now only ever binds the four meta-tools to the LLM."""
|
|
@@ -113,8 +110,7 @@ class CodeActPlaybookAgent(BaseAgent):
|
|
|
113
110
|
tools=agent_facing_tools,
|
|
114
111
|
tool_choice="auto",
|
|
115
112
|
)
|
|
116
|
-
|
|
117
|
-
response = cast(AIMessage, model_with_tools.invoke(messages))
|
|
113
|
+
response = cast(AIMessage, await model_with_tools.ainvoke(messages))
|
|
118
114
|
if response.tool_calls:
|
|
119
115
|
return Command(goto="execute_tools", update={"messages": [response]})
|
|
120
116
|
else:
|
|
@@ -146,7 +142,10 @@ class CodeActPlaybookAgent(BaseAgent):
|
|
|
146
142
|
)
|
|
147
143
|
return Command(
|
|
148
144
|
goto="agent_builder",
|
|
149
|
-
update={
|
|
145
|
+
update={
|
|
146
|
+
"agent_builder_mode": "planning",
|
|
147
|
+
"messages": [tool_message],
|
|
148
|
+
}, # Entered Agent Builder mode
|
|
150
149
|
)
|
|
151
150
|
elif tool_name == "execute_ipython_cell":
|
|
152
151
|
code = tool_call["args"]["snippet"]
|
|
@@ -162,7 +161,9 @@ class CodeActPlaybookAgent(BaseAgent):
|
|
|
162
161
|
tool_result = output
|
|
163
162
|
elif tool_name == "load_functions":
|
|
164
163
|
# The tool now does all the work of validation and formatting.
|
|
165
|
-
tool_result, new_context_for_sandbox, valid_tools, unconnected_links = await meta_tools[
|
|
164
|
+
tool_result, new_context_for_sandbox, valid_tools, unconnected_links = await meta_tools[
|
|
165
|
+
"load_functions"
|
|
166
|
+
].ainvoke(tool_args)
|
|
166
167
|
# We still need to update the sandbox context for `execute_ipython_cell`
|
|
167
168
|
new_tool_ids.extend(valid_tools)
|
|
168
169
|
if new_tool_ids:
|
|
@@ -187,7 +188,7 @@ class CodeActPlaybookAgent(BaseAgent):
|
|
|
187
188
|
tool_call_id=tool_call["id"],
|
|
188
189
|
)
|
|
189
190
|
tool_messages.append(tool_message)
|
|
190
|
-
|
|
191
|
+
|
|
191
192
|
if ask_user:
|
|
192
193
|
tool_messages.append(AIMessage(content=ai_msg))
|
|
193
194
|
return Command(
|
|
@@ -209,7 +210,7 @@ class CodeActPlaybookAgent(BaseAgent):
|
|
|
209
210
|
},
|
|
210
211
|
)
|
|
211
212
|
|
|
212
|
-
def agent_builder(state: CodeActState, writer: StreamWriter) -> Command[Literal["call_model"]]:
|
|
213
|
+
async def agent_builder(state: CodeActState, writer: StreamWriter) -> Command[Literal["call_model"]]:
|
|
213
214
|
agent_builder_mode = state.get("agent_builder_mode")
|
|
214
215
|
if agent_builder_mode == "planning":
|
|
215
216
|
plan_id = str(uuid.uuid4())
|
|
@@ -217,8 +218,10 @@ class CodeActPlaybookAgent(BaseAgent):
|
|
|
217
218
|
planning_instructions = self.instructions + AGENT_BUILDER_PLANNING_PROMPT
|
|
218
219
|
messages = [{"role": "system", "content": planning_instructions}] + state["messages"]
|
|
219
220
|
|
|
220
|
-
model_with_structured_output = self.agent_builder_model_instance.with_structured_output(
|
|
221
|
-
|
|
221
|
+
model_with_structured_output = self.agent_builder_model_instance.with_structured_output(
|
|
222
|
+
AgentBuilderPlan
|
|
223
|
+
)
|
|
224
|
+
response = await model_with_structured_output.ainvoke(messages)
|
|
222
225
|
plan = cast(AgentBuilderPlan, response)
|
|
223
226
|
|
|
224
227
|
writer({"type": "custom", id: plan_id, "name": "planning", "data": {"plan": plan.steps}})
|
|
@@ -277,8 +280,10 @@ class CodeActPlaybookAgent(BaseAgent):
|
|
|
277
280
|
meta_instructions = self.instructions + AGENT_BUILDER_META_PROMPT
|
|
278
281
|
messages = [{"role": "system", "content": meta_instructions}] + state["messages"]
|
|
279
282
|
|
|
280
|
-
model_with_structured_output = self.agent_builder_model_instance.with_structured_output(
|
|
281
|
-
|
|
283
|
+
model_with_structured_output = self.agent_builder_model_instance.with_structured_output(
|
|
284
|
+
AgentBuilderMeta
|
|
285
|
+
)
|
|
286
|
+
meta_response = await model_with_structured_output.ainvoke(messages)
|
|
282
287
|
meta = cast(AgentBuilderMeta, meta_response)
|
|
283
288
|
name, description = meta.name, meta.description
|
|
284
289
|
|
|
@@ -316,8 +321,10 @@ class CodeActPlaybookAgent(BaseAgent):
|
|
|
316
321
|
generating_instructions = self.instructions + AGENT_BUILDER_GENERATING_PROMPT
|
|
317
322
|
messages = [{"role": "system", "content": generating_instructions}] + state["messages"]
|
|
318
323
|
|
|
319
|
-
model_with_structured_output = self.agent_builder_model_instance.with_structured_output(
|
|
320
|
-
|
|
324
|
+
model_with_structured_output = self.agent_builder_model_instance.with_structured_output(
|
|
325
|
+
AgentBuilderCode
|
|
326
|
+
)
|
|
327
|
+
response = await model_with_structured_output.ainvoke(messages)
|
|
321
328
|
func_code = cast(AgentBuilderCode, response).code
|
|
322
329
|
|
|
323
330
|
# Extract function name (handle both regular and async functions)
|
|
@@ -367,23 +374,35 @@ class CodeActPlaybookAgent(BaseAgent):
|
|
|
367
374
|
},
|
|
368
375
|
}
|
|
369
376
|
)
|
|
377
|
+
mock_exit_tool_call = {
|
|
378
|
+
"name": "exit_agent_builder_mode",
|
|
379
|
+
"args": {},
|
|
380
|
+
"id": "exit_builder_1"
|
|
381
|
+
}
|
|
370
382
|
mock_assistant_message = AIMessage(
|
|
371
383
|
content=json.dumps(response.model_dump()),
|
|
384
|
+
tool_calls=[mock_exit_tool_call],
|
|
372
385
|
additional_kwargs={
|
|
373
386
|
"type": "generating",
|
|
374
387
|
"id": str(res.id),
|
|
375
388
|
"update": bool(self.agent),
|
|
376
|
-
"name": final_name,
|
|
389
|
+
"name": final_name.replace(" ", "_"),
|
|
377
390
|
"description": final_description,
|
|
378
391
|
},
|
|
379
392
|
)
|
|
393
|
+
|
|
394
|
+
mock_exit_tool_response = ToolMessage(
|
|
395
|
+
content=json.dumps("Exited Agent Builder Mode. Enter this mode again if you need to modify the saved agent."),
|
|
396
|
+
name="exit_agent_builder_mode",
|
|
397
|
+
tool_call_id="exit_builder_1"
|
|
398
|
+
)
|
|
380
399
|
|
|
381
|
-
return Command(update={"messages": [mock_assistant_message], "agent_builder_mode": "normal"})
|
|
400
|
+
return Command(update={"messages": [mock_assistant_message, mock_exit_tool_response], "agent_builder_mode": "normal"})
|
|
382
401
|
|
|
383
|
-
async def route_entry(state: CodeActState) -> Literal["call_model", "agent_builder"]:
|
|
402
|
+
async def route_entry(state: CodeActState) -> Command[Literal["call_model", "agent_builder", "execute_tools"]]:
|
|
384
403
|
"""Route to either normal mode or agent builder creation"""
|
|
385
|
-
|
|
386
|
-
|
|
404
|
+
await self.registry.load_tools(state["selected_tool_ids"])
|
|
405
|
+
all_tools = await self.registry.export_tools(format=ToolFormat.NATIVE)
|
|
387
406
|
|
|
388
407
|
# Create the initial system prompt and tools_context in one go
|
|
389
408
|
self.final_instructions, self.tools_context = create_default_prompt(
|
|
@@ -394,13 +413,19 @@ class CodeActPlaybookAgent(BaseAgent):
|
|
|
394
413
|
self.agent,
|
|
395
414
|
is_initial_prompt=True,
|
|
396
415
|
)
|
|
416
|
+
if len(state['messages']) == 1 and self.agent: # Inject the agent's script function into add_context for execution
|
|
417
|
+
script = self.agent.instructions.get('script')
|
|
418
|
+
add_context = {"functions":[script]}
|
|
419
|
+
return Command(goto="call_model", update = {"add_context": add_context})
|
|
420
|
+
|
|
397
421
|
if state.get("agent_builder_mode") in ["planning", "confirming", "generating"]:
|
|
398
|
-
return "agent_builder"
|
|
399
|
-
return "call_model"
|
|
422
|
+
return Command(goto="agent_builder")
|
|
423
|
+
return Command(goto="call_model")
|
|
400
424
|
|
|
401
425
|
agent = StateGraph(state_schema=CodeActState)
|
|
402
426
|
agent.add_node(call_model, retry_policy=RetryPolicy(max_attempts=3, retry_on=filter_retry_on))
|
|
403
427
|
agent.add_node(agent_builder)
|
|
404
428
|
agent.add_node(execute_tools)
|
|
405
|
-
agent.
|
|
429
|
+
agent.add_node(route_entry)
|
|
430
|
+
agent.add_edge(START, "route_entry")
|
|
406
431
|
return agent.compile(checkpointer=self.memory)
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import inspect
|
|
2
2
|
import re
|
|
3
|
-
from collections.abc import
|
|
3
|
+
from collections.abc import Callable
|
|
4
4
|
|
|
5
|
-
from
|
|
6
|
-
|
|
7
|
-
from universal_mcp.agents.codeact0.utils import schema_to_signature
|
|
5
|
+
from loguru import logger
|
|
8
6
|
|
|
9
7
|
uneditable_prompt = """
|
|
10
8
|
You are **Ruzo**, an AI Assistant created by AgentR — a creative, straight-forward, and direct principal software engineer with access to tools.
|
|
@@ -14,7 +12,7 @@ Your job is to answer the user's question or perform the task they ask for.
|
|
|
14
12
|
- For task requiring operations or access to external resources, you should achieve the task by executing Python code snippets.
|
|
15
13
|
- You have access to `execute_ipython_cell` tool that allows you to execute Python code in an IPython notebook cell.
|
|
16
14
|
- You also have access to two tools for finding and loading more python functions- `search_functions` and `load_functions`, which you must use for finding functions for using different external applications or additional functionality.
|
|
17
|
-
- Prioritize connected applications over unconnected ones from the output of `search_functions`.
|
|
15
|
+
- Prioritize connected applications over unconnected ones from the output of `search_functions`. However, if the user specifically asks for an application, you MUST use that irrespective of connection status.
|
|
18
16
|
- When multiple apps are connected, or none of the apps are connected, YOU MUST ask the user to choose the application(s). The search results will inform you when such a case occurs, and you must stop and ask the user if multiple apps are relevant.
|
|
19
17
|
- In writing or natural language processing tasks DO NOT answer directly. Instead use `execute_ipython_cell` tool with the AI functions provided to you for tasks like summarizing, text generation, classification, data extraction from text or unstructured data, etc. Avoid hardcoded approaches to classification, data extraction, or creative writing.
|
|
20
18
|
- The code you write will be executed in a sandbox environment, and you can use the output of previous executions in your code. variables, functions, imports are retained.
|
|
@@ -26,6 +24,7 @@ Your job is to answer the user's question or perform the task they ask for.
|
|
|
26
24
|
- Read and understand the output of the previous code snippet and use it to answer the user's request. Note that the code output is NOT visible to the user, so after the task is complete, you have to give the output to the user in a markdown format. Similarly, you should only use print/smart_print for your own analysis, the user does not get the output.
|
|
27
25
|
- If needed, feel free to ask for more information from the user (without using the `execute_ipython_cell` tool) to clarify the task.
|
|
28
26
|
- Always describe in 2-3 lines about the current progress. In each step, mention what has been achieved and what you are planning to do next.
|
|
27
|
+
- DO NOT use the code execution to communicate with the user. The user is not able to see the output of the code cells.
|
|
29
28
|
|
|
30
29
|
**Coding Best Practices:**
|
|
31
30
|
- Variables defined at the top level of previous code snippets can be referenced in your code.
|
|
@@ -72,7 +71,7 @@ You must output a JSON object with a single key "steps", which is a list of stri
|
|
|
72
71
|
|
|
73
72
|
Your plan should:
|
|
74
73
|
1. Identify the key steps in the workflow
|
|
75
|
-
2. Mark user-specific variables that should become the main agent function parameters using `variable_name` syntax. Intermediate variables
|
|
74
|
+
2. Mark user-specific variables that should become the main agent function parameters using `variable_name` syntax. Intermediate variables MUST not be highlighted using ``
|
|
76
75
|
3. Keep the logic generic and reusable
|
|
77
76
|
4. Be clear and concise
|
|
78
77
|
|
|
@@ -95,7 +94,8 @@ Your response must be ONLY the Python code for the function.
|
|
|
95
94
|
Do not include any other text, markdown, or explanations in your response.
|
|
96
95
|
Your response should start with `def` or `async def`.
|
|
97
96
|
The function should be a single, complete piece of code that can be executed independently, based on previously executed code snippets that executed correctly.
|
|
98
|
-
The parameters of the function
|
|
97
|
+
The parameters of the function MUST be exactly the same as the final confirmed agent plan. The variables will are indicated using `` in the plan.
|
|
98
|
+
Any additional functions you require should be child functions inside the main top level function, and thus the first function to appear must be the main agent executable function.
|
|
99
99
|
"""
|
|
100
100
|
|
|
101
101
|
|
|
@@ -132,9 +132,23 @@ def make_safe_function_name(name: str) -> str:
|
|
|
132
132
|
return safe_name
|
|
133
133
|
|
|
134
134
|
|
|
135
|
+
def build_tool_definitions(tools: list[Callable]) -> tuple[list[str], dict[str, Callable]]:
|
|
136
|
+
tool_definitions = []
|
|
137
|
+
context = {}
|
|
138
|
+
for tool in tools:
|
|
139
|
+
tool_name = tool.__name__
|
|
140
|
+
tool_definitions.append(
|
|
141
|
+
f'''{"async " if inspect.iscoroutinefunction(tool) else ""}def {tool_name} {str(inspect.signature(tool))}:
|
|
142
|
+
"""{tool.__doc__}"""
|
|
143
|
+
...'''
|
|
144
|
+
)
|
|
145
|
+
context[tool_name] = tool
|
|
146
|
+
return tool_definitions, context
|
|
147
|
+
|
|
148
|
+
|
|
135
149
|
def create_default_prompt(
|
|
136
|
-
tools:
|
|
137
|
-
additional_tools:
|
|
150
|
+
tools: list[Callable],
|
|
151
|
+
additional_tools: list[Callable],
|
|
138
152
|
base_prompt: str | None = None,
|
|
139
153
|
apps_string: str | None = None,
|
|
140
154
|
agent: object | None = None,
|
|
@@ -150,39 +164,7 @@ def create_default_prompt(
|
|
|
150
164
|
else:
|
|
151
165
|
system_prompt = ""
|
|
152
166
|
|
|
153
|
-
tools_context =
|
|
154
|
-
tool_definitions = []
|
|
155
|
-
|
|
156
|
-
for tool in tools:
|
|
157
|
-
if hasattr(tool, "func") and tool.func is not None:
|
|
158
|
-
tool_callable = tool.func
|
|
159
|
-
is_async = False
|
|
160
|
-
elif hasattr(tool, "coroutine") and tool.coroutine is not None:
|
|
161
|
-
tool_callable = tool.coroutine
|
|
162
|
-
is_async = True
|
|
163
|
-
tool_definitions.append(
|
|
164
|
-
f'''{"async " if is_async else ""}{schema_to_signature(tool.args, tool.name)}:
|
|
165
|
-
"""{tool.description}"""
|
|
166
|
-
...'''
|
|
167
|
-
)
|
|
168
|
-
safe_name = make_safe_function_name(tool.name)
|
|
169
|
-
tools_context[safe_name] = tool_callable
|
|
170
|
-
|
|
171
|
-
for tool in additional_tools:
|
|
172
|
-
if hasattr(tool, "func") and tool.func is not None:
|
|
173
|
-
tool_callable = tool.func
|
|
174
|
-
is_async = False
|
|
175
|
-
elif hasattr(tool, "coroutine") and tool.coroutine is not None:
|
|
176
|
-
tool_callable = tool.coroutine
|
|
177
|
-
is_async = True
|
|
178
|
-
tool_definitions.append(
|
|
179
|
-
f'''{"async " if is_async else ""}def {tool.name} {str(inspect.signature(tool_callable))}:
|
|
180
|
-
"""{tool.description}"""
|
|
181
|
-
...'''
|
|
182
|
-
)
|
|
183
|
-
safe_name = make_safe_function_name(tool.name)
|
|
184
|
-
tools_context[safe_name] = tool_callable
|
|
185
|
-
|
|
167
|
+
tool_definitions, tools_context = build_tool_definitions(tools + additional_tools)
|
|
186
168
|
system_prompt += "\n".join(tool_definitions)
|
|
187
169
|
|
|
188
170
|
if is_initial_prompt:
|
|
@@ -198,7 +180,7 @@ def create_default_prompt(
|
|
|
198
180
|
plan = pb.get("plan")
|
|
199
181
|
code = pb.get("script")
|
|
200
182
|
if plan or code:
|
|
201
|
-
system_prompt += "\n\
|
|
183
|
+
system_prompt += "\n\nYou have been provided an existing agent plan and code for performing a task.:\n"
|
|
202
184
|
if plan:
|
|
203
185
|
if isinstance(plan, list):
|
|
204
186
|
plan_block = "\n".join(f"- {str(s)}" for s in plan)
|
|
@@ -206,7 +188,7 @@ def create_default_prompt(
|
|
|
206
188
|
plan_block = str(plan)
|
|
207
189
|
system_prompt += f"Plan Steps:\n{plan_block}\n"
|
|
208
190
|
if code:
|
|
209
|
-
system_prompt += f"\nScript:\n```python\n{str(code)}\n```\
|
|
191
|
+
system_prompt += f"\nScript:\n```python\n{str(code)}\n```\nThis function can be called by you using `execute_ipython_code`, either directly or using asyncio.run (if an async function). Do NOT redefine the function, unless it has to be modified. For modifying it, you must enter agent_builder mode first so that it is modified in the database and not just the chat locally."
|
|
210
192
|
except Exception:
|
|
211
193
|
# Silently ignore formatting issues
|
|
212
194
|
pass
|
|
@@ -7,6 +7,7 @@ import socket
|
|
|
7
7
|
import threading
|
|
8
8
|
import types
|
|
9
9
|
from typing import Any
|
|
10
|
+
import pickle
|
|
10
11
|
|
|
11
12
|
from langchain_core.tools import tool
|
|
12
13
|
|
|
@@ -26,6 +27,7 @@ def eval_unsafe(
|
|
|
26
27
|
EXCLUDE_TYPES = (
|
|
27
28
|
types.ModuleType,
|
|
28
29
|
type(re.match("", "")),
|
|
30
|
+
type(re.compile("")),
|
|
29
31
|
type(threading.Lock()),
|
|
30
32
|
type(threading.RLock()),
|
|
31
33
|
threading.Event,
|
|
@@ -44,7 +46,7 @@ def eval_unsafe(
|
|
|
44
46
|
exec(code, _locals, _locals)
|
|
45
47
|
result_container["output"] = f.getvalue() or "<code ran, no output printed to stdout>"
|
|
46
48
|
except Exception as e:
|
|
47
|
-
result_container["output"] = "Error during execution:
|
|
49
|
+
result_container["output"] = f"Error during execution: {type(e).__name__}: {e}"
|
|
48
50
|
|
|
49
51
|
thread = threading.Thread(target=target)
|
|
50
52
|
thread.start()
|
|
@@ -64,7 +66,7 @@ def eval_unsafe(
|
|
|
64
66
|
# Filter locals for picklable/storable variables
|
|
65
67
|
all_vars = {}
|
|
66
68
|
for key, value in _locals.items():
|
|
67
|
-
if key
|
|
69
|
+
if key.startswith("__"):
|
|
68
70
|
continue
|
|
69
71
|
if inspect.iscoroutine(value) or inspect.iscoroutinefunction(value):
|
|
70
72
|
continue
|
|
@@ -73,7 +75,12 @@ def eval_unsafe(
|
|
|
73
75
|
if isinstance(value, EXCLUDE_TYPES):
|
|
74
76
|
continue
|
|
75
77
|
if not callable(value) or not hasattr(value, "__name__"):
|
|
76
|
-
|
|
78
|
+
# Only keep if it can be pickled (serialized) successfully
|
|
79
|
+
try:
|
|
80
|
+
pickle.dumps(value)
|
|
81
|
+
all_vars[key] = value
|
|
82
|
+
except Exception:
|
|
83
|
+
pass
|
|
77
84
|
|
|
78
85
|
# Safely derive context
|
|
79
86
|
try:
|
|
@@ -8,7 +8,7 @@ from pydantic import Field
|
|
|
8
8
|
from universal_mcp.agentr.registry import AgentrRegistry
|
|
9
9
|
from universal_mcp.types import ToolFormat
|
|
10
10
|
|
|
11
|
-
from universal_mcp.agents.codeact0.prompts import
|
|
11
|
+
from universal_mcp.agents.codeact0.prompts import build_tool_definitions
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def enter_agent_builder_mode():
|
|
@@ -181,7 +181,7 @@ def create_meta_tools(tool_registry: AgentrRegistry) -> dict[str, Any]:
|
|
|
181
181
|
result_parts.append("") # Empty line between apps
|
|
182
182
|
|
|
183
183
|
# Add connection status information
|
|
184
|
-
if len(connected_apps_in_results) == 0 and len(apps_in_results) >
|
|
184
|
+
if len(connected_apps_in_results) == 0 and len(apps_in_results) > 1:
|
|
185
185
|
result_parts.append(
|
|
186
186
|
"Connection Status: None of the apps in the results are connected. You must ask the user to choose the application."
|
|
187
187
|
)
|
|
@@ -192,7 +192,9 @@ def create_meta_tools(tool_registry: AgentrRegistry) -> dict[str, Any]:
|
|
|
192
192
|
)
|
|
193
193
|
|
|
194
194
|
result_parts.append("Call load_functions to select the required functions only.")
|
|
195
|
-
|
|
195
|
+
if len(connected_apps_in_results)>len(apps_in_results):
|
|
196
|
+
result_parts.append("Unconnected app functions can also be loaded if required by the user, but prefer connected ones.")
|
|
197
|
+
return " ".join(result_parts)
|
|
196
198
|
|
|
197
199
|
@tool
|
|
198
200
|
async def load_functions(tool_ids: list[str]) -> str:
|
|
@@ -218,16 +220,17 @@ def create_meta_tools(tool_registry: AgentrRegistry) -> dict[str, Any]:
|
|
|
218
220
|
return "Error: None of the provided tool IDs could be validated or loaded."
|
|
219
221
|
|
|
220
222
|
# Step 2: Export the schemas of the valid tools.
|
|
221
|
-
|
|
222
|
-
exported_tools =
|
|
223
|
-
|
|
223
|
+
await tool_registry.load_tools(valid_tools)
|
|
224
|
+
exported_tools = await tool_registry.export_tools(
|
|
225
|
+
valid_tools, ToolFormat.NATIVE
|
|
226
|
+
) # Get definition for only the new tools
|
|
224
227
|
|
|
225
228
|
# Step 3: Build the informational string for the agent.
|
|
226
|
-
tool_definitions, new_tools_context =
|
|
229
|
+
tool_definitions, new_tools_context = build_tool_definitions(exported_tools)
|
|
227
230
|
|
|
228
231
|
result_parts = [
|
|
229
232
|
f"Successfully loaded {len(exported_tools)} functions. They are now available for use inside `execute_ipython_cell`:",
|
|
230
|
-
tool_definitions,
|
|
233
|
+
"\n".join(tool_definitions),
|
|
231
234
|
]
|
|
232
235
|
|
|
233
236
|
response_string = "\n\n".join(result_parts)
|
|
@@ -235,7 +238,6 @@ def create_meta_tools(tool_registry: AgentrRegistry) -> dict[str, Any]:
|
|
|
235
238
|
|
|
236
239
|
return response_string, new_tools_context, valid_tools, unconnected_links
|
|
237
240
|
|
|
238
|
-
@tool
|
|
239
241
|
async def web_search(query: str) -> dict:
|
|
240
242
|
"""
|
|
241
243
|
Get an LLM answer to a question informed by Exa search results. Useful when you need information from a wide range of real-time sources on the web. Do not use this when you need to access contents of a specific webpage.
|
|
@@ -4,7 +4,7 @@ import re
|
|
|
4
4
|
from collections.abc import Sequence
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
|
-
from langchain_core.messages import BaseMessage
|
|
7
|
+
from langchain_core.messages import AIMessage, ToolMessage, BaseMessage
|
|
8
8
|
from universal_mcp.types import ToolConfig
|
|
9
9
|
|
|
10
10
|
MAX_CHARS = 5000
|
|
@@ -452,3 +452,78 @@ async def get_connected_apps_string(registry) -> str:
|
|
|
452
452
|
return "\n".join(apps_list)
|
|
453
453
|
except Exception:
|
|
454
454
|
return "Unable to retrieve connected applications."
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
def create_agent_call(agent: object, agent_args: dict[str, Any]) -> AIMessage:
|
|
458
|
+
"""Create an assistant tool-call message to execute the agent script.
|
|
459
|
+
|
|
460
|
+
This inspects the agent's generated script (expected at agent.instructions["script"]) to
|
|
461
|
+
locate the topmost function or async function, then constructs a Python snippet that:
|
|
462
|
+
- embeds the script as-is,
|
|
463
|
+
- deserializes the provided arguments as keyword arguments,
|
|
464
|
+
- invokes the detected function (awaiting it if async), and
|
|
465
|
+
- prints the result via smart_print.
|
|
466
|
+
|
|
467
|
+
If no top-level function is detected or the script cannot be parsed, a safe fallback
|
|
468
|
+
snippet is produced which simply prints the provided arguments.
|
|
469
|
+
|
|
470
|
+
Args:
|
|
471
|
+
agent: Object that provides an `instructions` mapping with a `script` string.
|
|
472
|
+
agent_args: Mapping of argument names to values to be passed as keyword args to the function.
|
|
473
|
+
|
|
474
|
+
Returns:
|
|
475
|
+
AIMessage: A synthetic assistant message containing a single tool call for
|
|
476
|
+
`execute_ipython_cell` with the constructed snippet.
|
|
477
|
+
"""
|
|
478
|
+
content = "Running the agent with your provided parameters"
|
|
479
|
+
script = agent.instructions.get("script") if hasattr(agent, "instructions") else None
|
|
480
|
+
args = agent_args or {}
|
|
481
|
+
|
|
482
|
+
func_name = None
|
|
483
|
+
is_async = False
|
|
484
|
+
|
|
485
|
+
if isinstance(script, str) and script.strip():
|
|
486
|
+
try:
|
|
487
|
+
tree = ast.parse(script)
|
|
488
|
+
for node in tree.body:
|
|
489
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
490
|
+
func_name = node.name
|
|
491
|
+
is_async = isinstance(node, ast.AsyncFunctionDef)
|
|
492
|
+
break
|
|
493
|
+
except SyntaxError:
|
|
494
|
+
func_name = None
|
|
495
|
+
|
|
496
|
+
# Fallback content/snippet if no callable function is found
|
|
497
|
+
if not func_name:
|
|
498
|
+
snippet = (
|
|
499
|
+
"import asyncio\n\n# Test fallback: no function detected in script; printing args\n"
|
|
500
|
+
f"smart_print({repr(args)})\n"
|
|
501
|
+
)
|
|
502
|
+
else:
|
|
503
|
+
import json as _json
|
|
504
|
+
args_json = _json.dumps(args)
|
|
505
|
+
if is_async:
|
|
506
|
+
snippet = (
|
|
507
|
+
f"{script}\n\n"
|
|
508
|
+
"import asyncio, json\n"
|
|
509
|
+
f"_kwargs = json.loads('{args_json}')\n"
|
|
510
|
+
f"async def __runner():\n result = await {func_name}(**_kwargs)\n smart_print(result)\n"
|
|
511
|
+
"asyncio.run(__runner())\n"
|
|
512
|
+
)
|
|
513
|
+
else:
|
|
514
|
+
snippet = (
|
|
515
|
+
f"{script}\n\n"
|
|
516
|
+
"import json\n"
|
|
517
|
+
f"_kwargs = json.loads('{args_json}')\n"
|
|
518
|
+
f"result = {func_name}(**_kwargs)\n"
|
|
519
|
+
"smart_print(result)\n"
|
|
520
|
+
)
|
|
521
|
+
|
|
522
|
+
mock_agent_call = {
|
|
523
|
+
"name": "execute_ipython_cell",
|
|
524
|
+
"args": {"snippet": snippet},
|
|
525
|
+
"id": "initial_agent_call",
|
|
526
|
+
"type": "tool_call",
|
|
527
|
+
}
|
|
528
|
+
mock_assistant_message = AIMessage(content=content, tool_calls=[mock_agent_call])
|
|
529
|
+
return mock_assistant_message
|
universal_mcp/agents/react.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
from langchain.agents import create_agent
|
|
1
2
|
from langgraph.checkpoint.base import BaseCheckpointSaver
|
|
2
|
-
from langgraph.prebuilt import create_react_agent
|
|
3
3
|
from loguru import logger
|
|
4
4
|
from rich import print
|
|
5
5
|
from universal_mcp.agentr.registry import AgentrRegistry
|
|
@@ -75,10 +75,10 @@ class ReactAgent(BaseAgent):
|
|
|
75
75
|
tools = []
|
|
76
76
|
|
|
77
77
|
logger.debug(f"Initialized ReactAgent: name={self.name}, model={self.model}")
|
|
78
|
-
return
|
|
78
|
+
return create_agent(
|
|
79
79
|
self.llm,
|
|
80
80
|
tools,
|
|
81
|
-
|
|
81
|
+
system_prompt=self._build_system_message(),
|
|
82
82
|
checkpointer=self.memory,
|
|
83
83
|
)
|
|
84
84
|
|
universal_mcp/agents/sandbox.py
CHANGED
|
@@ -1,90 +1,123 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
import base64
|
|
1
3
|
import contextlib
|
|
2
|
-
import inspect
|
|
3
4
|
import io
|
|
4
|
-
import
|
|
5
|
-
import re
|
|
6
|
-
import socket
|
|
7
|
-
import threading
|
|
8
|
-
import types
|
|
9
|
-
from typing import Any
|
|
5
|
+
import traceback
|
|
10
6
|
|
|
11
|
-
|
|
7
|
+
import cloudpickle as pickle
|
|
12
8
|
|
|
13
9
|
|
|
14
10
|
class Sandbox:
|
|
15
11
|
"""
|
|
16
|
-
A
|
|
12
|
+
A simulated environment for executing Python code cells with context
|
|
13
|
+
maintained across multiple runs.
|
|
17
14
|
"""
|
|
18
15
|
|
|
19
|
-
def __init__(self
|
|
16
|
+
def __init__(self):
|
|
17
|
+
# Dictionary to store variables (context) across runs
|
|
18
|
+
self.context = {}
|
|
19
|
+
|
|
20
|
+
def add_context(self, context: dict[str, any]):
|
|
21
|
+
"""
|
|
22
|
+
Adds a dictionary of context to the sandbox.
|
|
23
|
+
"""
|
|
24
|
+
self.context.update(context)
|
|
25
|
+
|
|
26
|
+
def save_context(self) -> str:
|
|
27
|
+
"""
|
|
28
|
+
Saves the context to a base64 string.
|
|
29
|
+
"""
|
|
30
|
+
pickled_data = pickle.dumps(self.context)
|
|
31
|
+
base64_encoded = base64.b64encode(pickled_data).decode("utf-8")
|
|
32
|
+
return base64_encoded
|
|
33
|
+
|
|
34
|
+
def load_context(self, context: str):
|
|
35
|
+
"""
|
|
36
|
+
Loads the context from a base64 string.
|
|
20
37
|
"""
|
|
21
|
-
|
|
38
|
+
pickled_data = base64.b64decode(context)
|
|
39
|
+
self.context = pickle.loads(pickled_data)
|
|
40
|
+
|
|
41
|
+
def run(self, code: str) -> dict[str, any]:
|
|
42
|
+
"""
|
|
43
|
+
Executes the provided Python code string in the maintained context.
|
|
44
|
+
|
|
22
45
|
Args:
|
|
23
|
-
|
|
46
|
+
code (str): The Python code to execute.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
dict: A dictionary containing the execution results.
|
|
24
50
|
"""
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
51
|
+
# Prepare the execution environment:
|
|
52
|
+
# Use a copy of the context for execution locals/globals
|
|
53
|
+
exec_scope = self.context.copy()
|
|
54
|
+
|
|
55
|
+
stdout_capture = io.StringIO()
|
|
56
|
+
stderr_output = ""
|
|
57
|
+
|
|
58
|
+
# Use a true context manager for robust stdout capture
|
|
59
|
+
try:
|
|
60
|
+
with contextlib.redirect_stdout(stdout_capture):
|
|
61
|
+
# Execute the code. Using the same dictionary for globals and locals
|
|
62
|
+
# allows newly created variables to be visible immediately.
|
|
63
|
+
exec(code, exec_scope, exec_scope)
|
|
64
|
+
|
|
65
|
+
# Update the context with any new/modified variables
|
|
66
|
+
# Filter out dunder methods/system keys that might be introduced by exec
|
|
67
|
+
new_context = {k: v for k, v in exec_scope.items() if not k.startswith("__")}
|
|
68
|
+
self.context.update(new_context)
|
|
28
69
|
|
|
29
|
-
|
|
70
|
+
except Exception:
|
|
71
|
+
# Capture the traceback for better error reporting (simulated stderr)
|
|
72
|
+
stderr_output = traceback.format_exc()
|
|
73
|
+
|
|
74
|
+
# The execution scope might contain partially defined variables,
|
|
75
|
+
# but we continue to maintain the *previous* valid context.
|
|
76
|
+
# We don't update self.context on failure to avoid polluting it.
|
|
77
|
+
|
|
78
|
+
return {"stdout": stdout_capture.getvalue(), "stderr": stderr_output, "success": stderr_output == ""}
|
|
79
|
+
|
|
80
|
+
def get_context(self) -> dict[str, any]:
|
|
81
|
+
"""
|
|
82
|
+
Returns a copy of the current execution context.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
dict: A copy of the context dictionary.
|
|
86
|
+
"""
|
|
87
|
+
return self.context.copy()
|
|
88
|
+
|
|
89
|
+
def reset(self):
|
|
30
90
|
"""
|
|
31
|
-
|
|
32
|
-
- Returns (output_str, filtered_locals_dict, new_add_context)
|
|
33
|
-
- Errors or timeout are returned as output_str.
|
|
34
|
-
- Previous variables in _locals persist across calls.
|
|
91
|
+
Resets the sandbox's context, clearing all defined variables.
|
|
35
92
|
"""
|
|
93
|
+
self.context = {}
|
|
94
|
+
|
|
95
|
+
async def arun(self, code: str) -> dict[str, any]:
|
|
96
|
+
"""
|
|
97
|
+
Asynchronously executes Python code, supporting top-level await.
|
|
98
|
+
"""
|
|
99
|
+
# Use a copy of the context for execution
|
|
100
|
+
exec_scope = self.context.copy()
|
|
101
|
+
stdout_capture = io.StringIO()
|
|
102
|
+
stderr_output = ""
|
|
36
103
|
|
|
37
|
-
EXCLUDE_TYPES = (
|
|
38
|
-
types.ModuleType,
|
|
39
|
-
type(re.match("", "")),
|
|
40
|
-
type(threading.Lock()),
|
|
41
|
-
type(threading.RLock()),
|
|
42
|
-
threading.Event,
|
|
43
|
-
threading.Condition,
|
|
44
|
-
threading.Semaphore,
|
|
45
|
-
queue.Queue,
|
|
46
|
-
socket.socket,
|
|
47
|
-
io.IOBase,
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
result_container = {"output": "<no output>"}
|
|
51
|
-
|
|
52
|
-
def target():
|
|
53
|
-
try:
|
|
54
|
-
with contextlib.redirect_stdout(io.StringIO()) as f:
|
|
55
|
-
exec(code, self._locals, self._locals)
|
|
56
|
-
result_container["output"] = f.getvalue() or "<code ran, no output printed to stdout>"
|
|
57
|
-
except Exception as e:
|
|
58
|
-
result_container["output"] = "Error during execution: " + str(e)
|
|
59
|
-
|
|
60
|
-
thread = threading.Thread(target=target)
|
|
61
|
-
thread.start()
|
|
62
|
-
thread.join(self.timeout)
|
|
63
|
-
|
|
64
|
-
if thread.is_alive():
|
|
65
|
-
result_container["output"] = f"Code timeout: code execution exceeded {self.timeout} seconds."
|
|
66
|
-
|
|
67
|
-
# Filter locals for picklable/storable variables
|
|
68
|
-
all_vars = {}
|
|
69
|
-
for key, value in self._locals.items():
|
|
70
|
-
if key == "__builtins__":
|
|
71
|
-
continue
|
|
72
|
-
if inspect.iscoroutine(value) or inspect.iscoroutinefunction(value):
|
|
73
|
-
continue
|
|
74
|
-
if inspect.isasyncgen(value) or inspect.isasyncgenfunction(value):
|
|
75
|
-
continue
|
|
76
|
-
if isinstance(value, EXCLUDE_TYPES):
|
|
77
|
-
continue
|
|
78
|
-
if not callable(value) or not hasattr(value, "__name__"):
|
|
79
|
-
all_vars[key] = value
|
|
80
|
-
|
|
81
|
-
self._locals = all_vars
|
|
82
|
-
|
|
83
|
-
# Safely derive context
|
|
84
104
|
try:
|
|
85
|
-
|
|
105
|
+
# Compile the code with the special flag to allow top-level await
|
|
106
|
+
compiled_code = compile(code, "<string>", "exec", flags=ast.PyCF_ALLOW_TOP_LEVEL_AWAIT)
|
|
107
|
+
|
|
108
|
+
with contextlib.redirect_stdout(stdout_capture):
|
|
109
|
+
# Eval the compiled code to get a coroutine
|
|
110
|
+
coroutine = eval(compiled_code, exec_scope, exec_scope)
|
|
111
|
+
|
|
112
|
+
# Await the coroutine to run the code if it's async
|
|
113
|
+
if coroutine:
|
|
114
|
+
await coroutine
|
|
115
|
+
|
|
116
|
+
# Update the context with any new/modified variables
|
|
117
|
+
new_context = {k: v for k, v in exec_scope.items() if not k.startswith("__")}
|
|
118
|
+
self.context.update(new_context)
|
|
119
|
+
|
|
86
120
|
except Exception:
|
|
87
|
-
|
|
88
|
-
pass
|
|
121
|
+
stderr_output = traceback.format_exc()
|
|
89
122
|
|
|
90
|
-
return
|
|
123
|
+
return {"stdout": stdout_capture.getvalue(), "stderr": stderr_output, "success": stderr_output == ""}
|
{universal_mcp_agents-0.1.23rc3.dist-info → universal_mcp_agents-0.1.23rc5.dist-info}/METADATA
RENAMED
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: universal-mcp-agents
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.23rc5
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Project-URL: Homepage, https://github.com/universal-mcp/applications
|
|
6
6
|
Project-URL: Repository, https://github.com/universal-mcp/applications
|
|
7
7
|
Author-email: Manoj Bajaj <manojbajaj95@gmail.com>
|
|
8
8
|
License: MIT
|
|
9
9
|
Requires-Python: >=3.11
|
|
10
|
+
Requires-Dist: cloudpickle>=3.1.1
|
|
10
11
|
Requires-Dist: langchain-anthropic>=0.3.19
|
|
11
12
|
Requires-Dist: langchain-google-genai>=2.1.10
|
|
12
13
|
Requires-Dist: langchain-openai>=0.3.32
|
|
13
14
|
Requires-Dist: langgraph>=0.6.6
|
|
14
|
-
Requires-Dist: typer>=0.17.4
|
|
15
15
|
Requires-Dist: universal-mcp-applications>=0.1.25
|
|
16
|
-
Requires-Dist: universal-mcp>=0.1.
|
|
16
|
+
Requires-Dist: universal-mcp>=0.1.24rc27
|
|
17
17
|
Provides-Extra: dev
|
|
18
18
|
Requires-Dist: pre-commit; extra == 'dev'
|
|
19
19
|
Requires-Dist: ruff; extra == 'dev'
|
|
20
|
+
Requires-Dist: typer>=0.17.4; extra == 'dev'
|
|
20
21
|
Provides-Extra: test
|
|
21
|
-
Requires-Dist: pytest-asyncio>=1.
|
|
22
|
+
Requires-Dist: pytest-asyncio>=1.2.0; extra == 'test'
|
|
22
23
|
Requires-Dist: pytest-cov; extra == 'test'
|
|
23
24
|
Requires-Dist: pytest<9.0.0,>=7.0.0; extra == 'test'
|
{universal_mcp_agents-0.1.23rc3.dist-info → universal_mcp_agents-0.1.23rc5.dist-info}/RECORD
RENAMED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
universal_mcp/agents/__init__.py,sha256=
|
|
2
|
-
universal_mcp/agents/base.py,sha256=
|
|
1
|
+
universal_mcp/agents/__init__.py,sha256=Ythw8tyq7p-w1SPnuO2JtS4TvYEP75PkQpdyvZv-ww4,914
|
|
2
|
+
universal_mcp/agents/base.py,sha256=Sa3ws87OlMklXv9NAs_kXNAvP5DbaAUnFQbx1WqEStM,7410
|
|
3
3
|
universal_mcp/agents/cli.py,sha256=9CG7majpWUz7C6t0d8xr-Sg2ZPKBuQdykTbYS6KIZ3A,922
|
|
4
4
|
universal_mcp/agents/hil.py,sha256=_5PCK6q0goGm8qylJq44aSp2MadP-yCPvhOJYKqWLMo,3808
|
|
5
5
|
universal_mcp/agents/llm.py,sha256=hVRwjZs3MHl5_3BWedmurs2Jt1oZDfFX0Zj9F8KH7fk,1787
|
|
6
|
-
universal_mcp/agents/react.py,sha256=
|
|
7
|
-
universal_mcp/agents/sandbox.py,sha256=
|
|
6
|
+
universal_mcp/agents/react.py,sha256=ocYm94HOiJVI2zwTjO1K2PNfVY7EILLJ6cd__jnGHPs,3327
|
|
7
|
+
universal_mcp/agents/sandbox.py,sha256=LL4OfavEzxbmTDcc_NxizRRpQnw5hc3G2bxvFY63scY,4241
|
|
8
8
|
universal_mcp/agents/simple.py,sha256=NSATg5TWzsRNS7V3LFiDG28WSOCIwCdcC1g7NRwg2nM,2095
|
|
9
9
|
universal_mcp/agents/utils.py,sha256=P6W9k6XAOBp6tdjC2VTP4tE0B2M4-b1EDmr-ylJ47Pw,7765
|
|
10
10
|
universal_mcp/agents/bigtool/__init__.py,sha256=mZG8dsaCVyKlm82otxtiTA225GIFLUCUUYPEIPF24uw,2299
|
|
@@ -13,7 +13,7 @@ universal_mcp/agents/bigtool/agent.py,sha256=mtCDNN8WjE2hjJjooDqusmbferKBHeJMHrh
|
|
|
13
13
|
universal_mcp/agents/bigtool/context.py,sha256=ny7gd-vvVpUOYAeQbAEUT0A6Vm6Nn2qGywxTzPBzYFg,929
|
|
14
14
|
universal_mcp/agents/bigtool/graph.py,sha256=2Sy0dtevTWeT3hJDq4BDerZFvk_zJqx15j8VH2XLq8Y,5848
|
|
15
15
|
universal_mcp/agents/bigtool/prompts.py,sha256=Joi5mCzZX63aM_6eBrMOKuNRHjTkceVIibSsGBGqhYE,2041
|
|
16
|
-
universal_mcp/agents/bigtool/state.py,sha256=
|
|
16
|
+
universal_mcp/agents/bigtool/state.py,sha256=Voh7HXGC0PVe_0qoRZ8ZYg9akg65_2jQIAV2eIwperE,737
|
|
17
17
|
universal_mcp/agents/bigtool/tools.py,sha256=-u80ta6xEaqzEMSzDVe3QZiTZm3YlgLkBD8WTghzClw,6315
|
|
18
18
|
universal_mcp/agents/builder/__main__.py,sha256=VJDJOr-dJJerT53ibh5LVqIsMJ0m0sG2UlzFB784pKw,11680
|
|
19
19
|
universal_mcp/agents/builder/builder.py,sha256=mh3MZpMVB1FE1DWzvMW9NnfiaF145VGn8cJzKSYUlzY,8587
|
|
@@ -21,16 +21,16 @@ universal_mcp/agents/builder/helper.py,sha256=8igR1b3Gy_N2u3WxHYKIWzvw7F5BMnfpO2
|
|
|
21
21
|
universal_mcp/agents/builder/prompts.py,sha256=8Xs6uzTUHguDRngVMLak3lkXFkk2VV_uQXaDllzP5cI,4670
|
|
22
22
|
universal_mcp/agents/builder/state.py,sha256=7DeWllxfN-yD6cd9wJ3KIgjO8TctkJvVjAbZT8W_zqk,922
|
|
23
23
|
universal_mcp/agents/codeact0/__init__.py,sha256=8-fvUo1Sm6dURGI-lW-X3Kd78LqySYbb5NMkNJ4NDwg,76
|
|
24
|
-
universal_mcp/agents/codeact0/__main__.py,sha256=
|
|
25
|
-
universal_mcp/agents/codeact0/agent.py,sha256=
|
|
24
|
+
universal_mcp/agents/codeact0/__main__.py,sha256=YyIoecUcKVUhTcCACzLlSmYrayMDsdwzDEqaV4VV4CE,766
|
|
25
|
+
universal_mcp/agents/codeact0/agent.py,sha256=jaBntdEGydWI6OvRPpDsrLjnNncDdvQtjJbAgkeYp-U,20545
|
|
26
26
|
universal_mcp/agents/codeact0/config.py,sha256=H-1woj_nhSDwf15F63WYn723y4qlRefXzGxuH81uYF0,2215
|
|
27
27
|
universal_mcp/agents/codeact0/langgraph_agent.py,sha256=8nz2wq-LexImx-l1y9_f81fK72IQetnCeljwgnduNGY,420
|
|
28
28
|
universal_mcp/agents/codeact0/llm_tool.py,sha256=-pAz04OrbZ_dJ2ueysT1qZd02DrbLY4EbU0tiuF_UNU,798
|
|
29
|
-
universal_mcp/agents/codeact0/prompts.py,sha256=
|
|
30
|
-
universal_mcp/agents/codeact0/sandbox.py,sha256=
|
|
31
|
-
universal_mcp/agents/codeact0/state.py,sha256=
|
|
32
|
-
universal_mcp/agents/codeact0/tools.py,sha256=
|
|
33
|
-
universal_mcp/agents/codeact0/utils.py,sha256=
|
|
29
|
+
universal_mcp/agents/codeact0/prompts.py,sha256=Zt0ea01ofz6oS7fgyGK2Q2zN9CNMHGubBdR54VgvKic,11684
|
|
30
|
+
universal_mcp/agents/codeact0/sandbox.py,sha256=AYy512wsOKgh4nmXccEF0mntuXDBeHaccsz0aUSIQMI,4696
|
|
31
|
+
universal_mcp/agents/codeact0/state.py,sha256=cf-94hfVub-HSQJk6b7_SzqBS-oxMABjFa8jqyjdDK0,1925
|
|
32
|
+
universal_mcp/agents/codeact0/tools.py,sha256=i2-WppqEfpJXPa7QouLfX3qXJgInBGVY9qxAGxFOUEg,14896
|
|
33
|
+
universal_mcp/agents/codeact0/utils.py,sha256=F2aFnN0tNXbFfe8imO1iccHXTvWwSSulIbsrkwhhpno,21123
|
|
34
34
|
universal_mcp/agents/shared/__main__.py,sha256=XxH5qGDpgFWfq7fwQfgKULXGiUgeTp_YKfcxftuVZq8,1452
|
|
35
35
|
universal_mcp/agents/shared/prompts.py,sha256=yjP3zbbuKi87qCj21qwTTicz8TqtkKgnyGSeEjMu3ho,3761
|
|
36
36
|
universal_mcp/agents/shared/tool_node.py,sha256=DC9F-Ri28Pam0u3sXWNODVgmj9PtAEUb5qP1qOoGgfs,9169
|
|
@@ -39,6 +39,6 @@ universal_mcp/applications/filesystem/app.py,sha256=0TRjjm8YnslVRSmfkXI7qQOAlqWl
|
|
|
39
39
|
universal_mcp/applications/llm/__init__.py,sha256=_XGRxN3O1--ZS5joAsPf8IlI9Qa6negsJrwJ5VJXno0,46
|
|
40
40
|
universal_mcp/applications/llm/app.py,sha256=g9mK-luOLUshZzBGyQZMOHBeCSXmh2kCKir40YnsGUo,12727
|
|
41
41
|
universal_mcp/applications/ui/app.py,sha256=c7OkZsO2fRtndgAzAQbKu-1xXRuRp9Kjgml57YD2NR4,9459
|
|
42
|
-
universal_mcp_agents-0.1.
|
|
43
|
-
universal_mcp_agents-0.1.
|
|
44
|
-
universal_mcp_agents-0.1.
|
|
42
|
+
universal_mcp_agents-0.1.23rc5.dist-info/METADATA,sha256=JN1atZb7RAGx_PCxS2MMWgRXQwkCHT1a-oi_2GzRDFA,931
|
|
43
|
+
universal_mcp_agents-0.1.23rc5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
44
|
+
universal_mcp_agents-0.1.23rc5.dist-info/RECORD,,
|
|
File without changes
|