aip-agents-binary 0.5.25__py3-none-macosx_13_0_arm64.whl → 0.6.8__py3-none-macosx_13_0_arm64.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.
- aip_agents/agent/__init__.py +44 -4
- aip_agents/agent/base_langgraph_agent.py +163 -74
- aip_agents/agent/base_langgraph_agent.pyi +3 -2
- aip_agents/agent/langgraph_memory_enhancer_agent.py +368 -34
- aip_agents/agent/langgraph_memory_enhancer_agent.pyi +3 -2
- aip_agents/agent/langgraph_react_agent.py +329 -22
- aip_agents/agent/langgraph_react_agent.pyi +41 -2
- aip_agents/examples/hello_world_ptc.py +49 -0
- aip_agents/examples/hello_world_ptc.pyi +5 -0
- aip_agents/examples/hello_world_ptc_custom_tools.py +83 -0
- aip_agents/examples/hello_world_ptc_custom_tools.pyi +7 -0
- aip_agents/examples/hello_world_tool_output_client.py +9 -0
- aip_agents/examples/tools/multiply_tool.py +43 -0
- aip_agents/examples/tools/multiply_tool.pyi +18 -0
- aip_agents/guardrails/engines/base.py +6 -6
- aip_agents/mcp/client/__init__.py +38 -2
- aip_agents/mcp/client/connection_manager.py +36 -1
- aip_agents/mcp/client/connection_manager.pyi +3 -0
- aip_agents/mcp/client/persistent_session.py +318 -68
- aip_agents/mcp/client/persistent_session.pyi +9 -0
- aip_agents/mcp/client/transports.py +37 -2
- aip_agents/mcp/client/transports.pyi +9 -0
- aip_agents/memory/adapters/base_adapter.py +98 -0
- aip_agents/memory/adapters/base_adapter.pyi +25 -0
- aip_agents/ptc/__init__.py +87 -0
- aip_agents/ptc/__init__.pyi +14 -0
- aip_agents/ptc/custom_tools.py +473 -0
- aip_agents/ptc/custom_tools.pyi +184 -0
- aip_agents/ptc/custom_tools_payload.py +400 -0
- aip_agents/ptc/custom_tools_payload.pyi +31 -0
- aip_agents/ptc/custom_tools_templates/__init__.py +1 -0
- aip_agents/ptc/custom_tools_templates/__init__.pyi +0 -0
- aip_agents/ptc/custom_tools_templates/custom_build_function.py.template +23 -0
- aip_agents/ptc/custom_tools_templates/custom_init.py.template +15 -0
- aip_agents/ptc/custom_tools_templates/custom_invoke.py.template +60 -0
- aip_agents/ptc/custom_tools_templates/custom_registry.py.template +87 -0
- aip_agents/ptc/custom_tools_templates/custom_sources_init.py.template +7 -0
- aip_agents/ptc/custom_tools_templates/custom_wrapper.py.template +19 -0
- aip_agents/ptc/doc_gen.py +122 -0
- aip_agents/ptc/doc_gen.pyi +40 -0
- aip_agents/ptc/exceptions.py +57 -0
- aip_agents/ptc/exceptions.pyi +37 -0
- aip_agents/ptc/executor.py +261 -0
- aip_agents/ptc/executor.pyi +99 -0
- aip_agents/ptc/mcp/__init__.py +45 -0
- aip_agents/ptc/mcp/__init__.pyi +7 -0
- aip_agents/ptc/mcp/sandbox_bridge.py +668 -0
- aip_agents/ptc/mcp/sandbox_bridge.pyi +47 -0
- aip_agents/ptc/mcp/templates/__init__.py +1 -0
- aip_agents/ptc/mcp/templates/__init__.pyi +0 -0
- aip_agents/ptc/mcp/templates/mcp_client.py.template +239 -0
- aip_agents/ptc/naming.py +196 -0
- aip_agents/ptc/naming.pyi +85 -0
- aip_agents/ptc/payload.py +26 -0
- aip_agents/ptc/payload.pyi +15 -0
- aip_agents/ptc/prompt_builder.py +673 -0
- aip_agents/ptc/prompt_builder.pyi +59 -0
- aip_agents/ptc/ptc_helper.py +16 -0
- aip_agents/ptc/ptc_helper.pyi +1 -0
- aip_agents/ptc/sandbox_bridge.py +256 -0
- aip_agents/ptc/sandbox_bridge.pyi +38 -0
- aip_agents/ptc/template_utils.py +33 -0
- aip_agents/ptc/template_utils.pyi +13 -0
- aip_agents/ptc/templates/__init__.py +1 -0
- aip_agents/ptc/templates/__init__.pyi +0 -0
- aip_agents/ptc/templates/ptc_helper.py.template +134 -0
- aip_agents/ptc/tool_def_helpers.py +101 -0
- aip_agents/ptc/tool_def_helpers.pyi +38 -0
- aip_agents/ptc/tool_enrichment.py +163 -0
- aip_agents/ptc/tool_enrichment.pyi +60 -0
- aip_agents/sandbox/__init__.py +43 -0
- aip_agents/sandbox/__init__.pyi +5 -0
- aip_agents/sandbox/defaults.py +205 -0
- aip_agents/sandbox/defaults.pyi +30 -0
- aip_agents/sandbox/e2b_runtime.py +295 -0
- aip_agents/sandbox/e2b_runtime.pyi +57 -0
- aip_agents/sandbox/template_builder.py +131 -0
- aip_agents/sandbox/template_builder.pyi +36 -0
- aip_agents/sandbox/types.py +24 -0
- aip_agents/sandbox/types.pyi +14 -0
- aip_agents/sandbox/validation.py +50 -0
- aip_agents/sandbox/validation.pyi +20 -0
- aip_agents/sentry/sentry.py +29 -8
- aip_agents/sentry/sentry.pyi +3 -2
- aip_agents/tools/__init__.py +13 -2
- aip_agents/tools/__init__.pyi +3 -1
- aip_agents/tools/browser_use/browser_use_tool.py +8 -0
- aip_agents/tools/browser_use/streaming.py +2 -0
- aip_agents/tools/date_range_tool.py +554 -0
- aip_agents/tools/date_range_tool.pyi +21 -0
- aip_agents/tools/execute_ptc_code.py +357 -0
- aip_agents/tools/execute_ptc_code.pyi +90 -0
- aip_agents/tools/memory_search/__init__.py +8 -1
- aip_agents/tools/memory_search/__init__.pyi +3 -3
- aip_agents/tools/memory_search/mem0.py +114 -1
- aip_agents/tools/memory_search/mem0.pyi +11 -1
- aip_agents/tools/memory_search/schema.py +33 -0
- aip_agents/tools/memory_search/schema.pyi +10 -0
- aip_agents/tools/memory_search_tool.py +8 -0
- aip_agents/tools/memory_search_tool.pyi +2 -2
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +26 -1
- aip_agents/utils/langgraph/tool_output_management.py +80 -0
- aip_agents/utils/langgraph/tool_output_management.pyi +37 -0
- {aip_agents_binary-0.5.25.dist-info → aip_agents_binary-0.6.8.dist-info}/METADATA +9 -19
- {aip_agents_binary-0.5.25.dist-info → aip_agents_binary-0.6.8.dist-info}/RECORD +107 -41
- {aip_agents_binary-0.5.25.dist-info → aip_agents_binary-0.6.8.dist-info}/WHEEL +1 -1
- aip_agents/examples/demo_memory_recall.py +0 -401
- aip_agents/examples/demo_memory_recall.pyi +0 -58
- {aip_agents_binary-0.5.25.dist-info → aip_agents_binary-0.6.8.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from aip_agents.ptc.custom_tools import PTCFileToolDef as PTCFileToolDef, PTCPackageToolDef as PTCPackageToolDef
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
def package_tool(name: str, *, import_path: str, class_name: str, package_path: str | None = None, description: str | None = None, input_schema: dict[str, Any] | None = None) -> PTCPackageToolDef:
|
|
5
|
+
'''Create a package-based tool definition.
|
|
6
|
+
|
|
7
|
+
Args:
|
|
8
|
+
name: Tool name (will be sanitized for Python compatibility).
|
|
9
|
+
import_path: Python import path (e.g., "aip_agents.tools.time_tool").
|
|
10
|
+
class_name: Tool class name to instantiate.
|
|
11
|
+
package_path: Optional local package path for bundling.
|
|
12
|
+
description: Optional tool description (auto-derived from tool if not provided).
|
|
13
|
+
input_schema: Optional JSON schema (auto-derived from tool if not provided).
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
PTCPackageToolDef dict ready for use in PTCCustomToolConfig.tools.
|
|
17
|
+
|
|
18
|
+
Example:
|
|
19
|
+
>>> package_tool("time_tool", import_path="aip_agents.tools.time_tool", class_name="TimeTool")
|
|
20
|
+
{\'name\': \'time_tool\', \'kind\': \'package\', \'import_path\': \'aip_agents.tools.time_tool\', \'class_name\': \'TimeTool\'}
|
|
21
|
+
'''
|
|
22
|
+
def file_tool(name: str, *, file_path: str, class_name: str, description: str | None = None, input_schema: dict[str, Any] | None = None) -> PTCFileToolDef:
|
|
23
|
+
'''Create a file-based tool definition.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
name: Tool name (will be sanitized for Python compatibility).
|
|
27
|
+
file_path: Absolute path to the Python file containing the tool.
|
|
28
|
+
class_name: Tool class name to instantiate.
|
|
29
|
+
description: Optional tool description (auto-derived from tool if not provided).
|
|
30
|
+
input_schema: Optional JSON schema (auto-derived from tool if not provided).
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
PTCFileToolDef dict ready for use in PTCCustomToolConfig.tools.
|
|
34
|
+
|
|
35
|
+
Example:
|
|
36
|
+
>>> file_tool("multiply", file_path="/path/to/multiply_tool.py", class_name="MultiplyTool")
|
|
37
|
+
{\'name\': \'multiply\', \'kind\': \'file\', \'file_path\': \'/path/to/multiply_tool.py\', \'class_name\': \'MultiplyTool\'}
|
|
38
|
+
'''
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""Tool metadata enrichment utilities.
|
|
2
|
+
|
|
3
|
+
This module provides functions to enrich custom tool definitions with metadata
|
|
4
|
+
from actual tool objects (name, description, input_schema).
|
|
5
|
+
|
|
6
|
+
Author: Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import logging
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
13
|
+
|
|
14
|
+
from aip_agents.ptc.custom_tools import (
|
|
15
|
+
PTCToolDef,
|
|
16
|
+
enrich_tool_def_with_metadata,
|
|
17
|
+
)
|
|
18
|
+
from aip_agents.ptc.naming import sanitize_function_name
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from aip_agents.ptc import PTCCustomToolConfig
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def build_tool_lookup(tools: list[object]) -> dict[str, object]:
|
|
27
|
+
"""Build a lookup map from tool objects for name-based matching.
|
|
28
|
+
|
|
29
|
+
Creates entries for both original and sanitized names to support
|
|
30
|
+
fuzzy matching (e.g., "web-search" matches "web_search").
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
tools: List of tool objects with `name` attribute.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Dict mapping tool names (and sanitized names) to tool objects.
|
|
37
|
+
|
|
38
|
+
Example:
|
|
39
|
+
>>> tools = [TimeTool(), WebSearchTool()] # names: "time_tool", "web-search"
|
|
40
|
+
>>> lookup = build_tool_lookup(tools)
|
|
41
|
+
>>> lookup.keys()
|
|
42
|
+
dict_keys(['time_tool', 'web-search', 'web_search'])
|
|
43
|
+
"""
|
|
44
|
+
tool_lookup: dict[str, object] = {}
|
|
45
|
+
|
|
46
|
+
for tool in tools:
|
|
47
|
+
if not hasattr(tool, "name"):
|
|
48
|
+
continue
|
|
49
|
+
|
|
50
|
+
tool_name = tool.name
|
|
51
|
+
if not tool_name: # Skip None or empty string names
|
|
52
|
+
continue
|
|
53
|
+
tool_name = str(tool_name)
|
|
54
|
+
tool_lookup[tool_name] = tool
|
|
55
|
+
|
|
56
|
+
# Also add sanitized name for fuzzy matching
|
|
57
|
+
sanitized = sanitize_function_name(tool_name)
|
|
58
|
+
if sanitized != tool_name:
|
|
59
|
+
tool_lookup[sanitized] = tool
|
|
60
|
+
|
|
61
|
+
return tool_lookup
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def match_tool_by_name(
|
|
65
|
+
tool_def: PTCToolDef,
|
|
66
|
+
tool_lookup: dict[str, object],
|
|
67
|
+
) -> tuple[object | None, str | None]:
|
|
68
|
+
"""Find a matching tool object for a tool definition.
|
|
69
|
+
|
|
70
|
+
Tries exact name match first, then falls back to sanitized name.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
tool_def: Tool definition dict with "name" key.
|
|
74
|
+
tool_lookup: Lookup map from build_tool_lookup().
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Tuple of (matching_tool, canonical_name) or (None, None) if no match.
|
|
78
|
+
canonical_name is the tool object's actual name (may differ from tool_def name).
|
|
79
|
+
"""
|
|
80
|
+
def_name = tool_def.get("name", "")
|
|
81
|
+
sanitized_def_name = sanitize_function_name(def_name)
|
|
82
|
+
|
|
83
|
+
# Try exact match first, then sanitized
|
|
84
|
+
matching_tool = tool_lookup.get(def_name) or tool_lookup.get(sanitized_def_name)
|
|
85
|
+
|
|
86
|
+
if matching_tool is None:
|
|
87
|
+
return None, None
|
|
88
|
+
|
|
89
|
+
# Get canonical name from tool object
|
|
90
|
+
canonical_name = str(getattr(matching_tool, "name", ""))
|
|
91
|
+
|
|
92
|
+
# Treat empty canonical name as no match
|
|
93
|
+
if not canonical_name:
|
|
94
|
+
return None, None
|
|
95
|
+
|
|
96
|
+
return matching_tool, canonical_name
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def enrich_custom_tools_from_agent(
|
|
100
|
+
custom_tools_config: PTCCustomToolConfig,
|
|
101
|
+
agent_tools: list[object],
|
|
102
|
+
agent_name: str = "",
|
|
103
|
+
) -> int:
|
|
104
|
+
"""Enrich custom tool definitions with metadata from agent's tool objects.
|
|
105
|
+
|
|
106
|
+
Matches custom tool definitions with actual tool objects by name (including
|
|
107
|
+
sanitized name matching) and enriches them with description and input_schema.
|
|
108
|
+
|
|
109
|
+
Note: This function modifies custom_tools_config.tools in-place.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
custom_tools_config: The PTCCustomToolConfig to enrich.
|
|
113
|
+
agent_tools: List of tool objects from the agent.
|
|
114
|
+
agent_name: Agent name for logging context.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
Number of tools that were enriched.
|
|
118
|
+
|
|
119
|
+
Example:
|
|
120
|
+
>>> config = PTCCustomToolConfig(enabled=True, tools=[{"name": "multiply", ...}])
|
|
121
|
+
>>> count = enrich_custom_tools_from_agent(config, [MultiplyTool()], "my_agent")
|
|
122
|
+
>>> count
|
|
123
|
+
1
|
|
124
|
+
"""
|
|
125
|
+
if not custom_tools_config.enabled:
|
|
126
|
+
return 0
|
|
127
|
+
|
|
128
|
+
if not custom_tools_config.tools:
|
|
129
|
+
return 0
|
|
130
|
+
|
|
131
|
+
# Build lookup map
|
|
132
|
+
tool_lookup = build_tool_lookup(agent_tools)
|
|
133
|
+
|
|
134
|
+
# Enrich each tool definition
|
|
135
|
+
enriched_count = 0
|
|
136
|
+
log_prefix = f"Agent '{agent_name}': " if agent_name else ""
|
|
137
|
+
|
|
138
|
+
for i, tool_def in enumerate(custom_tools_config.tools):
|
|
139
|
+
def_name = tool_def.get("name", "")
|
|
140
|
+
matching_tool, canonical_name = match_tool_by_name(tool_def, tool_lookup)
|
|
141
|
+
|
|
142
|
+
if matching_tool is None:
|
|
143
|
+
logger.debug(
|
|
144
|
+
f"{log_prefix}No matching tool object found for custom tool '{def_name}', using existing definition"
|
|
145
|
+
)
|
|
146
|
+
continue
|
|
147
|
+
|
|
148
|
+
# Handle name correction if matched by sanitized name
|
|
149
|
+
if canonical_name and canonical_name != def_name:
|
|
150
|
+
tool_def_copy = dict(tool_def)
|
|
151
|
+
tool_def_copy["name"] = canonical_name
|
|
152
|
+
enriched = enrich_tool_def_with_metadata(tool_def_copy, matching_tool)
|
|
153
|
+
else:
|
|
154
|
+
enriched = enrich_tool_def_with_metadata(tool_def, matching_tool)
|
|
155
|
+
|
|
156
|
+
custom_tools_config.tools[i] = enriched
|
|
157
|
+
enriched_count += 1
|
|
158
|
+
logger.debug(f"{log_prefix}Enriched custom tool '{def_name}' with metadata")
|
|
159
|
+
|
|
160
|
+
if enriched_count > 0:
|
|
161
|
+
logger.info(f"{log_prefix}Enriched {enriched_count} custom tool(s) with metadata")
|
|
162
|
+
|
|
163
|
+
return enriched_count
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from aip_agents.ptc import PTCCustomToolConfig as PTCCustomToolConfig
|
|
3
|
+
from aip_agents.ptc.custom_tools import PTCToolDef as PTCToolDef, enrich_tool_def_with_metadata as enrich_tool_def_with_metadata
|
|
4
|
+
from aip_agents.ptc.naming import sanitize_function_name as sanitize_function_name
|
|
5
|
+
|
|
6
|
+
logger: Incomplete
|
|
7
|
+
|
|
8
|
+
def build_tool_lookup(tools: list[object]) -> dict[str, object]:
|
|
9
|
+
'''Build a lookup map from tool objects for name-based matching.
|
|
10
|
+
|
|
11
|
+
Creates entries for both original and sanitized names to support
|
|
12
|
+
fuzzy matching (e.g., "web-search" matches "web_search").
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
tools: List of tool objects with `name` attribute.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
Dict mapping tool names (and sanitized names) to tool objects.
|
|
19
|
+
|
|
20
|
+
Example:
|
|
21
|
+
>>> tools = [TimeTool(), WebSearchTool()] # names: "time_tool", "web-search"
|
|
22
|
+
>>> lookup = build_tool_lookup(tools)
|
|
23
|
+
>>> lookup.keys()
|
|
24
|
+
dict_keys([\'time_tool\', \'web-search\', \'web_search\'])
|
|
25
|
+
'''
|
|
26
|
+
def match_tool_by_name(tool_def: PTCToolDef, tool_lookup: dict[str, object]) -> tuple[object | None, str | None]:
|
|
27
|
+
'''Find a matching tool object for a tool definition.
|
|
28
|
+
|
|
29
|
+
Tries exact name match first, then falls back to sanitized name.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
tool_def: Tool definition dict with "name" key.
|
|
33
|
+
tool_lookup: Lookup map from build_tool_lookup().
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Tuple of (matching_tool, canonical_name) or (None, None) if no match.
|
|
37
|
+
canonical_name is the tool object\'s actual name (may differ from tool_def name).
|
|
38
|
+
'''
|
|
39
|
+
def enrich_custom_tools_from_agent(custom_tools_config: PTCCustomToolConfig, agent_tools: list[object], agent_name: str = '') -> int:
|
|
40
|
+
'''Enrich custom tool definitions with metadata from agent\'s tool objects.
|
|
41
|
+
|
|
42
|
+
Matches custom tool definitions with actual tool objects by name (including
|
|
43
|
+
sanitized name matching) and enriches them with description and input_schema.
|
|
44
|
+
|
|
45
|
+
Note: This function modifies custom_tools_config.tools in-place.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
custom_tools_config: The PTCCustomToolConfig to enrich.
|
|
49
|
+
agent_tools: List of tool objects from the agent.
|
|
50
|
+
agent_name: Agent name for logging context.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Number of tools that were enriched.
|
|
54
|
+
|
|
55
|
+
Example:
|
|
56
|
+
>>> config = PTCCustomToolConfig(enabled=True, tools=[{"name": "multiply", ...}])
|
|
57
|
+
>>> count = enrich_custom_tools_from_agent(config, [MultiplyTool()], "my_agent")
|
|
58
|
+
>>> count
|
|
59
|
+
1
|
|
60
|
+
'''
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# flake8: noqa: F401
|
|
2
|
+
"""Sandbox module for isolated code execution.
|
|
3
|
+
|
|
4
|
+
This module provides abstractions for running code in sandboxed environments.
|
|
5
|
+
All components support lazy loading to work with optional dependencies (e2b).
|
|
6
|
+
|
|
7
|
+
Authors:
|
|
8
|
+
Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from typing import TYPE_CHECKING, Any
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from aip_agents.sandbox.e2b_runtime import E2BSandboxRuntime
|
|
15
|
+
from aip_agents.sandbox.template_builder import ensure_ptc_template
|
|
16
|
+
from aip_agents.sandbox.types import SandboxExecutionResult
|
|
17
|
+
|
|
18
|
+
_IMPORT_MAP = {
|
|
19
|
+
"E2BSandboxRuntime": "aip_agents.sandbox.e2b_runtime",
|
|
20
|
+
"ensure_ptc_template": "aip_agents.sandbox.template_builder",
|
|
21
|
+
"SandboxExecutionResult": "aip_agents.sandbox.types",
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
_cache: dict[str, Any] = {}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def __getattr__(name: str) -> Any:
|
|
28
|
+
"""Lazy import components on first access."""
|
|
29
|
+
if name in _cache:
|
|
30
|
+
return _cache[name]
|
|
31
|
+
|
|
32
|
+
if name in _IMPORT_MAP:
|
|
33
|
+
try:
|
|
34
|
+
module = __import__(_IMPORT_MAP[name], fromlist=[name])
|
|
35
|
+
_cache[name] = getattr(module, name)
|
|
36
|
+
return _cache[name]
|
|
37
|
+
except ImportError as e:
|
|
38
|
+
raise ImportError(f"Failed to import {name}. Install with: pip install aip-agents[local]") from e
|
|
39
|
+
|
|
40
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
__all__ = list(_IMPORT_MAP.keys())
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
from aip_agents.sandbox.e2b_runtime import E2BSandboxRuntime as E2BSandboxRuntime
|
|
2
|
+
from aip_agents.sandbox.template_builder import ensure_ptc_template as ensure_ptc_template
|
|
3
|
+
from aip_agents.sandbox.types import SandboxExecutionResult as SandboxExecutionResult
|
|
4
|
+
|
|
5
|
+
__all__ = ['E2BSandboxRuntime', 'ensure_ptc_template', 'SandboxExecutionResult']
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"""Defaults for PTC sandbox templates and packages."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from aip_agents.mcp.client.base_mcp_client import BaseMCPClient
|
|
9
|
+
from aip_agents.ptc.custom_tools import PTCCustomToolConfig
|
|
10
|
+
|
|
11
|
+
DEFAULT_PTC_TEMPLATE = "aip-agents-ptc-v1"
|
|
12
|
+
AIP_AGENTS_BINARY_LOCAL = "aip-agents-binary[local]"
|
|
13
|
+
DEFAULT_PTC_PACKAGES: tuple[str, ...] = (
|
|
14
|
+
AIP_AGENTS_BINARY_LOCAL,
|
|
15
|
+
"mcp",
|
|
16
|
+
"httpx",
|
|
17
|
+
"gllm-plugin-binary==0.0.7",
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _has_mcp_tools(mcp_client: BaseMCPClient | None) -> bool:
|
|
22
|
+
"""Check if MCP tools are present.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
mcp_client: The MCP client to check.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
True if MCP client has servers configured.
|
|
29
|
+
"""
|
|
30
|
+
return mcp_client is not None and bool(getattr(mcp_client, "servers", None))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _has_custom_tools(custom_tools_config: PTCCustomToolConfig | None) -> bool:
|
|
34
|
+
"""Check if custom tools are present and enabled.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
custom_tools_config: The custom tools configuration to check.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
True if custom tools are enabled and tools list is non-empty.
|
|
41
|
+
"""
|
|
42
|
+
return custom_tools_config is not None and custom_tools_config.enabled and bool(custom_tools_config.tools)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _has_native_aip_tools(custom_tools_config: PTCCustomToolConfig | None) -> bool:
|
|
46
|
+
"""Check if native AIP tools are present.
|
|
47
|
+
|
|
48
|
+
Native AIP tools are package-based custom tools with import_path starting with "aip_agents.tools.".
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
custom_tools_config: The custom tools configuration to check.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
True if at least one native AIP tool is found.
|
|
55
|
+
"""
|
|
56
|
+
if not _has_custom_tools(custom_tools_config):
|
|
57
|
+
return False
|
|
58
|
+
|
|
59
|
+
assert custom_tools_config is not None
|
|
60
|
+
for tool in custom_tools_config.tools:
|
|
61
|
+
if tool.get("kind") == "package":
|
|
62
|
+
import_path = tool.get("import_path", "")
|
|
63
|
+
if import_path.startswith("aip_agents.tools."):
|
|
64
|
+
return True
|
|
65
|
+
|
|
66
|
+
return False
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _merge_requirements(packages: list[str], requirements: list[str]) -> None:
|
|
70
|
+
"""Merge requirements into packages list, avoiding duplicates.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
packages: Target list to merge into (modified in place).
|
|
74
|
+
requirements: Requirements to merge.
|
|
75
|
+
"""
|
|
76
|
+
for req in requirements:
|
|
77
|
+
if req not in packages:
|
|
78
|
+
packages.append(req)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _merge_custom_requirements(
|
|
82
|
+
packages: list[str],
|
|
83
|
+
custom_tools_config: PTCCustomToolConfig | None,
|
|
84
|
+
) -> None:
|
|
85
|
+
"""Merge custom tool requirements into packages list.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
packages: Target list to merge into (modified in place).
|
|
89
|
+
custom_tools_config: Custom tools configuration.
|
|
90
|
+
"""
|
|
91
|
+
if not _has_custom_tools(custom_tools_config):
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
assert custom_tools_config is not None
|
|
95
|
+
if custom_tools_config.requirements:
|
|
96
|
+
_merge_requirements(packages, custom_tools_config.requirements)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _packages_for_default_template(
|
|
100
|
+
custom_tools_config: PTCCustomToolConfig | None,
|
|
101
|
+
user_ptc_packages: list[str] | None,
|
|
102
|
+
) -> list[str] | None:
|
|
103
|
+
"""Build package list when using the default template.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
custom_tools_config: Custom tools configuration.
|
|
107
|
+
user_ptc_packages: Explicitly provided packages by user (None if not set).
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
List of packages to install, or None to skip installation.
|
|
111
|
+
"""
|
|
112
|
+
packages = list(user_ptc_packages) if user_ptc_packages is not None else []
|
|
113
|
+
_merge_custom_requirements(packages, custom_tools_config)
|
|
114
|
+
return packages if packages else None
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _packages_for_other_templates(
|
|
118
|
+
*,
|
|
119
|
+
mcp_client: BaseMCPClient | None,
|
|
120
|
+
custom_tools_config: PTCCustomToolConfig | None,
|
|
121
|
+
user_ptc_packages: list[str] | None,
|
|
122
|
+
) -> list[str] | None:
|
|
123
|
+
"""Build package list when using a non-default template.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
mcp_client: The MCP client (check if has servers for MCP tools).
|
|
127
|
+
custom_tools_config: Custom tools configuration.
|
|
128
|
+
user_ptc_packages: Explicitly provided packages by user (None if not set).
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
List of packages to install, or None to skip installation.
|
|
132
|
+
"""
|
|
133
|
+
packages = list(user_ptc_packages) if user_ptc_packages is not None else []
|
|
134
|
+
base_packages = _build_base_packages(mcp_client=mcp_client, custom_tools_config=custom_tools_config)
|
|
135
|
+
_merge_requirements(packages, base_packages)
|
|
136
|
+
_merge_custom_requirements(packages, custom_tools_config)
|
|
137
|
+
return packages if packages else None
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _build_base_packages(
|
|
141
|
+
*,
|
|
142
|
+
mcp_client: BaseMCPClient | None,
|
|
143
|
+
custom_tools_config: PTCCustomToolConfig | None,
|
|
144
|
+
) -> list[str]:
|
|
145
|
+
"""Build base package list based on tool types.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
mcp_client: The MCP client (check if has servers for MCP tools).
|
|
149
|
+
custom_tools_config: Custom tools configuration.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
List of base packages needed for the tool types present.
|
|
153
|
+
"""
|
|
154
|
+
packages: list[str] = []
|
|
155
|
+
|
|
156
|
+
if _has_mcp_tools(mcp_client):
|
|
157
|
+
packages.extend(["mcp", "httpx"])
|
|
158
|
+
|
|
159
|
+
if _has_custom_tools(custom_tools_config):
|
|
160
|
+
packages.extend(["langchain", "gllm-plugin-binary==0.0.7"])
|
|
161
|
+
|
|
162
|
+
if _has_native_aip_tools(custom_tools_config):
|
|
163
|
+
if AIP_AGENTS_BINARY_LOCAL not in packages:
|
|
164
|
+
packages.append(AIP_AGENTS_BINARY_LOCAL)
|
|
165
|
+
|
|
166
|
+
return packages
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def select_sandbox_packages(
|
|
170
|
+
*,
|
|
171
|
+
mcp_client: BaseMCPClient | None,
|
|
172
|
+
custom_tools_config: PTCCustomToolConfig | None,
|
|
173
|
+
template: str | None,
|
|
174
|
+
user_ptc_packages: list[str] | None,
|
|
175
|
+
) -> list[str] | None:
|
|
176
|
+
"""Select minimal packages to install in sandbox based on tool types.
|
|
177
|
+
|
|
178
|
+
This function implements the smart package selection logic:
|
|
179
|
+
- DEFAULT_PTC_TEMPLATE + no user packages: Skip install (template has all deps)
|
|
180
|
+
- DEFAULT_PTC_TEMPLATE + user packages: User packages + PTCCustomToolConfig.requirements
|
|
181
|
+
- Other template + no user packages: Build packages from tool types
|
|
182
|
+
- Other template + user packages: User packages + tool-type packages + PTCCustomToolConfig.requirements
|
|
183
|
+
|
|
184
|
+
Key principle: Tools won't work without their required packages. Always ensure:
|
|
185
|
+
- MCP tools → mcp + httpx installed
|
|
186
|
+
- Custom LangChain tools → langchain + gllm-plugin-binary installed
|
|
187
|
+
- Native AIP tools → aip-agents-binary[local] installed
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
mcp_client: The MCP client (check if has servers for MCP tools).
|
|
191
|
+
custom_tools_config: Custom tools configuration (includes tools list and .requirements field).
|
|
192
|
+
template: Sandbox template being used.
|
|
193
|
+
user_ptc_packages: Explicitly provided packages by user (None if not set).
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
List of packages to install, or None to skip installation.
|
|
197
|
+
"""
|
|
198
|
+
if template == DEFAULT_PTC_TEMPLATE:
|
|
199
|
+
return _packages_for_default_template(custom_tools_config, user_ptc_packages)
|
|
200
|
+
|
|
201
|
+
return _packages_for_other_templates(
|
|
202
|
+
mcp_client=mcp_client,
|
|
203
|
+
custom_tools_config=custom_tools_config,
|
|
204
|
+
user_ptc_packages=user_ptc_packages,
|
|
205
|
+
)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from aip_agents.mcp.client.base_mcp_client import BaseMCPClient as BaseMCPClient
|
|
2
|
+
from aip_agents.ptc.custom_tools import PTCCustomToolConfig as PTCCustomToolConfig
|
|
3
|
+
|
|
4
|
+
DEFAULT_PTC_TEMPLATE: str
|
|
5
|
+
AIP_AGENTS_BINARY_LOCAL: str
|
|
6
|
+
DEFAULT_PTC_PACKAGES: tuple[str, ...]
|
|
7
|
+
|
|
8
|
+
def select_sandbox_packages(*, mcp_client: BaseMCPClient | None, custom_tools_config: PTCCustomToolConfig | None, template: str | None, user_ptc_packages: list[str] | None) -> list[str] | None:
|
|
9
|
+
"""Select minimal packages to install in sandbox based on tool types.
|
|
10
|
+
|
|
11
|
+
This function implements the smart package selection logic:
|
|
12
|
+
- DEFAULT_PTC_TEMPLATE + no user packages: Skip install (template has all deps)
|
|
13
|
+
- DEFAULT_PTC_TEMPLATE + user packages: User packages + PTCCustomToolConfig.requirements
|
|
14
|
+
- Other template + no user packages: Build packages from tool types
|
|
15
|
+
- Other template + user packages: User packages + tool-type packages + PTCCustomToolConfig.requirements
|
|
16
|
+
|
|
17
|
+
Key principle: Tools won't work without their required packages. Always ensure:
|
|
18
|
+
- MCP tools → mcp + httpx installed
|
|
19
|
+
- Custom LangChain tools → langchain + gllm-plugin-binary installed
|
|
20
|
+
- Native AIP tools → aip-agents-binary[local] installed
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
mcp_client: The MCP client (check if has servers for MCP tools).
|
|
24
|
+
custom_tools_config: Custom tools configuration (includes tools list and .requirements field).
|
|
25
|
+
template: Sandbox template being used.
|
|
26
|
+
user_ptc_packages: Explicitly provided packages by user (None if not set).
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
List of packages to install, or None to skip installation.
|
|
30
|
+
"""
|