aiecs 1.3.8__py3-none-any.whl → 1.4.0__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 aiecs might be problematic. Click here for more details.
- aiecs/__init__.py +1 -1
- aiecs/domain/__init__.py +120 -0
- aiecs/domain/agent/__init__.py +184 -0
- aiecs/domain/agent/base_agent.py +691 -0
- aiecs/domain/agent/exceptions.py +99 -0
- aiecs/domain/agent/hybrid_agent.py +495 -0
- aiecs/domain/agent/integration/__init__.py +23 -0
- aiecs/domain/agent/integration/context_compressor.py +219 -0
- aiecs/domain/agent/integration/context_engine_adapter.py +258 -0
- aiecs/domain/agent/integration/retry_policy.py +228 -0
- aiecs/domain/agent/integration/role_config.py +217 -0
- aiecs/domain/agent/lifecycle.py +298 -0
- aiecs/domain/agent/llm_agent.py +309 -0
- aiecs/domain/agent/memory/__init__.py +13 -0
- aiecs/domain/agent/memory/conversation.py +216 -0
- aiecs/domain/agent/migration/__init__.py +15 -0
- aiecs/domain/agent/migration/conversion.py +171 -0
- aiecs/domain/agent/migration/legacy_wrapper.py +97 -0
- aiecs/domain/agent/models.py +263 -0
- aiecs/domain/agent/observability.py +443 -0
- aiecs/domain/agent/persistence.py +287 -0
- aiecs/domain/agent/prompts/__init__.py +25 -0
- aiecs/domain/agent/prompts/builder.py +164 -0
- aiecs/domain/agent/prompts/formatters.py +192 -0
- aiecs/domain/agent/prompts/template.py +264 -0
- aiecs/domain/agent/registry.py +261 -0
- aiecs/domain/agent/tool_agent.py +267 -0
- aiecs/domain/agent/tools/__init__.py +13 -0
- aiecs/domain/agent/tools/schema_generator.py +222 -0
- aiecs/main.py +2 -2
- {aiecs-1.3.8.dist-info → aiecs-1.4.0.dist-info}/METADATA +1 -1
- {aiecs-1.3.8.dist-info → aiecs-1.4.0.dist-info}/RECORD +36 -9
- {aiecs-1.3.8.dist-info → aiecs-1.4.0.dist-info}/WHEEL +0 -0
- {aiecs-1.3.8.dist-info → aiecs-1.4.0.dist-info}/entry_points.txt +0 -0
- {aiecs-1.3.8.dist-info → aiecs-1.4.0.dist-info}/licenses/LICENSE +0 -0
- {aiecs-1.3.8.dist-info → aiecs-1.4.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tool Agent
|
|
3
|
+
|
|
4
|
+
Agent implementation specialized in tool usage and execution.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Dict, List, Any, Optional
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
|
|
11
|
+
from aiecs.tools import get_tool, BaseTool
|
|
12
|
+
|
|
13
|
+
from .base_agent import BaseAIAgent
|
|
14
|
+
from .models import AgentType, AgentConfiguration
|
|
15
|
+
from .exceptions import TaskExecutionError, ToolAccessDeniedError
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ToolAgent(BaseAIAgent):
|
|
21
|
+
"""
|
|
22
|
+
Agent specialized in tool selection and execution.
|
|
23
|
+
|
|
24
|
+
This agent can execute one or more tools to complete tasks.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
agent_id: str,
|
|
30
|
+
name: str,
|
|
31
|
+
tools: List[str],
|
|
32
|
+
config: AgentConfiguration,
|
|
33
|
+
description: Optional[str] = None,
|
|
34
|
+
version: str = "1.0.0",
|
|
35
|
+
):
|
|
36
|
+
"""
|
|
37
|
+
Initialize Tool agent.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
agent_id: Unique agent identifier
|
|
41
|
+
name: Agent name
|
|
42
|
+
tools: List of tool names agent can use
|
|
43
|
+
config: Agent configuration
|
|
44
|
+
description: Optional description
|
|
45
|
+
version: Agent version
|
|
46
|
+
"""
|
|
47
|
+
super().__init__(
|
|
48
|
+
agent_id=agent_id,
|
|
49
|
+
name=name,
|
|
50
|
+
agent_type=AgentType.TASK_EXECUTOR,
|
|
51
|
+
config=config,
|
|
52
|
+
description=description or "Tool-based task execution agent",
|
|
53
|
+
version=version,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
self._available_tools = tools
|
|
57
|
+
self._tool_instances: Dict[str, BaseTool] = {}
|
|
58
|
+
self._tool_usage_stats: Dict[str, Dict[str, int]] = {}
|
|
59
|
+
|
|
60
|
+
logger.info(f"ToolAgent initialized: {agent_id} with tools: {', '.join(tools)}")
|
|
61
|
+
|
|
62
|
+
async def _initialize(self) -> None:
|
|
63
|
+
"""Initialize Tool agent - load tools."""
|
|
64
|
+
# Load tool instances
|
|
65
|
+
for tool_name in self._available_tools:
|
|
66
|
+
try:
|
|
67
|
+
self._tool_instances[tool_name] = get_tool(tool_name)
|
|
68
|
+
self._tool_usage_stats[tool_name] = {
|
|
69
|
+
"success_count": 0,
|
|
70
|
+
"failure_count": 0,
|
|
71
|
+
"total_count": 0,
|
|
72
|
+
}
|
|
73
|
+
logger.debug(f"ToolAgent {self.agent_id} loaded tool: {tool_name}")
|
|
74
|
+
except Exception as e:
|
|
75
|
+
logger.warning(f"Failed to load tool {tool_name}: {e}")
|
|
76
|
+
|
|
77
|
+
logger.info(f"ToolAgent {self.agent_id} initialized with {len(self._tool_instances)} tools")
|
|
78
|
+
|
|
79
|
+
async def _shutdown(self) -> None:
|
|
80
|
+
"""Shutdown Tool agent."""
|
|
81
|
+
self._tool_instances.clear()
|
|
82
|
+
logger.info(f"ToolAgent {self.agent_id} shut down")
|
|
83
|
+
|
|
84
|
+
async def execute_task(
|
|
85
|
+
self,
|
|
86
|
+
task: Dict[str, Any],
|
|
87
|
+
context: Dict[str, Any]
|
|
88
|
+
) -> Dict[str, Any]:
|
|
89
|
+
"""
|
|
90
|
+
Execute a task using tools.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
task: Task specification with 'tool', 'operation', and 'parameters'
|
|
94
|
+
context: Execution context
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
Execution result with 'output', 'tool_used', 'execution_time'
|
|
98
|
+
|
|
99
|
+
Raises:
|
|
100
|
+
TaskExecutionError: If task execution fails
|
|
101
|
+
"""
|
|
102
|
+
start_time = datetime.utcnow()
|
|
103
|
+
|
|
104
|
+
try:
|
|
105
|
+
# Extract tool and operation
|
|
106
|
+
tool_name = task.get('tool')
|
|
107
|
+
operation = task.get('operation')
|
|
108
|
+
parameters = task.get('parameters', {})
|
|
109
|
+
|
|
110
|
+
if not tool_name:
|
|
111
|
+
raise TaskExecutionError(
|
|
112
|
+
"Task must contain 'tool' field",
|
|
113
|
+
agent_id=self.agent_id
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Check tool access
|
|
117
|
+
if tool_name not in self._available_tools:
|
|
118
|
+
raise ToolAccessDeniedError(self.agent_id, tool_name)
|
|
119
|
+
|
|
120
|
+
# Transition to busy state
|
|
121
|
+
self._transition_state(self.state.__class__.BUSY)
|
|
122
|
+
self._current_task_id = task.get('task_id')
|
|
123
|
+
|
|
124
|
+
# Execute tool
|
|
125
|
+
result = await self._execute_tool(tool_name, operation, parameters)
|
|
126
|
+
|
|
127
|
+
# Calculate execution time
|
|
128
|
+
execution_time = (datetime.utcnow() - start_time).total_seconds()
|
|
129
|
+
|
|
130
|
+
# Update metrics
|
|
131
|
+
self.update_metrics(
|
|
132
|
+
execution_time=execution_time,
|
|
133
|
+
success=True,
|
|
134
|
+
tool_calls=1,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Update tool usage stats
|
|
138
|
+
self._update_tool_stats(tool_name, success=True)
|
|
139
|
+
|
|
140
|
+
# Transition back to active
|
|
141
|
+
self._transition_state(self.state.__class__.ACTIVE)
|
|
142
|
+
self._current_task_id = None
|
|
143
|
+
self.last_active_at = datetime.utcnow()
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
"success": True,
|
|
147
|
+
"output": result,
|
|
148
|
+
"tool_used": tool_name,
|
|
149
|
+
"operation": operation,
|
|
150
|
+
"execution_time": execution_time,
|
|
151
|
+
"timestamp": datetime.utcnow().isoformat(),
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
except Exception as e:
|
|
155
|
+
logger.error(f"Task execution failed for {self.agent_id}: {e}")
|
|
156
|
+
|
|
157
|
+
# Update metrics for failure
|
|
158
|
+
execution_time = (datetime.utcnow() - start_time).total_seconds()
|
|
159
|
+
self.update_metrics(execution_time=execution_time, success=False)
|
|
160
|
+
|
|
161
|
+
# Update tool stats if tool was specified
|
|
162
|
+
if tool_name:
|
|
163
|
+
self._update_tool_stats(tool_name, success=False)
|
|
164
|
+
|
|
165
|
+
# Transition to error state
|
|
166
|
+
self._transition_state(self.state.__class__.ERROR)
|
|
167
|
+
self._current_task_id = None
|
|
168
|
+
|
|
169
|
+
raise TaskExecutionError(
|
|
170
|
+
f"Task execution failed: {str(e)}",
|
|
171
|
+
agent_id=self.agent_id,
|
|
172
|
+
task_id=task.get('task_id')
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
async def process_message(
|
|
176
|
+
self,
|
|
177
|
+
message: str,
|
|
178
|
+
sender_id: Optional[str] = None
|
|
179
|
+
) -> Dict[str, Any]:
|
|
180
|
+
"""
|
|
181
|
+
Process an incoming message.
|
|
182
|
+
|
|
183
|
+
For ToolAgent, this is limited - it's designed for direct tool execution.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
message: Message content
|
|
187
|
+
sender_id: Optional sender identifier
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
Response dictionary
|
|
191
|
+
"""
|
|
192
|
+
return {
|
|
193
|
+
"response": f"ToolAgent {self.name} received message but requires explicit tool tasks. "
|
|
194
|
+
f"Available tools: {', '.join(self._available_tools)}",
|
|
195
|
+
"available_tools": self._available_tools,
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async def _execute_tool(
|
|
199
|
+
self,
|
|
200
|
+
tool_name: str,
|
|
201
|
+
operation: Optional[str],
|
|
202
|
+
parameters: Dict[str, Any]
|
|
203
|
+
) -> Any:
|
|
204
|
+
"""
|
|
205
|
+
Execute a tool operation.
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
tool_name: Tool name
|
|
209
|
+
operation: Operation name (optional for tools with single operation)
|
|
210
|
+
parameters: Operation parameters
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
Tool execution result
|
|
214
|
+
"""
|
|
215
|
+
tool = self._tool_instances.get(tool_name)
|
|
216
|
+
if not tool:
|
|
217
|
+
raise ValueError(f"Tool {tool_name} not loaded")
|
|
218
|
+
|
|
219
|
+
# Execute tool
|
|
220
|
+
if operation:
|
|
221
|
+
result = await tool.run_async(operation, **parameters)
|
|
222
|
+
else:
|
|
223
|
+
# If no operation specified, try to call the tool directly
|
|
224
|
+
if hasattr(tool, 'run_async'):
|
|
225
|
+
result = await tool.run_async(**parameters)
|
|
226
|
+
else:
|
|
227
|
+
raise ValueError(f"Tool {tool_name} requires operation to be specified")
|
|
228
|
+
|
|
229
|
+
return result
|
|
230
|
+
|
|
231
|
+
def _update_tool_stats(self, tool_name: str, success: bool) -> None:
|
|
232
|
+
"""Update tool usage statistics."""
|
|
233
|
+
if tool_name not in self._tool_usage_stats:
|
|
234
|
+
self._tool_usage_stats[tool_name] = {
|
|
235
|
+
"success_count": 0,
|
|
236
|
+
"failure_count": 0,
|
|
237
|
+
"total_count": 0,
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
stats = self._tool_usage_stats[tool_name]
|
|
241
|
+
stats["total_count"] += 1
|
|
242
|
+
if success:
|
|
243
|
+
stats["success_count"] += 1
|
|
244
|
+
else:
|
|
245
|
+
stats["failure_count"] += 1
|
|
246
|
+
|
|
247
|
+
def get_tool_stats(self) -> Dict[str, Dict[str, int]]:
|
|
248
|
+
"""Get tool usage statistics."""
|
|
249
|
+
return self._tool_usage_stats.copy()
|
|
250
|
+
|
|
251
|
+
def get_available_tools(self) -> List[str]:
|
|
252
|
+
"""Get list of available tools."""
|
|
253
|
+
return self._available_tools.copy()
|
|
254
|
+
|
|
255
|
+
@classmethod
|
|
256
|
+
def from_dict(cls, data: Dict[str, Any]) -> "ToolAgent":
|
|
257
|
+
"""
|
|
258
|
+
Deserialize ToolAgent from dictionary.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
data: Dictionary representation
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
ToolAgent instance
|
|
265
|
+
"""
|
|
266
|
+
raise NotImplementedError("ToolAgent.from_dict not fully implemented yet")
|
|
267
|
+
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tool Schema Generator
|
|
3
|
+
|
|
4
|
+
Generate OpenAI-style function schemas from AIECS tools.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import inspect
|
|
8
|
+
import logging
|
|
9
|
+
from typing import Dict, Any, List, Optional, get_type_hints
|
|
10
|
+
from aiecs.tools import BaseTool, get_tool
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ToolSchemaGenerator:
|
|
16
|
+
"""
|
|
17
|
+
Generates OpenAI-style function calling schemas from AIECS tools.
|
|
18
|
+
|
|
19
|
+
Example:
|
|
20
|
+
generator = ToolSchemaGenerator()
|
|
21
|
+
schema = generator.generate_schema("search_tool", "search")
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
@staticmethod
|
|
25
|
+
def generate_schema(
|
|
26
|
+
tool_name: str,
|
|
27
|
+
operation: Optional[str] = None,
|
|
28
|
+
description: Optional[str] = None
|
|
29
|
+
) -> Dict[str, Any]:
|
|
30
|
+
"""
|
|
31
|
+
Generate OpenAI function schema for a tool operation.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
tool_name: Tool name
|
|
35
|
+
operation: Optional operation name
|
|
36
|
+
description: Optional custom description
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
OpenAI function schema dictionary
|
|
40
|
+
"""
|
|
41
|
+
try:
|
|
42
|
+
tool = get_tool(tool_name)
|
|
43
|
+
except Exception as e:
|
|
44
|
+
logger.error(f"Failed to get tool {tool_name}: {e}")
|
|
45
|
+
raise
|
|
46
|
+
|
|
47
|
+
# Generate function name
|
|
48
|
+
if operation:
|
|
49
|
+
function_name = f"{tool_name}_{operation}"
|
|
50
|
+
else:
|
|
51
|
+
function_name = tool_name
|
|
52
|
+
|
|
53
|
+
# Get operation method if specified
|
|
54
|
+
if operation:
|
|
55
|
+
if not hasattr(tool, operation):
|
|
56
|
+
raise ValueError(f"Tool {tool_name} has no operation '{operation}'")
|
|
57
|
+
method = getattr(tool, operation)
|
|
58
|
+
else:
|
|
59
|
+
# Default to 'run' method
|
|
60
|
+
method = getattr(tool, 'run', None)
|
|
61
|
+
if method is None:
|
|
62
|
+
raise ValueError(f"Tool {tool_name} has no 'run' method")
|
|
63
|
+
|
|
64
|
+
# Extract parameters
|
|
65
|
+
parameters = ToolSchemaGenerator._extract_parameters(method)
|
|
66
|
+
|
|
67
|
+
# Build schema
|
|
68
|
+
schema = {
|
|
69
|
+
"name": function_name,
|
|
70
|
+
"description": description or f"{tool_name} tool",
|
|
71
|
+
"parameters": {
|
|
72
|
+
"type": "object",
|
|
73
|
+
"properties": parameters,
|
|
74
|
+
"required": ToolSchemaGenerator._get_required_params(method),
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return schema
|
|
79
|
+
|
|
80
|
+
@staticmethod
|
|
81
|
+
def _extract_parameters(method) -> Dict[str, Dict[str, Any]]:
|
|
82
|
+
"""Extract parameter schemas from method."""
|
|
83
|
+
sig = inspect.signature(method)
|
|
84
|
+
parameters = {}
|
|
85
|
+
|
|
86
|
+
for param_name, param in sig.parameters.items():
|
|
87
|
+
# Skip 'self' and 'op' parameters
|
|
88
|
+
if param_name in ['self', 'op', 'cls']:
|
|
89
|
+
continue
|
|
90
|
+
|
|
91
|
+
param_schema = ToolSchemaGenerator._param_to_schema(param_name, param)
|
|
92
|
+
if param_schema:
|
|
93
|
+
parameters[param_name] = param_schema
|
|
94
|
+
|
|
95
|
+
return parameters
|
|
96
|
+
|
|
97
|
+
@staticmethod
|
|
98
|
+
def _param_to_schema(param_name: str, param: inspect.Parameter) -> Optional[Dict[str, Any]]:
|
|
99
|
+
"""Convert parameter to JSON schema."""
|
|
100
|
+
schema: Dict[str, Any] = {}
|
|
101
|
+
|
|
102
|
+
# Try to infer type from annotation
|
|
103
|
+
if param.annotation != inspect.Parameter.empty:
|
|
104
|
+
schema.update(ToolSchemaGenerator._type_to_schema(param.annotation))
|
|
105
|
+
|
|
106
|
+
# Add default if present
|
|
107
|
+
if param.default != inspect.Parameter.empty:
|
|
108
|
+
schema["default"] = param.default
|
|
109
|
+
|
|
110
|
+
# If no type info, default to string
|
|
111
|
+
if "type" not in schema:
|
|
112
|
+
schema["type"] = "string"
|
|
113
|
+
|
|
114
|
+
return schema
|
|
115
|
+
|
|
116
|
+
@staticmethod
|
|
117
|
+
def _type_to_schema(type_hint) -> Dict[str, Any]:
|
|
118
|
+
"""Convert Python type hint to JSON schema type."""
|
|
119
|
+
# Handle string annotations
|
|
120
|
+
if isinstance(type_hint, str):
|
|
121
|
+
if type_hint == "str":
|
|
122
|
+
return {"type": "string"}
|
|
123
|
+
elif type_hint == "int":
|
|
124
|
+
return {"type": "integer"}
|
|
125
|
+
elif type_hint == "float":
|
|
126
|
+
return {"type": "number"}
|
|
127
|
+
elif type_hint == "bool":
|
|
128
|
+
return {"type": "boolean"}
|
|
129
|
+
elif type_hint.startswith("List"):
|
|
130
|
+
return {"type": "array"}
|
|
131
|
+
elif type_hint.startswith("Dict"):
|
|
132
|
+
return {"type": "object"}
|
|
133
|
+
else:
|
|
134
|
+
return {"type": "string"}
|
|
135
|
+
|
|
136
|
+
# Handle actual types
|
|
137
|
+
if type_hint == str:
|
|
138
|
+
return {"type": "string"}
|
|
139
|
+
elif type_hint == int:
|
|
140
|
+
return {"type": "integer"}
|
|
141
|
+
elif type_hint == float:
|
|
142
|
+
return {"type": "number"}
|
|
143
|
+
elif type_hint == bool:
|
|
144
|
+
return {"type": "boolean"}
|
|
145
|
+
elif hasattr(type_hint, "__origin__"):
|
|
146
|
+
# Generic types (List, Dict, etc.)
|
|
147
|
+
origin = type_hint.__origin__
|
|
148
|
+
if origin == list:
|
|
149
|
+
return {"type": "array"}
|
|
150
|
+
elif origin == dict:
|
|
151
|
+
return {"type": "object"}
|
|
152
|
+
else:
|
|
153
|
+
return {"type": "string"}
|
|
154
|
+
else:
|
|
155
|
+
return {"type": "string"}
|
|
156
|
+
|
|
157
|
+
@staticmethod
|
|
158
|
+
def _get_required_params(method) -> List[str]:
|
|
159
|
+
"""Get list of required parameter names."""
|
|
160
|
+
sig = inspect.signature(method)
|
|
161
|
+
required = []
|
|
162
|
+
|
|
163
|
+
for param_name, param in sig.parameters.items():
|
|
164
|
+
# Skip 'self' and 'op' parameters
|
|
165
|
+
if param_name in ['self', 'op', 'cls']:
|
|
166
|
+
continue
|
|
167
|
+
|
|
168
|
+
# Required if no default value
|
|
169
|
+
if param.default == inspect.Parameter.empty:
|
|
170
|
+
required.append(param_name)
|
|
171
|
+
|
|
172
|
+
return required
|
|
173
|
+
|
|
174
|
+
@staticmethod
|
|
175
|
+
def generate_schemas_for_tools(
|
|
176
|
+
tool_names: List[str],
|
|
177
|
+
operations: Optional[Dict[str, List[str]]] = None
|
|
178
|
+
) -> List[Dict[str, Any]]:
|
|
179
|
+
"""
|
|
180
|
+
Generate schemas for multiple tools.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
tool_names: List of tool names
|
|
184
|
+
operations: Optional dict mapping tool names to operations
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
List of function schemas
|
|
188
|
+
"""
|
|
189
|
+
schemas = []
|
|
190
|
+
operations = operations or {}
|
|
191
|
+
|
|
192
|
+
for tool_name in tool_names:
|
|
193
|
+
tool_ops = operations.get(tool_name, [None])
|
|
194
|
+
|
|
195
|
+
for op in tool_ops:
|
|
196
|
+
try:
|
|
197
|
+
schema = ToolSchemaGenerator.generate_schema(tool_name, op)
|
|
198
|
+
schemas.append(schema)
|
|
199
|
+
except Exception as e:
|
|
200
|
+
logger.warning(f"Failed to generate schema for {tool_name}.{op}: {e}")
|
|
201
|
+
|
|
202
|
+
return schemas
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def generate_tool_schema(
|
|
206
|
+
tool_name: str,
|
|
207
|
+
operation: Optional[str] = None,
|
|
208
|
+
description: Optional[str] = None
|
|
209
|
+
) -> Dict[str, Any]:
|
|
210
|
+
"""
|
|
211
|
+
Convenience function to generate tool schema.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
tool_name: Tool name
|
|
215
|
+
operation: Optional operation name
|
|
216
|
+
description: Optional custom description
|
|
217
|
+
|
|
218
|
+
Returns:
|
|
219
|
+
OpenAI function schema dictionary
|
|
220
|
+
"""
|
|
221
|
+
return ToolSchemaGenerator.generate_schema(tool_name, operation, description)
|
|
222
|
+
|
aiecs/main.py
CHANGED
|
@@ -142,7 +142,7 @@ async def lifespan(app: FastAPI):
|
|
|
142
142
|
app = FastAPI(
|
|
143
143
|
title="AIECS - AI Execute Services",
|
|
144
144
|
description="Middleware service for AI-powered task execution and tool orchestration",
|
|
145
|
-
version="1.
|
|
145
|
+
version="1.4.0",
|
|
146
146
|
lifespan=lifespan
|
|
147
147
|
)
|
|
148
148
|
|
|
@@ -167,7 +167,7 @@ async def health_check():
|
|
|
167
167
|
return {
|
|
168
168
|
"status": "healthy",
|
|
169
169
|
"service": "aiecs",
|
|
170
|
-
"version": "1.
|
|
170
|
+
"version": "1.4.0"
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
aiecs/__init__.py,sha256=
|
|
1
|
+
aiecs/__init__.py,sha256=VdY9z5KOk6Ln2WD0We4kcYDufBZiCSN8RoAuxRl-_fM,1859
|
|
2
2
|
aiecs/__main__.py,sha256=AfQpzy3SgwWuP4DuymYcm4MISMuzqwhxxGSYo53PBvY,1035
|
|
3
3
|
aiecs/aiecs_client.py,sha256=gIqecRBBH_bYIWhqiHCemdVgmGb9Jqdxf1b6RoqXWlQ,17276
|
|
4
|
-
aiecs/main.py,sha256=
|
|
4
|
+
aiecs/main.py,sha256=GfKAtdvRYrGeK3II2eQGMkMTys6ozu4zDSL83hTu69w,10837
|
|
5
5
|
aiecs/application/__init__.py,sha256=NkmrUH1DqxJ3vaVC8QwscNdlWqHfC7ZagL4k3nZ_qz4,192
|
|
6
6
|
aiecs/application/executors/__init__.py,sha256=WIl7L9HBsEhNfbNtJdvBvFUJXzESvNZVaiAA6tdtJcs,191
|
|
7
7
|
aiecs/application/executors/operation_executor.py,sha256=-7mFo1hUnWdehVPg0fnSiRhW3LACpIiyLSH-iu7bX4U,13818
|
|
@@ -12,7 +12,34 @@ aiecs/core/__init__.py,sha256=H0ZIk96q0KHKivcobnUCVJdJZmewucVJ9MKhRgUxmk0,1037
|
|
|
12
12
|
aiecs/core/interface/__init__.py,sha256=soI7zdoN3eQynVb9uiwmgXkM5E75JYffTILktHb48x8,688
|
|
13
13
|
aiecs/core/interface/execution_interface.py,sha256=6bXruts8dyAg647lxPDQkF-cdJG1W8ZqpxFQ6hjVrd4,4810
|
|
14
14
|
aiecs/core/interface/storage_interface.py,sha256=F7GQEZ_ZiRWeen7oZO6A4S0nW0VORYsygk2BYLw5aiY,5680
|
|
15
|
-
aiecs/domain/__init__.py,sha256=
|
|
15
|
+
aiecs/domain/__init__.py,sha256=3JX4h1svFew0Zsy2_tMO2UxTUsSyzXywC-K_ooovjtk,6687
|
|
16
|
+
aiecs/domain/agent/__init__.py,sha256=pbg7QM__ZzdTdAzf9-CaeQd-rQwEZM0jq0kswwoGfRI,3725
|
|
17
|
+
aiecs/domain/agent/base_agent.py,sha256=wDQ6KuSjn-yTb6rv2iKv9SLBliMLyltc0a1uQLXCUD8,21995
|
|
18
|
+
aiecs/domain/agent/exceptions.py,sha256=PkPqFXdhPSN5Fe7Q6tH3mxl8GGlUsPRIWh1JwOiEV5g,2961
|
|
19
|
+
aiecs/domain/agent/hybrid_agent.py,sha256=CaC4VQHrRHpac00kgNEltoJRduqeyH5cXx7oYNtX7qA,17132
|
|
20
|
+
aiecs/domain/agent/lifecycle.py,sha256=2E4B1L1-ZTu6exMsW_lXZN8ammKqFS_g4lsaVfVfnrE,8858
|
|
21
|
+
aiecs/domain/agent/llm_agent.py,sha256=qVYetEZ6KdUm3sgQd9wIF1QCKC3wNIz3DybsIAcd30Y,10073
|
|
22
|
+
aiecs/domain/agent/models.py,sha256=m3sKJrUpF3qkEduTRs3RcwGjm0zE_xsF-LMkzQj2CS4,10404
|
|
23
|
+
aiecs/domain/agent/observability.py,sha256=z7ZEzZaEn_4cI18QTKyTmCvBcp6rak8hPg_riseZ6EY,11823
|
|
24
|
+
aiecs/domain/agent/persistence.py,sha256=RBv5zACZTXrz7_p04PFopYhMYk7osN24myVglND5DWA,8783
|
|
25
|
+
aiecs/domain/agent/registry.py,sha256=My0yiAqQbP2ha9PNS5iwYCZv6fuNJbGTAEt3y_-9o5U,6988
|
|
26
|
+
aiecs/domain/agent/tool_agent.py,sha256=TDou3QFfR0_jluqB7hU9JjuZZlW4e5JQHksUdnM7Gqo,8426
|
|
27
|
+
aiecs/domain/agent/integration/__init__.py,sha256=-YqOJXXcc7vK6w51riv-Q548ol1Rs7XZ1NGreUdStUc,591
|
|
28
|
+
aiecs/domain/agent/integration/context_compressor.py,sha256=Rbt6DoAyBP2QSDRXwsZRoVy5LJ0eQF_1-a1uNdxQ_b0,6593
|
|
29
|
+
aiecs/domain/agent/integration/context_engine_adapter.py,sha256=_lCZaqWy70px_kReZkCiIZNUCRtUya4B873F2tTJqlE,8608
|
|
30
|
+
aiecs/domain/agent/integration/retry_policy.py,sha256=qR5kndCz1pyadZYq7X1cWA6CyWDQlBLyHwmQ91jhg2A,6220
|
|
31
|
+
aiecs/domain/agent/integration/role_config.py,sha256=Tl51HNTu_VHhjugGoSUIrVtoybLej9jRbKRMwMnc8Ys,6674
|
|
32
|
+
aiecs/domain/agent/memory/__init__.py,sha256=faF8Mohlih5e0ZyjzGM8qiHE-jOzCRzMaJ_P2zL21K8,185
|
|
33
|
+
aiecs/domain/agent/memory/conversation.py,sha256=OLDnMxUNWEgVMYXe3vQRyzO2hgkf6-TZteqQ7X__YCk,6168
|
|
34
|
+
aiecs/domain/agent/migration/__init__.py,sha256=WSFQijiy8Z7hXVjsJcQPGvTP5I_iey20AuvnSaWN80s,321
|
|
35
|
+
aiecs/domain/agent/migration/conversion.py,sha256=EMMuLQ_sjzb4_EkEuF-ZAlBfvpZOgPXJKwhzo43iawI,4477
|
|
36
|
+
aiecs/domain/agent/migration/legacy_wrapper.py,sha256=I7CA0B-nAlxpB2vPPga7AUIIebyZfVVbKcXhcc5817A,2958
|
|
37
|
+
aiecs/domain/agent/prompts/__init__.py,sha256=M9wb69MkZawysZWnL4Sam3FmNm29AktTw6eUHQGyyGg,572
|
|
38
|
+
aiecs/domain/agent/prompts/builder.py,sha256=vYjCLGMdifpe-jdpy71FoLo6U3lxrMEkn7yX6cpBSkM,4094
|
|
39
|
+
aiecs/domain/agent/prompts/formatters.py,sha256=CYva2umS6G-82B1JgRGbwlSOMqOaK3S4-DRHZ4HxsSM,4605
|
|
40
|
+
aiecs/domain/agent/prompts/template.py,sha256=jk_k-z9Hz5lr7shQwv4qfiFBXMWXq_ZxGuxSapfodjs,7543
|
|
41
|
+
aiecs/domain/agent/tools/__init__.py,sha256=hQVIzYR1TK-tf3f7GBG4EkPBqoWU2tywJ1wwYofGbJY,227
|
|
42
|
+
aiecs/domain/agent/tools/schema_generator.py,sha256=pFShusTPLZPZ3meBoswzQsesYFrn8HpXW6Or2npJVfg,6863
|
|
16
43
|
aiecs/domain/community/__init__.py,sha256=SxP6IVtG6ZO5LSwzFEzOKAWjjsKO91s2Xgbp92L4R2I,3606
|
|
17
44
|
aiecs/domain/community/agent_adapter.py,sha256=QAIex0ftCSNlyC9eZPAOLtwCsX6kJrxGoC6rMq0gqgc,16070
|
|
18
45
|
aiecs/domain/community/analytics.py,sha256=M7uwkS5DLSYc4OA3H26CkHJigj7BG7aMtihO8piLZLw,18316
|
|
@@ -168,9 +195,9 @@ aiecs/utils/prompt_loader.py,sha256=cBS2bZXpYQOWSiOGkhwIzyy3_bETqwIblRi_9qQT9iQ,
|
|
|
168
195
|
aiecs/utils/token_usage_repository.py,sha256=1xjenLYwC0YT6lKZFEGO4scRCXLuWdec2MWjzih5SZY,10210
|
|
169
196
|
aiecs/ws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
170
197
|
aiecs/ws/socket_server.py,sha256=j_9idVY_rWlTsF51FgmuhWCWFVt7_gAHL8vNg3IxV5g,1476
|
|
171
|
-
aiecs-1.
|
|
172
|
-
aiecs-1.
|
|
173
|
-
aiecs-1.
|
|
174
|
-
aiecs-1.
|
|
175
|
-
aiecs-1.
|
|
176
|
-
aiecs-1.
|
|
198
|
+
aiecs-1.4.0.dist-info/licenses/LICENSE,sha256=_1YRaIS0eZu1pv6xfz245UkU0i1Va2B841hv3OWRwqg,12494
|
|
199
|
+
aiecs-1.4.0.dist-info/METADATA,sha256=KKow5_VX9OHucyFLUF_ULhv7IdYuWloDhyJECchLYWM,16635
|
|
200
|
+
aiecs-1.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
201
|
+
aiecs-1.4.0.dist-info/entry_points.txt,sha256=TfLBuwLOfgQqKvnoF1sgTS19-Hgl0aWvCZjIdblIiig,667
|
|
202
|
+
aiecs-1.4.0.dist-info/top_level.txt,sha256=22IlUlOqh9Ni3jXlQNMNUqzbW8dcxXPeR_EQ-BJVcV8,6
|
|
203
|
+
aiecs-1.4.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|