universal-mcp-agents 0.1.21__py3-none-any.whl → 0.1.23rc1__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.

@@ -16,10 +16,11 @@ from universal_mcp.agents.codeact0.llm_tool import smart_print
16
16
  from universal_mcp.agents.codeact0.prompts import (
17
17
  PLAYBOOK_GENERATING_PROMPT,
18
18
  PLAYBOOK_PLANNING_PROMPT,
19
+ PLAYBOOK_META_PROMPT,
19
20
  create_default_prompt,
20
21
  )
21
22
  from universal_mcp.agents.codeact0.sandbox import eval_unsafe, execute_ipython_cell, handle_execute_ipython_cell
22
- from universal_mcp.agents.codeact0.state import CodeActState, PlaybookCode, PlaybookPlan
23
+ from universal_mcp.agents.codeact0.state import CodeActState, PlaybookCode, PlaybookPlan, PlaybookMeta
23
24
  from universal_mcp.agents.codeact0.tools import (
24
25
  create_meta_tools,
25
26
  enter_playbook_mode,
@@ -28,6 +29,7 @@ from universal_mcp.agents.codeact0.tools import (
28
29
  from universal_mcp.agents.codeact0.utils import add_tools
29
30
  from universal_mcp.agents.llm import load_chat_model
30
31
  from universal_mcp.agents.utils import convert_tool_ids_to_dict, filter_retry_on, get_message_text
32
+ from universal_mcp.agents.codeact0.utils import get_connected_apps_string
31
33
 
32
34
 
33
35
  class CodeActPlaybookAgent(BaseAgent):
@@ -37,7 +39,6 @@ class CodeActPlaybookAgent(BaseAgent):
37
39
  instructions: str,
38
40
  model: str,
39
41
  memory: BaseCheckpointSaver | None = None,
40
- tools: ToolConfig | None = None,
41
42
  registry: ToolRegistry | None = None,
42
43
  playbook_registry: object | None = None,
43
44
  sandbox_timeout: int = 20,
@@ -52,18 +53,18 @@ class CodeActPlaybookAgent(BaseAgent):
52
53
  )
53
54
  self.model_instance = load_chat_model(model)
54
55
  self.playbook_model_instance = load_chat_model("azure/gpt-4.1")
55
- self.tools_config = tools or {}
56
56
  self.registry = registry
57
57
  self.playbook_registry = playbook_registry
58
58
  self.playbook = playbook_registry.get_agent() if playbook_registry else None
59
+ self.tools_config = self.playbook.tools if self.playbook else {}
59
60
  self.eval_fn = eval_unsafe
60
61
  self.sandbox_timeout = sandbox_timeout
61
62
  self.default_tools = {
62
63
  "llm": ["generate_text", "classify_data", "extract_data", "call_llm"],
63
- "markitdown": ["convert_to_markdown"],
64
64
  }
65
65
  add_tools(self.tools_config, self.default_tools)
66
66
 
67
+
67
68
  async def _build_graph(self):
68
69
  meta_tools = create_meta_tools(self.registry)
69
70
  additional_tools = [smart_print, meta_tools["web_search"]]
@@ -151,7 +152,7 @@ class CodeActPlaybookAgent(BaseAgent):
151
152
  else:
152
153
  raise Exception(
153
154
  f"Unexpected tool call: {tool_call['name']}. "
154
- "tool calls must be one of 'enter_playbook_mode', 'execute_ipython_cell', 'load_functions', or 'search_functions'"
155
+ "tool calls must be one of 'enter_playbook_mode', 'execute_ipython_cell', 'load_functions', or 'search_functions'. For using functions, call them in code using 'execute_ipython_cell'."
155
156
  )
156
157
  except Exception as e:
157
158
  tool_result = str(e)
@@ -167,7 +168,7 @@ class CodeActPlaybookAgent(BaseAgent):
167
168
  self.tools_config.extend(new_tool_ids)
168
169
  self.exported_tools = await self.registry.export_tools(new_tool_ids, ToolFormat.LANGCHAIN)
169
170
  self.final_instructions, self.tools_context = create_default_prompt(
170
- self.exported_tools, self.additional_tools, self.instructions, playbook=self.playbook
171
+ self.exported_tools, self.additional_tools, self.instructions, await get_connected_apps_string(self.registry), self.playbook
171
172
  )
172
173
  if ask_user:
173
174
  tool_messages.append(AIMessage(content=ai_msg))
@@ -224,7 +225,47 @@ class CodeActPlaybookAgent(BaseAgent):
224
225
 
225
226
  t = user_text.lower()
226
227
  if t == "yes, this is great":
227
- return Command(goto="playbook", update={"playbook_mode": "generating"})
228
+ self.meta_id = str(uuid.uuid4())
229
+ name, description = None, None
230
+ if self.playbook:
231
+ # Update flow: use existing name/description and do not re-generate
232
+ name = getattr(self.playbook, "name", None)
233
+ description = getattr(self.playbook, "description", None)
234
+ writer({
235
+ "type": "custom",
236
+ id: self.meta_id,
237
+ "name": "generating",
238
+ "data": {
239
+ "update": True,
240
+ "name": name,
241
+ "description": description,
242
+ }
243
+ })
244
+ else:
245
+ writer({
246
+ "type": "custom",
247
+ id: self.meta_id,
248
+ "name": "generating",
249
+ "data": {"update": False}
250
+ })
251
+
252
+ meta_instructions = self.instructions + PLAYBOOK_META_PROMPT
253
+ messages = [{"role": "system", "content": meta_instructions}] + state["messages"]
254
+
255
+ model_with_structured_output = self.playbook_model_instance.with_structured_output(PlaybookMeta)
256
+ meta_response = model_with_structured_output.invoke(messages)
257
+ meta = cast(PlaybookMeta, meta_response)
258
+ name, description = meta.name, meta.description
259
+
260
+ # Emit intermediary UI update with created name/description
261
+ writer({
262
+ "type": "custom",
263
+ id: self.meta_id,
264
+ "name": "generating",
265
+ "data": {"update": False, "name": name, "description": description}
266
+ })
267
+
268
+ return Command(goto="playbook", update={"playbook_mode": "generating", "playbook_name": name, "playbook_description": description})
228
269
  if t == "i would like to modify the plan":
229
270
  prompt_ai = AIMessage(content="What would you like to change about the plan? Let me know and I'll update the plan accordingly.", additional_kwargs={"stream": "true"})
230
271
  return Command(update={"playbook_mode": "planning", "messages": [prompt_ai]})
@@ -235,13 +276,6 @@ class CodeActPlaybookAgent(BaseAgent):
235
276
  return Command(goto="call_model", update={"playbook_mode": "inactive"})
236
277
 
237
278
  elif playbook_mode == "generating":
238
- generate_id = str(uuid.uuid4())
239
- writer({
240
- "type": "custom",
241
- id: generate_id,
242
- "name": "generating",
243
- "data": {"update": bool(self.playbook)}
244
- })
245
279
  generating_instructions = self.instructions + PLAYBOOK_GENERATING_PROMPT
246
280
  messages = [{"role": "system", "content": generating_instructions}] + state["messages"]
247
281
 
@@ -256,6 +290,10 @@ class CodeActPlaybookAgent(BaseAgent):
256
290
  else:
257
291
  function_name = "generated_playbook"
258
292
 
293
+ # Use generated metadata if available
294
+ final_name = state.get("playbook_name") or function_name
295
+ final_description = state.get("playbook_description") or f"Generated playbook: {function_name}"
296
+
259
297
  # Save or update an Agent using the helper registry
260
298
  try:
261
299
  if not self.playbook_registry:
@@ -271,8 +309,8 @@ class CodeActPlaybookAgent(BaseAgent):
271
309
  tool_dict = convert_tool_ids_to_dict(state["selected_tool_ids"])
272
310
 
273
311
  res = self.playbook_registry.upsert_agent(
274
- name=function_name,
275
- description=f"Generated playbook: {function_name}",
312
+ name=final_name,
313
+ description=final_description,
276
314
  instructions=instructions_payload,
277
315
  tools=tool_dict,
278
316
  visibility="private",
@@ -282,11 +320,25 @@ class CodeActPlaybookAgent(BaseAgent):
282
320
 
283
321
  writer({
284
322
  "type": "custom",
285
- id: generate_id,
323
+ id: self.meta_id,
286
324
  "name": "generating",
287
- "data": {"id": str(res.id), "update": bool(self.playbook)}
325
+ "data": {
326
+ "id": str(res.id),
327
+ "update": bool(self.playbook),
328
+ "name": final_name,
329
+ "description": final_description,
330
+ }
288
331
  })
289
- mock_assistant_message = AIMessage(content=json.dumps(response.dict()), additional_kwargs={"type": "generating", "id": str(res.id), "update": bool(self.playbook)})
332
+ mock_assistant_message = AIMessage(
333
+ content=json.dumps(response.dict()),
334
+ additional_kwargs={
335
+ "type": "generating",
336
+ "id": str(res.id),
337
+ "update": bool(self.playbook),
338
+ "name": final_name,
339
+ "description": final_description,
340
+ },
341
+ )
290
342
 
291
343
  return Command(
292
344
  update={"messages": [mock_assistant_message], "playbook_mode": "normal"}
@@ -298,7 +350,7 @@ class CodeActPlaybookAgent(BaseAgent):
298
350
  self.tools_config.extend(state.get("selected_tool_ids", []))
299
351
  self.exported_tools = await self.registry.export_tools(self.tools_config, ToolFormat.LANGCHAIN)
300
352
  self.final_instructions, self.tools_context = create_default_prompt(
301
- self.exported_tools, self.additional_tools, self.instructions, playbook=self.playbook
353
+ self.exported_tools, self.additional_tools, self.instructions, await get_connected_apps_string(self.registry), self.playbook
302
354
  )
303
355
  if state.get("playbook_mode") in ["planning", "confirming", "generating"]:
304
356
  return "playbook"
@@ -3,6 +3,7 @@ import re
3
3
  from collections.abc import Sequence
4
4
 
5
5
  from langchain_core.tools import StructuredTool
6
+ from universal_mcp.agents.codeact0.utils import schema_to_signature
6
7
 
7
8
  uneditable_prompt = """
8
9
  You are **Ruzo**, an AI Assistant created by AgentR — a creative, straight-forward, and direct principal software engineer with access to tools.
@@ -97,6 +98,26 @@ The parameters of the function should be the same as the final confirmed playboo
97
98
  """
98
99
 
99
100
 
101
+ PLAYBOOK_META_PROMPT = """
102
+ You are preparing metadata for a reusable playbook based on the confirmed step-by-step plan.
103
+
104
+ TASK: Create a concise, human-friendly name and a short description for the playbook.
105
+
106
+ INPUTS:
107
+ - Conversation context and plan steps will be provided in prior messages
108
+
109
+ REQUIREMENTS:
110
+ 1. Name: 3-6 words, Title Case, no punctuation except hyphens if needed
111
+ 2. Description: Single sentence, <= 140 characters, clearly states what the playbook does
112
+
113
+ OUTPUT: Return ONLY a JSON object with exactly these keys:
114
+ {
115
+ "name": "...",
116
+ "description": "..."
117
+ }
118
+ """
119
+
120
+
100
121
  def make_safe_function_name(name: str) -> str:
101
122
  """Convert a tool name to a valid Python function name."""
102
123
  # Replace non-alphanumeric characters with underscores
@@ -114,14 +135,31 @@ def create_default_prompt(
114
135
  tools: Sequence[StructuredTool],
115
136
  additional_tools: Sequence[StructuredTool],
116
137
  base_prompt: str | None = None,
138
+ apps_string: str | None = None,
117
139
  playbook: object | None = None,
118
140
  ):
119
- system_prompt = uneditable_prompt.strip() + (
120
- "\n\nIn addition to the Python Standard Library, you can use the following external functions:\n"
121
- )
141
+ system_prompt = uneditable_prompt.strip()
142
+ if apps_string:
143
+ system_prompt += f"\n\n**Connected external applications (These apps have been logged into by the user):**\n{apps_string}\n\n Use `search_functions` to search for functions you can perform using the above. You can also discover more applications using the `search_functions` tool to find additional tools and integrations, if required.\n"
144
+ system_prompt += "\n\nIn addition to the Python Standard Library, you can use the following external functions:\n"
145
+
122
146
  tools_context = {}
123
147
 
124
- for tool in tools + additional_tools:
148
+ for tool in tools:
149
+ if hasattr(tool, "func") and tool.func is not None:
150
+ tool_callable = tool.func
151
+ is_async = False
152
+ elif hasattr(tool, "coroutine") and tool.coroutine is not None:
153
+ tool_callable = tool.coroutine
154
+ is_async = True
155
+ system_prompt += f'''{"async " if is_async else ""}{schema_to_signature(tool.args, tool.name)}:
156
+ """{tool.description}"""
157
+ ...
158
+ '''
159
+ safe_name = make_safe_function_name(tool.name)
160
+ tools_context[safe_name] = tool_callable
161
+
162
+ for tool in additional_tools:
125
163
  if hasattr(tool, "func") and tool.func is not None:
126
164
  tool_callable = tool.func
127
165
  is_async = False
@@ -131,7 +169,7 @@ def create_default_prompt(
131
169
  system_prompt += f'''{"async " if is_async else ""}def {tool.name} {str(inspect.signature(tool_callable))}:
132
170
  """{tool.description}"""
133
171
  ...
134
- '''
172
+ '''
135
173
  safe_name = make_safe_function_name(tool.name)
136
174
  tools_context[safe_name] = tool_callable
137
175
 
@@ -12,6 +12,11 @@ class PlaybookCode(BaseModel):
12
12
  code: str = Field(description="The Python code for the playbook.")
13
13
 
14
14
 
15
+ class PlaybookMeta(BaseModel):
16
+ name: str = Field(description="Concise, title-cased playbook name (3-6 words).")
17
+ description: str = Field(description="Short, one-sentence description (<= 140 chars).")
18
+
19
+
15
20
  def _enqueue(left: list, right: list) -> list:
16
21
  """Treat left as a FIFO queue, append new items from right (preserve order),
17
22
  keep items unique, and cap total size to 20 (drop oldest items)."""
@@ -47,3 +52,7 @@ class CodeActState(AgentState):
47
52
  """Queue for tools exported from registry"""
48
53
  plan: list[str] | None
49
54
  """Plan for the playbook agent."""
55
+ playbook_name: str | None
56
+ """Generated playbook name after confirmation."""
57
+ playbook_description: str | None
58
+ """Generated short description after confirmation."""
@@ -14,12 +14,6 @@ def enter_playbook_mode():
14
14
  """Call this function to enter playbook mode. Playbook mode is when the user wants to store a repeated task as a script with some inputs for the future."""
15
15
  return
16
16
 
17
-
18
- def exit_playbook_mode():
19
- """Call this function to exit playbook mode. Playbook mode is when the user wants to store a repeated task as a script with some inputs for the future."""
20
- return
21
-
22
-
23
17
  def create_meta_tools(tool_registry: AgentrRegistry) -> dict[str, Any]:
24
18
  """Create the meta tools for searching and loading tools"""
25
19
 
@@ -70,9 +64,10 @@ def create_meta_tools(tool_registry: AgentrRegistry) -> dict[str, Any]:
70
64
 
71
65
  canonical_app_id = None
72
66
  found_tools_result = []
67
+ THRESHOLD = 0.8
73
68
 
74
69
  if app_id:
75
- relevant_apps = await registry.search_apps(query=app_id, distance_threshold=0.7)
70
+ relevant_apps = await registry.search_apps(query=app_id, distance_threshold=THRESHOLD)
76
71
  if not relevant_apps:
77
72
  return {
78
73
  "found_tools": [],
@@ -104,11 +99,11 @@ def create_meta_tools(tool_registry: AgentrRegistry) -> dict[str, Any]:
104
99
  prioritized_app_id_list = [canonical_app_id]
105
100
  else:
106
101
  # 1. Perform an initial broad search for tools.
107
- initial_tool_search_tasks = [registry.search_tools(query=q, distance_threshold=0.7) for q in queries]
102
+ initial_tool_search_tasks = [registry.search_tools(query=q, distance_threshold=THRESHOLD) for q in queries]
108
103
  initial_tool_results = await asyncio.gather(*initial_tool_search_tasks)
109
104
 
110
105
  # 2. Search for relevant apps.
111
- app_search_tasks = [registry.search_apps(query=q, distance_threshold=0.7) for q in queries]
106
+ app_search_tasks = [registry.search_apps(query=q, distance_threshold=THRESHOLD) for q in queries]
112
107
  app_search_results = await asyncio.gather(*app_search_tasks)
113
108
 
114
109
  # 3. Create a prioritized list of app IDs for the final search.
@@ -131,7 +126,7 @@ def create_meta_tools(tool_registry: AgentrRegistry) -> dict[str, Any]:
131
126
  for app_id_to_search in prioritized_app_id_list:
132
127
  for query in queries:
133
128
  final_tool_search_tasks.append(
134
- registry.search_tools(query=query, app_id=app_id_to_search, distance_threshold=0.7)
129
+ registry.search_tools(query=query, app_id=app_id_to_search, distance_threshold=THRESHOLD)
135
130
  )
136
131
  query_results = await asyncio.gather(*final_tool_search_tasks)
137
132
 
@@ -209,29 +204,27 @@ def create_meta_tools(tool_registry: AgentrRegistry) -> dict[str, Any]:
209
204
 
210
205
  @tool
211
206
  async def web_search(query: str) -> dict:
212
- """Get an LLM answer to a question informed by Perplexity web search results.
213
- Useful when you need information from a wide range of real-time sources on the web.
214
- Do not use this when you need to access contents of a specific webpage.
207
+ """
208
+ 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.
215
209
 
216
- This tool performs a Perplexity request via `perplexity__answer_with_search`, which:
217
- 1. Provides a **direct answer** for factual queries with citation(s)
210
+ This tool performs an Exa `/answer` request, which:
211
+ 1. Provides a **direct answer** for factual queries (e.g., "What is the capital of France?" → "Paris")
218
212
  2. Generates a **summary with citations** for open-ended questions
213
+ (e.g., "What is the state of AI in healthcare?" → A detailed summary with source links)
219
214
 
220
215
  Args:
221
216
  query (str): The question or topic to answer.
222
-
223
217
  Returns:
224
- dict: A structured response containing:
225
- - answer (str): Generated answer with markdown formatting and citation numbers [1][2]
226
- - citations (list[str]): List of source URLs corresponding to citation numbers
218
+ dict: A structured response containing only:
219
+ - answer (str): Generated answer
220
+ - citations (list[dict]): List of cited sources
227
221
  """
228
222
  await tool_registry.export_tools(["exa__answer"], ToolFormat.LANGCHAIN)
229
223
  response = await tool_registry.call_tool("exa__answer", {"query": query, "text": True})
230
- logger.info(f"Web search response: {response}")
231
224
 
232
225
  # Extract only desired fields
233
226
  return {
234
- "answer": response.get("content"),
227
+ "answer": response.get("answer"),
235
228
  "citations": response.get("citations", []),
236
229
  }
237
230
 
@@ -279,7 +272,7 @@ async def get_valid_tools(tool_ids: list[str], registry: AgentrRegistry) -> tupl
279
272
  continue
280
273
  if app not in connected_apps and app not in unconnected:
281
274
  unconnected.add(app)
282
- text = registry.authorise_app(app_id=app)
275
+ text = await registry.authorise_app(app_id=app)
283
276
  start = text.find(":") + 1
284
277
  end = text.find(". R", start)
285
278
  url = text[start:end].strip()
@@ -333,35 +333,48 @@ def inject_context(
333
333
  return namespace
334
334
 
335
335
 
336
- def schema_to_signature(schema: dict, func_name="my_function") -> str:
336
+ def schema_to_signature(schema: dict, func_name: str = "my_function") -> str:
337
+ """
338
+ Convert a JSON schema into a Python-style function signature string.
339
+ Handles fields with `type`, `anyOf`, defaults, and missing metadata safely.
340
+ """
337
341
  type_map = {
338
342
  "integer": "int",
339
343
  "string": "str",
340
344
  "boolean": "bool",
341
345
  "null": "None",
346
+ "number": "float",
347
+ "array": "list",
348
+ "object": "dict",
342
349
  }
343
350
 
344
351
  params = []
345
352
  for name, meta in schema.items():
346
- # figure out type
347
- if "type" in meta:
353
+ if not isinstance(meta, dict):
354
+ typ = "Any"
355
+ elif "type" in meta:
348
356
  typ = type_map.get(meta["type"], "Any")
349
357
  elif "anyOf" in meta:
350
- types = [type_map.get(t["type"], "Any") for t in meta["anyOf"]]
351
- typ = " | ".join(set(types))
358
+ types = []
359
+ for t in meta["anyOf"]:
360
+ if not isinstance(t, dict):
361
+ continue
362
+ t_type = t.get("type")
363
+ types.append(type_map.get(t_type, "Any") if t_type else "Any")
364
+ typ = " | ".join(sorted(set(types))) if types else "Any"
352
365
  else:
353
366
  typ = "Any"
354
367
 
355
- default = meta.get("default", None)
356
- default_repr = repr(default)
357
-
358
- params.append(f"{name}: {typ} = {default_repr}")
368
+ # Handle defaults gracefully
369
+ default = meta.get("default")
370
+ if default is None:
371
+ params.append(f"{name}: {typ}")
372
+ else:
373
+ params.append(f"{name}: {typ} = {repr(default)}")
359
374
 
360
- # join into signature
361
375
  param_str = ",\n ".join(params)
362
376
  return f"def {func_name}(\n {param_str},\n):"
363
377
 
364
-
365
378
  def smart_truncate(
366
379
  output: str, max_chars_full: int = 2000, max_lines_headtail: int = 20, summary_threshold: int = 10000
367
380
  ) -> str:
@@ -394,3 +407,27 @@ def smart_truncate(
394
407
  truncated = truncated[:summary_threshold] + "\n... [output truncated to fit context] ..."
395
408
 
396
409
  return truncated
410
+
411
+
412
+ async def get_connected_apps_string(registry) -> str:
413
+ """Get a formatted string of connected applications from the registry."""
414
+ if not registry:
415
+ return ""
416
+
417
+ try:
418
+ # Get connected apps from registry
419
+ connections = await registry.list_connected_apps()
420
+ if not connections:
421
+ return "No applications are currently connected."
422
+
423
+ # Extract app names from connections
424
+ connected_app_ids = {connection["app_id"] for connection in connections}
425
+
426
+ # Format the apps list
427
+ apps_list = []
428
+ for app_id in connected_app_ids:
429
+ apps_list.append(f"- {app_id}")
430
+
431
+ return "\n".join(apps_list)
432
+ except Exception:
433
+ return "Unable to retrieve connected applications."
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: universal-mcp-agents
3
- Version: 0.1.21
3
+ Version: 0.1.23rc1
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
@@ -22,15 +22,15 @@ universal_mcp/agents/builder/prompts.py,sha256=8Xs6uzTUHguDRngVMLak3lkXFkk2VV_uQ
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
24
  universal_mcp/agents/codeact0/__main__.py,sha256=_7qSz97YnRgYJTESkALS5_eBIGHiMjA5rhr3IAeBvVo,896
25
- universal_mcp/agents/codeact0/agent.py,sha256=KvIoZh2J2JQONfGf80LBuXDdQnnYja4ybZ4DluCKxPM,15192
25
+ universal_mcp/agents/codeact0/agent.py,sha256=--cAjQ05VntXga2ofpnL9oFXAk6ANZ2SftwtLkQgy00,17844
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=a5ja7KwSG1SmbCkoZVdyFOI5dz2Ul-OWG-JcakBySDM,9635
29
+ universal_mcp/agents/codeact0/prompts.py,sha256=Gk6WTx2X7IOlbC3wYtGwKWDoeUtgpkMeiyfhj6LEq2I,11221
30
30
  universal_mcp/agents/codeact0/sandbox.py,sha256=Xw4tbUV_6haYIZZvteJi6lIYsW6ni_3DCRCOkslTKgM,4459
31
- universal_mcp/agents/codeact0/state.py,sha256=Z9fUmBTw-29MZTq2GsYYyyjLPyrtE5GDnhX4gSqHhcA,1555
32
- universal_mcp/agents/codeact0/tools.py,sha256=qGhbJl74xflJBNfOCiy-Ts5zKIxXjE1JVyqvtVGHZNY,13363
33
- universal_mcp/agents/codeact0/utils.py,sha256=Rustf3MFoFbasdnwBh9YvNrXqasgANkBAWQn9AjqBO4,16240
31
+ universal_mcp/agents/codeact0/state.py,sha256=co3BZBuMIt1FP2qzgsbsLkyKbddCG1ieKyAw9TAskSU,1944
32
+ universal_mcp/agents/codeact0/tools.py,sha256=1EBStJQQQCuNeWOqt0VP-XFiT0fE4oCR9nvUiwzRhe4,13164
33
+ universal_mcp/agents/codeact0/utils.py,sha256=PgisAxmqYIzimc4lFA1nV-R7gxkICIrtO1q0FQZ-UoY,17580
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.21.dist-info/METADATA,sha256=2Nx9bEG_IEb5wHTV-8vXpQEUTNsl0bbQkPR6Ii4R1V0,878
43
- universal_mcp_agents-0.1.21.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
44
- universal_mcp_agents-0.1.21.dist-info/RECORD,,
42
+ universal_mcp_agents-0.1.23rc1.dist-info/METADATA,sha256=Fa-ACWH1oawoVDBAbp2iSSDGSCRovD2rWP9e9lUhcYE,881
43
+ universal_mcp_agents-0.1.23rc1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
44
+ universal_mcp_agents-0.1.23rc1.dist-info/RECORD,,